Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions lib/migration_generator/migration_generator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -649,14 +649,19 @@ defmodule AshPostgres.MigrationGenerator do
folder = get_snapshot_folder(snapshot, opts)
snapshot_path = get_snapshot_path(snapshot, folder)

snapshot_path
|> File.ls!()
|> Enum.filter(&String.contains?(&1, "_dev.json"))
|> Enum.each(fn snapshot_name ->
# Guard against missing directories - can happen for new resources or when
# get_snapshot_path's fallback logic returns a non-existent path for
# resources in non-public schemas
if File.dir?(snapshot_path) do
snapshot_path
|> Path.join(snapshot_name)
|> File.rm!()
end)
|> File.ls!()
|> Enum.filter(&String.contains?(&1, "_dev.json"))
|> Enum.each(fn snapshot_name ->
snapshot_path
|> Path.join(snapshot_name)
|> File.rm!()
end)
end
end)
end

Expand Down
7 changes: 7 additions & 0 deletions lib/resource_generator/resource_generator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ if Code.ensure_loaded?(Igniter) do
postgres do
table #{inspect(table_spec.table_name)}
repo #{inspect(table_spec.repo)}
#{schema_option(table_spec)}
#{no_migrate_flag}
#{references(table_spec, opts[:no_migrations])}
#{custom_indexes(table_spec, opts[:no_migrations])}
Expand Down Expand Up @@ -144,6 +145,12 @@ if Code.ensure_loaded?(Igniter) do
end)
end

defp schema_option(%{schema: schema}) when schema != "public" do
"schema #{inspect(schema)}"
end

defp schema_option(_), do: ""

defp default_actions(opts) do
cond do
opts[:default_actions] && opts[:public] ->
Expand Down
16 changes: 12 additions & 4 deletions lib/resource_generator/spec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,13 @@ defmodule AshPostgres.ResourceGenerator.Spec do
result
end

defp qualified_table_name(%{schema: schema, table_name: table_name}) do
"#{schema}.#{table_name}"
end

defp add_foreign_keys(spec) do
qualified_table = qualified_table_name(spec)

%Postgrex.Result{rows: fkey_rows} =
spec.repo.query!(
"""
Expand Down Expand Up @@ -178,7 +184,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
constraints.update_rule,
constraints.delete_rule
""",
[spec.table_name, spec.schema],
[qualified_table, spec.schema],
log: false
)

Expand Down Expand Up @@ -218,6 +224,8 @@ defmodule AshPostgres.ResourceGenerator.Spec do
end

defp add_check_constraints(spec) do
qualified_table = qualified_table_name(spec)

%Postgrex.Result{rows: check_constraint_rows} =
spec.repo.query!(
"""
Expand All @@ -230,7 +238,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
contype = 'c'
AND conrelid::regclass::text = $1
""",
[spec.table_name],
[qualified_table],
log: false
)

Expand Down Expand Up @@ -278,7 +286,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
LEFT JOIN
pg_constraint c ON c.conindid = ix.indexrelid AND c.contype = 'p'
JOIN
pg_indexes idx ON idx.indexname = i.relname AND idx.schemaname = 'public' -- Adjust schema name if necessary
pg_indexes idx ON idx.indexname = i.relname AND idx.schemaname = $2
JOIN information_schema.tables ta
ON ta.table_name = t.relname
WHERE
Expand Down Expand Up @@ -312,7 +320,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
LEFT JOIN
pg_constraint c ON c.conindid = ix.indexrelid AND c.contype = 'p'
JOIN
pg_indexes idx ON idx.indexname = i.relname AND idx.schemaname = 'public' -- Adjust schema name if necessary
pg_indexes idx ON idx.indexname = i.relname AND idx.schemaname = $2
JOIN information_schema.tables ta
ON ta.table_name = t.relname
WHERE
Expand Down
130 changes: 130 additions & 0 deletions test/resource_generator_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,134 @@ defmodule AshPostgres.ResourceGeenratorTests do
end
""")
end

test "a resource is generated from a table in a non-public schema with foreign keys and indexes" do
AshPostgres.TestRepo.query!("CREATE SCHEMA IF NOT EXISTS inventory")

AshPostgres.TestRepo.query!("DROP TABLE IF EXISTS inventory.products CASCADE")
AshPostgres.TestRepo.query!("DROP TABLE IF EXISTS inventory.warehouses CASCADE")

AshPostgres.TestRepo.query!("""
CREATE TABLE inventory.warehouses (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name VARCHAR(255) NOT NULL,
location VARCHAR(255)
)
""")

AshPostgres.TestRepo.query!("CREATE INDEX warehouses_name_idx ON inventory.warehouses(name)")

AshPostgres.TestRepo.query!("""
CREATE TABLE inventory.products (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name VARCHAR(255) NOT NULL,
warehouse_id UUID REFERENCES inventory.warehouses(id) ON DELETE CASCADE,
quantity INTEGER
)
""")

AshPostgres.TestRepo.query!(
"CREATE INDEX products_warehouse_id_idx ON inventory.products(warehouse_id)"
)

test_project()
|> Igniter.compose_task("ash_postgres.gen.resources", [
"MyApp.Inventory",
"--tables",
"inventory.warehouses,inventory.products",
"--yes",
"--repo",
"AshPostgres.TestRepo"
])
|> assert_creates("lib/my_app/inventory/warehouse.ex", """
defmodule MyApp.Inventory.Warehouse do
use Ash.Resource,
domain: MyApp.Inventory,
data_layer: AshPostgres.DataLayer

actions do
defaults([:read, :destroy, create: :*, update: :*])
end

postgres do
table("warehouses")
repo(AshPostgres.TestRepo)
schema("inventory")
end

attributes do
uuid_primary_key :id do
public?(true)
end

attribute :name, :string do
allow_nil?(false)
public?(true)
end

attribute :location, :string do
public?(true)
end
end

relationships do
has_many :products, MyApp.Inventory.Product do
public?(true)
end
end
end
""")
|> assert_creates("lib/my_app/inventory/product.ex", """
defmodule MyApp.Inventory.Product do
use Ash.Resource,
domain: MyApp.Inventory,
data_layer: AshPostgres.DataLayer

actions do
defaults([:read, :destroy, create: :*, update: :*])
end

postgres do
table("products")
repo(AshPostgres.TestRepo)
schema("inventory")

references do
reference :warehouse do
on_delete(:delete)
end
end
end

attributes do
uuid_primary_key :id do
public?(true)
end

uuid_primary_key :id do
public?(true)
end

attribute :name, :string do
public?(true)
end

attribute :name, :string do
allow_nil?(false)
public?(true)
end

attribute :quantity, :integer do
public?(true)
end
end

relationships do
belongs_to :warehouse, MyApp.Inventory.Warehouse do
public?(true)
end
end
end
""")
end
end
Loading