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,30 @@
# name: test/sql/optimizer/expression/test_casting_negative_integer_to_bit.test
# description: https://github.com/duckdb/duckdb/issues/13506
# group: [expression]
statement ok
CREATE TABLE t1 as select -1 c1 from range(1);
query I
SELECT t1.c1 FROM t1;
----
-1
query II
SELECT CAST(CAST(t1.c1 AS BIT) AS INTEGER), (1 BETWEEN -1 AND CAST(CAST(t1.c1 AS BIT) AS INTEGER)) FROM t1;
----
-1 false
# also fails
query II
select cast(cast(c1 as BIT) as INTEGER) as cast_res, 1 between -1 and cast(cast(c1 as BIT) as INTEGER) as watever from t1;
----
-1 false
query I
SELECT t1.c1 FROM t1 WHERE (1 BETWEEN -1 AND CAST(CAST(t1.c1 AS BIT) AS INTEGER));
----

View File

@@ -0,0 +1,72 @@
# name: test/sql/optimizer/expression/test_common_aggregate.test
# description: Test common aggregate
# group: [expression]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE integers(i INTEGER);
statement ok
INSERT INTO integers VALUES (1), (2), (3)
statement ok
PRAGMA explain_output = 'OPTIMIZED_ONLY';
# all of these are identical, i.e. this gets folded into a single count aggregate
query II
EXPLAIN SELECT COUNT(*), COUNT(), COUNT(i) FROM integers;
----
logical_opt <!REGEX>:.*AGGREGATE.*count.*count.*
query III
SELECT COUNT(*), COUNT(), COUNT(i) FROM integers;
----
3 3 3
# again, here there is only a single count and a single sum
query II
EXPLAIN SELECT COUNT(*), COUNT(), SUM(i), COUNT(i), SUM(i) / COUNT(i) FROM integers;
----
logical_opt <!REGEX>:.*AGGREGATE.*count.*count.*
query IIIII
SELECT COUNT(*), COUNT(), SUM(i), COUNT(i), SUM(i) / COUNT(i) FROM integers;
----
3 3 6 3 2
# however, once we add a null value COUNT(i) is no longer equal to COUNT(*)
statement ok
INSERT INTO integers VALUES (NULL)
# now there are two counts!
query II
EXPLAIN SELECT COUNT(*), COUNT(), SUM(i), COUNT(i), SUM(i) / COUNT(i) FROM integers;
----
logical_opt <REGEX>:.*AGGREGATE.*count.*count.*
query IIIII
SELECT COUNT(*), COUNT(), SUM(i), COUNT(i), SUM(i) / COUNT(i) FROM integers;
----
4 4 6 3 2
statement ok
CREATE TABLE groups(grp INTEGER, aggr1 INTEGER, aggr2 INTEGER, aggr3 INTEGER)
statement ok
INSERT INTO groups VALUES (1, 1, 2, 3), (1, 2, 4, 6), (2, 1, 2, 3), (2, 3, 6, 9);
query III
SELECT
sum(aggr1)::DOUBLE / count(aggr1)::DOUBLE AS avg_qty,
sum(aggr2)::DOUBLE / count(aggr2)::DOUBLE AS avg_price,
sum(aggr3)::DOUBLE / count(aggr3)::DOUBLE AS avg_disc
FROM
groups
GROUP BY
grp
ORDER BY grp;
----
1.5 3 4.5
2 4 6

View File

@@ -0,0 +1,39 @@
# name: test/sql/optimizer/expression/test_comparison_simplification.test
# description: Test ComparisonSimplificationRule
# group: [expression]
statement ok
PRAGMA enable_verification
# VARCHAR => TIME is not invertible.
query I
WITH results AS (
SELECT '2023-08-17T23:00:08.539Z' as timestamp
)
SELECT *
FROM results
WHERE timestamp::TIME BETWEEN '22:00:00'::TIME AND '23:59:59'::TIME ;
----
2023-08-17T23:00:08.539Z
# CAST(TIMESTAMP AS TIME) can't use statistics
statement ok
CREATE TABLE issue8316 (dt TIMESTAMP);
statement ok
INSERT INTO issue8316 VALUES
('2016-02-14 18:00:05'),
('2016-02-15 10:04:25'),
('2016-02-16 10:04:25'),
('2016-02-16 23:59:55'),
;
query I
SELECT dt
FROM issue8316
WHERE CAST(dt as TIME) = CAST('10:04:25' as TIME)
ORDER BY 1
;
----
2016-02-15 10:04:25
2016-02-16 10:04:25

View File

