Skip to content

Commit

Permalink
fix(sync-service): Fix bug with logical operators with 3 or more argu…
Browse files Browse the repository at this point in the history
…ments (#2225)

Fix for #2224
  • Loading branch information
robacourt authored Jan 13, 2025
1 parent 278bc4d commit e29724e
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/stale-bats-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@core/sync-service": patch
---

Fix bug with WHERE clauses with logical operators (AND, OR, etc.) with 3 or more conditions chained together
17 changes: 15 additions & 2 deletions packages/sync-service/lib/electric/replication/eval/parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,15 @@ defmodule Electric.Replication.Eval.Parser do
:NOT_EXPR -> {&Kernel.not/1, "not"}
end

maybe_reduce(%Func{
%Func{
implementation: fun,
name: name,
type: :bool,
args: args,
location: expr.location
})
}
|> to_binary_operators()
|> maybe_reduce()

%{location: loc} = node ->
{:error, {loc, "#{internal_node_to_error(node)} is not castable to bool"}}
Expand Down Expand Up @@ -1120,4 +1122,15 @@ defmodule Electric.Replication.Eval.Parser do
{:ok, arg}
end)
end

# to_binary_operators/1 coverts a function with more than two arguments to a tree of binary operators
defp to_binary_operators(%Func{args: [_, _]} = func) do
# The function is already a binary operator (it has two arguments) so just return the function
func
end

defp to_binary_operators(%Func{args: [arg | args]} = func) do
# The function has more than two arguments, reduce the number of arguments to two: the first argument and a binary operator
%Func{func | args: [arg, to_binary_operators(%Func{func | args: args})]}
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ defmodule Electric.Replication.Eval.RunnerTest do
|> Runner.execute(%{["test"] => "test"})
end

test "can evaluate AND expression with multiple conditions" do
assert {:ok, true} =
~S|test > 1 AND test = 2 AND test < 3|
|> Parser.parse_and_validate_expression!(%{["test"] => :int4})
|> Runner.execute(%{["test"] => 2})
end

test "should work with array types" do
assert {:ok, [[1, 2], [3, 4]]} =
~S|ARRAY[ARRAY[1, x], ARRAY['3', 2 + 2]]|
Expand Down

0 comments on commit e29724e

Please sign in to comment.