should be it

This commit is contained in:
2025-10-24 19:21:19 -05:00
parent a4b23fc57c
commit f09560c7b1
14047 changed files with 3161551 additions and 1 deletions

View File

@@ -0,0 +1,27 @@
# name: test/optimizer/pushdown/distinct_from_pushdown.test
# description: Test DISTINCT FROM pushed down into scans
# group: [pushdown]
statement ok
create table test as select 'tst' as tst;
query I
select * from test where tst is not distinct from 'a' or tst is not distinct from 'b';
----
query I
select * from test where tst is distinct from 'a' or tst is distinct from 'b';
----
tst
statement ok
create table test2 as select 42 as tst;
query I
select * from test2 where tst is not distinct from 12 or tst is not distinct from 13;
----
query I
select * from test2 where tst is distinct from 12 or tst is distinct from 13
----
42

View File

@@ -0,0 +1,65 @@
# name: test/optimizer/pushdown/filter_cannot_pushdown.test
# description: Test Filter Can Not Push Down
# group: [pushdown]
# test some expressions which have side effects can not push down
statement ok
PRAGMA explain_output = OPTIMIZED_ONLY;
query II
explain select rnd from (select random()) as t(rnd) where rnd < 0.5;
----
logical_opt <REGEX>:.*rnd < 0.5.*
query II
explain select * from (select rnd from (select random()) as t(rnd) where rnd < 0.5);
----
logical_opt <REGEX>:.*rnd < 0.5.*
statement ok
CREATE TABLE t(a integer, b integer, c integer);
query II
explain select rnd, a from (select random() as rnd, a from t) where rnd < 0.3 and a > 1;
----
logical_opt <REGEX>:.*rnd < 0.3.*
query II
explain select * from (select rnd, a from (select random() as rnd, a from t) where rnd < 0.3 and a > 1);
----
logical_opt <REGEX>:.*rnd < 0.3.*
query II
explain select rnd, a from (select random() as rnd, a from t) where rnd < 0.3 and a > 1;
----
logical_opt <!REGEX>:.*a > 1.*
query II
explain select rnd, a from (select random(), 2 as 'a') as t(rnd, a) where rnd < 1 and a > 0;
----
logical_opt <REGEX>:.*rnd < 1.0.*
statement ok
create table t1 as select range as a, random() as b from range(10);
query II
explain select a, b from (select random(), a, b from t1) as t(rnd, a, b) where rnd < 1 and a > 0;
----
logical_opt <REGEX>:.*rnd < 1.0.*
loop i 1 100
query I
WITH combined_results AS (
SELECT rnd > 0.5 as result FROM (SELECT random()) AS t(rnd) WHERE rnd < 0.5
UNION ALL
SELECT false
)
SELECT result
FROM combined_results
GROUP BY result;
----
False
endloop

View File

@@ -0,0 +1,15 @@
# name: test/optimizer/pushdown/issue_16104.test
# description: Test expressions in filter preserve the order in Push Down
# group: [pushdown]
statement ok
PRAGMA explain_output = OPTIMIZED_ONLY;
statement ok
WITH random_data AS (
SELECT random() * 2 AS col_double
FROM generate_series(1, 100)
)
SELECT *
FROM random_data
WHERE abs(col_double) < 1 AND acos(col_double) > 0;

View File

@@ -0,0 +1,18 @@
# name: test/optimizer/pushdown/issue_16671.test
# description: Test keeping alias in filter pushdown
# group: [pushdown]
require json
statement ok
set variable W to '{"a":[1,2], "b":[2,4]}';
query II
from (values (1,2),(2,3),(3,1),(1,2),(2,3),(2,4), (3,2)) test (a,b)
select *
where (getvariable('W') -> '/'||alias(columns(getvariable('W').json_keys())))
.json_contains(columns(getvariable('W').json_keys()));
----
1 2
1 2
2 4

View File

@@ -0,0 +1,15 @@
# name: test/optimizer/pushdown/issue_16863.test
# description: Test right join filter lost in filter pushdown
# group: [pushdown]
statement ok
CREATE TABLE t1 (c1 DATE);
statement ok
INSERT INTO t1 (c1) VALUES ('2023-10-31');
query II
SELECT t1.c1, (t1.c1 IS NULL)
FROM t1 RIGHT JOIN (SELECT NULL AS col0 FROM t1) AS sub0 ON true
WHERE (t1.c1 IS NULL);
----

View File

@@ -0,0 +1,35 @@
# name: test/optimizer/pushdown/issue_17042.test
# description: Test left join filter lost in filter pushdown
# group: [pushdown]
statement ok
pragma explain_output = optimized_only
statement ok
CREATE TABLE t2(c1 INTEGER);
statement ok
CREATE TABLE t0(c1 DOUBLE);
statement ok
INSERT INTO t0(c1) VALUES (0.1);
statement ok
INSERT INTO t2(c1) VALUES (2);
query II
SELECT * FROM t2 LEFT JOIN t0 ON true WHERE ((t0.c1<t2.c1) IS NULL);
----
statement ok
INSERT INTO t2(c1) VALUES (NULL);
query II
SELECT * FROM t2 LEFT JOIN t0 ON true WHERE ((t0.c1<t2.c1) IS NULL);
----
NULL 0.1
query II
explain SELECT * FROM t2 LEFT JOIN t0 ON true WHERE (t0.c1 is distinct from t2.c1) and (t2.c1 > t0.c1);
----
logical_opt <REGEX>:.*INNER.*CAST\(c1 AS DOUBLE\) > c1.*CAST\(c1 AS DOUBLE\) IS.*DISTINCT FROM c1.*

View File

@@ -0,0 +1,27 @@
# name: test/optimizer/pushdown/issue_18202.test
# description: Test join filter pushdown with join conditions reordered
# group: [pushdown]
statement ok
CREATE TABLE t0(c0 FLOAT , c1 CHAR);
statement ok
INSERT INTO t0 VALUES(0.001, 'WORLD');
statement ok
CREATE VIEW v0(c0) AS SELECT 1522975040 FROM t0;
statement ok
INSERT INTO t0 VALUES(3.14, 'ABCDE');
statement ok
CREATE INDEX t0i0 ON t0(c1);
statement ok
INSERT INTO t0(c1, c0) VALUES('WORLD', 3.1415);
statement ok
UPDATE t0 SET c1 = 'HELLO';
statement ok
explain SELECT v0, c1 FROM t0 JOIN v0 ON((c1) < (CAST(v0.c0 AS CHAR))) WHERE (NOT((v0) = ((CASE WHEN t0.c0 THEN c1 END))));

View File

