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..77fc6c9 --- /dev/null +++ b/test/sql/correctness.test @@ -0,0 +1,111 @@ +# name: test/sql/correctness.test +# group: [sql] + +# 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: 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 + +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..8e13651 --- /dev/null +++ b/test/sql/plan_negative.test @@ -0,0 +1,151 @@ +# name: test/sql/plan_negative.test +# group: [sql] + +# 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..8dd1b04 --- /dev/null +++ b/test/sql/plan_positive.test @@ -0,0 +1,148 @@ +# name: test/sql/plan_positive.test +# group: [sql] + +# 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