@@ -0,0 +1,118 @@
# name: test/sql/optimizer/expression/test_conjunction_optimization.test
# description: Test conjunction statements that can be simplified
# group: [expression]
statement ok
SET default_null_order='nulls_first';
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE integers(i INTEGER);
statement ok
INSERT INTO integers VALUES (1), (2), (3), (NULL)
# test conjunctions in FILTER clause
query I
SELECT i FROM integers WHERE (i=1 AND i>0) OR (i=1 AND i<3) ORDER BY i
----
1
query I
SELECT i FROM integers WHERE (i=1) OR (i=1) ORDER BY i
----
1
query I
SELECT i FROM integers WHERE (i=1) OR (i=1) OR (i=1) OR (i=1) OR (i=1) ORDER BY i
----
1
query I
SELECT i FROM integers WHERE (i IS NULL AND i=1) OR (i IS NULL AND i<10) ORDER BY i
----
query I
SELECT i FROM integers WHERE (i IS NOT NULL AND i>1) OR (i IS NOT NULL AND i<10) ORDER BY i
----
1
2
3
query I
SELECT i FROM integers WHERE (i IS NULL AND (i+1) IS NULL) OR (i IS NULL AND (i+2) IS NULL) ORDER BY i
----
NULL
query I
SELECT i FROM integers WHERE i=1 OR 1=1 ORDER BY i
----
NULL
1
2
3
query I
SELECT i FROM integers WHERE i=1 OR 1=0 OR 1=1 ORDER BY i
----
NULL
1
2
3
query I
SELECT i FROM integers WHERE (i=1 OR 1=0 OR i=1) AND (0=1 OR 1=0 OR 1=1) ORDER BY i
----
1
# test conjunctions in SELECT clause
query T
SELECT (i=1 AND i>0) OR (i=1 AND i<3) FROM integers ORDER BY i
----
NULL
1
0
0
query T
SELECT (i=1) OR (i=1) FROM integers ORDER BY i
----
NULL
1
0
0
query T
SELECT (i=1) OR (i=1) OR (i=1) OR (i=1) OR (i=1) FROM integers ORDER BY i
----
NULL
1
0
0
query T
SELECT (i IS NULL AND i=1) OR (i IS NULL AND i<10) FROM integers ORDER BY i
----
NULL
0
0
0
query T
SELECT (i IS NOT NULL AND i>1) OR (i IS NOT NULL AND i<10) FROM integers ORDER BY i
----
0
1
1
1
query T
SELECT (i IS NULL AND (i+1) IS NULL) OR (i IS NULL AND (i+2) IS NULL) FROM integers ORDER BY i
----
1
0
0
0

View File

@@ -0,0 +1,81 @@
# name: test/sql/optimizer/expression/test_cse.test
# description: Test queries involving Common SubExpressions
# group: [expression]
statement ok
SET default_null_order='nulls_first';
statement ok
PRAGMA enable_verification
statement ok
create table test(a integer);
statement ok
insert into test values (42);
# single CSE
query I
SELECT (a*2)+(a*2) FROM test
----
168
# multiple CSEs
query I
SELECT (a*2)+(a*2)+(a*2)+(a*2)+(a*2) FROM test
----
420
# use the actual columns still
query II
SELECT (a*2)+(a*2)+(a*2)+(a*2)+(a*2), a FROM test
----
420 42
# CSE in aggregates
query I
SELECT SUM((a*2)+(a*2)+(a*2)+(a*2)+(a*2)) FROM test
----
420
# also with group by clause
query II
SELECT a, SUM((a*2)+(a*2)+(a*2)+(a*2)+(a*2)) FROM test GROUP BY a
----
42 420
# CSE in WHERE clause
query I
SELECT * FROM test WHERE ((a*2)+(a*2))>100
----
42
# multiple CSE in WHERE clause
query I
SELECT * FROM test WHERE ((a*2)+(a*2)+(a*2)+(a*2)+(a*2))>400
----
42
# Strings and NULL values
statement ok
create table test2(a VARCHAR);
statement ok
insert into test2 values ('hello'), ('world'), (NULL);
# single CSE in projection
query T
SELECT substring(a, 1, 3)=substring(a, 1, 3) FROM test2 ORDER BY 1
----
NULL
1
1
# now with GROUP BY clause
query T
SELECT substring(a, 1, 3)=substring(a, 1, 3) AS b FROM test2 GROUP BY b ORDER BY b
----
NULL
1

View File