@@ -0,0 +1,46 @@
# name: test/optimizer/pushdown/issue_18603.test
# description: Test filter pushdown with conflict comparison filters
# group: [pushdown]
statement ok
pragma enable_verification
statement ok
CREATE TABLE t0(c0 INT, c1 BOOLEAN);
statement ok
CREATE TABLE t1(c0 INT);
statement ok
INSERT INTO t0(c0, c1) VALUES (0, 0);
statement ok
INSERT INTO t1(c0) VALUES (1);
# test different order of filters
query III
SELECT * FROM t0 INNER JOIN t1 ON (t0.c1 > t0.c0) AND (t1.c0 > t0.c0) AND (t0.c0 < 7) AND (t0.c1 = t0.c0);
----
query II
EXPLAIN SELECT * FROM t0 INNER JOIN t1 ON (t0.c1 > t0.c0) AND (t1.c0 > t0.c0) AND (t0.c0 < 7) AND (t0.c1 = t0.c0);
----
physical_plan <REGEX>:.*EMPTY_RESULT.*
query II
EXPLAIN SELECT * FROM t0 INNER JOIN t1 ON (t0.c1 > t0.c0) AND (t1.c0 > t0.c0) AND (t0.c0 < 7) AND (t0.c1 = t0.c0);
----
physical_plan <!REGEX>:.*c0 > c0.*
query II
EXPLAIN SELECT * FROM t0 INNER JOIN t1 ON (t0.c1 > t0.c0) AND (t1.c0 > t0.c0) AND (t0.c0 < 7) AND (t0.c1 = t0.c0);
----
physical_plan <!REGEX>:.*c0 < 7.*
query III
SELECT * FROM t0 INNER JOIN t1 ON (t0.c1 = t0.c0) AND (t0.c1 > t0.c0) AND (t1.c0 > t0.c0) AND (t0.c0 < 7);
----
query III
SELECT * FROM t0 INNER JOIN t1 ON (t0.c1 = t0.c0) AND (t0.c0 < 7) AND (t0.c1 > t0.c0) AND (t1.c0 > t0.c0);
----

View File

@@ -0,0 +1,58 @@
# name: test/optimizer/pushdown/issue_18653.test
# description: Performance issue with CROSS JOIN and LATERAL JOIN combined with unnest and json_each. Filter should be pushed down to reduce the joined rows
# group: [pushdown]
statement ok
PRAGMA enable_verification
statement ok
create table test_table as
select s.i as id, [1, 2, 3]::bigint[] as values from generate_series(1, 1000000) as s(i);
statement ok
create index test_table_id_idx on test_table(id);
query II
explain analyze
select id, value
from test_table
cross join unnest(values) as values(value) where id = 87100;
----
analyzed_plan <REGEX>:.*LEFT_DELIM_JOIN.*FILTER.*
query II
select id, value
from test_table
cross join unnest(values) as values(value) where id = 87100;
----
87100 3
87100 2
87100 1
query II
explain analyze
select id, value
from test_table t
left join lateral unnest(t.values) as value on true
where id = 87100;
----
analyzed_plan <REGEX>:.*LEFT_DELIM_JOIN.*FILTER.*
require json
statement ok
create table test_table2 as
select s.i as id, '{"key1": 1, "key2": 2, "key3": 3}'::JSON as values
from generate_series(1, 1000000) as s(i);
statement ok
create index test_table2_id_idx on test_table2(id);
query II
explain analyze
select t.id, key, value
from test_table2 t
cross join json_each(t.values) as kv(key, value)
where t.id = 87100;
----
analyzed_plan <REGEX>:.*LEFT_DELIM_JOIN.*Filters:.*id=87100.*

View File

@@ -0,0 +1,21 @@
# name: test/optimizer/pushdown/join_filter_pushdown.test
# description: Test sampling of larger relations
# group: [pushdown]
statement ok
CREATE TABLE t1 AS FROM VALUES
('619d9199-bc25-41d7-803e-1fa801b4b952'::UUID, NULL::VARCHAR),
('1ada8361-c20b-4e9f-9c8e-15689039cc75'::UUID, '91'::VARCHAR),
('f5a8a7d8-6bc5-4337-a296-d52078156051'::UUID, NULL::VARCHAR) t(s, i);
statement ok
CREATE TABLE t2 as from values
('Int'),
('91'),
('13',),
('sst',) t(v);
statement ok
SELECT t1.s
FROM t1
LEFT JOIN t2 ON t1.i = t2.v;

View File

@@ -0,0 +1,101 @@
# name: test/optimizer/pushdown/no_mark_to_semi_if_mark_index_is_projected.test
# description: No mark to semi conversion if the mark join index is projected
# group: [pushdown]
statement ok
CREATE OR REPLACE TABLE BaseData AS (
SELECT
'10' AS my_key,
'20' AS parent_key,
'30' AS payload,
'40' as foo,
'50' as foo2,
'60' as foo3
);
# Original query
query III
WITH
Example AS (
SELECT
c.my_key,
(c.parent_key IN (SELECT my_key FROM BaseData)) AS parentExists,
p.my_key IS NOT NULL AS parentExists2,
FROM BaseData AS c
LEFT JOIN BaseData AS p ON c.parent_key = p.my_key
)
SELECT *
FROM Example
WHERE parentExists
----
# original query no CTE
query III
SELECT
c.my_key,
(c.parent_key IN (SELECT my_key FROM BaseData)) AS parentExists,
p.my_key IS NOT NULL AS parentExists2,
FROM BaseData AS c
LEFT JOIN BaseData AS p ON c.parent_key = p.my_key
WHERE parentExists;
----
# original query but the CTE is a subquery
query III
SELECT *
FROM (SELECT
c.my_key,
(c.parent_key IN (SELECT my_key FROM BaseData)) AS parentExists,
p.my_key IS NOT NULL AS parentExists2,
FROM BaseData AS c
LEFT JOIN BaseData AS p ON c.parent_key = p.my_key
)
WHERE parentExists;
----
statement ok
PRAGMA explain_output='optimized_only'
query II
EXPLAIN
WITH Example AS (
SELECT
c.my_key,
(c.parent_key IN (SELECT my_key FROM BaseData)) AS parentExists,
p.my_key IS NOT NULL AS parentExists2,
FROM BaseData AS c
LEFT JOIN BaseData AS p ON c.parent_key = p.my_key
)
SELECT *
FROM Example
WHERE parentExists
----
logical_opt <REGEX>:.*MARK.*
query II
EXPLAIN
WITH Example AS (
SELECT
c.my_key,
(c.parent_key IN (SELECT my_key FROM BaseData)) AS parentExists,
p.my_key IS NOT NULL AS parentExists2,
FROM BaseData AS c
LEFT JOIN BaseData AS p ON c.parent_key = p.my_key
)
SELECT *
FROM Example
WHERE parentExists
----
logical_opt <!REGEX>:.*SEMI.*
statement ok
create table t0 as select range a from range(300);
statement ok
create table t2 as select range b from range(50000);
query I
select sum(in_alias::INT) FROM (select a in (select b from t2) as in_alias from t0) where in_alias;
----
300

