2020-09-11 12:26:47 +12:00
|
|
|
defmodule AshPostgres.MigrationGenerator.Operation do
|
|
|
|
@moduledoc false
|
2021-01-10 13:52:19 +13:00
|
|
|
|
|
|
|
defmodule Helper do
|
|
|
|
@moduledoc false
|
|
|
|
def join(list), do: list |> List.flatten() |> Enum.reject(&is_nil/1) |> Enum.join(", ")
|
|
|
|
|
|
|
|
def maybe_add_default("nil"), do: nil
|
|
|
|
def maybe_add_default(value), do: "default: #{value}"
|
|
|
|
|
|
|
|
def maybe_add_primary_key(true), do: "primary_key: true"
|
|
|
|
def maybe_add_primary_key(_), do: nil
|
|
|
|
|
|
|
|
def maybe_add_null(false), do: "null: false"
|
|
|
|
def maybe_add_null(_), do: nil
|
|
|
|
end
|
|
|
|
|
2020-09-11 12:26:47 +12:00
|
|
|
defmodule CreateTable do
|
|
|
|
@moduledoc false
|
2020-10-29 15:26:45 +13:00
|
|
|
defstruct [:table, :multitenancy, :old_multitenancy]
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
|
|
|
|
defmodule AddAttribute do
|
|
|
|
@moduledoc false
|
2020-10-29 15:26:45 +13:00
|
|
|
defstruct [:attribute, :table, :multitenancy, :old_multitenancy]
|
|
|
|
|
2021-01-10 13:52:19 +13:00
|
|
|
import Helper
|
|
|
|
|
2020-10-29 15:26:45 +13:00
|
|
|
def up(%{
|
|
|
|
multitenancy: %{strategy: :attribute, attribute: source_attribute},
|
|
|
|
attribute:
|
|
|
|
%{
|
|
|
|
references: %{
|
|
|
|
table: table,
|
|
|
|
destination_field: destination_field,
|
|
|
|
multitenancy: %{strategy: :attribute, attribute: destination_attribute}
|
|
|
|
}
|
|
|
|
} = attribute
|
|
|
|
}) do
|
2021-01-10 13:52:19 +13:00
|
|
|
[
|
|
|
|
"add #{inspect(attribute.name)}",
|
|
|
|
"references(#{inspect(table)}",
|
|
|
|
[
|
|
|
|
"type: #{inspect(attribute.type)}",
|
|
|
|
"column: #{inspect(destination_field)}",
|
|
|
|
"with: [#{source_attribute}: :#{destination_attribute}]"
|
|
|
|
],
|
|
|
|
")",
|
|
|
|
maybe_add_default(attribute.default),
|
|
|
|
maybe_add_primary_key(attribute.primary_key?)
|
|
|
|
]
|
|
|
|
|> join()
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
def up(%{
|
|
|
|
multitenancy: %{strategy: :context},
|
|
|
|
attribute:
|
|
|
|
%{
|
|
|
|
references: %{
|
|
|
|
table: table,
|
|
|
|
destination_field: destination_field,
|
|
|
|
multitenancy: %{strategy: :attribute}
|
|
|
|
}
|
|
|
|
} = attribute
|
|
|
|
}) do
|
2021-01-10 13:52:19 +13:00
|
|
|
[
|
|
|
|
"add #{inspect(attribute.name)}",
|
|
|
|
"references(#{inspect(table)}",
|
|
|
|
[
|
|
|
|
"type: #{inspect(attribute.type)}",
|
|
|
|
"column: #{inspect(destination_field)}",
|
|
|
|
"name: \"\#\{prefix\}_#{table}_#{attribute.name}_fkey\"",
|
|
|
|
"prefix: \"public\""
|
|
|
|
],
|
|
|
|
")",
|
|
|
|
maybe_add_default(attribute.default),
|
|
|
|
maybe_add_primary_key(attribute.primary_key?)
|
|
|
|
]
|
|
|
|
|> join()
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
def up(%{
|
|
|
|
multitenancy: %{strategy: :attribute},
|
|
|
|
table: current_table,
|
|
|
|
attribute:
|
|
|
|
%{
|
|
|
|
references: %{
|
|
|
|
table: table,
|
|
|
|
multitenancy: %{strategy: :context}
|
|
|
|
}
|
|
|
|
} = attribute
|
|
|
|
}) do
|
|
|
|
Mix.shell().info("""
|
|
|
|
table `#{current_table}` with attribute multitenancy refers to table `#{table}` with schema based multitenancy.
|
|
|
|
This means that it is not possible to use a foreign key. This is not necessarily a problem, just something
|
|
|
|
you should be aware of
|
|
|
|
""")
|
|
|
|
|
2021-01-10 13:52:19 +13:00
|
|
|
[
|
|
|
|
"add #{inspect(attribute.name)}",
|
|
|
|
inspect(attribute.type),
|
|
|
|
maybe_add_default(attribute.default),
|
|
|
|
maybe_add_primary_key(attribute.primary_key?)
|
|
|
|
]
|
|
|
|
|> join()
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
def up(%{
|
|
|
|
multitenancy: %{strategy: :context},
|
|
|
|
attribute:
|
|
|
|
%{references: %{table: table, destination_field: destination_field}} = attribute
|
|
|
|
}) do
|
2021-01-10 13:52:19 +13:00
|
|
|
[
|
|
|
|
"add #{inspect(attribute.name)}",
|
|
|
|
"references(#{inspect(table)}",
|
|
|
|
[
|
|
|
|
"type: #{inspect(attribute.type)}",
|
|
|
|
"column: #{inspect(destination_field)}",
|
|
|
|
"name: \"\#\{prefix\}_#{table}_#{attribute.name}_fkey\""
|
|
|
|
],
|
|
|
|
")",
|
|
|
|
maybe_add_default(attribute.default),
|
|
|
|
maybe_add_primary_key(attribute.primary_key?)
|
|
|
|
]
|
|
|
|
|> join()
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
2020-09-11 12:26:47 +12:00
|
|
|
|
|
|
|
def up(%{
|
|
|
|
attribute:
|
|
|
|
%{references: %{table: table, destination_field: destination_field}} = attribute
|
|
|
|
}) do
|
2021-01-10 13:52:19 +13:00
|
|
|
[
|
|
|
|
"add #{inspect(attribute.name)}",
|
|
|
|
"references(#{inspect(table)}",
|
|
|
|
[
|
|
|
|
"type: #{inspect(attribute.type)}",
|
|
|
|
"column: #{inspect(destination_field)}"
|
|
|
|
],
|
|
|
|
")",
|
|
|
|
maybe_add_default(attribute.default),
|
|
|
|
maybe_add_primary_key(attribute.primary_key?)
|
|
|
|
]
|
|
|
|
|> join()
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
|
2021-01-08 16:53:16 +13:00
|
|
|
def up(%{attribute: %{type: :integer, default: "nil", generated?: true} = attribute}) do
|
2021-01-10 13:52:19 +13:00
|
|
|
[
|
|
|
|
"add #{inspect(attribute.name)}",
|
|
|
|
":serial",
|
|
|
|
maybe_add_null(attribute.allow_nil?),
|
|
|
|
maybe_add_primary_key(attribute.primary_key?)
|
|
|
|
]
|
|
|
|
|> join()
|
2021-01-08 16:53:16 +13:00
|
|
|
end
|
|
|
|
|
2020-09-11 12:26:47 +12:00
|
|
|
def up(%{attribute: attribute}) do
|
2021-01-10 13:52:19 +13:00
|
|
|
[
|
|
|
|
"add #{inspect(attribute.name)}",
|
|
|
|
"#{inspect(attribute.type)}",
|
|
|
|
maybe_add_null(attribute.allow_nil?),
|
|
|
|
maybe_add_default(attribute.default),
|
|
|
|
maybe_add_primary_key(attribute.primary_key?)
|
|
|
|
]
|
|
|
|
|> join()
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
|
2020-11-07 18:00:41 +13:00
|
|
|
def down(
|
|
|
|
%{
|
|
|
|
attribute: attribute,
|
|
|
|
table: table,
|
|
|
|
multitenancy: multitenancy
|
|
|
|
} = op
|
|
|
|
) do
|
|
|
|
AshPostgres.MigrationGenerator.Operation.RemoveAttribute.up(%{
|
|
|
|
op
|
|
|
|
| attribute: attribute,
|
|
|
|
table: table,
|
|
|
|
multitenancy: multitenancy
|
|
|
|
})
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defmodule AlterAttribute do
|
|
|
|
@moduledoc false
|
2020-10-29 15:26:45 +13:00
|
|
|
defstruct [:old_attribute, :new_attribute, :table, :multitenancy, :old_multitenancy]
|
|
|
|
|
2020-11-07 18:00:41 +13:00
|
|
|
defp alter_opts(attribute, old_attribute) do
|
|
|
|
primary_key =
|
|
|
|
if attribute.primary_key? and !old_attribute.primary_key? do
|
|
|
|
", primary_key: true"
|
|
|
|
end
|
2020-10-29 15:26:45 +13:00
|
|
|
|
2020-11-07 18:00:41 +13:00
|
|
|
default =
|
|
|
|
if attribute.default != old_attribute.default do
|
2020-12-01 19:54:20 +13:00
|
|
|
if is_nil(attribute.default) do
|
|
|
|
", default: nil"
|
|
|
|
else
|
|
|
|
", default: #{attribute.default}"
|
|
|
|
end
|
2020-11-07 18:00:41 +13:00
|
|
|
end
|
2020-09-11 12:26:47 +12:00
|
|
|
|
2020-11-07 18:00:41 +13:00
|
|
|
null =
|
|
|
|
if attribute.allow_nil? != old_attribute.allow_nil? do
|
|
|
|
", null: #{attribute.allow_nil?}"
|
|
|
|
end
|
2020-10-29 15:26:45 +13:00
|
|
|
|
2020-11-07 18:00:41 +13:00
|
|
|
"#{null}#{default}#{primary_key}"
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
def up(%{
|
2020-11-07 18:00:41 +13:00
|
|
|
multitenancy: multitenancy,
|
|
|
|
old_attribute: old_attribute,
|
|
|
|
new_attribute: attribute
|
2020-09-11 12:26:47 +12:00
|
|
|
}) do
|
2020-11-07 18:00:41 +13:00
|
|
|
type_or_reference =
|
2020-11-18 12:35:57 +13:00
|
|
|
if AshPostgres.MigrationGenerator.has_reference?(multitenancy, attribute) and
|
2020-11-07 18:00:41 +13:00
|
|
|
Map.get(old_attribute, :references) != Map.get(attribute, :references) do
|
|
|
|
reference(multitenancy, attribute)
|
|
|
|
else
|
|
|
|
inspect(attribute.type)
|
|
|
|
end
|
2020-09-11 12:26:47 +12:00
|
|
|
|
2020-11-18 12:35:57 +13:00
|
|
|
"modify #{inspect(attribute.name)}, #{type_or_reference}#{
|
|
|
|
alter_opts(attribute, old_attribute)
|
|
|
|
}"
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
|
2020-11-07 18:00:41 +13:00
|
|
|
defp reference(%{strategy: :context}, %{
|
|
|
|
type: type,
|
|
|
|
name: name,
|
|
|
|
references: %{
|
|
|
|
multitenancy: %{strategy: :context},
|
|
|
|
table: table,
|
|
|
|
destination_field: destination_field
|
|
|
|
}
|
|
|
|
}) do
|
|
|
|
"references(#{inspect(table)}, type: #{inspect(type)}, column: #{inspect(destination_field)}, name: \"\#\{prefix\}_#{
|
|
|
|
table
|
|
|
|
}_#{name}_fkey\")"
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
|
|
|
|
2020-11-07 18:00:41 +13:00
|
|
|
defp reference(%{strategy: :attribute, attribute: source_attribute}, %{
|
|
|
|
type: type,
|
|
|
|
references: %{
|
|
|
|
multitenancy: %{strategy: :attribute, attribute: destination_attribute},
|
|
|
|
table: table,
|
|
|
|
destination_field: destination_field
|
|
|
|
}
|
|
|
|
}) do
|
|
|
|
"references(#{inspect(table)}, type: #{inspect(type)}, column: #{inspect(destination_field)}, with: [#{
|
|
|
|
source_attribute
|
|
|
|
}: :#{destination_attribute}])"
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
|
|
|
|
2020-11-07 18:00:41 +13:00
|
|
|
defp reference(_, %{
|
|
|
|
type: type,
|
|
|
|
references: %{
|
|
|
|
table: table,
|
|
|
|
destination_field: destination_field
|
|
|
|
}
|
|
|
|
}) do
|
|
|
|
"references(#{inspect(table)}, type: #{inspect(type)}, column: #{inspect(destination_field)})"
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
|
|
|
|
2020-11-07 18:00:41 +13:00
|
|
|
def down(op) do
|
|
|
|
up(%{
|
|
|
|
op
|
|
|
|
| old_attribute: op.new_attribute,
|
|
|
|
new_attribute: op.old_attribute,
|
|
|
|
old_multitenancy: op.multitenancy,
|
|
|
|
multitenancy: op.old_multitenancy
|
|
|
|
})
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-11-18 12:35:57 +13:00
|
|
|
defmodule DropForeignKey do
|
|
|
|
@moduledoc false
|
|
|
|
# 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`
|
|
|
|
# We only need to drop it before altering an attribute with `references/3`
|
|
|
|
defstruct [:attribute, :table, :multitenancy, :direction, no_phase: true]
|
|
|
|
|
|
|
|
def up(%{attribute: attribute, table: table, multitenancy: multitenancy, direction: :up}) do
|
|
|
|
if multitenancy && multitenancy.strategy == :context do
|
|
|
|
"drop constraint(:#{table}, \"\#\{prefix\}_#{table}_#{attribute.name}_fkey\")"
|
|
|
|
else
|
|
|
|
"drop constraint(:#{table}, \"#{table}_#{attribute.name}_fkey\")"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def up(_), do: ""
|
|
|
|
|
|
|
|
def down(%{attribute: attribute, table: table, multitenancy: multitenancy, direction: :down}) do
|
|
|
|
if multitenancy && multitenancy.strategy == :context do
|
|
|
|
"drop constraint(:#{table}, \"\#\{prefix\}_#{table}_#{attribute.name}_fkey\")"
|
|
|
|
else
|
|
|
|
"drop constraint(:#{table}, \"#{table}_#{attribute.name}_fkey\")"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def down(_), do: ""
|
|
|
|
end
|
|
|
|
|
2020-09-11 12:26:47 +12:00
|
|
|
defmodule RenameAttribute do
|
|
|
|
@moduledoc false
|
2021-01-13 08:21:44 +13:00
|
|
|
defstruct [
|
|
|
|
:old_attribute,
|
|
|
|
:new_attribute,
|
|
|
|
:table,
|
|
|
|
:multitenancy,
|
|
|
|
:old_multitenancy,
|
|
|
|
no_phase: true
|
|
|
|
]
|
2020-09-11 12:26:47 +12:00
|
|
|
|
|
|
|
def up(%{old_attribute: old_attribute, new_attribute: new_attribute, table: table}) do
|
|
|
|
"rename table(:#{table}), #{inspect(old_attribute.name)}, to: #{inspect(new_attribute.name)}"
|
|
|
|
end
|
|
|
|
|
|
|
|
def down(%{new_attribute: old_attribute, old_attribute: new_attribute, table: table}) do
|
|
|
|
"rename table(:#{table}), #{inspect(old_attribute.name)}, to: #{inspect(new_attribute.name)}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defmodule RemoveAttribute do
|
|
|
|
@moduledoc false
|
2020-11-20 16:09:26 +13:00
|
|
|
defstruct [:attribute, :table, :multitenancy, :old_multitenancy, commented?: true]
|
|
|
|
|
|
|
|
def up(%{attribute: attribute, commented?: true}) do
|
|
|
|
"""
|
|
|
|
# Attribute removal has been commented out to avoid data loss. See the migration generator documentation for more
|
|
|
|
# If you uncomment this, be sure to also uncomment the corresponding attribute *addition* in the `down` migration
|
|
|
|
# remove #{inspect(attribute.name)}
|
|
|
|
"""
|
|
|
|
end
|
2020-09-11 12:26:47 +12:00
|
|
|
|
2020-11-18 12:35:57 +13:00
|
|
|
def up(%{attribute: attribute}) do
|
|
|
|
"remove #{inspect(attribute.name)}"
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
|
2020-11-20 16:09:26 +13:00
|
|
|
def down(%{attribute: attribute, multitenancy: multitenancy, commented?: true}) do
|
|
|
|
prefix = """
|
|
|
|
# This is the `down` migration of the statement:
|
|
|
|
#
|
|
|
|
# remove #{inspect(attribute.name)}
|
|
|
|
#
|
|
|
|
"""
|
|
|
|
|
|
|
|
contents =
|
|
|
|
%AshPostgres.MigrationGenerator.Operation.AddAttribute{
|
|
|
|
attribute: attribute,
|
|
|
|
multitenancy: multitenancy
|
|
|
|
}
|
|
|
|
|> AshPostgres.MigrationGenerator.Operation.AddAttribute.up()
|
|
|
|
|> String.split("\n")
|
|
|
|
|> Enum.map(&"# #{&1}")
|
|
|
|
|> Enum.join("\n")
|
|
|
|
|
|
|
|
prefix <> "\n" <> contents
|
|
|
|
end
|
|
|
|
|
2020-11-07 18:00:41 +13:00
|
|
|
def down(%{attribute: attribute, multitenancy: multitenancy}) do
|
|
|
|
AshPostgres.MigrationGenerator.Operation.AddAttribute.up(
|
|
|
|
%AshPostgres.MigrationGenerator.Operation.AddAttribute{
|
|
|
|
attribute: attribute,
|
|
|
|
multitenancy: multitenancy
|
|
|
|
}
|
|
|
|
)
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defmodule AddUniqueIndex do
|
|
|
|
@moduledoc false
|
2020-10-29 15:26:45 +13:00
|
|
|
defstruct [:identity, :table, :multitenancy, :old_multitenancy, no_phase: true]
|
|
|
|
|
|
|
|
def up(%{
|
|
|
|
identity: %{name: name, keys: keys, base_filter: base_filter},
|
|
|
|
table: table,
|
|
|
|
multitenancy: multitenancy
|
|
|
|
}) do
|
2020-11-25 12:11:02 +13:00
|
|
|
{name_prefix, keys} =
|
|
|
|
case multitenancy.strategy do
|
|
|
|
:context ->
|
|
|
|
{"\#\{prefix\}_", keys}
|
|
|
|
|
|
|
|
:attribute ->
|
|
|
|
{"", [multitenancy.attribute | keys]}
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
{"", keys}
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
2020-09-11 12:26:47 +12:00
|
|
|
|
2020-09-20 10:08:09 +12:00
|
|
|
if base_filter do
|
|
|
|
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{
|
2020-10-29 15:26:45 +13:00
|
|
|
name_prefix
|
|
|
|
}#{table}_#{name}_unique_index\", where: \"#{base_filter}\")"
|
2020-09-20 10:08:09 +12:00
|
|
|
else
|
|
|
|
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{
|
2020-10-29 15:26:45 +13:00
|
|
|
name_prefix
|
|
|
|
}#{table}_#{name}_unique_index\")"
|
2020-09-20 10:08:09 +12:00
|
|
|
end
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
|
2020-11-25 12:11:02 +13:00
|
|
|
def down(%{
|
|
|
|
identity: %{name: name, keys: keys},
|
|
|
|
table: table,
|
|
|
|
multitenancy: multitenancy
|
|
|
|
}) do
|
|
|
|
{name_prefix, keys} =
|
|
|
|
case multitenancy.strategy do
|
|
|
|
:context ->
|
|
|
|
{"\#\{prefix\}_", keys}
|
|
|
|
|
|
|
|
:attribute ->
|
|
|
|
{"", [multitenancy.attribute | keys]}
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
{"", keys}
|
|
|
|
end
|
|
|
|
|
|
|
|
"drop_if_exists unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{
|
|
|
|
name_prefix
|
|
|
|
}#{table}_#{name}_unique_index\")"
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defmodule RemoveUniqueIndex do
|
|
|
|
@moduledoc false
|
2020-10-29 15:26:45 +13:00
|
|
|
defstruct [:identity, :table, :multitenancy, :old_multitenancy, no_phase: true]
|
2020-09-11 12:26:47 +12:00
|
|
|
|
2020-10-29 15:26:45 +13:00
|
|
|
def up(%{identity: %{name: name, keys: keys}, table: table, old_multitenancy: multitenancy}) do
|
2020-11-25 12:11:02 +13:00
|
|
|
{name_prefix, keys} =
|
|
|
|
case multitenancy.strategy do
|
|
|
|
:context ->
|
|
|
|
{"\#\{prefix\}_", keys}
|
|
|
|
|
|
|
|
:attribute ->
|
|
|
|
{"", [multitenancy.attribute | keys]}
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
{"", keys}
|
|
|
|
end
|
|
|
|
|
|
|
|
"drop_if_exists unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{
|
|
|
|
name_prefix
|
|
|
|
}#{table}_#{name}_unique_index\")"
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
|
2020-11-25 12:11:02 +13:00
|
|
|
def down(%{
|
|
|
|
identity: %{name: name, keys: keys, base_filter: base_filter},
|
|
|
|
table: table,
|
|
|
|
multitenancy: multitenancy
|
|
|
|
}) do
|
|
|
|
{name_prefix, keys} =
|
|
|
|
case multitenancy.strategy do
|
|
|
|
:context ->
|
|
|
|
{"\#\{prefix\}_", keys}
|
|
|
|
|
|
|
|
:attribute ->
|
|
|
|
{"", [multitenancy.attribute | keys]}
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
{"", keys}
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
|
|
|
|
2020-11-25 12:11:02 +13:00
|
|
|
if base_filter do
|
|
|
|
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{
|
|
|
|
name_prefix
|
|
|
|
}#{table}_#{name}_unique_index\", where: \"#{base_filter}\")"
|
2020-10-29 15:26:45 +13:00
|
|
|
else
|
|
|
|
"create unique_index(:#{table}, [#{Enum.map_join(keys, ",", &inspect/1)}], name: \"#{
|
2020-11-25 12:11:02 +13:00
|
|
|
name_prefix
|
|
|
|
}#{table}_#{name}_unique_index\")"
|
2020-10-29 15:26:45 +13:00
|
|
|
end
|
2020-09-11 12:26:47 +12:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|