@@ -0,0 +1,20 @@
# name: test/sql/optimizer/expression/test_date_subtract_filter.test
# description: Issue #9863 - query involving a subtraction between dates and a comparison
# group: [expression]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE dates(lo_commitdate DATE);
statement ok
INSERT INTO dates VALUES (DATE '1992-02-10');
query I
SELECT CAST('2020-02-20' AS date) - CAST(min("ta_1"."lo_commitdate") AS date) AS "ca_1"
FROM dates AS "ta_1"
HAVING CAST('2020-02-20' AS date) - CAST(min("ta_1"."lo_commitdate") AS date) > 4
ORDER BY "ca_1" ASC;
----
10237

View File

@@ -0,0 +1,118 @@
# name: test/sql/optimizer/expression/test_equal_or_null_optimization.test
# description: Test a=b OR (a IS NULL AND b IS NULL) to a IS NOT DISTINCT FROM b
# group: [expression]
statement ok
PRAGMA enable_verification
statement ok
PRAGMA explain_output = 'PHYSICAL_ONLY'
statement ok
CREATE TABLE test(i INTEGER, j INTEGER, k integer);
statement ok
INSERT INTO test VALUES (1,1,3), (2,2,4), (NULL,NULL,NULL);
query I rowsort
SELECT i FROM test WHERE (i=j) OR (i IS NULL AND j IS NULL);
----
1
2
NULL
query II nosort distinctrewrite1
EXPLAIN SELECT (i=j) OR (i IS NULL AND j IS NULL) FROM test;
----
physical_plan <REGEX>:.*DISTINCT.*
query I rowsort
SELECT i FROM test WHERE i IS NOT DISTINCT FROM j;
----
1
2
NULL
query II nosort distinctrewrite1
EXPLAIN SELECT i IS NOT DISTINCT FROM j FROM test;
----
physical_plan <REGEX>:.*DISTINCT.*
query I rowsort
SELECT i FROM test WHERE (i IS NULL AND j IS NULL) OR (i=j);
----
1
2
NULL
query II nosort distinctrewrite1
EXPLAIN SELECT (i IS NULL AND j IS NULL) OR (i=j) FROM test;
----
physical_plan <REGEX>:.*DISTINCT.*
# do a hash join
query I rowsort
SELECT test1.i FROM test AS test1, test AS test2 WHERE (test1.i=test2.j) OR (test1.i IS NULL AND test2.j IS NULL) ORDER BY 1;
----
1
2
NULL
query II nosort distinctrewrite2
EXPLAIN SELECT test1.i FROM test AS test1, test AS test2 WHERE (test1.i=test2.j) OR (test1.i IS NULL AND test2.j IS NULL);
----
physical_plan <REGEX>:.*DISTINCT.*
query II nosort distinctrewrite2
EXPLAIN SELECT test1.i FROM test AS test1, test AS test2 WHERE (test1.i IS NULL AND test2.j IS NULL) OR (test1.i=test2.j);
----
physical_plan <REGEX>:.*DISTINCT.*
# this one cannot be rewritten
query I nosort
SELECT i FROM test WHERE (i=k) OR (i IS NULL AND j IS NULL);
----
NULL
query II nosort nodistinctrewrite1
EXPLAIN SELECT i FROM test WHERE (i=k) OR (i IS NULL AND j IS NULL);
----
physical_plan <REGEX>:.*OR.*
# neither this one
query I nosort
SELECT i FROM test WHERE (i=j) OR (i IS NULL AND j = 1);
----
1
2
query II nosort nodistinctrewrite2
EXPLAIN SELECT i FROM test WHERE (i=j) OR (i IS NULL AND j = 1);
----
physical_plan <REGEX>:.*OR.*
# do a nested loop join because the OR cannot be rewritten here
query I rowsort
SELECT test1.i FROM test AS test1, test AS test2 WHERE (test1.i=test2.j) OR (test2.i IS NULL AND test1.j IS NULL);
----
1
2
NULL
query II nosort distinctrewrite3
EXPLAIN SELECT test1.i FROM test AS test1, test AS test2 WHERE (test1.i=test2.j) OR (test2.i IS NULL AND test1.j IS NULL);
----
physical_plan <REGEX>:.*OR.*
# same issue as the previous one
query I rowsort
SELECT test1.i FROM test AS test1, test AS test2 WHERE (test1.i=test2.k) OR (test2.i IS NULL AND test2.j IS NULL);
----
1
2
NULL
query II nosort distinctrewrite4
EXPLAIN SELECT test1.i FROM test AS test1, test AS test2 WHERE (test1.i=test2.k) OR (test2.i IS NULL AND test2.j IS NULL);
----
physical_plan <REGEX>:.*OR.*