View File

@@ -0,0 +1,66 @@
# name: test/optimizer/pushdown/parquet_or_pushdown.test
# description: Test Parquet With Pushing Down of OR Filters
# group: [pushdown]
require parquet
# FIXME: re-enable when or pushdown is fixed
mode skip
# Multiple column in the root OR node, don't push down
query II
EXPLAIN SELECT tbl.a, tbl.b FROM "data/parquet-testing/arrow/alltypes_plain.parquet" tbl(a, b) WHERE a=1 OR b=false
----
physical_plan <!REGEX>:.*PARQUET_SCAN.*Filters:.*
# Single column in the root OR node
query II
EXPLAIN SELECT tbl.a FROM "data/parquet-testing/arrow/alltypes_plain.parquet" tbl(a) WHERE a=1 OR a=2
----
physical_plan <REGEX>:.*PARQUET_SCAN.*Filters: a=1 OR a=2.*
# Single column + root OR node with AND
query II
EXPLAIN SELECT tbl.a FROM "data/parquet-testing/arrow/alltypes_plain.parquet" tbl(a) WHERE a=1 OR (a>3 AND a<5)
----
physical_plan <REGEX>:.*PARQUET_SCAN.*Filters: a=1 OR a>3 AND a<5|.*
# Single column multiple ORs
query II
EXPLAIN SELECT tbl.a FROM "data/parquet-testing/arrow/alltypes_plain.parquet" tbl(a) WHERE a=1 OR a>3 OR a<5
----
physical_plan <REGEX>:.*PARQUET_SCAN.*Filters: a=1 OR a>3 OR a<5|.*
# Testing not equal
query II
EXPLAIN SELECT tbl.a FROM "data/parquet-testing/arrow/alltypes_plain.parquet" tbl(a) WHERE a!=1 OR a>3 OR a<2
----
physical_plan <REGEX>:.*PARQUET_SCAN.*Filters: a!=1 OR a>3 OR a<2|.*
# Multiple OR filters connected with ANDs
query II
EXPLAIN SELECT tbl.a, tbl.b, tbl.c FROM "data/parquet-testing/arrow/alltypes_plain.parquet" tbl(a,b,c) WHERE (a<2 OR a>3) AND (a=1 OR a=4) AND (b=false OR c=1);
----
physical_plan <REGEX>:.*PARQUET_SCAN.*Filters: a<2 OR a>3 AND a=1.*OR a=4.*
# Testing the number of rows filtered (column "a" has eight values: 0 .. 7)
statement ok
PRAGMA enable_profiling
# should return 2 rows: 0 and 7
query II
EXPLAIN ANALYZE SELECT tbl.a FROM "data/parquet-testing/arrow/alltypes_plain.parquet" tbl(a) WHERE a<1 OR a>6;
----
analyzed_plan <REGEX>:.*PARQUET_SCAN.*Filters: a<1 OR a>6.*2[ \t].*
# should return 1 row: 0
query II
EXPLAIN ANALYZE SELECT tbl.a FROM "data/parquet-testing/arrow/alltypes_plain.parquet" tbl(a) WHERE a<1 OR a>8;
----
analyzed_plan <REGEX>:.*PARQUET_SCAN.*Filters: a<1 OR a>8.*1[ \t].*

View File

@@ -0,0 +1,42 @@
# name: test/optimizer/pushdown/pushdown_after_statistics.test
# description: Test Table Filter Push Down
# group: [pushdown]
statement ok
set explain_output='optimized_only';
statement ok
create table big_probe as select range%3000 a, range%4000 b from range(100000);
statement ok
create table into_semi as select range%300 c from range(10000);
statement ok
create table into_get as select range d from range(100);
# the IN filter becomes a mark join. We should keep it a mark join at this point
query II
explain select * from big_probe, into_semi, into_get where c in (1, 3, 5, 7, 10, 14, 16, 20, 22) and c = d and a = c;
----
logical_opt <REGEX>:.*MARK.*
statement ok
create table mark_join_build as select range e from range(200);
# Now the in filter is a semi join.
query II
explain select * from big_probe, into_semi, into_get where c in (select e from mark_join_build) and c = d and a = c;
----
logical_opt <REGEX>:.*SEMI.*
statement ok
select t1.a from big_probe t1
where t1.a in
(select t2.b
from big_probe t2
where t2.b in (1206, 1202, 1322, 1204, 1370)
and t2.b not in (select t2_filter.a from big_probe t2_filter));

View File

