mirror of
https://github.com/ash-project/ash_postgres.git
synced 2024-09-20 05:23:18 +12:00
fix: add back in inner join detection logic
This commit is contained in:
parent
ff588ca7d6
commit
0b7817e420
1 changed files with 79 additions and 51 deletions
|
@ -661,68 +661,96 @@ defmodule AshPostgres.DataLayer do
|
|||
})
|
||||
end
|
||||
|
||||
@known_inner_join_operators [
|
||||
Eq,
|
||||
GreaterThan,
|
||||
GreaterThanOrEqual,
|
||||
In,
|
||||
IsNil,
|
||||
LessThanOrEqual,
|
||||
LessThan,
|
||||
NotEq
|
||||
]
|
||||
|> Enum.map(&Module.concat(Ash.Query.Operator, &1))
|
||||
|
||||
@known_inner_join_functions [
|
||||
Ago,
|
||||
Contains,
|
||||
IsNil
|
||||
]
|
||||
|> Enum.map(&Module.concat(Ash.Query.Function, &1))
|
||||
|
||||
@known_inner_join_predicates @known_inner_join_functions ++ @known_inner_join_operators
|
||||
|
||||
# For consistency's sake, this logic was removed.
|
||||
# We can revisit it sometime though.
|
||||
defp can_inner_join?(_, _), do: false
|
||||
# defp can_inner_join?(path, expr, seen_an_or? \\ false)
|
||||
defp can_inner_join?(path, expr, seen_an_or? \\ false)
|
||||
|
||||
# defp can_inner_join?(path, %{expression: expr}, seen_an_or?),
|
||||
# do: can_inner_join?(path, expr, seen_an_or?)
|
||||
defp can_inner_join?(path, %{expression: expr}, seen_an_or?),
|
||||
do: can_inner_join?(path, expr, seen_an_or?)
|
||||
|
||||
# defp can_inner_join?(_path, expr, _seen_an_or?) when expr in [nil, true, false], do: true
|
||||
defp can_inner_join?(_path, expr, _seen_an_or?) when expr in [nil, true, false], do: true
|
||||
|
||||
# defp can_inner_join?(path, %BooleanExpression{op: :and, left: left, right: right}, seen_an_or?) do
|
||||
# can_inner_join?(path, left, seen_an_or?) || can_inner_join?(path, right, seen_an_or?)
|
||||
# end
|
||||
defp can_inner_join?(path, %BooleanExpression{op: :and, left: left, right: right}, seen_an_or?) do
|
||||
can_inner_join?(path, left, seen_an_or?) || can_inner_join?(path, right, seen_an_or?)
|
||||
end
|
||||
|
||||
# defp can_inner_join?(path, %BooleanExpression{op: :or, left: left, right: right}, _) do
|
||||
# can_inner_join?(path, left, true) && can_inner_join?(path, right, true)
|
||||
# end
|
||||
defp can_inner_join?(path, %BooleanExpression{op: :or, left: left, right: right}, _) do
|
||||
can_inner_join?(path, left, true) && can_inner_join?(path, right, true)
|
||||
end
|
||||
|
||||
# defp can_inner_join?(
|
||||
# path,
|
||||
# %Not{expression: %BooleanExpression{op: :or, left: left, right: right}},
|
||||
# seen_an_or?
|
||||
# ) do
|
||||
# can_inner_join?(
|
||||
# path,
|
||||
# %BooleanExpression{
|
||||
# op: :and,
|
||||
# left: %Not{expression: left},
|
||||
# right: %Not{expression: right}
|
||||
# },
|
||||
# # We count `not` as having seen an `or` to be conservative.
|
||||
# # The reason for this is that `id = 1 or not(id = 1)`
|
||||
# true
|
||||
# )
|
||||
# end
|
||||
defp can_inner_join?(
|
||||
path,
|
||||
%Not{expression: %BooleanExpression{op: :or, left: left, right: right}},
|
||||
seen_an_or?
|
||||
) do
|
||||
can_inner_join?(
|
||||
path,
|
||||
%BooleanExpression{
|
||||
op: :and,
|
||||
left: %Not{expression: left},
|
||||
right: %Not{expression: right}
|
||||
},
|
||||
seen_an_or?
|
||||
)
|
||||
end
|
||||
|
||||
# defp can_inner_join?(path, %Not{expression: expression}, seen_an_or?) do
|
||||
# can_inner_join?(path, expression, seen_an_or?)
|
||||
# end
|
||||
defp can_inner_join?(path, %Not{expression: expression}, seen_an_or?) do
|
||||
can_inner_join?(path, expression, seen_an_or?)
|
||||
end
|
||||
|
||||
# defp can_inner_join?(
|
||||
# search_path,
|
||||
# %{__operator__?: true, left: %Ref{relationship_path: relationship_path}},
|
||||
# seen_an_or?
|
||||
# )
|
||||
# when search_path == relationship_path do
|
||||
# not seen_an_or?
|
||||
# end
|
||||
defp can_inner_join?(
|
||||
search_path,
|
||||
%struct{__operator__?: true, left: %Ref{relationship_path: relationship_path}},
|
||||
seen_an_or?
|
||||
)
|
||||
when search_path == relationship_path and struct in @known_inner_join_predicates do
|
||||
not seen_an_or?
|
||||
end
|
||||
|
||||
# defp can_inner_join?(
|
||||
# search_path,
|
||||
# %{__function__?: true, arguments: arguments},
|
||||
# seen_an_or?
|
||||
# ) do
|
||||
# if Enum.any?(arguments, &match?(%Ref{relationship_path: ^search_path}, &1)) do
|
||||
# not seen_an_or?
|
||||
# else
|
||||
# true
|
||||
# end
|
||||
# end
|
||||
defp can_inner_join?(
|
||||
search_path,
|
||||
%struct{__operator__?: true, right: %Ref{relationship_path: relationship_path}},
|
||||
seen_an_or?
|
||||
)
|
||||
when search_path == relationship_path and struct in @known_inner_join_predicates do
|
||||
not seen_an_or?
|
||||
end
|
||||
|
||||
# defp can_inner_join?(_, _, _), do: true
|
||||
defp can_inner_join?(
|
||||
search_path,
|
||||
%struct{__function__?: true, arguments: arguments},
|
||||
seen_an_or?
|
||||
)
|
||||
when struct in @known_inner_join_predicates do
|
||||
if Enum.any?(arguments, &match?(%Ref{relationship_path: ^search_path}, &1)) do
|
||||
not seen_an_or?
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
defp can_inner_join?(_, _, _), do: false
|
||||
|
||||
@impl true
|
||||
def add_aggregate(query, aggregate, _resource) do
|
||||
|
|
Loading…
Reference in a new issue