View File

@@ -0,0 +1,29 @@
# name: test/sql/optimizer/expression/test_in_clause_simplification.test
# description: Test InClauseSimplificationRule
# group: [expression]
statement ok
PRAGMA enable_verification
# Removing the TIMESTAMP => DATE cast only works if the
# IN clause has TIMESTAMPs.
statement ok
CREATE TABLE issue13380(c0 TIMESTAMP);
statement ok
INSERT INTO issue13380(c0) VALUES ('2024-08-09 14:48:00');
query I
SELECT c0::DATE IN ('2024-08-09') d FROM issue13380;
----
true
query I
SELECT NOT (c0::DATE IN ('2024-08-09')) FROM issue13380;
----
false
query I
SELECT c0::DATE NOT IN ('2024-08-09') FROM issue13380;
----
false

View File

@@ -0,0 +1,25 @@
# name: test/sql/optimizer/expression/test_indistinct_aggregates.test
# description: Test DISTINCT-insensitive aggregate rules
# group: [expression]
statement ok
PRAGMA enable_verification
query I
SELECT max(distinct x) from range(10) tbl(x);
----
9
query II
SELECT x, max(distinct x) over (order by x desc) from range(10) tbl(x);
----
9 9
8 9
7 9
6 9
5 9
4 9
3 9
2 9
1 9
0 9

View File

@@ -0,0 +1,175 @@
# name: test/sql/optimizer/expression/test_move_constants.test
# description: Test queries involving constants that can be moved
# group: [expression]
statement ok
PRAGMA enable_verification
# move constants with signed value extremes
# tinyint
foreach type,min,max tinyint,-128,127 smallint,-32768,32767 integer,-2147483648,2147483647 bigint,-9223372036854775808,9223372036854775807 hugeint,-170141183460469231731687303715884105728,170141183460469231731687303715884105727
statement ok
CREATE OR REPLACE TABLE vals(v ${type});
statement ok
INSERT INTO vals VALUES (2), (NULL);
# +
query I
SELECT * FROM vals WHERE v+(${max}-10)::${type}=-100::${type};
----
query I
SELECT v+(${max}-10)::${type}=-100::${type} FROM vals;
----
false
NULL
# -
query I
SELECT * FROM vals WHERE v-${max}::${type}=${max}::${type};
----
query I
SELECT * FROM vals WHERE (${min}+100)::${type}-v=${max}::${type};
----
# *
# multiply by 0
query I
SELECT * FROM vals WHERE v*0::${type}=1::${type};
----
query I
SELECT * FROM vals WHERE v*0::${type}=0::${type};
----
2
query I
SELECT v*0::${type}=0::${type} FROM vals;
----
true
NULL
query I
SELECT v*0::${type}=1::${type} FROM vals;
----
false
NULL
# negative numbers
query I
SELECT * FROM vals WHERE v*(-1)::${type}=(${min})::${type};
----
query I
SELECT * FROM vals WHERE v*(-2)::${type}=(${min})::${type};
----
endloop
# move constants with unsigned values
foreach utype utinyint usmallint uinteger ubigint
statement ok
CREATE OR REPLACE TABLE vals(v ${utype});
statement ok
INSERT INTO vals VALUES (2), (NULL);
# +
query I
SELECT * FROM vals WHERE v+5::${utype}=3::${utype};
----
query I
SELECT v+5::${utype}=3::${utype} FROM vals;
----
false
NULL
query I
SELECT * FROM vals WHERE 5::${utype}+v=3::${utype};
----
query I
SELECT * FROM vals WHERE v+1::${utype}=3::${utype};
----
2
query I
SELECT * FROM vals WHERE 1::${utype}+v=3::${utype};
----
2
# -
query I
SELECT * FROM vals WHERE v-2::${utype}=255::${utype};
----
query I
SELECT * FROM vals WHERE 2::${utype}-v=3::${utype};
----
query I
SELECT * FROM vals WHERE v-1::${utype}=1::${utype};
----
2
query I
SELECT * FROM vals WHERE 4::${utype}-v=2::${utype};
----
2
# *
# multiply by 0
query I
SELECT * FROM vals WHERE v*0::${utype}=1::${utype};
----
query I
SELECT * FROM vals WHERE v*0::${utype}=0::${utype};
----
2
query I
SELECT v*0::${utype}=0::${utype} FROM vals;
----
true
NULL
query I
SELECT v*0::${utype}=1::${utype} FROM vals;
----
false
NULL
# rhs value is not cleanly divisible
# this is always false, since there is no integer value for which x*3=7
query I
SELECT * FROM vals WHERE v*3::${utype}=7::${utype};
----
query I
SELECT v*3::${utype}=7::${utype} FROM vals;
----
false
NULL
query I
SELECT * FROM vals WHERE v*3::${utype}=6::${utype};
----
2
query I
SELECT v*3::${utype}=6::${utype} FROM vals;
----
true
NULL
statement ok
DROP TABLE vals
endloop