@@ -0,0 +1,181 @@
# name: test/optimizer/pushdown/pushdown_filter_on_coalesced_equal_outer_join_keys.test
# description: Test pushdown of filters on coalesced join keys compared for equality in the join condition
# group: [pushdown]
# enable query verification
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE t1 AS FROM VALUES
(1),
(2),
(NULL),
(4) t(id);
statement ok
CREATE TABLE t2 AS FROM VALUES
(1),
(3),
(NULL),
(4) t(id);
statement ok
CREATE TABLE t3 AS FROM VALUES
(1),
(3),
(NULL),
(4) t(id);
query I
SELECT id FROM t1 FULL OUTER JOIN t2 USING (id) WHERE id >=2 ORDER BY id
----
2
3
4
# should find all NULL rows correctly
query I
SELECT id FROM t1 FULL OUTER JOIN t2 USING (id) WHERE id IS NULL
----
NULL
NULL
statement ok
set explain_output='optimized_only';
# optimized plan is equivalent to plan with manually pushed down filter
query II nosort single_join
EXPLAIN SELECT id
FROM (SELECT id FROM t1) FULL OUTER JOIN (SELECT id FROM t2) USING (id)
WHERE id >= 2
----
query II nosort single_join
EXPLAIN SELECT id
FROM (SELECT id FROM t1 WHERE id >= 2) FULL OUTER JOIN (SELECT id FROM t2 WHERE id >= 2) USING (id)
----
# optimized plan is equivalent to plan with manually pushed down filter when using IS NULL as a filtering predicate
query II nosort single_join_isnull_filter
EXPLAIN SELECT id
FROM (SELECT id FROM t1) FULL OUTER JOIN (SELECT id FROM t2) USING (id)
WHERE id IS NULL
----
query II nosort single_join_isnull_filter
EXPLAIN SELECT id
FROM (SELECT id FROM t1 WHERE id IS NULL) FULL OUTER JOIN (SELECT id FROM t2 WHERE id IS NULL) USING (id)
----
# optimized plan is equivalent to plan with manually pushed down filter in the case of multiple joins
query II nosort multiple_joins
EXPLAIN SELECT id
FROM (SELECT id FROM t1) FULL OUTER JOIN (SELECT id FROM t2) USING (id) FULL OUTER JOIN (SELECT id FROM t3) USING (id) WHERE id >= 2;
----
query II nosort multiple_joins
EXPLAIN SELECT id
FROM (SELECT id FROM t1 WHERE id >= 2)
FULL OUTER JOIN (SELECT id FROM t2 WHERE id >= 2) USING (id)
FULL OUTER JOIN (SELECT id FROM t3 WHERE id >= 2) USING (id);
----
# should pushdown filter with multiple occurrences of the same coalesced join keys
query II nosort multiple_occurrences_of_the_same_coalesced_join_keys
EXPLAIN
SELECT id FROM (SELECT id FROM t1) FULL OUTER JOIN (SELECT id FROM t2) USING (id)
WHERE id >= 2 OR id IN (1, 4) OR id IS NULL;
----
query II nosort multiple_occurrences_of_the_same_coalesced_join_keys
EXPLAIN SELECT id
FROM (SELECT id FROM t1 WHERE id >= 2 OR id IN (1, 4) OR id IS NULL)
FULL OUTER JOIN (SELECT id FROM t2 WHERE id >= 2 OR id IN (1, 4) OR id IS NULL)
USING (id);
----
# should pushdown filter containing different but equivalent coalesced join keys
query II
EXPLAIN SELECT t1.id, t2.id
FROM t1 FULL OUTER JOIN t2 ON t1.id = t2.id
WHERE COALESCE(t1.id, t2.id) >= 2 OR COALESCE(t2.id, t1.id) IS NULL;
----
logical_opt <REGEX>:.*SEQ_SCAN.*Filters.*\(id >= 2\) OR \(id IS NULL\).*
# should not pushdown a volatile filter
query II
EXPLAIN SELECT id
FROM t1 FULL OUTER JOIN t2 USING (id)
WHERE trunc(random() * id) >= 2
----
logical_opt <!REGEX>:.*SEQ_SCAN.*Filters.*
# coalescing right and left is optimized like coalescing left and right
query II nosort left_right_coalesce
EXPLAIN SELECT t1.id, t2.id
FROM t1 FULL OUTER JOIN t2 ON t1.id = t2.id
WHERE COALESCE(t1.id, t2.id) >= 2;
----
query II nosort left_right_coalesce
EXPLAIN SELECT t1.id, t2.id
FROM t1 FULL OUTER JOIN t2 ON t1.id = t2.id
WHERE COALESCE(t2.id, t1.id) >= 2;
----
statement ok
CREATE TABLE t4 AS FROM VALUES
(1, 20),
(2, NULL),
(3, 16)
t(id, a);
statement ok
CREATE TABLE t5 AS FROM VALUES
(1, NULL),
(1, 30)
t(id, a);
# should not pushdown filter on coalesced keys that also depend on other columns
query II
EXPLAIN SELECT id FROM t1 FULL OUTER JOIN t4 USING (id) WHERE id = a;
----
logical_opt <!REGEX>:.*SEQ_SCAN.*Filters.*
# should not pushdown single filter containing coalesced keys from different join conditions
query II
EXPLAIN SELECT id FROM t4 FULL OUTER JOIN t5 USING (id, a) WHERE id IN (a, 1)
----
logical_opt <!REGEX>:.*SEQ_SCAN.*Filters.*
query II nosort nullif_func_join_keys
EXPLAIN SELECT *
FROM (SELECT id, a FROM t4 WHERE nullif(id, a) < 3) AS t4
FULL OUTER JOIN (SELECT id, a FROM t5 WHERE nullif(id, a) < 3) AS t5
ON nullif(t4.id, t4.a) = nullif(t5.id, t5.a)
----
# should pushdown filter containing coalesced keys which are functions of the input table
query II nosort nullif_func_join_keys
EXPLAIN SELECT *
FROM (SELECT id, a FROM t4) AS t4
FULL OUTER JOIN (SELECT id, a FROM t5) AS t5
ON nullif(t4.id, t4.a) = nullif(t5.id, t5.a)
WHERE coalesce(nullif(t4.id, t4.a), nullif(t5.id, t5.a)) < 3;
----
query II nosort list_func_join_keys
EXPLAIN SELECT * FROM
(SELECT id, a FROM t4) AS t4
FULL OUTER JOIN (SELECT id, a FROM t5) AS t5
ON [t4.id, t4.a] = [t5.id, t5.a]
WHERE coalesce([t4.id, t4.a], [t5.id, t5.a])[0] < 4;
----
query II nosort list_func_join_keys
EXPLAIN SELECT * FROM
(SELECT id, a FROM t4, WHERE [id, a][0] < 4) AS t4
FULL OUTER JOIN (SELECT id, a FROM t5 WHERE [id, a][0] < 4) AS t5
ON [t4.id, t4.a] = [t5.id, t5.a]
----

View File

@@ -0,0 +1,25 @@
# name: test/optimizer/pushdown/pushdown_in_to_parquet.test
# description: Parquet filter of IN with 1 argument can be converted to =
# group: [pushdown]
require parquet
statement ok
PRAGMA enable_verification
statement ok
create table t1 as select range::VARCHAR a from range(1000);
statement ok
copy t1 to '__TEST_DIR__/t1.parquet' (FORMAT PARQUET);
query II
explain select * from '__TEST_DIR__/t1.parquet' where a in ('400');
----
physical_plan <!REGEX>:.*FILTER.*PARQUET_SCAN.*
query II
explain select * from '__TEST_DIR__/t1.parquet' where a in ('400');
----
physical_plan <REGEX>:.*PARQUET_SCAN.*Filters:.*

View File

@@ -0,0 +1,31 @@
# name: test/optimizer/pushdown/pushdown_unnest_into_cte.test
# description: Parquet filter of IN with 1 argument can be converted to =
# group: [pushdown]
statement ok
CREATE TABLE tbl2 as SELECT i as id1, [i-3, i+1, i+2] as somelist FROM generate_series(1, 10_000) s(i);
statement ok
pragma explain_output='OPTIMIZED_ONLY';
query II
EXPLAIN SELECT id1, element
FROM (
SELECT id1, UNNEST(somelist) AS element
FROM tbl2
) tmp
WHERE id1=10;
----
logical_opt <REGEX>:.*UNNEST.*SEQ_SCAN.*Filters.*
query II
EXPLAIN WITH tmp AS (
SELECT id1, generate_subscripts(somelist, 1) AS index, UNNEST(somelist) AS element
FROM tbl2
)
SELECT id1, index, element
FROM tmp
WHERE id1=10;
----
logical_opt <REGEX>:.*UNNEST.*SEQ_SCAN.*Filters.*

View File

