mirror of
https://github.com/ash-project/ash_postgres.git
synced 2024-09-20 05:23:18 +12:00
improvement: add static schema specification in DSL
improvement: support static schema specification in migration generator
This commit is contained in:
parent
4e85466724
commit
6c5ee9aae5
7 changed files with 501 additions and 143 deletions
|
@ -27,6 +27,7 @@ locals_without_parens = [
|
||||||
reference: 1,
|
reference: 1,
|
||||||
reference: 2,
|
reference: 2,
|
||||||
repo: 1,
|
repo: 1,
|
||||||
|
schema: 1,
|
||||||
skip_unique_indexes: 1,
|
skip_unique_indexes: 1,
|
||||||
table: 1,
|
table: 1,
|
||||||
template: 1,
|
template: 1,
|
||||||
|
|
|
@ -19,6 +19,11 @@ defmodule AshPostgres do
|
||||||
Extension.get_opt(resource, [:postgres], :table, nil, true)
|
Extension.get_opt(resource, [:postgres], :table, nil, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc "The configured schema for a resource"
|
||||||
|
def schema(resource) do
|
||||||
|
Extension.get_opt(resource, [:postgres], :schema, nil, true)
|
||||||
|
end
|
||||||
|
|
||||||
@doc "The configured references for a resource"
|
@doc "The configured references for a resource"
|
||||||
def references(resource) do
|
def references(resource) do
|
||||||
Extension.get_entities(resource, [:postgres, :references])
|
Extension.get_entities(resource, [:postgres, :references])
|
||||||
|
|
|
@ -290,8 +290,19 @@ defmodule AshPostgres.DataLayer do
|
||||||
],
|
],
|
||||||
table: [
|
table: [
|
||||||
type: :string,
|
type: :string,
|
||||||
doc:
|
doc: """
|
||||||
"The table to store and read the resource from. Required unless `polymorphic?` is true."
|
The table to store and read the resource from. Required unless `polymorphic?` is true.
|
||||||
|
|
||||||
|
If this is changed, the migration generator will not remove the old table.
|
||||||
|
"""
|
||||||
|
],
|
||||||
|
schema: [
|
||||||
|
type: :string,
|
||||||
|
doc: """
|
||||||
|
The schema that the table is located in.
|
||||||
|
Multitenancy supersedes this, so this acts as the schema in the cases that `global?: true` is set.
|
||||||
|
If this is changed, the migration generator will not remove the old table in the old schema.
|
||||||
|
"""
|
||||||
],
|
],
|
||||||
polymorphic?: [
|
polymorphic?: [
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
|
@ -320,7 +331,7 @@ defmodule AshPostgres.DataLayer do
|
||||||
alias Ash.Filter
|
alias Ash.Filter
|
||||||
alias Ash.Query.{BooleanExpression, Not}
|
alias Ash.Query.{BooleanExpression, Not}
|
||||||
|
|
||||||
import AshPostgres, only: [repo: 1]
|
import AshPostgres, only: [repo: 1, schema: 1]
|
||||||
|
|
||||||
@behaviour Ash.DataLayer
|
@behaviour Ash.DataLayer
|
||||||
|
|
||||||
|
@ -438,6 +449,13 @@ defmodule AshPostgres.DataLayer do
|
||||||
data_layer_query
|
data_layer_query
|
||||||
end
|
end
|
||||||
|
|
||||||
|
data_layer_query =
|
||||||
|
if context[:data_layer][:schema] do
|
||||||
|
Ecto.Query.put_query_prefix(data_layer_query, to_string(context[:data_layer][:schema]))
|
||||||
|
else
|
||||||
|
data_layer_query
|
||||||
|
end
|
||||||
|
|
||||||
data_layer_query =
|
data_layer_query =
|
||||||
data_layer_query
|
data_layer_query
|
||||||
|> default_bindings(resource, context)
|
|> default_bindings(resource, context)
|
||||||
|
@ -474,7 +492,11 @@ defmodule AshPostgres.DataLayer do
|
||||||
if Ash.Resource.Info.multitenancy_strategy(resource) == :context do
|
if Ash.Resource.Info.multitenancy_strategy(resource) == :context do
|
||||||
[prefix: tenant]
|
[prefix: tenant]
|
||||||
else
|
else
|
||||||
[]
|
if schema = schema(resource) do
|
||||||
|
[prefix: schema]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|> add_timeout(changeset)
|
|> add_timeout(changeset)
|
||||||
end
|
end
|
||||||
|
@ -491,7 +513,11 @@ defmodule AshPostgres.DataLayer do
|
||||||
if Ash.Resource.Info.multitenancy_strategy(resource) == :context do
|
if Ash.Resource.Info.multitenancy_strategy(resource) == :context do
|
||||||
[prefix: tenant]
|
[prefix: tenant]
|
||||||
else
|
else
|
||||||
[]
|
if schema = schema(resource) do
|
||||||
|
[prefix: schema]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|> add_timeout(query)
|
|> add_timeout(query)
|
||||||
end
|
end
|
||||||
|
@ -798,7 +824,7 @@ defmodule AshPostgres.DataLayer do
|
||||||
data_layer_query
|
data_layer_query
|
||||||
| prefix:
|
| prefix:
|
||||||
to_string(
|
to_string(
|
||||||
source_query.tenant || config[:default_prefix] ||
|
source_query.tenant || schema(resource) || config[:default_prefix] ||
|
||||||
"public"
|
"public"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -807,7 +833,7 @@ defmodule AshPostgres.DataLayer do
|
||||||
data_layer_query
|
data_layer_query
|
||||||
| prefix:
|
| prefix:
|
||||||
to_string(
|
to_string(
|
||||||
config[:default_prefix] ||
|
schema(resource) || config[:default_prefix] ||
|
||||||
"public"
|
"public"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -932,10 +958,19 @@ defmodule AshPostgres.DataLayer do
|
||||||
if AshPostgres.polymorphic?(record.__struct__) do
|
if AshPostgres.polymorphic?(record.__struct__) do
|
||||||
table = changeset.context[:data_layer][:table] || AshPostgres.table(record.__struct__)
|
table = changeset.context[:data_layer][:table] || AshPostgres.table(record.__struct__)
|
||||||
|
|
||||||
if table do
|
record =
|
||||||
Ecto.put_meta(record, source: table)
|
if table do
|
||||||
|
Ecto.put_meta(record, source: table)
|
||||||
|
else
|
||||||
|
raise_table_error!(changeset.resource, operation)
|
||||||
|
end
|
||||||
|
|
||||||
|
prefix = changeset.context[:data_layer][:schema] || AshPostgres.schema(record.__struct__)
|
||||||
|
|
||||||
|
if prefix do
|
||||||
|
Ecto.put_meta(record, prefix: table)
|
||||||
else
|
else
|
||||||
raise_table_error!(changeset.resource, operation)
|
record
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
record
|
record
|
||||||
|
|
|
@ -276,7 +276,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
defp deduplicate_snapshots(snapshots, opts, existing_snapshots \\ []) do
|
defp deduplicate_snapshots(snapshots, opts, existing_snapshots \\ []) do
|
||||||
snapshots
|
snapshots
|
||||||
|> Enum.group_by(fn snapshot ->
|
|> Enum.group_by(fn snapshot ->
|
||||||
snapshot.table
|
{snapshot.table, snapshot.schema}
|
||||||
end)
|
end)
|
||||||
|> Enum.map(fn {_table, [snapshot | _] = snapshots} ->
|
|> Enum.map(fn {_table, [snapshot | _] = snapshots} ->
|
||||||
existing_snapshot =
|
existing_snapshot =
|
||||||
|
@ -397,7 +397,8 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
on_delete: merge_uniq!(references, table, :on_delete, name),
|
on_delete: merge_uniq!(references, table, :on_delete, name),
|
||||||
on_update: merge_uniq!(references, table, :on_update, name),
|
on_update: merge_uniq!(references, table, :on_update, name),
|
||||||
name: merge_uniq!(references, table, :name, name),
|
name: merge_uniq!(references, table, :name, name),
|
||||||
table: merge_uniq!(references, table, :table, name)
|
table: merge_uniq!(references, table, :table, name),
|
||||||
|
schema: merge_uniq!(references, table, :schema, name)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -762,6 +763,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
attribute: %{
|
attribute: %{
|
||||||
source: name
|
source: name
|
||||||
},
|
},
|
||||||
|
schema: schema,
|
||||||
table: table
|
table: table
|
||||||
} = add
|
} = add
|
||||||
| rest
|
| rest
|
||||||
|
@ -770,7 +772,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
) do
|
) do
|
||||||
rest
|
rest
|
||||||
|> Enum.take_while(fn op ->
|
|> Enum.take_while(fn op ->
|
||||||
op.table == table
|
op.table == table && op.schema == schema
|
||||||
end)
|
end)
|
||||||
|> Enum.with_index()
|
|> Enum.with_index()
|
||||||
|> Enum.find(fn
|
|> Enum.find(fn
|
||||||
|
@ -808,40 +810,46 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp group_into_phases(
|
defp group_into_phases(
|
||||||
[%Operation.CreateTable{table: table, multitenancy: multitenancy} | rest],
|
[
|
||||||
|
%Operation.CreateTable{table: table, schema: schema, multitenancy: multitenancy} | rest
|
||||||
|
],
|
||||||
nil,
|
nil,
|
||||||
acc
|
acc
|
||||||
) do
|
) do
|
||||||
group_into_phases(rest, %Phase.Create{table: table, multitenancy: multitenancy}, acc)
|
group_into_phases(
|
||||||
|
rest,
|
||||||
|
%Phase.Create{table: table, schema: schema, multitenancy: multitenancy},
|
||||||
|
acc
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp group_into_phases(
|
defp group_into_phases(
|
||||||
[%Operation.AddAttribute{table: table} = op | rest],
|
[%Operation.AddAttribute{table: table, schema: schema} = op | rest],
|
||||||
%{table: table} = phase,
|
%{table: table, schema: schema} = phase,
|
||||||
acc
|
acc
|
||||||
) do
|
) do
|
||||||
group_into_phases(rest, %{phase | operations: [op | phase.operations]}, acc)
|
group_into_phases(rest, %{phase | operations: [op | phase.operations]}, acc)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp group_into_phases(
|
defp group_into_phases(
|
||||||
[%Operation.AlterAttribute{table: table} = op | rest],
|
[%Operation.AlterAttribute{table: table, schema: schema} = op | rest],
|
||||||
%Phase.Alter{table: table} = phase,
|
%Phase.Alter{table: table, schema: schema} = phase,
|
||||||
acc
|
acc
|
||||||
) do
|
) do
|
||||||
group_into_phases(rest, %{phase | operations: [op | phase.operations]}, acc)
|
group_into_phases(rest, %{phase | operations: [op | phase.operations]}, acc)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp group_into_phases(
|
defp group_into_phases(
|
||||||
[%Operation.RenameAttribute{table: table} = op | rest],
|
[%Operation.RenameAttribute{table: table, schema: schema} = op | rest],
|
||||||
%Phase.Alter{table: table} = phase,
|
%Phase.Alter{table: table, schema: schema} = phase,
|
||||||
acc
|
acc
|
||||||
) do
|
) do
|
||||||
group_into_phases(rest, %{phase | operations: [op | phase.operations]}, acc)
|
group_into_phases(rest, %{phase | operations: [op | phase.operations]}, acc)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp group_into_phases(
|
defp group_into_phases(
|
||||||
[%Operation.RemoveAttribute{table: table} = op | rest],
|
[%Operation.RemoveAttribute{table: table, schema: schema} = op | rest],
|
||||||
%{table: table} = phase,
|
%{table: table, schema: schema} = phase,
|
||||||
acc
|
acc
|
||||||
) do
|
) do
|
||||||
group_into_phases(rest, %{phase | operations: [op | phase.operations]}, acc)
|
group_into_phases(rest, %{phase | operations: [op | phase.operations]}, acc)
|
||||||
|
@ -855,7 +863,8 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
phase = %Phase.Alter{
|
phase = %Phase.Alter{
|
||||||
operations: [operation],
|
operations: [operation],
|
||||||
multitenancy: operation.multitenancy,
|
multitenancy: operation.multitenancy,
|
||||||
table: operation.table
|
table: operation.table,
|
||||||
|
schema: operation.schema
|
||||||
}
|
}
|
||||||
|
|
||||||
group_into_phases(rest, phase, acc)
|
group_into_phases(rest, phase, acc)
|
||||||
|
@ -889,25 +898,27 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.AddAttribute{attribute: %{order: l}, table: table},
|
%Operation.AddAttribute{attribute: %{order: l}, table: table, schema: schema},
|
||||||
%Operation.AddAttribute{attribute: %{order: r}, table: table}
|
%Operation.AddAttribute{attribute: %{order: r}, table: table, schema: schema}
|
||||||
),
|
),
|
||||||
do: l > r
|
do: l > r
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.RenameUniqueIndex{
|
%Operation.RenameUniqueIndex{
|
||||||
table: table
|
table: table,
|
||||||
|
schema: schema
|
||||||
},
|
},
|
||||||
%{table: table}
|
%{table: table, schema: schema}
|
||||||
) do
|
) do
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.AddUniqueIndex{
|
%Operation.AddUniqueIndex{
|
||||||
table: table
|
table: table,
|
||||||
|
schema: schema
|
||||||
},
|
},
|
||||||
%{table: table}
|
%{table: table, schema: schema}
|
||||||
) do
|
) do
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
@ -916,9 +927,10 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
%Operation.AddCheckConstraint{
|
%Operation.AddCheckConstraint{
|
||||||
constraint: %{attribute: attribute_or_attributes},
|
constraint: %{attribute: attribute_or_attributes},
|
||||||
table: table,
|
table: table,
|
||||||
multitenancy: multitenancy
|
multitenancy: multitenancy,
|
||||||
|
schema: schema
|
||||||
},
|
},
|
||||||
%Operation.AddAttribute{table: table, attribute: %{source: source}}
|
%Operation.AddAttribute{table: table, attribute: %{source: source}, schema: schema}
|
||||||
) do
|
) do
|
||||||
source in List.wrap(attribute_or_attributes) ||
|
source in List.wrap(attribute_or_attributes) ||
|
||||||
(multitenancy.attribute && multitenancy.attribute in List.wrap(attribute_or_attributes))
|
(multitenancy.attribute && multitenancy.attribute in List.wrap(attribute_or_attributes))
|
||||||
|
@ -926,24 +938,30 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.AddCustomIndex{
|
%Operation.AddCustomIndex{
|
||||||
table: table
|
table: table,
|
||||||
|
schema: schema
|
||||||
},
|
},
|
||||||
%Operation.AddAttribute{table: table}
|
%Operation.AddAttribute{table: table, schema: schema}
|
||||||
) do
|
) do
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
defp after?(%Operation.AddCheckConstraint{table: table}, %Operation.RemoveCheckConstraint{
|
defp after?(
|
||||||
table: table
|
%Operation.AddCheckConstraint{table: table, schema: schema},
|
||||||
}),
|
%Operation.RemoveCheckConstraint{
|
||||||
|
table: table,
|
||||||
|
schema: schema
|
||||||
|
}
|
||||||
|
),
|
||||||
do: true
|
do: true
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.AddCheckConstraint{
|
%Operation.AddCheckConstraint{
|
||||||
constraint: %{attribute: attribute_or_attributes},
|
constraint: %{attribute: attribute_or_attributes},
|
||||||
table: table
|
table: table,
|
||||||
|
schema: schema
|
||||||
},
|
},
|
||||||
%Operation.AlterAttribute{table: table, new_attribute: %{source: source}}
|
%Operation.AlterAttribute{table: table, new_attribute: %{source: source}, schema: schema}
|
||||||
) do
|
) do
|
||||||
source in List.wrap(attribute_or_attributes)
|
source in List.wrap(attribute_or_attributes)
|
||||||
end
|
end
|
||||||
|
@ -951,43 +969,61 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.AddCheckConstraint{
|
%Operation.AddCheckConstraint{
|
||||||
constraint: %{attribute: attribute_or_attributes},
|
constraint: %{attribute: attribute_or_attributes},
|
||||||
table: table
|
table: table,
|
||||||
|
schema: schema
|
||||||
},
|
},
|
||||||
%Operation.RenameAttribute{table: table, new_attribute: %{source: source}}
|
%Operation.RenameAttribute{
|
||||||
|
table: table,
|
||||||
|
new_attribute: %{source: source},
|
||||||
|
schema: schema
|
||||||
|
}
|
||||||
) do
|
) do
|
||||||
source in List.wrap(attribute_or_attributes)
|
source in List.wrap(attribute_or_attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.RemoveUniqueIndex{table: table},
|
%Operation.RemoveUniqueIndex{table: table, schema: schema},
|
||||||
%Operation.AddUniqueIndex{table: table}
|
%Operation.AddUniqueIndex{table: table, schema: schema}
|
||||||
) do
|
) do
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.RemoveUniqueIndex{table: table},
|
%Operation.RemoveUniqueIndex{table: table, schema: schema},
|
||||||
%{table: table}
|
%{table: table, schema: schema}
|
||||||
) do
|
) do
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.RemoveCheckConstraint{constraint: %{attribute: attributes}, table: table},
|
%Operation.RemoveCheckConstraint{
|
||||||
%Operation.RemoveAttribute{table: table, attribute: %{source: source}}
|
constraint: %{attribute: attributes},
|
||||||
|
table: table,
|
||||||
|
schema: schema
|
||||||
|
},
|
||||||
|
%Operation.RemoveAttribute{table: table, attribute: %{source: source}, schema: schema}
|
||||||
) do
|
) do
|
||||||
source in List.wrap(attributes)
|
source in List.wrap(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.RemoveCheckConstraint{constraint: %{attribute: attributes}, table: table},
|
%Operation.RemoveCheckConstraint{
|
||||||
%Operation.RenameAttribute{table: table, old_attribute: %{source: source}}
|
constraint: %{attribute: attributes},
|
||||||
|
table: table,
|
||||||
|
schema: schema
|
||||||
|
},
|
||||||
|
%Operation.RenameAttribute{
|
||||||
|
table: table,
|
||||||
|
old_attribute: %{source: source},
|
||||||
|
schema: schema
|
||||||
|
}
|
||||||
) do
|
) do
|
||||||
source in List.wrap(attributes)
|
source in List.wrap(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp after?(%Operation.AlterAttribute{table: table}, %Operation.DropForeignKey{
|
defp after?(%Operation.AlterAttribute{table: table, schema: schema}, %Operation.DropForeignKey{
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
direction: :up
|
direction: :up
|
||||||
}),
|
}),
|
||||||
do: true
|
do: true
|
||||||
|
@ -995,56 +1031,68 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.DropForeignKey{
|
%Operation.DropForeignKey{
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
direction: :down
|
direction: :down
|
||||||
},
|
},
|
||||||
%Operation.AlterAttribute{table: table}
|
%Operation.AlterAttribute{table: table, schema: schema}
|
||||||
),
|
),
|
||||||
do: true
|
do: true
|
||||||
|
|
||||||
defp after?(%Operation.AddAttribute{table: table}, %Operation.CreateTable{table: table}) do
|
defp after?(%Operation.AddAttribute{table: table, schema: schema}, %Operation.CreateTable{
|
||||||
|
table: table,
|
||||||
|
schema: schema
|
||||||
|
}) do
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.AddAttribute{
|
%Operation.AddAttribute{
|
||||||
attribute: %{
|
attribute: %{
|
||||||
references: %{table: table, destination_field: name}
|
references: %{table: table, destination_field: name, schema: schema}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
%Operation.AddAttribute{table: table, attribute: %{source: name}}
|
%Operation.AddAttribute{table: table, schema: schema, attribute: %{source: name}}
|
||||||
),
|
),
|
||||||
do: true
|
do: true
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.AddAttribute{
|
%Operation.AddAttribute{
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
attribute: %{
|
attribute: %{
|
||||||
primary_key?: false
|
primary_key?: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
%Operation.AddAttribute{table: table, attribute: %{primary_key?: true}}
|
%Operation.AddAttribute{schema: schema, table: table, attribute: %{primary_key?: true}}
|
||||||
),
|
),
|
||||||
do: true
|
do: true
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.AddAttribute{
|
%Operation.AddAttribute{
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
attribute: %{
|
attribute: %{
|
||||||
primary_key?: true
|
primary_key?: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
%Operation.RemoveAttribute{table: table, attribute: %{primary_key?: true}}
|
%Operation.RemoveAttribute{
|
||||||
|
schema: schema,
|
||||||
|
table: table,
|
||||||
|
attribute: %{primary_key?: true}
|
||||||
|
}
|
||||||
),
|
),
|
||||||
do: true
|
do: true
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.AlterAttribute{
|
%Operation.AlterAttribute{
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
new_attribute: %{primary_key?: false},
|
new_attribute: %{primary_key?: false},
|
||||||
old_attribute: %{primary_key?: true}
|
old_attribute: %{primary_key?: true}
|
||||||
},
|
},
|
||||||
%Operation.AddAttribute{
|
%Operation.AddAttribute{
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
attribute: %{
|
attribute: %{
|
||||||
primary_key?: true
|
primary_key?: true
|
||||||
}
|
}
|
||||||
|
@ -1053,9 +1101,11 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
do: true
|
do: true
|
||||||
|
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.RemoveAttribute{attribute: %{source: source}, table: table},
|
%Operation.RemoveAttribute{attribute: %{source: source}, table: table, schema: schema},
|
||||||
%Operation.AlterAttribute{
|
%Operation.AlterAttribute{
|
||||||
old_attribute: %{references: %{table: table, destination_field: source}}
|
old_attribute: %{
|
||||||
|
references: %{table: table, schema: schema, destination_field: source}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
do: true
|
do: true
|
||||||
|
@ -1063,14 +1113,17 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
defp after?(
|
defp after?(
|
||||||
%Operation.AlterAttribute{
|
%Operation.AlterAttribute{
|
||||||
new_attribute: %{
|
new_attribute: %{
|
||||||
references: %{table: table, destination_field: name}
|
references: %{table: table, schema: schema, destination_field: name}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
%Operation.AddAttribute{table: table, attribute: %{source: name}}
|
%Operation.AddAttribute{schema: schema, table: table, attribute: %{source: name}}
|
||||||
),
|
),
|
||||||
do: true
|
do: true
|
||||||
|
|
||||||
defp after?(%Operation.AddCheckConstraint{table: table}, %Operation.CreateTable{table: table}) do
|
defp after?(%Operation.AddCheckConstraint{table: table, schema: schema}, %Operation.CreateTable{
|
||||||
|
table: table,
|
||||||
|
schema: schema
|
||||||
|
}) do
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1098,10 +1151,21 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
|
|
||||||
defp do_fetch_operations(snapshot, existing_snapshot, opts, acc \\ [])
|
defp do_fetch_operations(snapshot, existing_snapshot, opts, acc \\ [])
|
||||||
|
|
||||||
|
defp do_fetch_operations(
|
||||||
|
%{schema: new_schema} = snapshot,
|
||||||
|
%{schema: old_schema},
|
||||||
|
opts,
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
when new_schema != old_schema do
|
||||||
|
do_fetch_operations(snapshot, nil, opts, [])
|
||||||
|
end
|
||||||
|
|
||||||
defp do_fetch_operations(snapshot, nil, opts, acc) do
|
defp do_fetch_operations(snapshot, nil, opts, acc) do
|
||||||
empty_snapshot = %{
|
empty_snapshot = %{
|
||||||
attributes: [],
|
attributes: [],
|
||||||
identities: [],
|
identities: [],
|
||||||
|
schema: nil,
|
||||||
custom_indexes: [],
|
custom_indexes: [],
|
||||||
check_constraints: [],
|
check_constraints: [],
|
||||||
table: snapshot.table,
|
table: snapshot.table,
|
||||||
|
@ -1117,6 +1181,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
do_fetch_operations(snapshot, empty_snapshot, opts, [
|
do_fetch_operations(snapshot, empty_snapshot, opts, [
|
||||||
%Operation.CreateTable{
|
%Operation.CreateTable{
|
||||||
table: snapshot.table,
|
table: snapshot.table,
|
||||||
|
schema: snapshot.schema,
|
||||||
multitenancy: snapshot.multitenancy,
|
multitenancy: snapshot.multitenancy,
|
||||||
old_multitenancy: empty_snapshot.multitenancy
|
old_multitenancy: empty_snapshot.multitenancy
|
||||||
}
|
}
|
||||||
|
@ -1138,9 +1203,10 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
|> Enum.map(fn custom_index ->
|
|> Enum.map(fn custom_index ->
|
||||||
%Operation.AddCustomIndex{
|
%Operation.AddCustomIndex{
|
||||||
index: custom_index,
|
index: custom_index,
|
||||||
table: old_snapshot.table,
|
table: snapshot.table,
|
||||||
multitenancy: old_snapshot.multitenancy,
|
schema: snapshot.schema,
|
||||||
base_filter: old_snapshot.base_filter
|
multitenancy: snapshot.multitenancy,
|
||||||
|
base_filter: snapshot.base_filter
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -1154,9 +1220,10 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
|> Enum.map(fn custom_index ->
|
|> Enum.map(fn custom_index ->
|
||||||
%Operation.RemoveCustomIndex{
|
%Operation.RemoveCustomIndex{
|
||||||
index: custom_index,
|
index: custom_index,
|
||||||
table: snapshot.table,
|
table: old_snapshot.table,
|
||||||
multitenancy: snapshot.multitenancy,
|
schema: old_snapshot.schema,
|
||||||
base_filter: snapshot.base_filter
|
multitenancy: old_snapshot.multitenancy,
|
||||||
|
base_filter: old_snapshot.base_filter
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -1173,7 +1240,11 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|> Enum.map(fn identity ->
|
|> Enum.map(fn identity ->
|
||||||
%Operation.RemoveUniqueIndex{identity: identity, table: snapshot.table}
|
%Operation.RemoveUniqueIndex{
|
||||||
|
identity: identity,
|
||||||
|
table: snapshot.table,
|
||||||
|
schema: snapshot.schema
|
||||||
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
unique_indexes_to_rename =
|
unique_indexes_to_rename =
|
||||||
|
@ -1195,6 +1266,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
%Operation.RenameUniqueIndex{
|
%Operation.RenameUniqueIndex{
|
||||||
old_identity: old_identity,
|
old_identity: old_identity,
|
||||||
new_identity: new_identity,
|
new_identity: new_identity,
|
||||||
|
schema: snapshot.schema,
|
||||||
table: snapshot.table
|
table: snapshot.table
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
@ -1214,6 +1286,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
|> Enum.map(fn identity ->
|
|> Enum.map(fn identity ->
|
||||||
%Operation.AddUniqueIndex{
|
%Operation.AddUniqueIndex{
|
||||||
identity: identity,
|
identity: identity,
|
||||||
|
schema: snapshot.schema,
|
||||||
table: snapshot.table
|
table: snapshot.table
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
@ -1228,7 +1301,8 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
|> Enum.map(fn constraint ->
|
|> Enum.map(fn constraint ->
|
||||||
%Operation.AddCheckConstraint{
|
%Operation.AddCheckConstraint{
|
||||||
constraint: constraint,
|
constraint: constraint,
|
||||||
table: snapshot.table
|
table: snapshot.table,
|
||||||
|
schema: snapshot.schema
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -1242,7 +1316,8 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
|> Enum.map(fn old_constraint ->
|
|> Enum.map(fn old_constraint ->
|
||||||
%Operation.RemoveCheckConstraint{
|
%Operation.RemoveCheckConstraint{
|
||||||
constraint: old_constraint,
|
constraint: old_constraint,
|
||||||
table: old_snapshot.table
|
table: old_snapshot.table,
|
||||||
|
schema: old_snapshot.schema
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -1289,7 +1364,12 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
|
|
||||||
rename_attribute_events =
|
rename_attribute_events =
|
||||||
Enum.map(attributes_to_rename, fn {new, old} ->
|
Enum.map(attributes_to_rename, fn {new, old} ->
|
||||||
%Operation.RenameAttribute{new_attribute: new, old_attribute: old, table: snapshot.table}
|
%Operation.RenameAttribute{
|
||||||
|
new_attribute: new,
|
||||||
|
old_attribute: old,
|
||||||
|
table: snapshot.table,
|
||||||
|
schema: snapshot.schema
|
||||||
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
add_attribute_events =
|
add_attribute_events =
|
||||||
|
@ -1298,16 +1378,19 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
[
|
[
|
||||||
%Operation.AddAttribute{
|
%Operation.AddAttribute{
|
||||||
attribute: Map.delete(attribute, :references),
|
attribute: Map.delete(attribute, :references),
|
||||||
|
schema: snapshot.schema,
|
||||||
table: snapshot.table
|
table: snapshot.table
|
||||||
},
|
},
|
||||||
%Operation.AlterAttribute{
|
%Operation.AlterAttribute{
|
||||||
old_attribute: Map.delete(attribute, :references),
|
old_attribute: Map.delete(attribute, :references),
|
||||||
new_attribute: attribute,
|
new_attribute: attribute,
|
||||||
|
schema: snapshot.schema,
|
||||||
table: snapshot.table
|
table: snapshot.table
|
||||||
},
|
},
|
||||||
%Operation.DropForeignKey{
|
%Operation.DropForeignKey{
|
||||||
attribute: attribute,
|
attribute: attribute,
|
||||||
table: snapshot.table,
|
table: snapshot.table,
|
||||||
|
schema: snapshot.schema,
|
||||||
multitenancy: Map.get(attribute, :multitenancy),
|
multitenancy: Map.get(attribute, :multitenancy),
|
||||||
direction: :down
|
direction: :down
|
||||||
}
|
}
|
||||||
|
@ -1316,7 +1399,8 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
[
|
[
|
||||||
%Operation.AddAttribute{
|
%Operation.AddAttribute{
|
||||||
attribute: attribute,
|
attribute: attribute,
|
||||||
table: snapshot.table
|
table: snapshot.table,
|
||||||
|
schema: snapshot.schema
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
@ -1330,12 +1414,14 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
%Operation.DropForeignKey{
|
%Operation.DropForeignKey{
|
||||||
attribute: old_attribute,
|
attribute: old_attribute,
|
||||||
table: snapshot.table,
|
table: snapshot.table,
|
||||||
|
schema: snapshot.schema,
|
||||||
multitenancy: old_snapshot.multitenancy,
|
multitenancy: old_snapshot.multitenancy,
|
||||||
direction: :up
|
direction: :up
|
||||||
},
|
},
|
||||||
%Operation.AlterAttribute{
|
%Operation.AlterAttribute{
|
||||||
new_attribute: new_attribute,
|
new_attribute: new_attribute,
|
||||||
old_attribute: old_attribute,
|
old_attribute: old_attribute,
|
||||||
|
schema: snapshot.schema,
|
||||||
table: snapshot.table
|
table: snapshot.table
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1346,6 +1432,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
%Operation.DropForeignKey{
|
%Operation.DropForeignKey{
|
||||||
attribute: new_attribute,
|
attribute: new_attribute,
|
||||||
table: snapshot.table,
|
table: snapshot.table,
|
||||||
|
schema: snapshot.schema,
|
||||||
multitenancy: snapshot.multitenancy,
|
multitenancy: snapshot.multitenancy,
|
||||||
direction: :down
|
direction: :down
|
||||||
}
|
}
|
||||||
|
@ -1358,6 +1445,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
%Operation.AlterAttribute{
|
%Operation.AlterAttribute{
|
||||||
new_attribute: Map.delete(new_attribute, :references),
|
new_attribute: Map.delete(new_attribute, :references),
|
||||||
old_attribute: Map.delete(old_attribute, :references),
|
old_attribute: Map.delete(old_attribute, :references),
|
||||||
|
schema: snapshot.schema,
|
||||||
table: snapshot.table
|
table: snapshot.table
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1369,6 +1457,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
%Operation.RemoveAttribute{
|
%Operation.RemoveAttribute{
|
||||||
attribute: attribute,
|
attribute: attribute,
|
||||||
table: snapshot.table,
|
table: snapshot.table,
|
||||||
|
schema: snapshot.schema,
|
||||||
commented?: !opts.drop_columns
|
commented?: !opts.drop_columns
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
@ -1572,7 +1661,10 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
|> Enum.map(fn relationship ->
|
|> Enum.map(fn relationship ->
|
||||||
resource
|
resource
|
||||||
|> do_snapshot(relationship.context[:data_layer][:table])
|
|> do_snapshot(
|
||||||
|
relationship.context[:data_layer][:table],
|
||||||
|
relationship.context[:data_layer][:schema]
|
||||||
|
)
|
||||||
|> Map.update!(:identities, fn identities ->
|
|> Map.update!(:identities, fn identities ->
|
||||||
identity_index_names = AshPostgres.identity_index_names(resource)
|
identity_index_names = AshPostgres.identity_index_names(resource)
|
||||||
|
|
||||||
|
@ -1603,6 +1695,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
destination_field_generated: source_attribute.generated?,
|
destination_field_generated: source_attribute.generated?,
|
||||||
multitenancy: multitenancy(relationship.source),
|
multitenancy: multitenancy(relationship.source),
|
||||||
table: AshPostgres.table(relationship.source),
|
table: AshPostgres.table(relationship.source),
|
||||||
|
schema: AshPostgres.table(relationship.source),
|
||||||
on_delete: AshPostgres.polymorphic_on_delete(relationship.source),
|
on_delete: AshPostgres.polymorphic_on_delete(relationship.source),
|
||||||
on_update: AshPostgres.polymorphic_on_update(relationship.source),
|
on_update: AshPostgres.polymorphic_on_update(relationship.source),
|
||||||
name:
|
name:
|
||||||
|
@ -1620,11 +1713,12 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_snapshot(resource, table) do
|
defp do_snapshot(resource, table, schema \\ nil) do
|
||||||
snapshot = %{
|
snapshot = %{
|
||||||
attributes: attributes(resource, table),
|
attributes: attributes(resource, table),
|
||||||
identities: identities(resource),
|
identities: identities(resource),
|
||||||
table: table || AshPostgres.table(resource),
|
table: table || AshPostgres.table(resource),
|
||||||
|
schema: schema || AshPostgres.schema(resource),
|
||||||
check_constraints: check_constraints(resource),
|
check_constraints: check_constraints(resource),
|
||||||
custom_indexes: custom_indexes(resource),
|
custom_indexes: custom_indexes(resource),
|
||||||
repo: AshPostgres.repo(resource),
|
repo: AshPostgres.repo(resource),
|
||||||
|
@ -1776,6 +1870,10 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
on_delete: configured_reference.on_delete,
|
on_delete: configured_reference.on_delete,
|
||||||
on_update: configured_reference.on_update,
|
on_update: configured_reference.on_update,
|
||||||
name: configured_reference.name,
|
name: configured_reference.name,
|
||||||
|
schema:
|
||||||
|
relationship.context[:data_layer][:schema] ||
|
||||||
|
AshPostgres.schema(relationship.destination) ||
|
||||||
|
AshPostgres.repo(relationship.destination).config()[:default_prefix],
|
||||||
table:
|
table:
|
||||||
relationship.context[:data_layer][:table] ||
|
relationship.context[:data_layer][:table] ||
|
||||||
AshPostgres.table(relationship.destination)
|
AshPostgres.table(relationship.destination)
|
||||||
|
@ -1792,6 +1890,10 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
|> Kernel.||(%{
|
|> Kernel.||(%{
|
||||||
on_delete: nil,
|
on_delete: nil,
|
||||||
on_update: nil,
|
on_update: nil,
|
||||||
|
schema:
|
||||||
|
relationship.context[:data_layer][:schema] ||
|
||||||
|
AshPostgres.schema(relationship.destination) ||
|
||||||
|
AshPostgres.repo(relationship.destination).config()[:default_prefix],
|
||||||
name: nil
|
name: nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1929,6 +2031,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
defp sanitize_snapshot(snapshot) do
|
defp sanitize_snapshot(snapshot) do
|
||||||
snapshot
|
snapshot
|
||||||
|> Map.put_new(:has_create_action, true)
|
|> Map.put_new(:has_create_action, true)
|
||||||
|
|> Map.put_new(:schema, nil)
|
||||||
|> Map.update!(:identities, fn identities ->
|
|> Map.update!(:identities, fn identities ->
|
||||||
Enum.map(identities, &load_identity(&1, snapshot.table))
|
Enum.map(identities, &load_identity(&1, snapshot.table))
|
||||||
end)
|
end)
|
||||||
|
@ -2007,6 +2110,7 @@ defmodule AshPostgres.MigrationGenerator do
|
||||||
references ->
|
references ->
|
||||||
references
|
references
|
||||||
|> Map.update!(:destination_field, &String.to_atom/1)
|
|> Map.update!(:destination_field, &String.to_atom/1)
|
||||||
|
|> Map.put_new(:schema, nil)
|
||||||
|> Map.put_new(:destination_field_default, "nil")
|
|> Map.put_new(:destination_field_default, "nil")
|
||||||
|> Map.put_new(:destination_field_generated, false)
|
|> Map.put_new(:destination_field_generated, false)
|
||||||
|> Map.put_new(:on_delete, nil)
|
|> Map.put_new(:on_delete, nil)
|
||||||
|
|
|
@ -20,6 +20,12 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
def maybe_add_null(false), do: "null: false"
|
def maybe_add_null(false), do: "null: false"
|
||||||
def maybe_add_null(_), do: nil
|
def maybe_add_null(_), do: nil
|
||||||
|
|
||||||
|
def maybe_add_prefix(nil), do: nil
|
||||||
|
def maybe_add_prefix(prefix), do: "prefix: #{prefix}"
|
||||||
|
|
||||||
|
def in_quotes(nil), do: nil
|
||||||
|
def in_quotes(value), do: "\"#{value}\""
|
||||||
|
|
||||||
def option(key, value) do
|
def option(key, value) do
|
||||||
if value do
|
if value do
|
||||||
"#{key}: #{inspect(value)}"
|
"#{key}: #{inspect(value)}"
|
||||||
|
@ -60,12 +66,12 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
|
|
||||||
defmodule CreateTable do
|
defmodule CreateTable do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:table, :multitenancy, :old_multitenancy]
|
defstruct [:table, :schema, :multitenancy, :old_multitenancy]
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule AddAttribute do
|
defmodule AddAttribute do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:attribute, :table, :multitenancy, :old_multitenancy]
|
defstruct [:attribute, :table, :schema, :multitenancy, :old_multitenancy]
|
||||||
|
|
||||||
import Helper
|
import Helper
|
||||||
|
|
||||||
|
@ -77,6 +83,7 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
%{
|
%{
|
||||||
table: table,
|
table: table,
|
||||||
destination_field: destination_field,
|
destination_field: destination_field,
|
||||||
|
schema: destination_schema,
|
||||||
multitenancy: %{strategy: :attribute, attribute: destination_attribute}
|
multitenancy: %{strategy: :attribute, attribute: destination_attribute}
|
||||||
} = reference
|
} = reference
|
||||||
} = attribute
|
} = attribute
|
||||||
|
@ -99,6 +106,7 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
with_match,
|
with_match,
|
||||||
"name: #{inspect(reference.name)}",
|
"name: #{inspect(reference.name)}",
|
||||||
"type: #{inspect(reference_type(attribute, reference))}",
|
"type: #{inspect(reference_type(attribute, reference))}",
|
||||||
|
option("prefix", destination_schema),
|
||||||
on_delete(reference),
|
on_delete(reference),
|
||||||
on_update(reference),
|
on_update(reference),
|
||||||
size
|
size
|
||||||
|
@ -119,6 +127,7 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
%{
|
%{
|
||||||
table: table,
|
table: table,
|
||||||
destination_field: destination_field,
|
destination_field: destination_field,
|
||||||
|
schema: destination_schema,
|
||||||
multitenancy: %{strategy: :attribute}
|
multitenancy: %{strategy: :attribute}
|
||||||
} = reference
|
} = reference
|
||||||
} = attribute
|
} = attribute
|
||||||
|
@ -133,7 +142,7 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
"references(:#{table}",
|
"references(:#{table}",
|
||||||
[
|
[
|
||||||
"column: #{inspect(destination_field)}",
|
"column: #{inspect(destination_field)}",
|
||||||
"prefix: \"public\"",
|
option("prefix", destination_schema),
|
||||||
"name: #{inspect(reference.name)}",
|
"name: #{inspect(reference.name)}",
|
||||||
"type: #{inspect(reference_type(attribute, reference))}",
|
"type: #{inspect(reference_type(attribute, reference))}",
|
||||||
size,
|
size,
|
||||||
|
@ -212,11 +221,13 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
|
|
||||||
def up(%{
|
def up(%{
|
||||||
multitenancy: %{strategy: :context},
|
multitenancy: %{strategy: :context},
|
||||||
|
schema: schema,
|
||||||
attribute:
|
attribute:
|
||||||
%{
|
%{
|
||||||
references:
|
references:
|
||||||
%{
|
%{
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: destination_schema,
|
||||||
destination_field: destination_field
|
destination_field: destination_field
|
||||||
} = reference
|
} = reference
|
||||||
} = attribute
|
} = attribute
|
||||||
|
@ -226,6 +237,11 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
"size: #{attribute[:size]}"
|
"size: #{attribute[:size]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
destination_schema =
|
||||||
|
if schema != destination_schema do
|
||||||
|
destination_schema
|
||||||
|
end
|
||||||
|
|
||||||
[
|
[
|
||||||
"add #{inspect(attribute.source)}",
|
"add #{inspect(attribute.source)}",
|
||||||
"references(:#{table}",
|
"references(:#{table}",
|
||||||
|
@ -233,7 +249,7 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
"column: #{inspect(destination_field)}",
|
"column: #{inspect(destination_field)}",
|
||||||
"name: #{inspect(reference.name)}",
|
"name: #{inspect(reference.name)}",
|
||||||
"type: #{inspect(reference_type(attribute, reference))}",
|
"type: #{inspect(reference_type(attribute, reference))}",
|
||||||
"prefix: \"public\"",
|
option("prefix", destination_schema),
|
||||||
size,
|
size,
|
||||||
on_delete(reference),
|
on_delete(reference),
|
||||||
on_update(reference)
|
on_update(reference)
|
||||||
|
@ -248,8 +264,11 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
|
|
||||||
def up(%{
|
def up(%{
|
||||||
attribute:
|
attribute:
|
||||||
%{references: %{table: table, destination_field: destination_field} = reference} =
|
%{
|
||||||
attribute
|
references:
|
||||||
|
%{table: table, schema: destination_schema, destination_field: destination_field} =
|
||||||
|
reference
|
||||||
|
} = attribute
|
||||||
}) do
|
}) do
|
||||||
size =
|
size =
|
||||||
if attribute[:size] do
|
if attribute[:size] do
|
||||||
|
@ -263,6 +282,7 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
"column: #{inspect(destination_field)}",
|
"column: #{inspect(destination_field)}",
|
||||||
"name: #{inspect(reference.name)}",
|
"name: #{inspect(reference.name)}",
|
||||||
"type: #{inspect(reference_type(attribute, reference))}",
|
"type: #{inspect(reference_type(attribute, reference))}",
|
||||||
|
option("prefix", destination_schema),
|
||||||
size,
|
size,
|
||||||
on_delete(reference),
|
on_delete(reference),
|
||||||
on_update(reference)
|
on_update(reference)
|
||||||
|
@ -330,7 +350,14 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
|
|
||||||
defmodule AlterAttribute do
|
defmodule AlterAttribute do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:old_attribute, :new_attribute, :table, :multitenancy, :old_multitenancy]
|
defstruct [
|
||||||
|
:old_attribute,
|
||||||
|
:new_attribute,
|
||||||
|
:table,
|
||||||
|
:schema,
|
||||||
|
:multitenancy,
|
||||||
|
:old_multitenancy
|
||||||
|
]
|
||||||
|
|
||||||
import Helper
|
import Helper
|
||||||
|
|
||||||
|
@ -360,12 +387,13 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
def up(%{
|
def up(%{
|
||||||
multitenancy: multitenancy,
|
multitenancy: multitenancy,
|
||||||
old_attribute: old_attribute,
|
old_attribute: old_attribute,
|
||||||
new_attribute: attribute
|
new_attribute: attribute,
|
||||||
|
schema: schema
|
||||||
}) do
|
}) do
|
||||||
type_or_reference =
|
type_or_reference =
|
||||||
if AshPostgres.MigrationGenerator.has_reference?(multitenancy, attribute) and
|
if AshPostgres.MigrationGenerator.has_reference?(multitenancy, attribute) and
|
||||||
Map.get(old_attribute, :references) != Map.get(attribute, :references) do
|
Map.get(old_attribute, :references) != Map.get(attribute, :references) do
|
||||||
reference(multitenancy, attribute)
|
reference(multitenancy, attribute, schema)
|
||||||
else
|
else
|
||||||
inspect(attribute.type)
|
inspect(attribute.type)
|
||||||
end
|
end
|
||||||
|
@ -382,7 +410,8 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
table: table,
|
table: table,
|
||||||
destination_field: destination_field
|
destination_field: destination_field
|
||||||
} = reference
|
} = reference
|
||||||
} = attribute
|
} = attribute,
|
||||||
|
_schema
|
||||||
) do
|
) do
|
||||||
size =
|
size =
|
||||||
if attribute[:size] do
|
if attribute[:size] do
|
||||||
|
@ -408,10 +437,17 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
%{
|
%{
|
||||||
multitenancy: %{strategy: :attribute, attribute: destination_attribute},
|
multitenancy: %{strategy: :attribute, attribute: destination_attribute},
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: destination_schema,
|
||||||
destination_field: destination_field
|
destination_field: destination_field
|
||||||
} = reference
|
} = reference
|
||||||
} = attribute
|
} = attribute,
|
||||||
|
schema
|
||||||
) do
|
) do
|
||||||
|
destination_schema =
|
||||||
|
if schema != destination_schema do
|
||||||
|
destination_schema
|
||||||
|
end
|
||||||
|
|
||||||
with_match =
|
with_match =
|
||||||
if destination_attribute != destination_field do
|
if destination_attribute != destination_field do
|
||||||
"with: [#{source_attribute}: :#{destination_attribute}], match: :full"
|
"with: [#{source_attribute}: :#{destination_attribute}], match: :full"
|
||||||
|
@ -428,6 +464,7 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
"name: #{inspect(reference.name)}",
|
"name: #{inspect(reference.name)}",
|
||||||
"type: #{inspect(reference_type(attribute, reference))}",
|
"type: #{inspect(reference_type(attribute, reference))}",
|
||||||
size,
|
size,
|
||||||
|
option("prefix", destination_schema),
|
||||||
on_delete(reference),
|
on_delete(reference),
|
||||||
on_update(reference),
|
on_update(reference),
|
||||||
")"
|
")"
|
||||||
|
@ -440,17 +477,25 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
references:
|
references:
|
||||||
%{
|
%{
|
||||||
table: table,
|
table: table,
|
||||||
destination_field: destination_field
|
destination_field: destination_field,
|
||||||
|
schema: destination_schema
|
||||||
} = reference
|
} = reference
|
||||||
} = attribute
|
} = attribute,
|
||||||
|
schema
|
||||||
) do
|
) do
|
||||||
size =
|
size =
|
||||||
if attribute[:size] do
|
if attribute[:size] do
|
||||||
"size: #{attribute[:size]}"
|
"size: #{attribute[:size]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
destination_schema =
|
||||||
|
if schema != destination_schema do
|
||||||
|
destination_schema
|
||||||
|
end
|
||||||
|
|
||||||
join([
|
join([
|
||||||
"references(:#{table}, column: #{inspect(destination_field)}, prefix: \"public\"",
|
"references(:#{table}, column: #{inspect(destination_field)}",
|
||||||
|
option("prefix", destination_schema),
|
||||||
"name: #{inspect(reference.name)}",
|
"name: #{inspect(reference.name)}",
|
||||||
"type: #{inspect(reference_type(attribute, reference))}",
|
"type: #{inspect(reference_type(attribute, reference))}",
|
||||||
size,
|
size,
|
||||||
|
@ -466,10 +511,17 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
references:
|
references:
|
||||||
%{
|
%{
|
||||||
table: table,
|
table: table,
|
||||||
destination_field: destination_field
|
destination_field: destination_field,
|
||||||
|
schema: destination_schema
|
||||||
} = reference
|
} = reference
|
||||||
} = attribute
|
} = attribute,
|
||||||
|
schema
|
||||||
) do
|
) do
|
||||||
|
destination_schema =
|
||||||
|
if schema != destination_schema do
|
||||||
|
destination_schema
|
||||||
|
end
|
||||||
|
|
||||||
size =
|
size =
|
||||||
if attribute[:size] do
|
if attribute[:size] do
|
||||||
"size: #{attribute[:size]}"
|
"size: #{attribute[:size]}"
|
||||||
|
@ -477,6 +529,7 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
|
|
||||||
join([
|
join([
|
||||||
"references(:#{table}, column: #{inspect(destination_field)}",
|
"references(:#{table}, column: #{inspect(destination_field)}",
|
||||||
|
option("prefix", destination_schema),
|
||||||
"name: #{inspect(reference.name)}",
|
"name: #{inspect(reference.name)}",
|
||||||
"type: #{inspect(reference_type(attribute, reference))}",
|
"type: #{inspect(reference_type(attribute, reference))}",
|
||||||
size,
|
size,
|
||||||
|
@ -502,18 +555,25 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
# We only run this migration in one direction, based on the input
|
# We only run this migration in one direction, based on the input
|
||||||
# This is because the creation of a foreign key is handled by `references/3`
|
# This is because the creation of a foreign key is handled by `references/3`
|
||||||
# We only need to drop it before altering an attribute with `references/3`
|
# We only need to drop it before altering an attribute with `references/3`
|
||||||
defstruct [:attribute, :table, :multitenancy, :direction, no_phase: true]
|
defstruct [:attribute, :schema, :table, :multitenancy, :direction, no_phase: true]
|
||||||
|
|
||||||
def up(%{table: table, attribute: %{references: reference}, direction: :up}) do
|
import Helper
|
||||||
"drop constraint(:#{table}, #{inspect(reference.name)})"
|
|
||||||
|
def up(%{table: table, schema: schema, attribute: %{references: reference}, direction: :up}) do
|
||||||
|
"drop constraint(:#{table}, #{join([inspect(reference.name), option("prefix", schema)])})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def up(_) do
|
def up(_) do
|
||||||
""
|
""
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{table: table, attribute: %{references: reference}, direction: :down}) do
|
def down(%{
|
||||||
"drop constraint(:#{table}, #{inspect(reference.name)})"
|
table: table,
|
||||||
|
schema: schema,
|
||||||
|
attribute: %{references: reference},
|
||||||
|
direction: :down
|
||||||
|
}) do
|
||||||
|
"drop constraint(:#{table}, #{join([inspect(reference.name), option("prefix", schema)])})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(_) do
|
def down(_) do
|
||||||
|
@ -527,23 +587,36 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
:old_attribute,
|
:old_attribute,
|
||||||
:new_attribute,
|
:new_attribute,
|
||||||
:table,
|
:table,
|
||||||
|
:schema,
|
||||||
:multitenancy,
|
:multitenancy,
|
||||||
:old_multitenancy,
|
:old_multitenancy,
|
||||||
no_phase: true
|
no_phase: true
|
||||||
]
|
]
|
||||||
|
|
||||||
def up(%{old_attribute: old_attribute, new_attribute: new_attribute, table: table}) do
|
import Helper
|
||||||
"rename table(:#{table}), #{inspect(old_attribute.source)}, to: #{inspect(new_attribute.source)}"
|
|
||||||
|
def up(%{
|
||||||
|
old_attribute: old_attribute,
|
||||||
|
new_attribute: new_attribute,
|
||||||
|
schema: schema,
|
||||||
|
table: table
|
||||||
|
}) do
|
||||||
|
"rename table(:#{table}), #{inspect(old_attribute.source)}, to: #{join([inspect(new_attribute.source), option("prefix", schema)])}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{new_attribute: old_attribute, old_attribute: new_attribute, table: table}) do
|
def down(
|
||||||
"rename table(:#{table}), #{inspect(old_attribute.source)}, to: #{inspect(new_attribute.source)}"
|
%{
|
||||||
|
new_attribute: old_attribute,
|
||||||
|
old_attribute: new_attribute
|
||||||
|
} = data
|
||||||
|
) do
|
||||||
|
up(%{data | new_attribute: old_attribute, old_attribute: new_attribute})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule RemoveAttribute do
|
defmodule RemoveAttribute do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:attribute, :table, :multitenancy, :old_multitenancy, commented?: true]
|
defstruct [:attribute, :schema, :table, :multitenancy, :old_multitenancy, commented?: true]
|
||||||
|
|
||||||
def up(%{attribute: attribute, commented?: true}) do
|
def up(%{attribute: attribute, commented?: true}) do
|
||||||
"""
|
"""
|
||||||
|
@ -577,10 +650,12 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
prefix <> "\n" <> contents
|
prefix <> "\n" <> contents
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{attribute: attribute, multitenancy: multitenancy}) do
|
def down(%{attribute: attribute, multitenancy: multitenancy, table: table, schema: schema}) do
|
||||||
AshPostgres.MigrationGenerator.Operation.AddAttribute.up(
|
AshPostgres.MigrationGenerator.Operation.AddAttribute.up(
|
||||||
%AshPostgres.MigrationGenerator.Operation.AddAttribute{
|
%AshPostgres.MigrationGenerator.Operation.AddAttribute{
|
||||||
attribute: attribute,
|
attribute: attribute,
|
||||||
|
table: table,
|
||||||
|
schema: schema,
|
||||||
multitenancy: multitenancy
|
multitenancy: multitenancy
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -589,11 +664,14 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
|
|
||||||
defmodule AddUniqueIndex do
|
defmodule AddUniqueIndex do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:identity, :table, :multitenancy, :old_multitenancy, no_phase: true]
|
defstruct [:identity, :table, :schema, :multitenancy, :old_multitenancy, no_phase: true]
|
||||||
|
|
||||||
|
import Helper
|
||||||
|
|
||||||
def up(%{
|
def up(%{
|
||||||
identity: %{name: name, keys: keys, base_filter: base_filter, index_name: index_name},
|
identity: %{name: name, keys: keys, base_filter: base_filter, index_name: index_name},
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
multitenancy: multitenancy
|
multitenancy: multitenancy
|
||||||
}) do
|
}) do
|
||||||
keys =
|
keys =
|
||||||
|
@ -608,15 +686,16 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
index_name = index_name || "#{table}_#{name}_index"
|
index_name = index_name || "#{table}_#{name}_index"
|
||||||
|
|
||||||
if base_filter do
|
if base_filter do
|
||||||
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{index_name}\", where: \"#{base_filter}\")"
|
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], where: \"#{base_filter}\", #{join(["name: \"#{index_name}\"", option("prefix", schema)])})"
|
||||||
else
|
else
|
||||||
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{index_name}\")"
|
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], #{join(["name: \"#{index_name}\"", option("prefix", schema)])})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{
|
def down(%{
|
||||||
identity: %{name: name, keys: keys, index_name: index_name},
|
identity: %{name: name, keys: keys, index_name: index_name},
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
multitenancy: multitenancy
|
multitenancy: multitenancy
|
||||||
}) do
|
}) do
|
||||||
keys =
|
keys =
|
||||||
|
@ -630,18 +709,19 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
|
|
||||||
index_name = index_name || "#{table}_#{name}_index"
|
index_name = index_name || "#{table}_#{name}_index"
|
||||||
|
|
||||||
"drop_if_exists unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{index_name}\")"
|
"drop_if_exists unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], #{join(["name: \"#{index_name}\"", option("prefix", schema)])})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule AddCustomIndex do
|
defmodule AddCustomIndex do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:table, :index, :base_filter, :multitenancy, no_phase: true]
|
defstruct [:table, :schema, :index, :base_filter, :multitenancy, no_phase: true]
|
||||||
import Helper
|
import Helper
|
||||||
|
|
||||||
def up(%{
|
def up(%{
|
||||||
index: index,
|
index: index,
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
base_filter: base_filter,
|
base_filter: base_filter,
|
||||||
multitenancy: multitenancy
|
multitenancy: multitenancy
|
||||||
}) do
|
}) do
|
||||||
|
@ -669,7 +749,8 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
option(:using, index.using),
|
option(:using, index.using),
|
||||||
option(:prefix, index.prefix),
|
option(:prefix, index.prefix),
|
||||||
option(:where, index.where),
|
option(:where, index.where),
|
||||||
option(:include, index.include)
|
option(:include, index.include),
|
||||||
|
option(:prefix, schema)
|
||||||
])
|
])
|
||||||
|
|
||||||
if opts == "",
|
if opts == "",
|
||||||
|
@ -677,7 +758,7 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
else: "create index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], #{opts})"
|
else: "create index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], #{opts})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{index: index, table: table, multitenancy: multitenancy}) do
|
def down(%{schema: schema, index: index, table: table, multitenancy: multitenancy}) do
|
||||||
index_name = AshPostgres.CustomIndex.name(table, index)
|
index_name = AshPostgres.CustomIndex.name(table, index)
|
||||||
|
|
||||||
keys =
|
keys =
|
||||||
|
@ -689,16 +770,16 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
index.fields
|
index.fields
|
||||||
end
|
end
|
||||||
|
|
||||||
"drop_if_exists index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{index_name}\")"
|
"drop_if_exists index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], #{join(["name: \"#{index_name}\"", option(:prefix, schema)])})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule RemoveCustomIndex do
|
defmodule RemoveCustomIndex do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:table, :index, :base_filter, :multitenancy, no_phase: true]
|
defstruct [:schema, :table, :index, :base_filter, :multitenancy, no_phase: true]
|
||||||
import Helper
|
import Helper
|
||||||
|
|
||||||
def up(%{index: index, table: table, multitenancy: multitenancy}) do
|
def up(%{index: index, table: table, multitenancy: multitenancy, schema: schema}) do
|
||||||
index_name = AshPostgres.CustomIndex.name(table, index)
|
index_name = AshPostgres.CustomIndex.name(table, index)
|
||||||
|
|
||||||
keys =
|
keys =
|
||||||
|
@ -710,12 +791,13 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
index.fields
|
index.fields
|
||||||
end
|
end
|
||||||
|
|
||||||
"drop_if_exists index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{index_name}\")"
|
"drop_if_exists index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], #{join(["name: \"#{index_name}\"", option(:prefix, schema)])})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{
|
def down(%{
|
||||||
index: index,
|
index: index,
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
base_filter: base_filter,
|
base_filter: base_filter,
|
||||||
multitenancy: multitenancy
|
multitenancy: multitenancy
|
||||||
}) do
|
}) do
|
||||||
|
@ -743,7 +825,8 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
option(:using, index.using),
|
option(:using, index.using),
|
||||||
option(:prefix, index.prefix),
|
option(:prefix, index.prefix),
|
||||||
option(:where, index.where),
|
option(:where, index.where),
|
||||||
option(:include, index.include)
|
option(:include, index.include),
|
||||||
|
option(:prefix, schema)
|
||||||
])
|
])
|
||||||
|
|
||||||
"create index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], #{opts})"
|
"create index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], #{opts})"
|
||||||
|
@ -756,41 +839,55 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
:new_identity,
|
:new_identity,
|
||||||
:old_identity,
|
:old_identity,
|
||||||
:table,
|
:table,
|
||||||
|
:schema,
|
||||||
:multitenancy,
|
:multitenancy,
|
||||||
:old_multitenancy,
|
:old_multitenancy,
|
||||||
no_phase: true
|
no_phase: true
|
||||||
]
|
]
|
||||||
|
|
||||||
|
defp prefix_name(name, prefix) do
|
||||||
|
if prefix do
|
||||||
|
"#{prefix}.#{name}"
|
||||||
|
else
|
||||||
|
name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def up(%{
|
def up(%{
|
||||||
old_identity: %{index_name: old_index_name, name: old_name},
|
old_identity: %{index_name: old_index_name, name: old_name},
|
||||||
new_identity: %{index_name: new_index_name},
|
new_identity: %{index_name: new_index_name},
|
||||||
|
schema: schema,
|
||||||
table: table
|
table: table
|
||||||
}) do
|
}) do
|
||||||
old_index_name = old_index_name || "#{table}_#{old_name}_index"
|
old_index_name = old_index_name || "#{table}_#{old_name}_index"
|
||||||
|
|
||||||
"execute(\"ALTER INDEX #{old_index_name} " <>
|
"execute(\"ALTER INDEX #{prefix_name(old_index_name, schema)} " <>
|
||||||
"RENAME TO #{new_index_name}\")\n"
|
"RENAME TO #{prefix_name(new_index_name, schema)}\")\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{
|
def down(%{
|
||||||
old_identity: %{index_name: old_index_name, name: old_name},
|
old_identity: %{index_name: old_index_name, name: old_name},
|
||||||
new_identity: %{index_name: new_index_name},
|
new_identity: %{index_name: new_index_name},
|
||||||
|
schema: schema,
|
||||||
table: table
|
table: table
|
||||||
}) do
|
}) do
|
||||||
old_index_name = old_index_name || "#{table}_#{old_name}_index"
|
old_index_name = old_index_name || "#{table}_#{old_name}_index"
|
||||||
|
|
||||||
"execute(\"ALTER INDEX #{new_index_name} " <>
|
"execute(\"ALTER INDEX #{prefix_name(new_index_name, schema)} " <>
|
||||||
"RENAME TO #{old_index_name}\")\n"
|
"RENAME TO #{prefix_name(old_index_name, schema)}\")\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule RemoveUniqueIndex do
|
defmodule RemoveUniqueIndex do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:identity, :table, :multitenancy, :old_multitenancy, no_phase: true]
|
defstruct [:identity, :schema, :table, :multitenancy, :old_multitenancy, no_phase: true]
|
||||||
|
|
||||||
|
import Helper
|
||||||
|
|
||||||
def up(%{
|
def up(%{
|
||||||
identity: %{name: name, keys: keys, index_name: index_name},
|
identity: %{name: name, keys: keys, index_name: index_name},
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
old_multitenancy: multitenancy
|
old_multitenancy: multitenancy
|
||||||
}) do
|
}) do
|
||||||
keys =
|
keys =
|
||||||
|
@ -804,12 +901,13 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
|
|
||||||
index_name = index_name || "#{table}_#{name}_index"
|
index_name = index_name || "#{table}_#{name}_index"
|
||||||
|
|
||||||
"drop_if_exists unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{index_name}\")"
|
"drop_if_exists unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], #{join(["name: \"#{index_name}\"", option(:prefix, schema)])})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{
|
def down(%{
|
||||||
identity: %{name: name, keys: keys, base_filter: base_filter, index_name: index_name},
|
identity: %{name: name, keys: keys, base_filter: base_filter, index_name: index_name},
|
||||||
table: table,
|
table: table,
|
||||||
|
schema: schema,
|
||||||
multitenancy: multitenancy
|
multitenancy: multitenancy
|
||||||
}) do
|
}) do
|
||||||
keys =
|
keys =
|
||||||
|
@ -824,18 +922,21 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
index_name = index_name || "#{table}_#{name}_index"
|
index_name = index_name || "#{table}_#{name}_index"
|
||||||
|
|
||||||
if base_filter do
|
if base_filter do
|
||||||
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{index_name}\", where: \"#{base_filter}\")"
|
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], where: \"#{base_filter}\", #{join(["name: \"#{index_name}\"", option(:prefix, schema)])})"
|
||||||
else
|
else
|
||||||
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{index_name}\")"
|
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], #{join(["name: \"#{index_name}\"", option(:prefix, schema)])})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule AddCheckConstraint do
|
defmodule AddCheckConstraint do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:table, :constraint, :multitenancy, :old_multitenancy, no_phase: true]
|
defstruct [:table, :schema, :constraint, :multitenancy, :old_multitenancy, no_phase: true]
|
||||||
|
|
||||||
|
import Helper
|
||||||
|
|
||||||
def up(%{
|
def up(%{
|
||||||
|
schema: schema,
|
||||||
constraint: %{
|
constraint: %{
|
||||||
name: name,
|
name: name,
|
||||||
check: check,
|
check: check,
|
||||||
|
@ -844,26 +945,29 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
table: table
|
table: table
|
||||||
}) do
|
}) do
|
||||||
if base_filter do
|
if base_filter do
|
||||||
"create constraint(:#{table}, :#{name}, check: \"#{base_filter} AND #{check}\")"
|
"create constraint(:#{table}, :#{name}, #{join(["check: \"#{base_filter} AND #{check}\")", option(:prefix, schema)])}"
|
||||||
else
|
else
|
||||||
"create constraint(:#{table}, :#{name}, check: \"#{check}\")"
|
"create constraint(:#{table}, :#{name}, #{join(["check: \"#{check}\")", option(:prefix, schema)])}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{
|
def down(%{
|
||||||
constraint: %{name: name},
|
constraint: %{name: name},
|
||||||
|
schema: schema,
|
||||||
table: table
|
table: table
|
||||||
}) do
|
}) do
|
||||||
"drop_if_exists constraint(:#{table}, :#{name})"
|
"drop_if_exists constraint(:#{table}, #{join([":#{name}", option(:prefix, schema)])})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule RemoveCheckConstraint do
|
defmodule RemoveCheckConstraint do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:table, :constraint, :multitenancy, :old_multitenancy, no_phase: true]
|
defstruct [:table, :schema, :constraint, :multitenancy, :old_multitenancy, no_phase: true]
|
||||||
|
|
||||||
def up(%{constraint: %{name: name}, table: table}) do
|
import Helper
|
||||||
"drop_if_exists constraint(:#{table}, :#{name})"
|
|
||||||
|
def up(%{constraint: %{name: name}, schema: schema, table: table}) do
|
||||||
|
"drop_if_exists constraint(:#{table}, #{join([":#{name}", option(:prefix, schema)])})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{
|
def down(%{
|
||||||
|
@ -872,12 +976,13 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
||||||
check: check,
|
check: check,
|
||||||
base_filter: base_filter
|
base_filter: base_filter
|
||||||
},
|
},
|
||||||
|
schema: schema,
|
||||||
table: table
|
table: table
|
||||||
}) do
|
}) do
|
||||||
if base_filter do
|
if base_filter do
|
||||||
"create constraint(:#{table}, :#{name}, check: \"#{base_filter} AND #{check}\")"
|
"create constraint(:#{table}, :#{name}, #{join(["check: \"#{base_filter} AND #{check}\")", option(:prefix, schema)])}"
|
||||||
else
|
else
|
||||||
"create constraint(:#{table}, :#{name}, check: \"#{check}\")"
|
"create constraint(:#{table}, :#{name}, #{join(["check: \"#{check}\")", option(:prefix, schema)])}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,34 +3,48 @@ defmodule AshPostgres.MigrationGenerator.Phase do
|
||||||
|
|
||||||
defmodule Create do
|
defmodule Create do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:table, :multitenancy, operations: [], commented?: false]
|
defstruct [:table, :schema, :multitenancy, operations: [], commented?: false]
|
||||||
|
|
||||||
def up(%{table: table, operations: operations, multitenancy: multitenancy}) do
|
def up(%{schema: schema, table: table, operations: operations, multitenancy: multitenancy}) do
|
||||||
if multitenancy.strategy == :context do
|
if multitenancy.strategy == :context do
|
||||||
"create table(:#{table}, primary_key: false, prefix: prefix()) do\n" <>
|
"create table(:#{table}, primary_key: false, prefix: prefix()) do\n" <>
|
||||||
Enum.map_join(operations, "\n", fn operation -> operation.__struct__.up(operation) end) <>
|
Enum.map_join(operations, "\n", fn operation -> operation.__struct__.up(operation) end) <>
|
||||||
"\nend"
|
"\nend"
|
||||||
else
|
else
|
||||||
"create table(:#{table}, primary_key: false) do\n" <>
|
opts =
|
||||||
|
if schema do
|
||||||
|
", prefix: \"#{schema}\""
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end
|
||||||
|
|
||||||
|
"create table(:#{table}, primary_key: false#{opts}) do\n" <>
|
||||||
Enum.map_join(operations, "\n", fn operation -> operation.__struct__.up(operation) end) <>
|
Enum.map_join(operations, "\n", fn operation -> operation.__struct__.up(operation) end) <>
|
||||||
"\nend"
|
"\nend"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{table: table, multitenancy: multitenancy}) do
|
def down(%{schema: schema, table: table, multitenancy: multitenancy}) do
|
||||||
if multitenancy.strategy == :context do
|
if multitenancy.strategy == :context do
|
||||||
"drop table(:#{inspect(table)}, prefix: prefix())"
|
"drop table(:#{inspect(table)}, prefix: prefix())"
|
||||||
else
|
else
|
||||||
"drop table(:#{inspect(table)})"
|
opts =
|
||||||
|
if schema do
|
||||||
|
", prefix: \"#{schema}\""
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end
|
||||||
|
|
||||||
|
"drop table(:#{inspect(table)}#{opts})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule Alter do
|
defmodule Alter do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
defstruct [:table, :multitenancy, operations: [], commented?: false]
|
defstruct [:schema, :table, :multitenancy, operations: [], commented?: false]
|
||||||
|
|
||||||
def up(%{table: table, operations: operations, multitenancy: multitenancy}) do
|
def up(%{table: table, schema: schema, operations: operations, multitenancy: multitenancy}) do
|
||||||
body =
|
body =
|
||||||
Enum.map_join(operations, "\n", fn operation -> operation.__struct__.up(operation) end)
|
Enum.map_join(operations, "\n", fn operation -> operation.__struct__.up(operation) end)
|
||||||
|
|
||||||
|
@ -39,13 +53,20 @@ defmodule AshPostgres.MigrationGenerator.Phase do
|
||||||
body <>
|
body <>
|
||||||
"\nend"
|
"\nend"
|
||||||
else
|
else
|
||||||
"alter table(:#{table}) do\n" <>
|
opts =
|
||||||
|
if schema do
|
||||||
|
", prefix: \"#{schema}\""
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end
|
||||||
|
|
||||||
|
"alter table(:#{table}#{opts}) do\n" <>
|
||||||
body <>
|
body <>
|
||||||
"\nend"
|
"\nend"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def down(%{table: table, operations: operations, multitenancy: multitenancy}) do
|
def down(%{table: table, schema: schema, operations: operations, multitenancy: multitenancy}) do
|
||||||
body =
|
body =
|
||||||
operations
|
operations
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|
@ -56,7 +77,14 @@ defmodule AshPostgres.MigrationGenerator.Phase do
|
||||||
body <>
|
body <>
|
||||||
"\nend"
|
"\nend"
|
||||||
else
|
else
|
||||||
"alter table(:#{table}) do\n" <>
|
opts =
|
||||||
|
if schema do
|
||||||
|
", prefix: \"#{schema}\""
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end
|
||||||
|
|
||||||
|
"alter table(:#{table}#{opts}) do\n" <>
|
||||||
body <>
|
body <>
|
||||||
"\nend"
|
"\nend"
|
||||||
end
|
end
|
||||||
|
|
|
@ -128,6 +128,86 @@ defmodule AshPostgres.MigrationGeneratorTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "creating initial snapshots for resources with a schema" do
|
||||||
|
setup do
|
||||||
|
on_exit(fn ->
|
||||||
|
File.rm_rf!("test_snapshots_path")
|
||||||
|
File.rm_rf!("test_migration_path")
|
||||||
|
end)
|
||||||
|
|
||||||
|
defposts do
|
||||||
|
postgres do
|
||||||
|
migration_types second_title: {:varchar, 16}
|
||||||
|
schema("example")
|
||||||
|
end
|
||||||
|
|
||||||
|
identities do
|
||||||
|
identity(:title, [:title])
|
||||||
|
end
|
||||||
|
|
||||||
|
attributes do
|
||||||
|
uuid_primary_key(:id)
|
||||||
|
attribute(:title, :string)
|
||||||
|
attribute(:second_title, :string)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defapi([Post])
|
||||||
|
|
||||||
|
Mix.shell(Mix.Shell.Process)
|
||||||
|
|
||||||
|
{:ok, _} =
|
||||||
|
Ecto.Adapters.SQL.query(
|
||||||
|
AshPostgres.TestRepo,
|
||||||
|
"""
|
||||||
|
CREATE SCHEMA IF NOT EXISTS example;
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
AshPostgres.MigrationGenerator.generate(Api,
|
||||||
|
snapshot_path: "test_snapshots_path",
|
||||||
|
migration_path: "test_migration_path",
|
||||||
|
quiet: true,
|
||||||
|
format: false
|
||||||
|
)
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
test "the migration sets up resources correctly" do
|
||||||
|
# the snapshot exists and contains valid json
|
||||||
|
assert File.read!(Path.wildcard("test_snapshots_path/test_repo/posts/*.json"))
|
||||||
|
|> Jason.decode!(keys: :atoms!)
|
||||||
|
|
||||||
|
assert [file] = Path.wildcard("test_migration_path/**/*_migrate_resources*.exs")
|
||||||
|
|
||||||
|
file_contents = File.read!(file)
|
||||||
|
|
||||||
|
# the migration creates the table
|
||||||
|
assert file_contents =~ "create table(:posts, primary_key: false, prefix: \"example\") do"
|
||||||
|
|
||||||
|
# the migration sets up the custom_indexes
|
||||||
|
assert file_contents =~
|
||||||
|
~S{create index(:posts, ["id"], name: "test_unique_index", unique: true, prefix: "example")}
|
||||||
|
|
||||||
|
assert file_contents =~ ~S{create index(:posts, ["id"]}
|
||||||
|
|
||||||
|
# the migration adds the id, with its default
|
||||||
|
assert file_contents =~
|
||||||
|
~S[add :id, :uuid, null: false, default: fragment("uuid_generate_v4()"), primary_key: true]
|
||||||
|
|
||||||
|
# the migration adds other attributes
|
||||||
|
assert file_contents =~ ~S[add :title, :text]
|
||||||
|
|
||||||
|
# the migration adds custom attributes
|
||||||
|
assert file_contents =~ ~S[add :second_title, :varchar, size: 16]
|
||||||
|
|
||||||
|
# the migration creates unique_indexes based on the identities of the resource
|
||||||
|
assert file_contents =~
|
||||||
|
~S{create unique_index(:posts, [:title], name: "posts_title_index", prefix: "example")}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "creating follow up migrations" do
|
describe "creating follow up migrations" do
|
||||||
setup do
|
setup do
|
||||||
on_exit(fn ->
|
on_exit(fn ->
|
||||||
|
@ -527,7 +607,7 @@ defmodule AshPostgres.MigrationGeneratorTest do
|
||||||
assert [file] = Path.wildcard("test_migration_path/**/*_migrate_resources*.exs")
|
assert [file] = Path.wildcard("test_migration_path/**/*_migrate_resources*.exs")
|
||||||
|
|
||||||
assert File.read!(file) =~
|
assert File.read!(file) =~
|
||||||
~S[references(:posts, column: :id, name: "posts_post_id_fkey", type: :uuid)]
|
~S[references(:posts, column: :id, name: "posts_post_id_fkey", type: :uuid, prefix: "public")]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "when modified, the foreign key is dropped before modification" do
|
test "when modified, the foreign key is dropped before modification" do
|
||||||
|
@ -590,7 +670,7 @@ defmodule AshPostgres.MigrationGeneratorTest do
|
||||||
|> Enum.at(1)
|
|> Enum.at(1)
|
||||||
|
|
||||||
assert File.read!(file) =~
|
assert File.read!(file) =~
|
||||||
~S[references(:posts, column: :id, name: "special_post_fkey", type: :uuid, on_delete: :delete_all, on_update: :update_all)]
|
~S[references(:posts, column: :id, prefix: "public", name: "special_post_fkey", type: :uuid, on_delete: :delete_all, on_update: :update_all)]
|
||||||
|
|
||||||
assert File.read!(file) =~ ~S[drop constraint(:posts, "posts_post_id_fkey")]
|
assert File.read!(file) =~ ~S[drop constraint(:posts, "posts_post_id_fkey")]
|
||||||
end
|
end
|
||||||
|
@ -757,7 +837,7 @@ defmodule AshPostgres.MigrationGeneratorTest do
|
||||||
assert [file] = Path.wildcard("test_migration_path/**/*_migrate_resources*.exs")
|
assert [file] = Path.wildcard("test_migration_path/**/*_migrate_resources*.exs")
|
||||||
|
|
||||||
assert File.read!(file) =~
|
assert File.read!(file) =~
|
||||||
~S[references(:post_comments, column: :id, name: "posts_best_comment_id_fkey", type: :uuid)]
|
~S[references(:post_comments, column: :id, name: "posts_best_comment_id_fkey", type: :uuid, prefix: "public")]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue