mirror of
https://github.com/ash-project/ash_postgres.git
synced 2024-09-19 21:13:19 +12:00
improvement: update ash
and support new identity
features
This commit is contained in:
parent
4e84a3f75d
commit
8ad92cc3c0
15 changed files with 971 additions and 49 deletions
|
@ -1,6 +1,7 @@
|
|||
spark_locals_without_parens = [
|
||||
all_tenants?: 1,
|
||||
base_filter_sql: 1,
|
||||
calculations_to_sql: 1,
|
||||
check: 1,
|
||||
check_constraint: 2,
|
||||
check_constraint: 3,
|
||||
|
@ -13,6 +14,7 @@ spark_locals_without_parens = [
|
|||
exclusion_constraint_names: 1,
|
||||
foreign_key_names: 1,
|
||||
identity_index_names: 1,
|
||||
identity_wheres_to_sql: 1,
|
||||
ignore?: 1,
|
||||
include: 1,
|
||||
index: 1,
|
||||
|
|
29
CHANGELOG.md
29
CHANGELOG.md
|
@ -7,46 +7,37 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline
|
|||
|
||||
## [v2.0.4](https://github.com/ash-project/ash_postgres/compare/v2.0.3...v2.0.4) (2024-05-23)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* ensure update's reselect all changing values
|
||||
[updates] ensure update's reselect all changing values
|
||||
|
||||
## [v2.0.3](https://github.com/ash-project/ash_postgres/compare/v2.0.2...v2.0.3) (2024-05-22)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* handle complex maps/list on update
|
||||
[updates] handle complex maps/list on update
|
||||
|
||||
* support anonymous aggregates in sorts
|
||||
[Ash.Query] support anonymous aggregates in sorts
|
||||
|
||||
* ensure parent_as bindings properly reference binding names
|
||||
[exists] ensure parent_as bindings properly reference binding names
|
||||
|
||||
* add and remove custom indexes in tandem properly
|
||||
[migration generator] add and remove custom indexes in tandem properly
|
||||
|
||||
### Improvements:
|
||||
|
||||
* support `on_delete: :nilify` for specific columns (#289)
|
||||
[references] support `on_delete: :nilify` for specific columns (#289)
|
||||
|
||||
## [v2.0.2](https://github.com/ash-project/ash_postgres/compare/v2.0.1...v2.0.2) (2024-05-15)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* [update_query/destroy_query] rework the update and destroy query builder to support multiple kinds of joining
|
||||
- [update_query/destroy_query] rework the update and destroy query builder to support multiple kinds of joining
|
||||
|
||||
* [mix ash_postgres.migrate] remove duplicate repo flags (#285)
|
||||
- [mix ash_postgres.migrate] remove duplicate repo flags (#285)
|
||||
|
||||
* [Ash.Error.Changes.StaleRecord] ensure filter is included in stale record error messages we return
|
||||
- [Ash.Error.Changes.StaleRecord] ensure filter is included in stale record error messages we return
|
||||
|
||||
* [AshPostgres.MigrationGenerator] properly parse previous version from migration generation
|
||||
- [AshPostgres.MigrationGenerator] properly parse previous version from migration generation
|
||||
|
||||
## [v2.0.1](https://github.com/ash-project/ash_postgres/compare/v2.0.0...v2.0.1) (2024-05-12)
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ end
|
|||
| [`migrate?`](#postgres-migrate?){: #postgres-migrate? } | `boolean` | `true` | Whether or not to include this resource in the generated migrations with `mix ash.generate_migrations` |
|
||||
| [`migration_types`](#postgres-migration_types){: #postgres-migration_types } | `keyword` | `[]` | A keyword list of attribute names to the ecto migration type that should be used for that attribute. Only necessary if you need to override the defaults. |
|
||||
| [`migration_defaults`](#postgres-migration_defaults){: #postgres-migration_defaults } | `keyword` | `[]` | A keyword list of attribute names to the ecto migration default that should be used for that attribute. The string you use will be placed verbatim in the migration. Use fragments like `fragment(\\"now()\\")`, or for `nil`, use `\\"nil\\"`. |
|
||||
| [`calculations_to_sql`](#postgres-calculations_to_sql){: #postgres-calculations_to_sql } | `keyword` | | A keyword list of calculations and their SQL representation. Used when creating unique indexes for identities over calculations |
|
||||
| [`identity_wheres_to_sql`](#postgres-identity_wheres_to_sql){: #postgres-identity_wheres_to_sql } | `keyword` | | A keyword list of identity names and the SQL representation of their `where` clause. Used when creating unique indexes for identities over calculations |
|
||||
| [`base_filter_sql`](#postgres-base_filter_sql){: #postgres-base_filter_sql } | `String.t` | | A raw sql version of the base_filter, e.g `representative = true`. Required if trying to create a unique constraint on a resource with a base_filter |
|
||||
| [`simple_join_first_aggregates`](#postgres-simple_join_first_aggregates){: #postgres-simple_join_first_aggregates } | `list(atom)` | `[]` | A list of `:first` type aggregate names that can be joined to using a simple join. Use when you have a `:first` aggregate that uses a to-many relationship , but your `filter` statement ensures that there is only one result. Optimizes the generated query. |
|
||||
| [`skip_unique_indexes`](#postgres-skip_unique_indexes){: #postgres-skip_unique_indexes } | `atom \| list(atom)` | `false` | Skip generating unique indexes when generating migrations |
|
||||
|
|
|
@ -300,6 +300,16 @@ defmodule AshPostgres.DataLayer do
|
|||
A keyword list of attribute names to the ecto migration default that should be used for that attribute. The string you use will be placed verbatim in the migration. Use fragments like `fragment(\\\\"now()\\\\")`, or for `nil`, use `\\\\"nil\\\\"`.
|
||||
"""
|
||||
],
|
||||
calculations_to_sql: [
|
||||
type: :keyword_list,
|
||||
doc:
|
||||
"A keyword list of calculations and their SQL representation. Used when creating unique indexes for identities over calculations"
|
||||
],
|
||||
identity_wheres_to_sql: [
|
||||
type: :keyword_list,
|
||||
doc:
|
||||
"A keyword list of identity names and the SQL representation of their `where` clause. Used when creating unique indexes for identities over calculations"
|
||||
],
|
||||
base_filter_sql: [
|
||||
type: :string,
|
||||
doc:
|
||||
|
|
|
@ -14,6 +14,24 @@ defmodule AshPostgres.DataLayer.Info do
|
|||
end
|
||||
end
|
||||
|
||||
@doc "A keyword list of calculations to their sql representation"
|
||||
def calculations_to_sql(resource) do
|
||||
Extension.get_opt(resource, [:postgres], :calculations_to_sql, [])
|
||||
end
|
||||
|
||||
def calculation_to_sql(resource, calc) do
|
||||
calculations_to_sql(resource)[calc]
|
||||
end
|
||||
|
||||
@doc "A keyword list of identity names to the sql representation of their where clauses"
|
||||
def identity_wheres_to_sql(resource) do
|
||||
Extension.get_opt(resource, [:postgres], :identity_wheres_to_sql, [])
|
||||
end
|
||||
|
||||
def identity_where_to_sql(resource, identity) do
|
||||
identity_wheres_to_sql(resource)[identity]
|
||||
end
|
||||
|
||||
@doc "Checks a version requirement against the resource's repo's postgres version"
|
||||
def pg_version_matches?(resource, requirement) do
|
||||
resource
|
||||
|
|
|
@ -1817,7 +1817,9 @@ defmodule AshPostgres.MigrationGenerator do
|
|||
old_identity.name == identity.name &&
|
||||
Enum.sort(old_identity.keys) == Enum.sort(identity.keys) &&
|
||||
old_identity.base_filter == identity.base_filter &&
|
||||
old_identity.all_tenants? == identity.all_tenants?
|
||||
old_identity.all_tenants? == identity.all_tenants? &&
|
||||
old_identity.nils_distinct? == identity.nils_distinct? &&
|
||||
old_identity.where == identity.where
|
||||
end)
|
||||
else
|
||||
false
|
||||
|
@ -1829,7 +1831,9 @@ defmodule AshPostgres.MigrationGenerator do
|
|||
old_identity.name == identity.name &&
|
||||
Enum.sort(old_identity.keys) == Enum.sort(identity.keys) &&
|
||||
old_identity.base_filter == identity.base_filter &&
|
||||
old_identity.all_tenants? == identity.all_tenants?
|
||||
old_identity.all_tenants? == identity.all_tenants? &&
|
||||
old_identity.nils_distinct? == identity.nils_distinct? &&
|
||||
old_identity.where == identity.where
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
@ -2820,23 +2824,32 @@ defmodule AshPostgres.MigrationGenerator do
|
|||
|> Enum.reject(fn identity ->
|
||||
identity.name in AshPostgres.DataLayer.Info.skip_unique_indexes(resource)
|
||||
end)
|
||||
|> Enum.filter(fn identity ->
|
||||
Enum.all?(identity.keys, fn key ->
|
||||
Ash.Resource.Info.attribute(resource, key)
|
||||
end)
|
||||
end)
|
||||
|> Enum.sort_by(& &1.name)
|
||||
|> Enum.map(&Map.take(&1, [:name, :keys, :all_tenants?]))
|
||||
|> Enum.map(fn %{keys: keys} = identity ->
|
||||
%{
|
||||
identity
|
||||
| keys:
|
||||
Enum.map(keys, fn key ->
|
||||
attribute = Ash.Resource.Info.attribute(resource, key)
|
||||
attribute.source || attribute.name
|
||||
case Ash.Resource.Info.field(resource, key) do
|
||||
%Ash.Resource.Attribute{} = attribute ->
|
||||
to_string(attribute.source || attribute.name)
|
||||
|
||||
%Ash.Resource.Calculation{} ->
|
||||
AshPostgres.DataLayer.Info.calculation_to_sql(resource, key) ||
|
||||
raise "Must define an entry for :#{key} in `postgres.calculations_to_sql`, or skip this identity with `postgres.skip_unique_indexes`"
|
||||
end
|
||||
end)
|
||||
|> Enum.sort(),
|
||||
where:
|
||||
if identity.where do
|
||||
AshPostgres.DataLayer.Info.identity_where_to_sql(resource, identity.name) ||
|
||||
raise(
|
||||
"Must provide an entry for :#{identity.name} in `postgres.identity_wheres_to_sql`, or skip this identity with `postgres.skip_unique_indexes`"
|
||||
)
|
||||
end
|
||||
}
|
||||
end)
|
||||
|> Enum.map(&Map.take(&1, [:name, :keys, :where, :all_tenants?, :nils_distinct?]))
|
||||
|> Enum.map(fn identity ->
|
||||
Map.put(
|
||||
identity,
|
||||
|
@ -3179,13 +3192,13 @@ defmodule AshPostgres.MigrationGenerator do
|
|||
identity
|
||||
|> Map.update!(:name, &maybe_to_atom/1)
|
||||
|> Map.update!(:keys, fn keys ->
|
||||
keys
|
||||
|> Enum.map(&maybe_to_atom/1)
|
||||
|> Enum.sort()
|
||||
Enum.sort(keys)
|
||||
end)
|
||||
|> add_index_name(table)
|
||||
|> Map.put_new(:base_filter, nil)
|
||||
|> Map.put_new(:all_tenants?, false)
|
||||
|> Map.put_new(:where, nil)
|
||||
|> Map.put_new(:nils_distinct?, true)
|
||||
end
|
||||
|
||||
defp add_index_name(%{name: name} = index, table) do
|
||||
|
|
|
@ -30,7 +30,7 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
|||
# sobelow_skip ["DOS.StringToAtom"]
|
||||
def as_atom(value), do: Macro.inspect_atom(:remote_call, String.to_atom(value))
|
||||
|
||||
def option(:nulls_distinct = key, value) do
|
||||
def option(key, value) when key in [:nulls_distinct, "nulls_distinct"] do
|
||||
if !value do
|
||||
"#{as_atom(key)}: #{inspect(value)}"
|
||||
end
|
||||
|
@ -790,6 +790,8 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
|||
identity: %{
|
||||
name: name,
|
||||
keys: keys,
|
||||
nils_distinct?: nils_distinct?,
|
||||
where: where,
|
||||
base_filter: base_filter,
|
||||
index_name: index_name,
|
||||
all_tenants?: all_tenants?
|
||||
|
@ -813,10 +815,17 @@ defmodule AshPostgres.MigrationGenerator.Operation do
|
|||
|
||||
index_name = index_name || "#{table}_#{name}_index"
|
||||
|
||||
if base_filter do
|
||||
"create unique_index(:#{as_atom(table)}, [#{Enum.map_join(keys, ", ", &inspect/1)}], where: \"#{base_filter}\", #{join(["name: \"#{index_name}\"", option("prefix", schema)])})"
|
||||
else
|
||||
"create unique_index(:#{as_atom(table)}, [#{Enum.map_join(keys, ", ", &inspect/1)}], #{join(["name: \"#{index_name}\"", option("prefix", schema)])})"
|
||||
cond do
|
||||
base_filter && where ->
|
||||
where = "(#{where}) AND (#{base_filter})"
|
||||
|
||||
"create unique_index(:#{as_atom(table)}, [#{Enum.map_join(keys, ", ", &inspect/1)}], #{join(["name: \"#{index_name}\"", option("prefix", schema), option("nulls_distinct", nils_distinct?), option("where", where)])})"
|
||||
|
||||
base_filter ->
|
||||
"create unique_index(:#{as_atom(table)}, [#{Enum.map_join(keys, ", ", &inspect/1)}], where: \"#{base_filter}\", #{join(["name: \"#{index_name}\"", option("prefix", schema), option("nulls_distinct", nils_distinct?)])})"
|
||||
|
||||
true ->
|
||||
"create unique_index(:#{as_atom(table)}, [#{Enum.map_join(keys, ", ", &inspect/1)}], #{join(["name: \"#{index_name}\"", option("prefix", schema), option("nulls_distinct", nils_distinct?), option("where", where)])})"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
2
mix.exs
2
mix.exs
|
@ -162,7 +162,7 @@ defmodule AshPostgres.MixProject do
|
|||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
{:ash, ash_version("~> 3.0 and >= 3.0.6")},
|
||||
{:ash, ash_version("~> 3.0 and >= 3.0.7")},
|
||||
{:ash_sql, ash_sql_version("~> 0.1 and >= 0.1.3")},
|
||||
{:ecto_sql, "~> 3.9"},
|
||||
{:ecto, "~> 3.9"},
|
||||
|
|
4
mix.lock
4
mix.lock
|
@ -1,5 +1,5 @@
|
|||
%{
|
||||
"ash": {:hex, :ash, "3.0.6", "888a5b81a0106e7122a487ea55cd968d8acfc5ac85a22c876eef7ffea9083041", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, ">= 0.8.1 and < 1.0.0-0", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.1.18 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c3d529933cfe53fb9e018f04cc7106eef74d74872edee1288d0ba75d9e97202d"},
|
||||
"ash": {:hex, :ash, "3.0.7", "6c37e092f53b1b21eb89596f600a652b2a601f84378f44fd5dd1cdec72eb1cc2", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, ">= 0.8.1 and < 1.0.0-0", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.1.18 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9288ddb50fe727096c6f63fd82c631de2505dcd29bdfa50b5dc13c865f0bf434"},
|
||||
"ash_sql": {:hex, :ash_sql, "0.1.3", "c9acc4809b7f253aad31764024aee0cd632077a32cff6bea3b105c7b8d9015b7", [:mix], [{:ash, "~> 3.0", [hex: :ash, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.9", [hex: :ecto_sql, repo: "hexpm", optional: false]}], "hexpm", "d2d3d1044f0fa48454d0cdaeb22d55a2de3210d48a2208fd2eecf6f3007a5216"},
|
||||
"benchee": {:hex, :benchee, "1.3.0", "f64e3b64ad3563fa9838146ddefb2d2f94cf5b473bdfd63f5ca4d0657bf96694", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "34f4294068c11b2bd2ebf2c59aac9c7da26ffa0068afdf3419f1b176e16c5f81"},
|
||||
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
|
||||
|
@ -30,7 +30,7 @@
|
|||
"reactor": {:hex, :reactor, "0.8.2", "b2be82b1c3402537d06a8f85bb1849f72cb6b4be140495cb8956de7aec2fdebd", [:mix], [{:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c35eb23b77cc77ba922af108722ac93257899e35cfdd18882f0e659ad2cac9f3"},
|
||||
"simple_sat": {:hex, :simple_sat, "0.1.3", "f650fc3c184a5fe741868b5ac56dc77fdbb428468f6dbf1978e14d0334497578", [:mix], [], "hexpm", "a54305066a356b7194dc81db2a89232bacdc0b3edaef68ed9aba28dcbc34887b"},
|
||||
"sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
|
||||
"sourceror": {:hex, :sourceror, "1.2.0", "471232b2eb9ab930b90673d37cf005bbaec0ef02dadf5bf4c8c00c3d75a6c131", [:mix], [], "hexpm", "f01796ce1b87016573ce7b66073d6b48297c4d233982340340834269b8c95e51"},
|
||||
"sourceror": {:hex, :sourceror, "1.2.1", "b415255ad8bd05f0e859bb3d7ea617f6c2a4a405f2a534a231f229bd99b89f8b", [:mix], [], "hexpm", "e4d97087e67584a7585b5fe3d5a71bf8e7332f795dd1a44983d750003d5e750c"},
|
||||
"spark": {:hex, :spark, "2.1.22", "a36400eede64c51af578de5fdb5a5aaa3e0811da44bcbe7545fce059bd2a990b", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "f764611d0b15ac132e72b2326539acc11fc4e63baa3e429f541bca292b5f7064"},
|
||||
"splode": {:hex, :splode, "0.2.4", "71046334c39605095ca4bed5d008372e56454060997da14f9868534c17b84b53", [:mix], [], "hexpm", "ca3b95f0d8d4b482b5357954fec857abd0fa3ea509d623334c1328e7382044c2"},
|
||||
"statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"},
|
||||
|
|
371
priv/resource_snapshots/test_repo/posts/20240524031113.json
Normal file
371
priv/resource_snapshots/test_repo/posts/20240524031113.json
Normal file
|
@ -0,0 +1,371 @@
|
|||
{
|
||||
"attributes": [
|
||||
{
|
||||
"default": "fragment(\"gen_random_uuid()\")",
|
||||
"size": null,
|
||||
"type": "uuid",
|
||||
"source": "id",
|
||||
"references": null,
|
||||
"allow_nil?": false,
|
||||
"generated?": false,
|
||||
"primary_key?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "title_column",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "timestamptz(6)",
|
||||
"source": "datetime",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "bigint",
|
||||
"source": "score",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "boolean",
|
||||
"source": "public",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "citext",
|
||||
"source": "category",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "\"sponsored\"",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "type",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "bigint",
|
||||
"source": "price",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "\"0\"",
|
||||
"size": null,
|
||||
"type": "decimal",
|
||||
"source": "decimal",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "status",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "status",
|
||||
"source": "status_enum",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": [
|
||||
"array",
|
||||
"float"
|
||||
],
|
||||
"source": "point",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "custom_point",
|
||||
"source": "composite_point",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "map",
|
||||
"source": "stuff",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": [
|
||||
"array",
|
||||
"map"
|
||||
],
|
||||
"source": "list_of_stuff",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_one",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_two",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_custom_one",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_custom_two",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_on_upper",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": [
|
||||
"array",
|
||||
"text"
|
||||
],
|
||||
"source": "list_containing_nils",
|
||||
"references": null,
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||
"size": null,
|
||||
"type": "utc_datetime_usec",
|
||||
"source": "created_at",
|
||||
"references": null,
|
||||
"allow_nil?": false,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||
"size": null,
|
||||
"type": "timestamptz(6)",
|
||||
"source": "updated_at",
|
||||
"references": null,
|
||||
"allow_nil?": false,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "uuid",
|
||||
"source": "organization_id",
|
||||
"references": {
|
||||
"name": "posts_organization_id_fkey",
|
||||
"table": "orgs",
|
||||
"schema": "public",
|
||||
"on_delete": null,
|
||||
"multitenancy": {
|
||||
"global": null,
|
||||
"attribute": null,
|
||||
"strategy": null
|
||||
},
|
||||
"primary_key?": true,
|
||||
"destination_attribute": "id",
|
||||
"on_update": null,
|
||||
"deferrable": false,
|
||||
"match_type": null,
|
||||
"match_with": null,
|
||||
"destination_attribute_default": null,
|
||||
"destination_attribute_generated": null
|
||||
},
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "uuid",
|
||||
"source": "author_id",
|
||||
"references": {
|
||||
"name": "posts_author_id_fkey",
|
||||
"table": "authors",
|
||||
"schema": "public",
|
||||
"on_delete": null,
|
||||
"multitenancy": {
|
||||
"global": null,
|
||||
"attribute": null,
|
||||
"strategy": null
|
||||
},
|
||||
"primary_key?": true,
|
||||
"destination_attribute": "id",
|
||||
"on_update": null,
|
||||
"deferrable": false,
|
||||
"match_type": null,
|
||||
"match_with": null,
|
||||
"destination_attribute_default": null,
|
||||
"destination_attribute_generated": null
|
||||
},
|
||||
"allow_nil?": true,
|
||||
"generated?": false,
|
||||
"primary_key?": false
|
||||
}
|
||||
],
|
||||
"table": "posts",
|
||||
"hash": "A602EBEA21CE56CC203A0FC8EA66D35D5FD2DA646411088CE343EF793C9D3E9C",
|
||||
"repo": "Elixir.AshPostgres.TestRepo",
|
||||
"identities": [
|
||||
{
|
||||
"name": "uniq_one_and_two",
|
||||
"keys": [
|
||||
"uniq_one",
|
||||
"uniq_two"
|
||||
],
|
||||
"base_filter": "type = 'sponsored'",
|
||||
"all_tenants?": false,
|
||||
"index_name": "posts_uniq_one_and_two_index"
|
||||
},
|
||||
{
|
||||
"name": "uniq_on_upper",
|
||||
"keys": [
|
||||
"UPPER(uniq_on_upper)"
|
||||
],
|
||||
"base_filter": "type = 'sponsored'",
|
||||
"all_tenants?": false,
|
||||
"index_name": "posts_uniq_on_upper_index"
|
||||
}
|
||||
],
|
||||
"schema": null,
|
||||
"check_constraints": [
|
||||
{
|
||||
"name": "price_must_be_positive",
|
||||
"check": "price > 0",
|
||||
"attribute": [
|
||||
"price"
|
||||
],
|
||||
"base_filter": "type = 'sponsored'"
|
||||
}
|
||||
],
|
||||
"custom_indexes": [
|
||||
{
|
||||
"message": "dude what the heck",
|
||||
"name": null,
|
||||
"table": null,
|
||||
"include": null,
|
||||
"fields": [
|
||||
{
|
||||
"type": "atom",
|
||||
"value": "uniq_custom_one"
|
||||
},
|
||||
{
|
||||
"type": "atom",
|
||||
"value": "uniq_custom_two"
|
||||
}
|
||||
],
|
||||
"prefix": null,
|
||||
"where": null,
|
||||
"unique": true,
|
||||
"all_tenants?": false,
|
||||
"concurrently": true,
|
||||
"error_fields": [
|
||||
"uniq_custom_one",
|
||||
"uniq_custom_two"
|
||||
],
|
||||
"nulls_distinct": true,
|
||||
"using": null
|
||||
}
|
||||
],
|
||||
"base_filter": "type = 'sponsored'",
|
||||
"multitenancy": {
|
||||
"global": null,
|
||||
"attribute": null,
|
||||
"strategy": null
|
||||
},
|
||||
"custom_statements": [],
|
||||
"has_create_action": true
|
||||
}
|
396
priv/resource_snapshots/test_repo/posts/20240524041750.json
Normal file
396
priv/resource_snapshots/test_repo/posts/20240524041750.json
Normal file
|
@ -0,0 +1,396 @@
|
|||
{
|
||||
"attributes": [
|
||||
{
|
||||
"default": "fragment(\"gen_random_uuid()\")",
|
||||
"size": null,
|
||||
"type": "uuid",
|
||||
"source": "id",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": true,
|
||||
"allow_nil?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "title_column",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "timestamptz(6)",
|
||||
"source": "datetime",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "bigint",
|
||||
"source": "score",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "boolean",
|
||||
"source": "public",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "citext",
|
||||
"source": "category",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "\"sponsored\"",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "type",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "bigint",
|
||||
"source": "price",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "\"0\"",
|
||||
"size": null,
|
||||
"type": "decimal",
|
||||
"source": "decimal",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "status",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "status",
|
||||
"source": "status_enum",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": [
|
||||
"array",
|
||||
"float"
|
||||
],
|
||||
"source": "point",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "custom_point",
|
||||
"source": "composite_point",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "map",
|
||||
"source": "stuff",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": [
|
||||
"array",
|
||||
"map"
|
||||
],
|
||||
"source": "list_of_stuff",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_one",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_two",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_custom_one",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_custom_two",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_on_upper",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "text",
|
||||
"source": "uniq_if_contains_foo",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": [
|
||||
"array",
|
||||
"text"
|
||||
],
|
||||
"source": "list_containing_nils",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||
"size": null,
|
||||
"type": "utc_datetime_usec",
|
||||
"source": "created_at",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": false
|
||||
},
|
||||
{
|
||||
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||
"size": null,
|
||||
"type": "timestamptz(6)",
|
||||
"source": "updated_at",
|
||||
"references": null,
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": false
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "uuid",
|
||||
"source": "organization_id",
|
||||
"references": {
|
||||
"name": "posts_organization_id_fkey",
|
||||
"table": "orgs",
|
||||
"on_delete": null,
|
||||
"on_update": null,
|
||||
"destination_attribute_generated": null,
|
||||
"destination_attribute_default": null,
|
||||
"primary_key?": true,
|
||||
"destination_attribute": "id",
|
||||
"multitenancy": {
|
||||
"global": null,
|
||||
"attribute": null,
|
||||
"strategy": null
|
||||
},
|
||||
"match_with": null,
|
||||
"match_type": null,
|
||||
"schema": "public",
|
||||
"deferrable": false
|
||||
},
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
},
|
||||
{
|
||||
"default": "nil",
|
||||
"size": null,
|
||||
"type": "uuid",
|
||||
"source": "author_id",
|
||||
"references": {
|
||||
"name": "posts_author_id_fkey",
|
||||
"table": "authors",
|
||||
"on_delete": null,
|
||||
"on_update": null,
|
||||
"destination_attribute_generated": null,
|
||||
"destination_attribute_default": null,
|
||||
"primary_key?": true,
|
||||
"destination_attribute": "id",
|
||||
"multitenancy": {
|
||||
"global": null,
|
||||
"attribute": null,
|
||||
"strategy": null
|
||||
},
|
||||
"match_with": null,
|
||||
"match_type": null,
|
||||
"schema": "public",
|
||||
"deferrable": false
|
||||
},
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"allow_nil?": true
|
||||
}
|
||||
],
|
||||
"table": "posts",
|
||||
"hash": "1C2BE60C682696F09AC2505B2B8844DFA449834F0E05B4C69D8E8F40B8C9CA89",
|
||||
"repo": "Elixir.AshPostgres.TestRepo",
|
||||
"multitenancy": {
|
||||
"global": null,
|
||||
"attribute": null,
|
||||
"strategy": null
|
||||
},
|
||||
"schema": null,
|
||||
"base_filter": "type = 'sponsored'",
|
||||
"custom_indexes": [
|
||||
{
|
||||
"message": "dude what the heck",
|
||||
"name": null,
|
||||
"table": null,
|
||||
"include": null,
|
||||
"where": null,
|
||||
"prefix": null,
|
||||
"fields": [
|
||||
{
|
||||
"type": "atom",
|
||||
"value": "uniq_custom_one"
|
||||
},
|
||||
{
|
||||
"type": "atom",
|
||||
"value": "uniq_custom_two"
|
||||
}
|
||||
],
|
||||
"unique": true,
|
||||
"nulls_distinct": true,
|
||||
"all_tenants?": false,
|
||||
"concurrently": true,
|
||||
"using": null,
|
||||
"error_fields": [
|
||||
"uniq_custom_one",
|
||||
"uniq_custom_two"
|
||||
]
|
||||
}
|
||||
],
|
||||
"has_create_action": true,
|
||||
"identities": [
|
||||
{
|
||||
"name": "uniq_on_upper",
|
||||
"keys": [
|
||||
"UPPER(uniq_on_upper)"
|
||||
],
|
||||
"where": null,
|
||||
"nils_distinct?": true,
|
||||
"base_filter": "type = 'sponsored'",
|
||||
"index_name": "posts_uniq_on_upper_index",
|
||||
"all_tenants?": false
|
||||
},
|
||||
{
|
||||
"name": "uniq_one_and_two",
|
||||
"keys": [
|
||||
"uniq_one",
|
||||
"uniq_two"
|
||||
],
|
||||
"where": null,
|
||||
"nils_distinct?": true,
|
||||
"base_filter": "type = 'sponsored'",
|
||||
"index_name": "posts_uniq_one_and_two_index",
|
||||
"all_tenants?": false
|
||||
},
|
||||
{
|
||||
"name": "uniq_if_contains_foo",
|
||||
"keys": [
|
||||
"uniq_if_contains_foo"
|
||||
],
|
||||
"where": "(uniq_if_contains_foo LIKE '%foo%')",
|
||||
"nils_distinct?": true,
|
||||
"base_filter": "type = 'sponsored'",
|
||||
"index_name": "posts_uniq_if_contains_foo_index",
|
||||
"all_tenants?": false
|
||||
}
|
||||
],
|
||||
"custom_statements": [],
|
||||
"check_constraints": [
|
||||
{
|
||||
"name": "price_must_be_positive",
|
||||
"check": "price > 0",
|
||||
"attribute": [
|
||||
"price"
|
||||
],
|
||||
"base_filter": "type = 'sponsored'"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
defmodule AshPostgres.TestRepo.Migrations.MigrateResources25 do
|
||||
@moduledoc """
|
||||
Updates resources based on their most recent snapshots.
|
||||
|
||||
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||
"""
|
||||
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:posts) do
|
||||
add(:uniq_on_upper, :text)
|
||||
end
|
||||
|
||||
create(
|
||||
unique_index(:posts, ["UPPER(uniq_on_upper)"],
|
||||
where: "type = 'sponsored'",
|
||||
name: "posts_uniq_on_upper_index"
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def down do
|
||||
drop_if_exists(
|
||||
unique_index(:posts, ["UPPER(uniq_on_upper)"], name: "posts_uniq_on_upper_index")
|
||||
)
|
||||
|
||||
alter table(:posts) do
|
||||
remove(:uniq_on_upper)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,54 @@
|
|||
defmodule AshPostgres.TestRepo.Migrations.MigrateResources26 do
|
||||
@moduledoc """
|
||||
Updates resources based on their most recent snapshots.
|
||||
|
||||
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||
"""
|
||||
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:posts) do
|
||||
add(:uniq_if_contains_foo, :text)
|
||||
end
|
||||
|
||||
drop_if_exists(
|
||||
unique_index(:posts, [:"UPPER(uniq_on_upper)"], name: "posts_uniq_on_upper_index")
|
||||
)
|
||||
|
||||
create(
|
||||
unique_index(:posts, ["UPPER(uniq_on_upper)"],
|
||||
where: "type = 'sponsored'",
|
||||
name: "posts_uniq_on_upper_index"
|
||||
)
|
||||
)
|
||||
|
||||
create(
|
||||
unique_index(:posts, [:uniq_if_contains_foo],
|
||||
name: "posts_uniq_if_contains_foo_index",
|
||||
where: "((uniq_if_contains_foo LIKE '%foo%')) AND (type = 'sponsored')"
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def down do
|
||||
drop_if_exists(
|
||||
unique_index(:posts, [:uniq_if_contains_foo], name: "posts_uniq_if_contains_foo_index")
|
||||
)
|
||||
|
||||
drop_if_exists(
|
||||
unique_index(:posts, ["UPPER(uniq_on_upper)"], name: "posts_uniq_on_upper_index")
|
||||
)
|
||||
|
||||
create(
|
||||
unique_index(:posts, [:"UPPER(uniq_on_upper)"],
|
||||
where: "type = 'sponsored'",
|
||||
name: "posts_uniq_on_upper_index"
|
||||
)
|
||||
)
|
||||
|
||||
alter table(:posts) do
|
||||
remove(:uniq_if_contains_foo)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -155,15 +155,16 @@ defmodule AshPostgres.MigrationGeneratorTest do
|
|||
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")}
|
||||
assert file_contents =~
|
||||
~S{create unique_index(:posts, ["title"], name: "posts_title_index")}
|
||||
|
||||
# the migration creates unique_indexes based on the identities of the resource
|
||||
assert file_contents =~
|
||||
~S{create unique_index(:posts, [:title, :second_title], name: "posts_thing_index")}
|
||||
~S{create unique_index(:posts, ["second_title", "title"], name: "posts_thing_index")}
|
||||
|
||||
# the migration creates unique_indexes using the `source` on the attributes of the identity on the resource
|
||||
assert file_contents =~
|
||||
~S{create unique_index(:posts, [:title, :t_w_s], name: "posts_thing_with_source_index")}
|
||||
~S{create unique_index(:posts, ["t_w_s", "title"], name: "posts_thing_with_source_index")}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -177,11 +178,19 @@ defmodule AshPostgres.MigrationGeneratorTest do
|
|||
defposts do
|
||||
postgres do
|
||||
migration_types(second_title: {:varchar, 16})
|
||||
|
||||
identity_wheres_to_sql(second_title: "(second_title like '%foo%')")
|
||||
|
||||
schema("example")
|
||||
end
|
||||
|
||||
identities do
|
||||
identity(:title, [:title])
|
||||
|
||||
identity :second_title, [:second_title] do
|
||||
nils_distinct?(false)
|
||||
where expr(contains(second_title, "foo"))
|
||||
end
|
||||
end
|
||||
|
||||
attributes do
|
||||
|
@ -231,6 +240,9 @@ defmodule AshPostgres.MigrationGeneratorTest do
|
|||
|
||||
assert file_contents =~ ~S{create index(:posts, ["id"]}
|
||||
|
||||
assert file_contents =~
|
||||
~S{create unique_index(:posts, ["second_title"], name: "posts_second_title_index", prefix: "example", nulls_distinct: false, where: "(second_title like '%foo%')")}
|
||||
|
||||
# the migration adds the id, with its default
|
||||
assert file_contents =~
|
||||
~S[add :id, :uuid, null: false, default: fragment("gen_random_uuid()"), primary_key: true]
|
||||
|
@ -243,7 +255,7 @@ defmodule AshPostgres.MigrationGeneratorTest do
|
|||
|
||||
# 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")}
|
||||
~S{create unique_index(:posts, ["title"], name: "posts_title_index", prefix: "example")}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -703,18 +715,18 @@ defmodule AshPostgres.MigrationGeneratorTest do
|
|||
file1_content = File.read!(file1)
|
||||
|
||||
assert file1_content =~
|
||||
"create unique_index(:posts, [:title], name: \"posts_title_index\")"
|
||||
"create unique_index(:posts, [\"title\"], name: \"posts_title_index\")"
|
||||
|
||||
file2_content = File.read!(file2)
|
||||
|
||||
assert file2_content =~
|
||||
"drop_if_exists unique_index(:posts, [:title], name: \"posts_title_index\")"
|
||||
"drop_if_exists unique_index(:posts, [\"title\"], name: \"posts_title_index\")"
|
||||
|
||||
assert file2_content =~
|
||||
"create unique_index(:posts, [:name], name: \"posts_unique_name_index\")"
|
||||
"create unique_index(:posts, [\"name\"], name: \"posts_unique_name_index\")"
|
||||
|
||||
assert file2_content =~
|
||||
"create unique_index(:posts, [:title], name: \"posts_unique_title_index\")"
|
||||
"create unique_index(:posts, [\"title\"], name: \"posts_unique_title_index\")"
|
||||
end
|
||||
|
||||
test "when an attribute exists only on some of the resources that use the same table, it isn't marked as null: false" do
|
||||
|
@ -1073,7 +1085,7 @@ defmodule AshPostgres.MigrationGeneratorTest do
|
|||
assert [file] = Path.wildcard("test_migration_path/**/*_migrate_resources*.exs")
|
||||
|
||||
assert File.read!(file) =~
|
||||
~S{create unique_index(:users, [:name], name: "users_unique_name_index")}
|
||||
~S{create unique_index(:users, ["name"], name: "users_unique_name_index")}
|
||||
end
|
||||
|
||||
test "when modified, the foreign key is dropped before modification" do
|
||||
|
|
|
@ -60,6 +60,9 @@ defmodule AshPostgres.Test.Post do
|
|||
repo(AshPostgres.TestRepo)
|
||||
base_filter_sql("type = 'sponsored'")
|
||||
|
||||
calculations_to_sql(upper_thing: "UPPER(uniq_on_upper)")
|
||||
identity_wheres_to_sql(uniq_if_contains_foo: "(uniq_if_contains_foo LIKE '%foo%')")
|
||||
|
||||
check_constraints do
|
||||
check_constraint(:price, "price_must_be_positive",
|
||||
message: "yo, bad price",
|
||||
|
@ -186,6 +189,11 @@ defmodule AshPostgres.Test.Post do
|
|||
|
||||
identities do
|
||||
identity(:uniq_one_and_two, [:uniq_one, :uniq_two])
|
||||
identity(:uniq_on_upper, [:upper_thing])
|
||||
|
||||
identity(:uniq_if_contains_foo, [:uniq_if_contains_foo]) do
|
||||
where expr(contains(title, "foo"))
|
||||
end
|
||||
end
|
||||
|
||||
attributes do
|
||||
|
@ -219,6 +227,8 @@ defmodule AshPostgres.Test.Post do
|
|||
attribute(:uniq_two, :string, public?: true)
|
||||
attribute(:uniq_custom_one, :string, public?: true)
|
||||
attribute(:uniq_custom_two, :string, public?: true)
|
||||
attribute(:uniq_on_upper, :string, public?: true)
|
||||
attribute(:uniq_if_contains_foo, :string, public?: true)
|
||||
|
||||
attribute :list_containing_nils, {:array, :string} do
|
||||
public?(true)
|
||||
|
@ -335,6 +345,8 @@ defmodule AshPostgres.Test.Post do
|
|||
end
|
||||
|
||||
calculations do
|
||||
calculate(:upper_thing, :string, expr(fragment("UPPER(?)", uniq_on_upper)))
|
||||
|
||||
calculate(
|
||||
:author_has_post_with_follower_named_fred,
|
||||
:boolean,
|
||||
|
|
Loading…
Reference in a new issue