@@ -0,0 +1,150 @@
# name: test/optimizer/pushdown/pushdown_window_partition_filter.test
# description: Test pushdown of filters through window operators that are partitioned by.
# group: [pushdown]
statement ok
create table t1 as from VALUES
('A', 1),
('B', 3),
('C', 12),
('A', 5),
('B', 8),
('C', 9),
('A', 10),
('B', 20),
('C', 3)
t(a, b);
statement ok
pragma explain_output=OPTIMIZED_ONLY
statement ok
create view window_with_filter as select a, b, LEAD(b) OVER (partition by a) as lead from t1 where a != 'C';
statement ok
create view window_no_filter as select a, b, LEAD(b) OVER (partition by a) as lead from t1;
query III no_sort result_1
select * from window_with_filter where a != 'C' order by all;
----
query III no_sort result_1
select * from window_no_filter where a != 'C' order by all;
----
statement ok
create table partition_and_rank_me as from values
('A', 10, 'A', 'id'),
('A', 20, 'A', 'id'),
('A', 30, 'B', 'id'),
('D', 40, 'B', 'id'),
('D', 50, 'C', 'id'),
('D', 60, 'C', 'id')
t(a, b, c, d);
query IIII
select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY d ORDER BY b)
from partition_and_rank_me order by all
----
A A 30 1
A A 30 2
A B 70 3
D B 70 4
D C 110 5
D C 110 6
# can't push down the filter c!='B', since the values of the rank() window function
# are affected by the existence of the rows where c='B'
query IIII
select * from (
select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY d ORDER BY b)
from partition_and_rank_me
) where c != 'B' order by all;
----
A A 30 1
A A 30 2
D C 110 5
D C 110 6
# One filter clause is on the partitioned column but the filter clause is an AND conjunction, so we don't push that down.
query IIII
select * from (
select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY c ORDER BY b)
from partition_and_rank_me
) where (c = 'B' AND a = 'D') order by all;
----
D B 70 2
# result of above query with pushdown
query IIII
select * from (
select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY c ORDER BY b)
from partition_and_rank_me where (c = 'B' AND a = 'D')
) order by all;
----
D B 40 1
# The filter is on the partitioned column, but is part of an OR conjunction, so we can push it down
query IIII
select * from (
select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY c ORDER BY b)
from partition_and_rank_me
) where (c = 'B' OR a = 'D') order by all;
----
A B 70 1
D B 70 2
D C 110 1
D C 110 2
# result of above query with pushdown
query IIII
select * from (
select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY c ORDER BY b)
from partition_and_rank_me
where (c = 'B' OR a = 'D')
) order by all;
----
A B 70 1
D B 70 2
D C 110 1
D C 110 2
# The filter is a function expression, so we don't push it down
query IIII
select * from (
select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY c ORDER BY b)
from partition_and_rank_me
) where (c || 'Z' = 'BZ') order by all;
----
A B 70 1
D B 70 2
# can't push down the filter c!='B', since the values of the rank() window function
# are affected by the existence of the rows where c='B'
query II
explain select * from (select a, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY d ORDER BY b), c from partition_and_rank_me) where c != 'B' order by all;
----
logical_opt <REGEX>:.*FILTER.*WINDOW.*
query II
explain select * from window_no_filter where a != 'C' order by a;
----
logical_opt <REGEX>:.*WINDOW.*Filters.*
statement ok
create table t2 as select range a, range%50 b, range%25 c from range(500);
# second window expression is not paritioned on b, so filter expression cannot be
# pushed down
query II
explain select * from (select a, b, c, sum(a) OVER (PARTITION BY b, c), sum(b) OVER (PARTITION BY a, c) from t2) where b > 25;
----
logical_opt <REGEX>:.*FILTER.*WINDOW.*
query II
explain select * from (select a, b, c, sum(a) OVER (PARTITION BY b, c), sum(b) OVER (PARTITION BY a, c) from t2) where c = 20;
----
logical_opt <REGEX>:.*WINDOW.*c=20.*

View File