View File

@@ -0,0 +1,33 @@
# name: test/sql/optimizer/expression/test_negation_limits.test
# description: Test negation limits
# group: [expression]
statement ok
PRAGMA enable_verification
# tinyint
foreach type,min,max tinyint,-128,127 smallint,-32768,32767 integer,-2147483648,2147483647 bigint,-9223372036854775808,9223372036854775807
statement ok
CREATE OR REPLACE TABLE vals(id INTEGER, v ${type});
statement ok
INSERT INTO vals VALUES (0, ${min}), (1, ${max}), (2, 0), (3, -2), (4, 2);
# cannot negate the min value
statement error
SELECT -v FROM vals;
----
# we can negate the maximum value
statement ok
SELECT -v FROM vals WHERE id>0
query I
SELECT -v FROM vals WHERE id>1 ORDER BY id
----
0
2
-2
endloop

View File

@@ -0,0 +1,128 @@
# name: test/sql/optimizer/expression/test_nop_arithmetic.test
# description: Test NOP arithmetic expressions
# group: [expression]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE test (a INTEGER, b INTEGER)
statement ok
INSERT INTO test VALUES (42, 10), (43, 100);
# a + 0
query I
SELECT a + 0 FROM test
----
42
43
# 0 + a
query I
SELECT 0 + a FROM test
----
42
43
# a - 0
query I
SELECT a - 0 FROM test
----
42
43
# 0 - a
query I
SELECT 0 - a FROM test
----
-42
-43
# a * 1
query I
SELECT a * 1 FROM test
----
42
43
# 1 * a
query I
SELECT 1 * a FROM test
----
42
43
# a * 0 => 0
query I
SELECT a * 0 FROM test
----
0
0
query I
SELECT 0 * a FROM test
----
0
0
# a / 1
query I
SELECT a / 1 FROM test
----
42
43
# 1 / a
query I
SELECT 1 // a FROM test
----
0
0
# a / 0 => NULL
query I
SELECT a // 0 FROM test
----
NULL
NULL
# 0 / a => 0
query I
SELECT 0 // a FROM test
----
0
0
# test expressions involving NULL as well
statement ok
UPDATE test SET a=NULL
# NULL * 0 = NULL
query I
SELECT a * 0 FROM test
----
NULL
NULL
query I
SELECT rowid * 0 FROM test
----
0
0
# 0 / NULL = NULL
query I
SELECT 0 / a FROM test
----
NULL
NULL
statement ok
SET ieee_floating_point_ops=false;
query I
SELECT 0 / rowid FROM test
----
NULL
0

View File

@@ -0,0 +1,50 @@
# name: test/sql/optimizer/expression/test_timestamp_offset.test
# description: Test pushdown of varchars converted to timestamps
# group: [expression]
statement ok
PRAGMA enable_verification
statement ok
create or replace table table1 (
timestamp_str varchar
);
statement ok
insert into table1 values ('2024-05-03 01:00:00'), ('2024-05-03 01:00:02');
query II
select timestamp_str, cast(timestamp_str as timestamp)
from table1
where cast(timestamp_str as timestamp) > cast('2024-05-03 01:00:00' as timestamp);
----
2024-05-03 01:00:02 2024-05-03 01:00:02
statement ok
truncate table table1;
statement ok
insert into table1 values ('2024-05-03T01:00:00+00:00'), ('2024-05-03T01:00:02+00:00');
query II
select timestamp_str, cast(timestamp_str as timestamp)
from table1
where cast(timestamp_str as timestamp) > cast('2024-05-03 01:00:00' as timestamp);
----
2024-05-03T01:00:02+00:00 2024-05-03 01:00:02
query II
select timestamp_str, cast(timestamp_str as timestamp)
from table1
where cast(timestamp_str as timestamp) > cast('2024-05-03T01:00:00+00:00' as timestamp);
----
2024-05-03T01:00:02+00:00 2024-05-03 01:00:02
query II
select * from (
select timestamp_str, cast(timestamp_str as timestamp) as timestamp_column
from table1
)
where timestamp_column > cast('2024-05-03 01:00:00' as timestamp);
----
2024-05-03T01:00:02+00:00 2024-05-03 01:00:02