From be7fe2723ff8db438e441d02ede020d2905635db Mon Sep 17 00:00:00 2001 From: jianhongshi123 Date: Wed, 1 Jul 2026 20:21:25 -0500 Subject: [PATCH 1/3] Add SQLLogicTest for Robust --- test/README.md | 11 +-- test/sql/correctness.test | 130 +++++++++++++++++++++++++++++++ test/sql/plan_negative.test | 150 ++++++++++++++++++++++++++++++++++++ test/sql/plan_positive.test | 147 +++++++++++++++++++++++++++++++++++ 4 files changed, 433 insertions(+), 5 deletions(-) create mode 100644 test/sql/correctness.test create mode 100644 test/sql/plan_negative.test create mode 100644 test/sql/plan_positive.test diff --git a/test/README.md b/test/README.md index fb5e514..3898419 100644 --- a/test/README.md +++ b/test/README.md @@ -1,11 +1,12 @@ # Testing this extension -This directory contains all the tests for this extension. The `sql` directory holds tests that are written as [SQLLogicTests](https://duckdb.org/dev/sqllogictest/intro.html). DuckDB aims to have most its tests in this format as SQL statements, so for the quack extension, this should probably be the goal too. +This directory contains all the tests for Robust extension. The `sql` directory holds tests that are written as [SQLLogicTests](https://duckdb.org/dev/sqllogictest/intro.html). DuckDB aims to have most of its tests in this format as SQL statements, so for the Robust extension, this should probably be the goal too. + +The current test files are: +- `test/sql/correctness.test`: checks that several representative join shapes return the expected results across Robust setting combinations. +- `test/sql/plan_positive.test`: checks that Robust filter operators are inserted for several eligible joins across Robust setting combinations. +- `test/sql/plan_negative.test`: checks that Robust filter operators are not inserted for serveral ineligible plans across Robust setting combinations. The root makefile contains targets to build and run all of these tests. To run the SQLLogicTests: ```bash make test -``` -or -```bash -make test_debug ``` \ No newline at end of file diff --git a/test/sql/correctness.test b/test/sql/correctness.test new file mode 100644 index 0000000..5dfbac8 --- /dev/null +++ b/test/sql/correctness.test @@ -0,0 +1,130 @@ +# name: test/sql/correctness.test +# group: [robust] +# run Robust correctness tests across settings combinations. + +statement ok +LOAD 'build/release/extension/robust/robust.duckdb_extension'; + +statement ok +SET disabled_optimizers = 'join_filter_pushdown'; + +statement ok +CREATE TABLE t1(k12 INTEGER, k13 INTEGER, k14 INTEGER, v1 INTEGER); + +statement ok +CREATE TABLE t2(k12 INTEGER, k23 INTEGER, k24 INTEGER, v2 INTEGER); + +statement ok +CREATE TABLE t3(k13 INTEGER, k23 INTEGER, k34 INTEGER, v3 INTEGER); + +statement ok +CREATE TABLE t4(k14 INTEGER, k24 INTEGER, k34 INTEGER, v4 INTEGER); + +statement ok +INSERT INTO t1 VALUES + (1, 10, 100, 1), + (2, 20, NULL, 2), + (2, 30, 300, 3), + (NULL, 30, 400, 4), + (5, 40, 700, 5); + +statement ok +INSERT INTO t2 VALUES + (1, 1000, 10000, 10), + (2, 2000, 20000, 20), + (3, 3000, 30000, 30), + (NULL, 4000, 40000, 40); + +statement ok +INSERT INTO t3 VALUES + (10, 1000, 100000, 100), + (20, 2000, 200000, 200), + (20, 6000, 500000, 300), + (40, 4000, NULL, 400), + (NULL, 5000, 500000, 500); + +statement ok +INSERT INTO t4 VALUES + (100, 10000, 100000, 1000), + (200, 20000, 200000, 2000), + (300, 21000, 200000, 3000), + (400, 40000, 300000, 4000), + (NULL, 50000, 500000, 5000); + +foreach heuristic join_order largest_root + +foreach pass_mode both forward_only + +foreach flip_roots true false + +statement ok +SET robust_heuristic = '${heuristic}'; + +statement ok +SET robust_pass_mode = '${pass_mode}'; + +statement ok +SET robust_flip_roots = ${flip_roots}; + +# Correctness: two-way join +query III +SELECT count(*), sum(t1.v1), sum(t2.v2) +FROM t1, t2 +WHERE t1.k12 = t2.k12; +---- +3 6 50 + +# Correctness: three-table chain join +query IIII +SELECT count(*), sum(t1.v1), sum(t2.v2), sum(t3.v3) +FROM t1, t2, t3 +WHERE t1.k12 = t2.k12 + AND t2.k23 = t3.k23; +---- +3 6 50 500 + +# Correctness: triangle join +query IIII +SELECT count(*), sum(t2.v2), sum(t3.v3), sum(t4.v4) +FROM t2, t3, t4 +WHERE t2.k23 = t3.k23 + AND t3.k34 = t4.k34 + AND t2.k24 = t4.k24; +---- +2 30 300 3000 + +# Correctness: four-table chain join +query IIIII +SELECT count(*), sum(t1.v1), sum(t2.v2), sum(t3.v3), sum(t4.v4) +FROM t1, t2, t3, t4 +WHERE t1.k12 = t2.k12 + AND t2.k23 = t3.k23 + AND t3.k34 = t4.k34; +---- +5 11 90 900 11000 + +# Correctness: star join +query IIIII +SELECT count(*), sum(t1.v1), sum(t2.v2), sum(t3.v3), sum(t4.v4) +FROM t1, t2, t3, t4 +WHERE t1.k12 = t2.k12 + AND t2.k23 = t3.k23 + AND t2.k24 = t4.k24; +---- +3 6 50 500 5000 + +# Correctness: two separate two-way equality join connected by a inequality join +query IIIII +SELECT count(*), sum(t1.v1), sum(t2.v2), sum(t3.v3), sum(t4.v4) +FROM t1, t2, t3, t4 +WHERE t1.k12 = t2.k12 + AND t2.k23 < t3.k23 + AND t3.k34 = t4.k34; +---- +8 14 120 2800 35000 + +endloop + +endloop + +endloop \ No newline at end of file diff --git a/test/sql/plan_negative.test b/test/sql/plan_negative.test new file mode 100644 index 0000000..d32c973 --- /dev/null +++ b/test/sql/plan_negative.test @@ -0,0 +1,150 @@ +# name: test/sql/plan_negative.test +# group: [robust] +# run plans which Robust filters should not be inserted across settings combinations. + +statement ok +LOAD 'build/release/extension/robust/robust.duckdb_extension'; + +statement ok +SET disabled_optimizers = 'join_filter_pushdown'; + +statement ok +CREATE TABLE t1(k12 INTEGER, k13 INTEGER, k14 INTEGER, v1 INTEGER); + +statement ok +CREATE TABLE t2(k12 INTEGER, k23 INTEGER, k24 INTEGER, v2 INTEGER); + +statement ok +CREATE TABLE t3(k13 INTEGER, k23 INTEGER, k34 INTEGER, v3 INTEGER); + +statement ok +CREATE TABLE t4(k14 INTEGER, k24 INTEGER, k34 INTEGER, v4 INTEGER); + +statement ok +INSERT INTO t1 VALUES + (1, 10, 100, 1), + (2, 20, NULL, 2), + (2, 30, 300, 3), + (NULL, 30, 400, 4), + (5, 40, 700, 5); + +statement ok +INSERT INTO t2 VALUES + (1, 1000, 10000, 10), + (2, 2000, 20000, 20), + (3, 3000, 30000, 30), + (NULL, 4000, 40000, 40); + +statement ok +INSERT INTO t3 VALUES + (10, 1000, 100000, 100), + (20, 2000, 200000, 200), + (20, 6000, 500000, 300), + (40, 4000, NULL, 400), + (NULL, 5000, 500000, 500); + +statement ok +INSERT INTO t4 VALUES + (100, 10000, 100000, 1000), + (200, 20000, 200000, 2000), + (300, 21000, 200000, 3000), + (400, 40000, 300000, 4000), + (NULL, 50000, 500000, 5000); + +foreach heuristic join_order largest_root + +foreach pass_mode both forward_only + +foreach flip_roots true false + +statement ok +SET robust_heuristic = '${heuristic}'; + +statement ok +SET robust_pass_mode = '${pass_mode}'; + +statement ok +SET robust_flip_roots = ${flip_roots}; + +# Negative: no join appear +query II +EXPLAIN SELECT count(*) +FROM t1 +---- +physical_plan :.*CREATE_FILTER.* + +query II +EXPLAIN SELECT count(*) +FROM t1 +---- +physical_plan :.*PROBE_FILTER.* + +# Negative: two-way join +query II +EXPLAIN SELECT count(*) +FROM t1, t2 +WHERE t1.k12 = t2.k12; +---- +physical_plan :.*CREATE_FILTER.* + +query II +EXPLAIN SELECT count(*) +FROM t1, t2 +WHERE t1.k12 = t2.k12; +---- +physical_plan :.*PROBE_FILTER.* + +# Negative: two-way join and tree tables appear +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3 +WHERE t1.k12 = t2.k12; +---- +physical_plan :.*CREATE_FILTER.* + +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3 +WHERE t1.k12 = t2.k12; +---- +physical_plan :.*PROBE_FILTER.* + +# Negative: two joins appear but both not equality join +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3 +WHERE t1.k12 < t2.k12 +AND t2.k23 < t3.k23; +---- +physical_plan :.*CREATE_FILTER.* + +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3 +WHERE t1.k12 < t2.k12 +AND t2.k23 < t3.k23; +---- +physical_plan :.*PROBE_FILTER.* + +# Negative: two joins appear but one is not equality join +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3 +WHERE t1.k12 < t2.k12 +AND t2.k23 = t3.k23; +---- +physical_plan :.*CREATE_FILTER.* + +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3 +WHERE t1.k12 < t2.k12 +AND t2.k23 = t3.k23; +---- +physical_plan :.*PROBE_FILTER.* + +endloop + +endloop + +endloop \ No newline at end of file diff --git a/test/sql/plan_positive.test b/test/sql/plan_positive.test new file mode 100644 index 0000000..e10b35a --- /dev/null +++ b/test/sql/plan_positive.test @@ -0,0 +1,147 @@ +# name: test/sql/plan_positive.test +# group: [robust] +# run plans which Robust filters should be inserted across settings combinations. + +statement ok +LOAD 'build/release/extension/robust/robust.duckdb_extension'; + +statement ok +SET disabled_optimizers = 'join_filter_pushdown'; + +statement ok +CREATE TABLE t1(k12 INTEGER, k13 INTEGER, k14 INTEGER, v1 INTEGER); + +statement ok +CREATE TABLE t2(k12 INTEGER, k23 INTEGER, k24 INTEGER, v2 INTEGER); + +statement ok +CREATE TABLE t3(k13 INTEGER, k23 INTEGER, k34 INTEGER, v3 INTEGER); + +statement ok +CREATE TABLE t4(k14 INTEGER, k24 INTEGER, k34 INTEGER, v4 INTEGER); + +statement ok +INSERT INTO t1 VALUES + (1, 10, 100, 1), + (2, 20, NULL, 2), + (2, 30, 300, 3), + (NULL, 30, 400, 4), + (5, 40, 700, 5); + +statement ok +INSERT INTO t2 VALUES + (1, 1000, 10000, 10), + (2, 2000, 20000, 20), + (3, 3000, 30000, 30), + (NULL, 4000, 40000, 40); + +statement ok +INSERT INTO t3 VALUES + (10, 1000, 100000, 100), + (20, 2000, 200000, 200), + (20, 6000, 500000, 300), + (40, 4000, NULL, 400), + (NULL, 5000, 500000, 500); + +statement ok +INSERT INTO t4 VALUES + (100, 10000, 100000, 1000), + (200, 20000, 200000, 2000), + (300, 21000, 200000, 3000), + (400, 40000, 300000, 4000), + (NULL, 50000, 500000, 5000); + +foreach heuristic join_order largest_root + +foreach pass_mode both forward_only + +foreach flip_roots true false + +statement ok +SET robust_heuristic = '${heuristic}'; + +statement ok +SET robust_pass_mode = '${pass_mode}'; + +statement ok +SET robust_flip_roots = ${flip_roots}; + +# Positive: three-table chain join +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3 +WHERE t1.k12 = t2.k12 + AND t2.k23 = t3.k23; +---- +physical_plan :.*CREATE_FILTER.* + +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3 +WHERE t1.k12 = t2.k12 + AND t2.k23 = t3.k23; +---- +physical_plan :.*PROBE_FILTER.* + +# Correctness: triangle join +query II +EXPLAIN SELECT count(*) +FROM t2, t3, t4 +WHERE t2.k23 = t3.k23 + AND t3.k34 = t4.k34 + AND t2.k24 = t4.k24; +---- +physical_plan :.*CREATE_FILTER.* + +query II +EXPLAIN SELECT count(*) +FROM t2, t3, t4 +WHERE t2.k23 = t3.k23 + AND t3.k34 = t4.k34 + AND t2.k24 = t4.k24; +---- +physical_plan :.*PROBE_FILTER.* + +# Negative: four-table chain join +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3, t4 +WHERE t1.k12 = t2.k12 + AND t2.k23 = t3.k23 + AND t3.k34 = t4.k34; +---- +physical_plan :.*CREATE_FILTER.* + +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3, t4 +WHERE t1.k12 = t2.k12 + AND t2.k23 = t3.k23 + AND t3.k34 = t4.k34; +---- +physical_plan :.*PROBE_FILTER.* + +# Positive: star join +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3, t4 +WHERE t1.k12 = t2.k12 + AND t2.k23 = t3.k23 + AND t2.k24 = t4.k24; +---- +physical_plan :.*CREATE_FILTER.* + +query II +EXPLAIN SELECT count(*) +FROM t1, t2, t3, t4 +WHERE t1.k12 = t2.k12 + AND t2.k23 = t3.k23 + AND t2.k24 = t4.k24; +---- +physical_plan :.*PROBE_FILTER.* + +endloop + +endloop + +endloop \ No newline at end of file From df5442585852aa2686cc154a3f413a4577df7dc7 Mon Sep 17 00:00:00 2001 From: jianhongshi123 Date: Fri, 3 Jul 2026 20:30:28 -0500 Subject: [PATCH 2/3] Fix Format --- test/sql/correctness.test | 3 ++- test/sql/plan_negative.test | 3 ++- test/sql/plan_positive.test | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/sql/correctness.test b/test/sql/correctness.test index 5dfbac8..45ee181 100644 --- a/test/sql/correctness.test +++ b/test/sql/correctness.test @@ -1,5 +1,6 @@ # name: test/sql/correctness.test -# group: [robust] +# group: [sql] + # run Robust correctness tests across settings combinations. statement ok diff --git a/test/sql/plan_negative.test b/test/sql/plan_negative.test index d32c973..8e13651 100644 --- a/test/sql/plan_negative.test +++ b/test/sql/plan_negative.test @@ -1,5 +1,6 @@ # name: test/sql/plan_negative.test -# group: [robust] +# group: [sql] + # run plans which Robust filters should not be inserted across settings combinations. statement ok diff --git a/test/sql/plan_positive.test b/test/sql/plan_positive.test index e10b35a..8dd1b04 100644 --- a/test/sql/plan_positive.test +++ b/test/sql/plan_positive.test @@ -1,5 +1,6 @@ # name: test/sql/plan_positive.test -# group: [robust] +# group: [sql] + # run plans which Robust filters should be inserted across settings combinations. statement ok From 6b3601ef831c3835e89a19cb756ac6c747f69031 Mon Sep 17 00:00:00 2001 From: jianhongshi123 Date: Tue, 7 Jul 2026 16:20:12 -0500 Subject: [PATCH 3/3] restrict robust tests to currently supported join patterns --- test/sql/correctness.test | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/test/sql/correctness.test b/test/sql/correctness.test index 45ee181..77fc6c9 100644 --- a/test/sql/correctness.test +++ b/test/sql/correctness.test @@ -84,16 +84,6 @@ WHERE t1.k12 = t2.k12 ---- 3 6 50 500 -# Correctness: triangle join -query IIII -SELECT count(*), sum(t2.v2), sum(t3.v3), sum(t4.v4) -FROM t2, t3, t4 -WHERE t2.k23 = t3.k23 - AND t3.k34 = t4.k34 - AND t2.k24 = t4.k24; ----- -2 30 300 3000 - # Correctness: four-table chain join query IIIII SELECT count(*), sum(t1.v1), sum(t2.v2), sum(t3.v3), sum(t4.v4) @@ -114,16 +104,6 @@ WHERE t1.k12 = t2.k12 ---- 3 6 50 500 5000 -# Correctness: two separate two-way equality join connected by a inequality join -query IIIII -SELECT count(*), sum(t1.v1), sum(t2.v2), sum(t3.v3), sum(t4.v4) -FROM t1, t2, t3, t4 -WHERE t1.k12 = t2.k12 - AND t2.k23 < t3.k23 - AND t3.k34 = t4.k34; ----- -8 14 120 2800 35000 - endloop endloop