@@ -0,0 +1,217 @@
# name: test/optimizer/pushdown/table_filter_pushdown.test
# description: Test Table Filter Push Down
# group: [pushdown]
statement ok
CREATE TABLE integers(i integer, j integer, k integer)
statement ok
INSERT INTO integers VALUES (5, 5, 5), (10, 10, 10)
statement ok
PRAGMA explain_output = OPTIMIZED_ONLY;
# complex filter cannot be entirely pushed down
query II
EXPLAIN SELECT k FROM integers where i+j > 10 and j = 5 and i = k+1
----
logical_opt <REGEX>:.*FILTER.*
# simple filter is pushed down: no filter remaining
query II
EXPLAIN SELECT k FROM integers where j=5
----
logical_opt <!REGEX>:.*FILTER.*
# complex filters are also pushed down
query I
SELECT k FROM integers where j::VARCHAR SIMILAR TO '[0-9]*'
----
5
10
# multiple filters pushed down
query II
EXPLAIN SELECT k FROM integers where j = 5 and i = 10
----
logical_opt <!REGEX>:.*FILTER.*
# complex filter is pushed down: no filter remaining
query II
EXPLAIN SELECT k FROM integers where j::VARCHAR SIMILAR TO '[0-9]*'
----
logical_opt <!REGEX>:.*FILTER.*
# we cannot push down expressions that can throw errors
query I
SELECT k FROM integers where j%50=j
----
5
10
query II
EXPLAIN SELECT k FROM integers where j%50=j
----
logical_opt <REGEX>:.*FILTER.*
# test different data types
foreach type <numeric>
statement ok
CREATE TABLE tablinho_numbers(i ${type}, j ${type}, k ${type})
statement ok
INSERT INTO tablinho_numbers VALUES (0, 0, 0), (1, 1, 1), (2, 2, 2)
# simple filters are pushed down
query II
EXPLAIN SELECT k FROM tablinho_numbers where j = 1
----
logical_opt <!REGEX>:.*FILTER.*
query II
EXPLAIN SELECT k FROM tablinho_numbers where j > 1
----
logical_opt <!REGEX>:.*FILTER.*
query II
EXPLAIN SELECT k FROM tablinho_numbers where j >= 1
----
logical_opt <!REGEX>:.*FILTER.*
query II
EXPLAIN SELECT k FROM tablinho_numbers where j < 1
----
logical_opt <!REGEX>:.*FILTER.*
query II
EXPLAIN SELECT k FROM tablinho_numbers where j <= 1
----
logical_opt <!REGEX>:.*FILTER.*
statement ok
DROP TABLE tablinho_numbers
endloop
# pushdown string
statement ok
CREATE TABLE tablinho(i varchar)
statement ok
INSERT INTO tablinho VALUES ('a'), ('bla'), ('c')
# simple filters are pushed down
query II
EXPLAIN SELECT i FROM tablinho where i = 'bla'
----
logical_opt <!REGEX>:.*FILTER.*
query II
EXPLAIN SELECT i FROM tablinho where i > 'bla'
----
logical_opt <!REGEX>:.*FILTER.*
query II
EXPLAIN SELECT i FROM tablinho where i >= 'bla'
----
logical_opt <!REGEX>:.*FILTER.*
query II
EXPLAIN SELECT i FROM tablinho where i < 'bla'
----
logical_opt <!REGEX>:.*FILTER.*
query II
EXPLAIN SELECT i FROM tablinho where i <= 'bla'
----
logical_opt <!REGEX>:.*FILTER.*
# more complex filters can be pushed down as long as they only involve one column
query II
EXPLAIN SELECT i FROM tablinho where i like 'bl_a%'
----
logical_opt <REGEX>:.*FILTER.*
query II
EXPLAIN SELECT i FROM tablinho where i like '%bla'
----
logical_opt <!REGEX>:.*FILTER.*
query II
EXPLAIN SELECT i FROM tablinho where i like '_bla'
----
logical_opt <!REGEX>:.*FILTER.*
# test Q6 pushdown
statement ok
CREATE TABLE LINEITEM(L_ORDERKEY INTEGER NOT NULL, L_PARTKEY INTEGER NOT NULL,L_SUPPKEY INTEGER NOT NULL, L_LINENUMBER INTEGER NOT NULL,L_QUANTITY DECIMAL(15,2) NOT NULL,L_EXTENDEDPRICE DECIMAL(15,2) NOT NULL, L_DISCOUNT DECIMAL(15,2) NOT NULL, L_TAX DECIMAL(15,2) NOT NULL,L_RETURNFLAG CHAR(1) NOT NULL, L_LINESTATUS CHAR(1) NOT NULL, L_SHIPDATE DATE NOT NULL, L_COMMITDATE DATE NOT NULL,L_RECEIPTDATE DATE NOT NULL, L_SHIPINSTRUCT CHAR(25) NOT NULL, L_SHIPMODE CHAR(10) NOT NULL, L_COMMENT VARCHAR(44) NOT NULL)
query II
explain select sum(l_extendedprice * l_discount) as revenue from lineitem where l_shipdate >= '1994-01-01' and l_shipdate < '1995-01-01' and l_discount between 0.05 and 0.07 and l_quantity < 24
----
logical_opt <!REGEX>:.*FILTER.*
statement ok
create temporary table t as select range a, range % 10 b, mod(range,10000) c, 5 d, 10000 e from range(100);
statement ok
PRAGMA explain_output = PHYSICAL_ONLY;
query II
explain select count(*) from t where b <=3 and b>=0;
----
physical_plan <REGEX>:.*b<=3.*
# test time pushdown
statement ok
CREATE TABLE test_time (a TIME, b TIME, c TIME)
statement ok
INSERT INTO test_time VALUES ('00:01:00','00:01:00','00:01:00'),('00:10:00','00:10:00','00:10:00'),('01:00:00','00:10:00','01:00:00'),(NULL,NULL,NULL)
statement ok
PRAGMA explain_output = OPTIMIZED_ONLY;
query II
EXPLAIN SELECT count(*) from test_time where a ='00:01:00'
----
logical_opt <!REGEX>:.*FILTER.*
# test bool pushdown
statement ok
CREATE TABLE test_bool (i bool, j bool)
statement ok
INSERT INTO test_bool VALUES (TRUE,TRUE),(TRUE,FALSE),(FALSE,TRUE),(NULL,NULL)
statement ok
PRAGMA explain_output = OPTIMIZED_ONLY;
query II
EXPLAIN SELECT i FROM test_bool where j = TRUE
----
logical_opt <!REGEX>:.*FILTER.*
# test now() pushdown
statement ok
CREATE TABLE test_timestamps (ts TIMESTAMP);
statement ok
INSERT INTO test_timestamps VALUES (NOW()::TIMESTAMP), (NOW()::TIMESTAMP - INTERVAL 10 YEARS);
statement ok
PRAGMA explain_output = OPTIMIZED_ONLY;
query II
EXPLAIN SELECT * FROM test_timestamps where ts >= NOW()::TIMESTAMP - INTERVAL 1 YEAR;
----
logical_opt <!REGEX>:.*FILTER.*
query I
SELECT COUNT(*) FROM test_timestamps where ts >= NOW()::TIMESTAMP - INTERVAL 1 YEAR;
----
1

View File

