fix: don't optimize across or boundaries

This commit is contained in:
Zach Daniel 2023-04-20 17:30:44 -06:00
parent 2e5f045f72
commit b67c2b7f34
2 changed files with 21 additions and 17 deletions

View file

@ -804,15 +804,15 @@ defmodule Ash.Filter do
defp simple_eq?(_, _), do: false
def find_value(expr, pred) do
do_find(expr, pred, true)
do_find(expr, pred, true, true)
end
@doc "Find an expression inside of a filter that matches the provided predicate"
def find(expr, pred) do
do_find(expr, pred, false)
def find(expr, pred, ors? \\ true) do
do_find(expr, pred, false, ors?)
end
defp do_find(expr, pred, value?) do
defp do_find(expr, pred, value?, ors?) do
if value = pred.(expr) do
if value? do
value
@ -822,22 +822,26 @@ defmodule Ash.Filter do
else
case expr do
%__MODULE__{expression: expression} ->
find(expression, pred)
find(expression, pred, ors?)
%Not{expression: expression} ->
find(expression, pred)
find(expression, pred, ors?)
%BooleanExpression{left: left, right: right} ->
find(left, pred) || find(right, pred)
%BooleanExpression{op: op, left: left, right: right} ->
if op == :or && !ors? do
nil
else
find(left, pred, ors?) || find(right, pred, ors?)
end
%Call{args: arguments} ->
Enum.find(arguments, &find(&1, pred))
Enum.find(arguments, &find(&1, pred, ors?))
%{__operator__?: true, left: left, right: right} ->
find(left, pred) || find(right, pred)
find(left, pred, ors?) || find(right, pred, ors?)
%{__function__?: true, arguments: arguments} ->
Enum.find(arguments, &find(&1, pred))
Enum.find(arguments, &find(&1, pred, ors?))
_ ->
nil

View file

@ -220,15 +220,15 @@ defmodule Ash.Query.BooleanExpression do
end
def optimized_new(
op,
%__MODULE__{left: left, right: right} = left_expr,
:and,
%__MODULE__{op: :and, left: left, right: right} = left_expr,
right_expr,
op
) do
case right_expr do
%In{} = in_op ->
with {:left, nil} <- {:left, Ash.Filter.find(left, &simplify?(&1, in_op))},
{:right, nil} <- {:right, Ash.Filter.find(right, &simplify?(&1, in_op))} do
with {:left, nil} <- {:left, Ash.Filter.find(left, &simplify?(&1, in_op), false)},
{:right, nil} <- {:right, Ash.Filter.find(right, &simplify?(&1, in_op), false)} do
do_new(op, left_expr, in_op)
else
{:left, _} ->
@ -240,9 +240,9 @@ defmodule Ash.Query.BooleanExpression do
%Eq{} = eq_op ->
with {:left, nil} <-
{:left, Ash.Filter.find(left, &simplify?(&1, eq_op))},
{:left, Ash.Filter.find(left, &simplify?(&1, eq_op), false)},
{:right, nil} <-
{:right, Ash.Filter.find(right, &simplify?(&1, eq_op))} do
{:right, Ash.Filter.find(right, &simplify?(&1, eq_op), false)} do
do_new(op, left_expr, eq_op)
else
{:left, _} ->