fix: add back in inner join detection logic

This commit is contained in:
Zach Daniel 2021-03-04 22:50:12 -05:00
parent ff588ca7d6
commit 0b7817e420

View file

@ -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