Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions packages/sync-service/test/electric/shapes/filter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,38 @@ defmodule Electric.Shapes.FilterTest do
assert Filter.indexed_shape?(shape)
end

test "returns true for OR shapes when both branches are indexed" do
shape = Shape.new!("t1", where: "id = 7 OR id = 8", inspector: @inspector)
test "returns true for the indexed where clause forms supported by WhereCondition" do
[
"id = 7",
"7 = id",
"id = 7 AND id > 6",
"id > 6 AND id = 7",
"id = 7 AND number = 11",
"an_array @> '{5, 11, 29}'",
"'{5, 11, 29}' <@ an_array",
"7 = ANY(an_array)",
"1 = ANY(an_array) AND id = 7",
"id = 7 AND 1 = ANY(an_array)",
"id IN (1, 2, 3)",
"id = 1 OR id = 2",
"id = 1 AND (number = 2 OR number = 3)",
"(id = 1 OR id = 2) AND number = 3",
"(id = 1 AND number > 2) OR (id = 1 AND number < 1)",
"id IN (SELECT id FROM another_table)",
"NOT id IN (SELECT id FROM another_table)",
"id IN (SELECT id FROM another_table) OR id = 1",
"(id, number) IN (SELECT id, number FROM another_table)"
]
|> Enum.each(fn where ->
shape =
Shape.new!("table",
where: where,
inspector: @inspector,
feature_flags: ["allow_subqueries"]
)

assert Filter.indexed_shape?(shape)
assert Filter.indexed_shape?(shape), "#{where} should be indexed"
end)
end

test "returns false for OR shapes when one branch is not indexed" do
Expand Down Expand Up @@ -664,6 +692,7 @@ defmodule Electric.Shapes.FilterTest do
@shape_count 1000
@max_reductions 1300

@tag :performance
test "where clause in the form `field = const` is optimised" do
filter = Filter.new()

Expand All @@ -688,6 +717,7 @@ defmodule Electric.Shapes.FilterTest do
end)
end

@tag :performance
test "where clause in the form `field = const AND another_condition` is optimised" do
filter = Filter.new()

Expand All @@ -712,6 +742,7 @@ defmodule Electric.Shapes.FilterTest do
end)
end

@tag :performance
test "where clause in the form `a_condition AND field = const` is optimised" do
filter = Filter.new()

Expand All @@ -736,6 +767,7 @@ defmodule Electric.Shapes.FilterTest do
end)
end

@tag :performance
test "where clause in the form `field1 = const1 AND field2 = const2` is optimised for lots of const1 values" do
filter = Filter.new()

Expand All @@ -758,6 +790,7 @@ defmodule Electric.Shapes.FilterTest do
end)
end

@tag :performance
test "where clause in the form `field1 = const1 AND field2 = const2` is optimised for lots of const2 values" do
filter = Filter.new()

Expand All @@ -780,6 +813,7 @@ defmodule Electric.Shapes.FilterTest do
end)
end

@tag :performance
test "where clause in the form `array_field @> const_array` is optimised" do
# The optimisation for `@>` is less performant than the other optimisations,
# however it performs well with lots of shapes. While it can't do
Expand Down Expand Up @@ -827,6 +861,7 @@ defmodule Electric.Shapes.FilterTest do
end)
end

@tag :performance
test "where clause in the form `const = ANY(array_field)` is optimised" do
# Same shape count as @> but higher budget per shape because the ANY
# AST is deeper to pattern-match through the planner
Expand Down Expand Up @@ -854,6 +889,7 @@ defmodule Electric.Shapes.FilterTest do
end)
end

@tag :performance
test "where clause in the form `field = const1 OR field = const2` is optimised" do
max_reductions = @max_reductions * 2
filter = Filter.new()
Expand Down
7 changes: 6 additions & 1 deletion packages/sync-service/test/test_helper.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
# Registry.start_link(name: Electric.Application.process_registry(), keys: :unique)

ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter])
ExUnit.start(assert_receive_timeout: 400, exclude: [:slow, :oracle], capture_log: true)

ExUnit.start(
assert_receive_timeout: 400,
exclude: [:slow, :oracle, :performance],
capture_log: true
)

# Start electric_client application directly, bypassing OTP's dependency resolution.
# This avoids a circular dependency: electric_client has :electric as an optional dep,
Expand Down
Loading