2022-12-02 14:24:49 +13:00
|
|
|
defmodule AshPostgres.Transformers.PreventMultidimensionalArrayAggregates do
|
2023-09-23 08:14:25 +12:00
|
|
|
@moduledoc false
|
2022-12-02 14:24:49 +13:00
|
|
|
use Spark.Dsl.Transformer
|
|
|
|
alias Spark.Dsl.Transformer
|
|
|
|
|
|
|
|
def after_compile?, do: true
|
|
|
|
|
|
|
|
def transform(dsl) do
|
|
|
|
resource = Transformer.get_persisted(dsl, :module)
|
|
|
|
|
|
|
|
dsl
|
|
|
|
|> Ash.Resource.Info.aggregates()
|
|
|
|
|> Stream.filter(&(&1.kind in [:list, :first]))
|
|
|
|
|> Stream.filter(& &1.field)
|
|
|
|
|> Enum.each(fn aggregate ->
|
|
|
|
related = Ash.Resource.Info.related(resource, aggregate.relationship_path)
|
2023-01-12 01:51:12 +13:00
|
|
|
type = Ash.Resource.Info.field(related, aggregate.field).type
|
2022-12-02 14:24:49 +13:00
|
|
|
|
|
|
|
case type do
|
|
|
|
{:array, _} ->
|
|
|
|
raise Spark.Error.DslError,
|
|
|
|
module: resource,
|
|
|
|
path: [:aggregates, aggregate.name],
|
|
|
|
message: """
|
|
|
|
Aggregate not supported.
|
|
|
|
|
|
|
|
Aggregate #{inspect(resource)}.#{aggregate.name} is not supported, because its type is `#{aggregate.kind}`, and the destination attribute is an array.
|
|
|
|
|
|
|
|
Postgres does not support multidimensional arrays with differing lengths internally. In the future we may be able to remove this restriction
|
|
|
|
for the `:first` type aggregate, but likely never for `:list`. In the meantime, you will have to use a custom calculation to get this data.
|
|
|
|
"""
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
:ok
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2023-11-15 06:59:42 +13:00
|
|
|
repo = AshPostgres.DataLayer.Info.repo(dsl, :mutate)
|
2022-12-02 14:24:49 +13:00
|
|
|
|
|
|
|
cond do
|
|
|
|
match?({:error, _}, Code.ensure_compiled(repo)) ->
|
|
|
|
{:error, "Could not find repo module #{repo}"}
|
|
|
|
|
|
|
|
repo.__adapter__() != Ecto.Adapters.Postgres ->
|
|
|
|
{:error, "Expected a repo using the postgres adapter `Ecto.Adapters.Postgres`"}
|
|
|
|
|
|
|
|
true ->
|
|
|
|
{:ok, dsl}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|