mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
fix: don't eager evaluate exists erroneously
This commit is contained in:
parent
ca61d56fcf
commit
fa172b3be2
2 changed files with 153 additions and 39 deletions
|
@ -116,6 +116,12 @@ defmodule Ash.Filter.Runtime do
|
||||||
[] ->
|
[] ->
|
||||||
[record]
|
[record]
|
||||||
|
|
||||||
|
%Ash.NotLoaded{} = not_loaded ->
|
||||||
|
[Ash.Resource.set_metadata(record, %{unflattened_rels: %{rel => not_loaded}})]
|
||||||
|
|
||||||
|
%Ash.ForbiddenField{} = forbidden ->
|
||||||
|
[Ash.Resource.set_metadata(record, %{unflattened_rels: %{rel => forbidden}})]
|
||||||
|
|
||||||
value when is_list(value) ->
|
value when is_list(value) ->
|
||||||
flatten_many_to_many(record, rel, value, rest)
|
flatten_many_to_many(record, rel, value, rest)
|
||||||
|
|
||||||
|
@ -740,6 +746,9 @@ defmodule Ash.Filter.Runtime do
|
||||||
%Ash.NotLoaded{} ->
|
%Ash.NotLoaded{} ->
|
||||||
:unknown
|
:unknown
|
||||||
|
|
||||||
|
%Ash.ForbiddenField{} ->
|
||||||
|
:unknown
|
||||||
|
|
||||||
other ->
|
other ->
|
||||||
{:ok, other}
|
{:ok, other}
|
||||||
end
|
end
|
||||||
|
@ -827,6 +836,13 @@ defmodule Ash.Filter.Runtime do
|
||||||
) do
|
) do
|
||||||
if load do
|
if load do
|
||||||
case Map.get(record, load) do
|
case Map.get(record, load) do
|
||||||
|
%Ash.ForbiddenField{} ->
|
||||||
|
if unknown_on_unknown_refs? do
|
||||||
|
:unknown
|
||||||
|
else
|
||||||
|
{:ok, nil}
|
||||||
|
end
|
||||||
|
|
||||||
%Ash.NotLoaded{} ->
|
%Ash.NotLoaded{} ->
|
||||||
if unknown_on_unknown_refs? do
|
if unknown_on_unknown_refs? do
|
||||||
:unknown
|
:unknown
|
||||||
|
@ -974,9 +990,24 @@ defmodule Ash.Filter.Runtime do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_related(
|
||||||
|
%Ash.ForbiddenField{},
|
||||||
|
_,
|
||||||
|
unknown_on_unknown_refs?,
|
||||||
|
_join_filters,
|
||||||
|
_parent_stack,
|
||||||
|
_domain
|
||||||
|
) do
|
||||||
|
if unknown_on_unknown_refs? do
|
||||||
|
:unknown
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def get_related(
|
def get_related(
|
||||||
%Ash.NotLoaded{},
|
%Ash.NotLoaded{},
|
||||||
[],
|
_,
|
||||||
unknown_on_unknown_refs?,
|
unknown_on_unknown_refs?,
|
||||||
_join_filters,
|
_join_filters,
|
||||||
_parent_stack,
|
_parent_stack,
|
||||||
|
@ -1004,6 +1035,125 @@ defmodule Ash.Filter.Runtime do
|
||||||
when is_list(records) do
|
when is_list(records) do
|
||||||
{join_filter, rest_join_filters} = Map.pop(join_filters, [])
|
{join_filter, rest_join_filters} = Map.pop(join_filters, [])
|
||||||
|
|
||||||
|
rest_join_filters =
|
||||||
|
Enum.reduce(rest_join_filters, %{}, fn {path, filter}, acc ->
|
||||||
|
if List.starts_with?(path, [key]) do
|
||||||
|
Map.put(acc, Enum.drop(path, 1), filter)
|
||||||
|
else
|
||||||
|
acc
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
filtered =
|
||||||
|
if Map.has_key?(join_filters, []) do
|
||||||
|
filter_matches(domain, records, join_filter,
|
||||||
|
parent: parent_stack,
|
||||||
|
unknown_on_unknown_refs?: unknown_on_unknown_refs?
|
||||||
|
)
|
||||||
|
else
|
||||||
|
{:ok, records}
|
||||||
|
end
|
||||||
|
|
||||||
|
case filtered do
|
||||||
|
{:ok, matches} ->
|
||||||
|
matches
|
||||||
|
|> Enum.reduce_while([], fn match, acc ->
|
||||||
|
case Map.get(match, key) do
|
||||||
|
%Ash.NotLoaded{} when unknown_on_unknown_refs? ->
|
||||||
|
{:halt, :unknown}
|
||||||
|
|
||||||
|
%Ash.ForbiddenField{} when unknown_on_unknown_refs? ->
|
||||||
|
{:halt, :unknown}
|
||||||
|
|
||||||
|
nil when unknown_on_unknown_refs? ->
|
||||||
|
{:halt, :unknown}
|
||||||
|
|
||||||
|
nil ->
|
||||||
|
{:cont, acc}
|
||||||
|
|
||||||
|
match_keys ->
|
||||||
|
match_keys
|
||||||
|
|> List.wrap()
|
||||||
|
|> Enum.reduce_while([], fn this_match, inner_acc ->
|
||||||
|
case get_related(
|
||||||
|
this_match,
|
||||||
|
rest,
|
||||||
|
unknown_on_unknown_refs?,
|
||||||
|
rest_join_filters,
|
||||||
|
[match | parent_stack],
|
||||||
|
domain
|
||||||
|
) do
|
||||||
|
:unknown -> {:halt, :unknown}
|
||||||
|
value -> {:cont, inner_acc ++ List.wrap(value)}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|> case do
|
||||||
|
:unknown -> {:halt, :unknown}
|
||||||
|
list -> {:cont, acc ++ list}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
if unknown_on_unknown_refs? do
|
||||||
|
:unknown
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_related(
|
||||||
|
record,
|
||||||
|
[key | _] = path,
|
||||||
|
unknown_on_unknown_refs?,
|
||||||
|
join_filters,
|
||||||
|
parent_stack,
|
||||||
|
domain
|
||||||
|
) do
|
||||||
|
case Map.get(record, key) do
|
||||||
|
%Ash.NotLoaded{} when unknown_on_unknown_refs? ->
|
||||||
|
:unknown
|
||||||
|
|
||||||
|
%Ash.ForbiddenField{} when unknown_on_unknown_refs? ->
|
||||||
|
:unknown
|
||||||
|
|
||||||
|
nil when unknown_on_unknown_refs? ->
|
||||||
|
:unknown
|
||||||
|
|
||||||
|
_value ->
|
||||||
|
case get_related(
|
||||||
|
[record],
|
||||||
|
path,
|
||||||
|
unknown_on_unknown_refs?,
|
||||||
|
join_filters,
|
||||||
|
parent_stack,
|
||||||
|
domain
|
||||||
|
) do
|
||||||
|
:unknown ->
|
||||||
|
if unknown_on_unknown_refs? do
|
||||||
|
:unknown
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
related ->
|
||||||
|
List.wrap(related)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def old_get_related(
|
||||||
|
records,
|
||||||
|
[key | rest],
|
||||||
|
unknown_on_unknown_refs?,
|
||||||
|
join_filters,
|
||||||
|
parent_stack,
|
||||||
|
domain
|
||||||
|
)
|
||||||
|
when is_list(records) do
|
||||||
|
{join_filter, rest_join_filters} = Map.pop(join_filters, [])
|
||||||
|
|
||||||
rest_join_filters =
|
rest_join_filters =
|
||||||
Enum.reduce(rest_join_filters, %{}, fn {path, filter}, acc ->
|
Enum.reduce(rest_join_filters, %{}, fn {path, filter}, acc ->
|
||||||
if List.starts_with?(path, [key]) do
|
if List.starts_with?(path, [key]) do
|
||||||
|
@ -1065,43 +1215,6 @@ defmodule Ash.Filter.Runtime do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_related(
|
|
||||||
record,
|
|
||||||
[key | _] = path,
|
|
||||||
unknown_on_unknown_refs?,
|
|
||||||
join_filters,
|
|
||||||
parent_stack,
|
|
||||||
domain
|
|
||||||
) do
|
|
||||||
case Map.get(record, key) do
|
|
||||||
%Ash.NotLoaded{} when unknown_on_unknown_refs? ->
|
|
||||||
:unknown
|
|
||||||
|
|
||||||
nil when unknown_on_unknown_refs? ->
|
|
||||||
:unknown
|
|
||||||
|
|
||||||
_value ->
|
|
||||||
case get_related(
|
|
||||||
[record],
|
|
||||||
path,
|
|
||||||
unknown_on_unknown_refs?,
|
|
||||||
join_filters,
|
|
||||||
parent_stack,
|
|
||||||
domain
|
|
||||||
) do
|
|
||||||
:unknown ->
|
|
||||||
if unknown_on_unknown_refs? do
|
|
||||||
:unknown
|
|
||||||
else
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
|
|
||||||
related ->
|
|
||||||
List.wrap(related)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp parent_stack(nil), do: []
|
defp parent_stack(nil), do: []
|
||||||
defp parent_stack(%resource{}), do: [resource]
|
defp parent_stack(%resource{}), do: [resource]
|
||||||
defp parent_stack(value) when is_list(value), do: value
|
defp parent_stack(value) when is_list(value), do: value
|
||||||
|
|
3
mix.exs
3
mix.exs
|
@ -328,7 +328,8 @@ defmodule Ash.MixProject do
|
||||||
defp deps do
|
defp deps do
|
||||||
[
|
[
|
||||||
# DSLs
|
# DSLs
|
||||||
{:spark, "~> 2.1 and >= 2.1.18"},
|
# {:spark, "~> 2.1 and >= 2.1.18"},
|
||||||
|
{:spark, path: "../spark", override: true},
|
||||||
# Ash resources are backed by ecto scheams
|
# Ash resources are backed by ecto scheams
|
||||||
{:ecto, "~> 3.7"},
|
{:ecto, "~> 3.7"},
|
||||||
# Used by the ETS data layer
|
# Used by the ETS data layer
|
||||||
|
|
Loading…
Reference in a new issue