@@ -0,0 +1,399 @@
# name: test/optimizer/pushdown/table_or_pushdown.test
# description: Test Table OR Filter Push Down
# group: [pushdown]
statement ok
CREATE TABLE integers AS SELECT a as a, a as b FROM generate_series(1, 5, 1) tbl(a)
#### test OR filters with multiple columns in the root OR, e.g., a=1 OR b=2
query II
EXPLAIN SELECT * FROM integers WHERE a=1 OR b=2 AND (a>3 OR b<5)
----
physical_plan <!REGEX>:.*SEQ_SCAN.*Filters:.*
query II
SELECT * FROM integers WHERE a=1 OR b=2 AND (a>3 OR b<5)
----
1 1
2 2
#### test OR filters with AND that triggers a stop early condition
query II
EXPLAIN SELECT * FROM integers WHERE a=1 OR a=2 AND (a>3 OR b<5)
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters: a=1 OR a=2[ ]*|.*
query II
SELECT * FROM integers WHERE a=1 OR a=2 AND (a>3 OR b<5)
----
1 1
2 2
#### test OR filters with AND in the same column
query II
EXPLAIN SELECT * FROM integers WHERE a=1 OR (a>3 AND a<5)
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters: a=1 OR a>3 AND a<5|.*
query II
SELECT * FROM integers WHERE a=1 OR (a>3 AND a<5)
----
1 1
4 4
#### test only OR filters
query II
EXPLAIN SELECT * FROM integers WHERE a=1 OR a>3 OR a<5
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters: a=1 OR a>3 OR a<5|.*
query II
SELECT * FROM integers WHERE a=1 OR a>3 OR a<5 ORDER by a
----
1 1
2 2
3 3
4 4
5 5
######### Testing String ######################################################
statement ok
CREATE TABLE strings(s VARCHAR)
statement ok
INSERT INTO strings VALUES ('AAAAAAAAAAAAAAA11111'), ('AAAAAAAAAAAAAAA99999')
query II
EXPLAIN SELECT * FROM strings WHERE s>'AAAAAAAAAAAAAAA1'
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*s>'AAAAAAAAAAAAAAA1'.*
query I
SELECT * FROM strings WHERE s>'AAAAAAAAAAAAAAA1'
----
AAAAAAAAAAAAAAA11111
AAAAAAAAAAAAAAA99999
#### test only OR filters
query II
EXPLAIN SELECT * FROM strings WHERE s>'AAAAAAAAAAAAAAA' OR s<'AAAAAAAAAAAAAAA99999A'
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*s>.*'AAAAAAAAAAAAAAA'|.*OR.*s<.*'AAAAAAAAAAAAAAA99999A'.*
query I
SELECT * FROM strings WHERE s>'AAAAAAAAAAAAAAA' OR s<'AAAAAAAAAAAAAAA99999A'
----
AAAAAAAAAAAAAAA11111
AAAAAAAAAAAAAAA99999
statement ok
INSERT INTO strings VALUES ('BBBB'), ('CCCC')
# testing string statistics
query II
EXPLAIN SELECT * FROM strings WHERE s!='111' OR s!='WWW'
----
physical_plan <!REGEX>:.*SEQ_SCAN.*Filters:.*
query I
SELECT * FROM strings WHERE s!='111' OR s!='WWW' ORDER BY s
----
AAAAAAAAAAAAAAA11111
AAAAAAAAAAAAAAA99999
BBBB
CCCC
#### Testing not equal
query II
EXPLAIN SELECT * FROM strings WHERE s!='BBBB' or s>'BBBB'
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*s!=.*'BBBB'.*OR.*s>.*'BBBB'.*
query I
SELECT * FROM strings WHERE s!='BBBB' or s>'BBBB'
----
AAAAAAAAAAAAAAA11111
AAAAAAAAAAAAAAA99999
CCCC
query II
EXPLAIN SELECT * FROM integers WHERE a!=1 OR a!=2
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*a!=1.*OR.*a!=2.*
query II
SELECT * FROM integers WHERE a!=1 OR a!=2 ORDER BY a
----
1 1
2 2
3 3
4 4
5 5
#### Testing AND priority
query II
EXPLAIN SELECT * FROM integers WHERE a>2 AND (a=3 OR a=5)
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*a>2.*
query II
SELECT * FROM integers WHERE a>2 AND (a=3 OR a=5) ORDER BY a
----
3 3
5 5
######### Complex filters #####################################################
#### multiple OR filters connected with ANDs
query II
EXPLAIN SELECT * FROM integers WHERE (a<2 OR a>3) AND (a=1 OR a=4)
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*a<2.*OR.*a>3.*AND.*a=1.*OR.*a=4.*
query II
SELECT * FROM integers WHERE (a<2 OR a>3) AND (a=1 OR a=4)
----
1 1
4 4
query II
EXPLAIN SELECT * FROM integers WHERE (a<2 OR a>3) AND (a=1 OR a=4) AND (b=1 OR b<5)
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*a<2.*OR.*a>3.*AND.*a=1.*OR.*a=4.*b=1 OR b<5.*
query II
SELECT * FROM integers WHERE (a<2 OR a>3) AND (a=1 OR a=4) AND (b=1 OR b<5)
----
1 1
4 4
#### OR filters with functions: concat(...)
query II
EXPLAIN SELECT * FROM integers WHERE concat(a=1, b=1)='truetrue' OR a=2 ORDER by a
----
physical_plan <!REGEX>:.*SEQ_SCAN.*Filters:.*
query II
SELECT * FROM integers WHERE concat(a=1, b=1)='truetrue' OR a=2 ORDER by a
----
1 1
2 2
#### LIKE operator
query II
EXPLAIN SELECT * FROM strings WHERE s>'BBBB' OR s LIKE '%AAAAAAAAAAAAAAA%' ORDER BY s
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*
query I
SELECT * FROM strings WHERE s>'BBBB' OR s LIKE '%AAAAAAAAAAAAAAA%' ORDER BY s
----
AAAAAAAAAAAAAAA11111
AAAAAAAAAAAAAAA99999
CCCC
#### OR filters with CASE statement
query II
EXPLAIN SELECT * FROM integers WHERE a=1 OR (CASE WHEN a=2 THEN true WHEN a=4 THEN true ELSE false END)
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*
query II
SELECT * FROM integers WHERE a=1 OR (CASE WHEN a=2 THEN true WHEN a=4 THEN true ELSE false END)
----
1 1
2 2
4 4
#### multiple complex OR filters connected with ANDs
query II
EXPLAIN SELECT * FROM integers WHERE (a=1 OR a=4) AND (a=1 OR (CASE WHEN a%2=0 THEN true ELSE false END)) AND (concat(a=1, b=1)='truetrue' OR a=2) AND (a::CHAR LIKE '1' OR a=5)
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*a=1.*OR.*a=4.*|$
query II
SELECT * FROM integers WHERE (a=1 OR a=4) AND (a=1 OR (CASE WHEN a%2=0 THEN true ELSE false END)) AND (concat(a=1, b=1)='truetrue' OR a=2) AND (a::CHAR LIKE '1' OR a=5)
----
1 1
#### OR filters with NULL
statement ok
INSERT INTO integers VALUES (NULL, NULL)
query II
EXPLAIN SELECT * FROM integers WHERE a=1 OR a IS NULL ORDER BY a
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*
query II
SELECT * FROM integers WHERE a=1 OR a IS NULL ORDER BY a
----
1 1
NULL NULL
query II
EXPLAIN SELECT * FROM integers WHERE a=1 OR a IS NOT NULL
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*
query II
SELECT * FROM integers WHERE a=1 OR a IS NOT NULL
----
1 1
2 2
3 3
4 4
5 5
# notequal and null
query II
EXPLAIN SELECT * FROM integers WHERE a!=1 OR a IS NULL ORDER BY a
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*
query II
SELECT * FROM integers WHERE a!=1 OR a IS NULL ORDER BY a
----
2 2
3 3
4 4
5 5
NULL NULL
# notequal and not null
query II
EXPLAIN SELECT * FROM integers WHERE a!=1 OR a IS NOT NULL ORDER BY a
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*
query II
SELECT * FROM integers WHERE a!=1 OR a IS NOT NULL ORDER BY a
----
1 1
2 2
3 3
4 4
5 5
query II
EXPLAIN SELECT * FROM integers WHERE a!=1 OR a>3 OR a<2 ORDER by a
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*a!=1.*OR.*a>3.*OR.*a.*<.*2.*
query II
SELECT * FROM integers WHERE a!=1 OR a>3 OR a<2 ORDER by a
----
1 1
2 2
3 3
4 4
5 5
# test comparison with null in OR conjunctions uses ISNULL/ISNOTNULL table filter
statement ok
CREATE TABLE t0 as from values (1), (2), (2), (0), (NULL) t(c1);
# is distinct from NULL
query I
SELECT * FROM t0 WHERE ((t0.c1 IS DISTINCT FROM NULL) OR (NULL));
----
1
2
2
0
# is not distinct from NULL
query I
SELECT * FROM t0 WHERE ((t0.c1 IS NOT DISTINCT FROM NULL) OR (NULL));
----
NULL
# = NULL in conjunction or
query I
SELECT * FROM t0 WHERE ((t0.c1 = NULL) OR (NULL));
----
query I
SELECT * FROM t0 WHERE ((t0.c1 != NULL) OR (NULL));
----
statement ok
SELECT * FROM t0 WHERE ((t0.c1 = NULL) OR (NOT NULL) OR (t0.c1 = 1));
query I
select * from t0 where (NULL OR cast(t0.c1 as bool)) order by all;
----
1
2
2
mode skip
#### numeric statistics
# notequal and constant > max
query II
EXPLAIN SELECT * FROM integers WHERE a!=10 OR a>3
----
physical_plan <!REGEX>:.*SEQ_SCAN.*Filters:.*
## The predicate a!=10 is greater than the numeric_statistics::max implying that it is always true within an OR conjunction
mode unskip
query II
SELECT * FROM integers WHERE a!=10 OR a>3
----
1 1
2 2
3 3
4 4
5 5
# Testing the number of rows filtered (column "a" has five values: 1 .. 5)
statement ok
PRAGMA enable_profiling
mode skip
# should return 2 rows: 1 and 5
query II
EXPLAIN ANALYZE SELECT a FROM integers WHERE a<2 OR a>4
----
analyzed_plan <REGEX>:.*SEQ_SCAN.*Filters:.*a<2.*OR.*a>4.*2 Rows.*
# should return 1 row: 1
query II
EXPLAIN ANALYZE SELECT a FROM integers WHERE a<2 OR a>5
----
analyzed_plan <REGEX>:.*SEQ_SCAN.*Filters: a<2 OR a>5.*1 Rows.*
mode unskip
statement ok
PRAGMA disable_profiling
# notequal and min == max && min == constant
statement ok
DROP TABLE integers
statement ok
CREATE TABLE integers AS SELECT a as A, a as B FROM generate_series(1, 1, 1) tbl(a)
query II
EXPLAIN SELECT * FROM integers WHERE a!=1 OR a<2
----
physical_plan <!REGEX>:.*SEQ_SCAN.*Filters:.*
query II
SELECT * FROM integers WHERE a!=1 OR a<3
----
1 1

View File

@@ -0,0 +1,25 @@
# name: test/optimizer/pushdown/test_constant_or_null_pushdown.test
# description: Test Table OR Filter Push Down
# group: [pushdown]
statement ok
create table t1 (ts_stop TIMESTAMPTZ);
statement ok
insert into t1 values (NULL), (NULL);
query II
explain select count(*) from t1 where constant_or_null(true, COALESCE(ts_stop, '9999-09-09 07:09:09+00'::TIMESTAMPTZ), '2025-06-23 10:32:02.216+00'::TIMESTAMPTZ);
----
physical_plan <REGEX>:.*constant_or_null.*
statement ok
create table t2 as select range%2 a, range b from range(100);
statement ok
insert into t2 values (NULL, NULL), (NULL, NULL), (NULL, NULL);
query II
explain select * from t2 where constant_or_null(true, a);
----
physical_plan <REGEX>:.*a IS NOT NULL.*

View File

@@ -0,0 +1,61 @@
# name: test/optimizer/pushdown/test_pushdown_cte_group_by_all.test
# description: If a CTE contains GROUP BY ALL then predicate pushdown on non-aggregated columns should occur
# group: [pushdown]
statement ok
create or replace table my_temp as
from generate_series(99) t(i)
select i, i % 10 as group_1;
statement ok
pragma explain_output='optimized_only';
query II
explain
with my_cte as (
from my_temp
select
group_1,
min(i) as min_i,
max(i) as max_i
group by ALL
)
from my_cte
where
group_1 = 2;
----
logical_opt <REGEX>:.*Filters:.*
query II
explain
with my_cte as (
from my_temp
select
group_1,
min(i) as min_i,
max(i) as max_i
group by group_1
)
from my_cte
where
group_1 = 2;
----
logical_opt <REGEX>:.*Filters:.*
query II
explain
with my_cte as (
from my_temp
select
group_1,
min(i) as min_i,
max(i) as max_i
group by group_1 having min_i > 1
)
from my_cte
where group_1 = 2;
----
logical_opt <REGEX>:.*FILTER.*Filters:.*

View File

@@ -0,0 +1,53 @@
# name: test/optimizer/pushdown/test_pushdown_or.test_slow
# group: [pushdown]
require tpch
statement ok
create table t1 as select range a, range b from range(0,1000000) ;
statement ok
create table t2(a int);
statement ok
insert into t2 from range(10) t(a);
#statement ok
#select * from t1 join t2 using (a);
query I
select a from t1 where a = 30000 or a = 50000 or a = 500;
----
500
30000
50000
statement ok
call dbgen(sf=1);
query I
select l_orderkey from lineitem where l_orderkey = 6 or l_orderkey = 5999971;
----
6
5999971
5999971
5999971
5999971
5999971
5999971
query II
select l_orderkey, l_partkey from lineitem where l_orderkey = 6 or l_partkey = 4991;
----
6 139636
403456 4991
535522 4991
981987 4991
2593475 4991
3237285 4991
3695110 4991
4093507 4991
4437666 4991
4734181 4991
5552582 4991

View File

@@ -0,0 +1,79 @@
# name: test/optimizer/pushdown/timestamp_to_date_pushdown.test
# description: Test Tpushdown of timestamp to date filters
# group: [pushdown]
require icu
foreach timezone UTC ECT
statement ok
set TimeZone='${timezone}';
statement ok
create or replace table t1 (ts timestamp, i int);
statement ok
insert into t1 select '2024-05-01 00:00:00'::timestamp, i from generate_series(1, 2000) g(i);
statement ok
insert into t1 select '2024-05-02 00:00:00'::timestamp, i from generate_series(1, 1000) g(i);
statement ok
insert into t1 select '2024-05-02 00:22:00'::timestamp, i from generate_series(1, 1000) g(i);
statement ok
insert into t1 select '2024-05-03 00:00:00'::timestamp, i from generate_series(1, 2000) g(i);
query II
explain select * from t1 where ts::date == '2024-05-02';
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*
query II
explain select * from t1 where '2024-05-02' == ts::date;
----
physical_plan <REGEX>:.*SEQ_SCAN.*Filters:.*
statement ok
pragma disable_optimizer;
query II nosort no_opt_result
select * from t1 where ts::date == '2024-05-02';
----
statement ok
pragma enable_optimizer;
query II nosort no_opt_result
select * from t1 where ts::date == '2024-05-02';
----
# pattern is still recognized in conjunction
query II
explain select count(*) from t1 where ts::date == '2024-05-02' and i > 122880/2;
----
physical_plan <!REGEX>:.*FILTER.*SEQ_SCAN:.*
query I
select count(*) from t1 where ts::date == '2024-05-02' and i > 1000;
----
0
query I
select count(*) from t1 where ts::date == '2024-05-02' and i <= 500;
----
1000
endloop
query I
select count(*) from t1 where ts::date == '2024-05-01' and i <= 500;
----
500
query I
select count(*) from t1 where ts::date == '2024-05-03';
----
2000