should be it
This commit is contained in:
152
external/duckdb/test/optimizer/statistics/statistics_aggregate.test
vendored
Normal file
152
external/duckdb/test/optimizer/statistics/statistics_aggregate.test
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
# name: test/optimizer/statistics/statistics_aggregate.test
|
||||
# description: Statistics propagation test with aggregates expression
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
SET default_null_order='nulls_first';
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# statistics propagation in groups
|
||||
# no null values
|
||||
query II
|
||||
EXPLAIN SELECT i IS NULL FROM (SELECT i FROM integers GROUP BY i) integers(i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS_NULL.*
|
||||
|
||||
# i=4 is out of range [1,3]
|
||||
query II
|
||||
EXPLAIN SELECT i=4 FROM (SELECT i FROM integers GROUP BY i) integers(i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i = 4\).*
|
||||
|
||||
# i=3 is in range [1,3]
|
||||
query II
|
||||
EXPLAIN SELECT i=3 FROM (SELECT i FROM integers GROUP BY i) integers(i);
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i = 3\).*
|
||||
|
||||
# count without null values
|
||||
query I
|
||||
SELECT COUNT(i) FROM integers;
|
||||
----
|
||||
3
|
||||
|
||||
query II
|
||||
SELECT i, COUNT(i) FROM integers GROUP BY i ORDER BY i;
|
||||
----
|
||||
1 1
|
||||
2 1
|
||||
3 1
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers VALUES (NULL);
|
||||
|
||||
# count with null values
|
||||
query I
|
||||
SELECT COUNT(i) FROM integers;
|
||||
----
|
||||
3
|
||||
|
||||
query II
|
||||
SELECT i, COUNT(i) FROM integers GROUP BY i ORDER BY i;
|
||||
----
|
||||
NULL 0
|
||||
1 1
|
||||
2 1
|
||||
3 1
|
||||
|
||||
# sum
|
||||
# sum that fits in int64
|
||||
statement ok
|
||||
CREATE TABLE bigints AS SELECT i::BIGINT as i FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
query I
|
||||
SELECT SUM(i) FROM bigints;
|
||||
----
|
||||
6
|
||||
|
||||
# avg
|
||||
query I
|
||||
SELECT AVG(i) FROM bigints;
|
||||
----
|
||||
2
|
||||
|
||||
# sum no longer fits in int64
|
||||
statement ok
|
||||
INSERT INTO bigints VALUES (9223372036854775806);
|
||||
|
||||
query I
|
||||
SELECT SUM(i) FROM bigints;
|
||||
----
|
||||
9223372036854775812
|
||||
|
||||
query I
|
||||
SELECT AVG(i) FROM bigints;
|
||||
----
|
||||
2305843009213693952
|
||||
|
||||
statement ok
|
||||
DROP TABLE bigints;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE bigints AS SELECT i::BIGINT as i FROM (VALUES (-1), (-2), (-3)) tbl(i);
|
||||
|
||||
query I
|
||||
SELECT SUM(i) FROM bigints;
|
||||
----
|
||||
-6
|
||||
|
||||
# avg
|
||||
query I
|
||||
SELECT AVG(i) FROM bigints;
|
||||
----
|
||||
-2
|
||||
|
||||
# sum no longer fits in int64 [negative]
|
||||
statement ok
|
||||
INSERT INTO bigints VALUES (-9223372036854775806);
|
||||
|
||||
query I
|
||||
SELECT SUM(i) FROM bigints;
|
||||
----
|
||||
-9223372036854775812
|
||||
|
||||
query I
|
||||
SELECT AVG(i) FROM bigints;
|
||||
----
|
||||
-2305843009213693952
|
||||
|
||||
# now with decimals
|
||||
# sum that fits in int64
|
||||
statement ok
|
||||
CREATE TABLE decimals AS SELECT i::DECIMAL(18,1) as i FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
query I
|
||||
SELECT SUM(i) FROM decimals;
|
||||
----
|
||||
6.0
|
||||
|
||||
# avg
|
||||
query I
|
||||
SELECT AVG(i) FROM decimals;
|
||||
----
|
||||
2.0
|
||||
|
||||
# sum no longer fits in int64
|
||||
statement ok
|
||||
INSERT INTO decimals SELECT 99999999999999999.9 FROM repeat(1, 10)
|
||||
|
||||
query I
|
||||
SELECT SUM(i) FROM decimals;
|
||||
----
|
||||
1000000000000000005.0
|
||||
|
||||
query I
|
||||
SELECT AVG(i) FROM decimals;
|
||||
----
|
||||
76923076923076923
|
||||
191
external/duckdb/test/optimizer/statistics/statistics_between.test
vendored
Normal file
191
external/duckdb/test/optimizer/statistics/statistics_between.test
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
# name: test/optimizer/statistics/statistics_between.test
|
||||
# description: Statistics propagation test with between expression
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# filter is out of range: no need to execute it
|
||||
query II
|
||||
EXPLAIN SELECT i=3 FROM integers WHERE i BETWEEN 0 AND 2
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i = 3\).*
|
||||
|
||||
# filter is in range: need to execute it
|
||||
query II
|
||||
EXPLAIN SELECT i=1 FROM integers WHERE i BETWEEN 0 AND 2
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i = 1\).*
|
||||
|
||||
# between where lhs is bigger than rhs: we can prune this entirely
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i BETWEEN 3 AND 2
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# now verify all of the results
|
||||
query I
|
||||
SELECT i=3 FROM integers WHERE i BETWEEN 0 AND 2;
|
||||
----
|
||||
0
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i=1 FROM integers WHERE i BETWEEN 0 AND 2;
|
||||
----
|
||||
1
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i BETWEEN 3 AND 2;
|
||||
----
|
||||
|
||||
# now test the same with a subquery, where we don't have filter pushdown into the scan
|
||||
query II
|
||||
EXPLAIN SELECT i=3 FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 0 AND 2
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i = 3\).*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i=1 FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 0 AND 2
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i = 1\).*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 3 AND 2
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# lower clause is always true: between should be converted into i <= 2
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 0 AND 2;
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i <= 2\).*
|
||||
|
||||
# upper clause is always true: between should be converted into i >= 2
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 2 AND 10;
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i >= 2\).*
|
||||
|
||||
# between is always false
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN -1 AND 0;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i BETWEEN -1 AND 0 FROM (SELECT * FROM integers LIMIT 10) integers(i);
|
||||
----
|
||||
logical_opt <REGEX>:.*false.*
|
||||
|
||||
# verify the results
|
||||
query I
|
||||
SELECT i=3 FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 0 AND 2;
|
||||
----
|
||||
0
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i=1 FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 0 AND 2;
|
||||
----
|
||||
1
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 3 AND 2;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 0 AND 10;
|
||||
----
|
||||
1
|
||||
2
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 0 AND 2;
|
||||
----
|
||||
1
|
||||
2
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 2 AND 10;
|
||||
----
|
||||
2
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN -1 AND 0;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT i BETWEEN -1 AND 0 FROM (SELECT * FROM integers LIMIT 10) integers(i);
|
||||
----
|
||||
0
|
||||
0
|
||||
0
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = PHYSICAL_ONLY;
|
||||
|
||||
# wide between: both are always true, entire filter can be pruned. (happens during physical planning).
|
||||
# see https://github.com/duckdb/duckdb-fuzzer/issues/1357
|
||||
# https://github.com/duckdb/duckdb-fuzzer/issues/1358
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 0 AND 10;
|
||||
----
|
||||
physical_plan <!REGEX>:.*FILTER.*
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# now insert a null value
|
||||
statement ok
|
||||
INSERT INTO integers VALUES (NULL)
|
||||
|
||||
# between is always false or null: we can still prune the entire filter
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN -1 AND 0;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# between is always false or null: we can still prune the entire filter
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN -1 AND 0;
|
||||
----
|
||||
logical_opt <!REGEX>:.*FILTER.*
|
||||
|
||||
# however, if used in a select clause, we can only replace it with a constant_or_null clause
|
||||
query II
|
||||
EXPLAIN SELECT i BETWEEN -1 AND 0 FROM (SELECT * FROM integers LIMIT 10) integers(i);
|
||||
----
|
||||
logical_opt <REGEX>:.*constant_or_null.*
|
||||
|
||||
# in the case of null values we cannot prune the filter here
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 0 AND 10;
|
||||
----
|
||||
logical_opt <REGEX>:.*FILTER.*
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN -1 AND 0;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT i BETWEEN -1 AND 0 FROM (SELECT * FROM integers LIMIT 10) integers(i);
|
||||
----
|
||||
0
|
||||
0
|
||||
0
|
||||
NULL
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i BETWEEN 0 AND 10;
|
||||
----
|
||||
1
|
||||
2
|
||||
3
|
||||
46
external/duckdb/test/optimizer/statistics/statistics_case.test
vendored
Normal file
46
external/duckdb/test/optimizer/statistics/statistics_case.test
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
# name: test/optimizer/statistics/statistics_case.test
|
||||
# description: Test filter propagation in CASE expression
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
# "i" does not contain null values, so we can statically determine this will not be null
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE (CASE WHEN i=2 THEN i+1 ELSE i+2 END) IS NULL;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# we can't here, because one of the children of the case has null
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE (CASE WHEN i=2 THEN i+1 ELSE NULL END) IS NULL;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# now check overflow testing
|
||||
# this gives an overflow on the RHS
|
||||
statement error
|
||||
SELECT 123::TINYINT + (CASE WHEN i=2 THEN (i+1)::TINYINT ELSE (i+2)::TINYINT END) FROM integers;
|
||||
----
|
||||
<REGEX>:Out of Range Error:.*Overflow in addition.*
|
||||
|
||||
# this does not
|
||||
query I
|
||||
SELECT 122::TINYINT + (CASE WHEN i=2 THEN (i+1)::TINYINT ELSE (i+2)::TINYINT END) FROM integers;
|
||||
----
|
||||
125
|
||||
125
|
||||
127
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE (CASE WHEN i=2 THEN i+1 ELSE i+2 END) IS NULL;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE (CASE WHEN i=2 THEN i+1 ELSE NULL END) IS NULL;
|
||||
----
|
||||
1
|
||||
3
|
||||
109
external/duckdb/test/optimizer/statistics/statistics_coalesce.test
vendored
Normal file
109
external/duckdb/test/optimizer/statistics/statistics_coalesce.test
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
# name: test/optimizer/statistics/statistics_coalesce.test
|
||||
# description: Test statistics propagation in COALESCE expression
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
# "i" does not contain null values, so the coalesce expression is short-circuited
|
||||
# "17" is never output
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE (COALESCE(i, 17)=17);
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# adding NULLs randomly into the coalesce does not change anything
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE (COALESCE(NULL, NULL, NULL, i, NULL, 17)=17);
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# same here, i is never output, the expression is a constant false
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE (COALESCE(4, i, 17)=3);
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE (COALESCE(i, 4, 17)=3);
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# execute the queries
|
||||
query I
|
||||
SELECT * FROM integers WHERE (COALESCE(i, 17)=17);
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE (COALESCE(NULL, NULL, NULL, i, NULL, 17)=17);
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE (COALESCE(4, i, 17)=3);
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE (COALESCE(i, 4, 17)=3);
|
||||
----
|
||||
3
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers VALUES (NULL);
|
||||
|
||||
# after inserting a NULL, the coalesce result changes
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE (COALESCE(i, 17)=17);
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE (COALESCE(NULL, NULL, NULL, i, NULL, 17)=17);
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE (COALESCE(4, i, 17)=3);
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE (COALESCE(i, 4, 17)=3);
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# execute the queries
|
||||
query I
|
||||
SELECT * FROM integers WHERE (COALESCE(i, 17)=17);
|
||||
----
|
||||
NULL
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE (COALESCE(NULL, NULL, NULL, i, NULL, 17)=17);
|
||||
----
|
||||
NULL
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE (COALESCE(4, i, 17)=3);
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE (COALESCE(i, 4, 17)=3);
|
||||
----
|
||||
3
|
||||
|
||||
# Verification compares results, which are different for random().
|
||||
|
||||
statement ok
|
||||
PRAGMA disable_verification
|
||||
|
||||
statement ok
|
||||
PRAGMA disable_verify_fetch_row;
|
||||
|
||||
# COALESCE without statistics.
|
||||
|
||||
statement ok
|
||||
SELECT COALESCE (CASE WHEN RANDOM() < 100 THEN RANDOM() ELSE NULL END, NULL, 42)
|
||||
FROM range(10)
|
||||
259
external/duckdb/test/optimizer/statistics/statistics_filter.test_slow
vendored
Normal file
259
external/duckdb/test/optimizer/statistics/statistics_filter.test_slow
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
# name: test/optimizer/statistics/statistics_filter.test_slow
|
||||
# description: Statistics propagation test with filters
|
||||
# group: [statistics]
|
||||
|
||||
foreach type utinyint usmallint uinteger ubigint tinyint smallint integer bigint hugeint uhugeint float double
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT i::${type} i FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification
|
||||
|
||||
# = filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i=0;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i=4;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# = filter is in range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i=1;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# > filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i>3;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# > filter is in of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i>2;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# >= filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i>=4;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# >= filter is in of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i>=3;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# < filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i<1;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# < filter is in of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i<2;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# <= filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i<=0;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# <= filter is in of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i<=1;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# verify that all these queries return correct results
|
||||
query I
|
||||
SELECT * FROM integers WHERE i=0;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i=4;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i=1;
|
||||
----
|
||||
1
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i>3;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i>2;
|
||||
----
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i>=4;
|
||||
----
|
||||
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i>=3;
|
||||
----
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i<1;
|
||||
----
|
||||
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i<2;
|
||||
----
|
||||
1
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i<=0;
|
||||
----
|
||||
|
||||
|
||||
query I
|
||||
SELECT * FROM integers WHERE i<=1;
|
||||
----
|
||||
1
|
||||
|
||||
# we repeat everything we did above, but with a subquery with a limit
|
||||
# the limit prevents the filter from being pushed down into the scan
|
||||
# which causes these tests to test different behavior
|
||||
|
||||
# = filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i=0;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i=4;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# = filter is in range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i=1;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# > filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i>3;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# > filter is in of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i>2;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# >= filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i>=4;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# >= filter is in of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i>=3;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# < filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i<1;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# < filter is in of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i<2;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# <= filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i<=0;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# <= filter is in of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i<=1;
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# verify that all these queries return correct results
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i=0;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i=4;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i=1;
|
||||
----
|
||||
1
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i>3;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i>2;
|
||||
----
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i>=4;
|
||||
----
|
||||
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i>=3;
|
||||
----
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i<1;
|
||||
----
|
||||
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i<2;
|
||||
----
|
||||
1
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i<=0;
|
||||
----
|
||||
|
||||
|
||||
query I
|
||||
SELECT * FROM (SELECT * FROM integers LIMIT 10) integers(i) WHERE i<=1;
|
||||
----
|
||||
1
|
||||
|
||||
statement ok
|
||||
DROP TABLE integers;
|
||||
|
||||
endloop
|
||||
133
external/duckdb/test/optimizer/statistics/statistics_filter_multicolumn.test
vendored
Normal file
133
external/duckdb/test/optimizer/statistics/statistics_filter_multicolumn.test
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
# name: test/optimizer/statistics/statistics_filter_multicolumn.test
|
||||
# description: Statistics propagation through filters with multiple columns
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers2 AS SELECT * FROM (VALUES (2), (3), (4)) tbl(i);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# we can statically prove that i=1 is false
|
||||
query II
|
||||
EXPLAIN SELECT i=1 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i = 1\).*
|
||||
|
||||
# same with i=4
|
||||
query II
|
||||
EXPLAIN SELECT i=4 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i = 4\).*
|
||||
|
||||
# and with i>3
|
||||
query II
|
||||
EXPLAIN SELECT i>3 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i > 3\).*
|
||||
|
||||
# and with i<2
|
||||
query II
|
||||
EXPLAIN SELECT i<2 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i < 2\).*
|
||||
|
||||
# NOT the case for i>2
|
||||
query II
|
||||
EXPLAIN SELECT i>2 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i > 2\).*
|
||||
|
||||
# OR i<3
|
||||
query II
|
||||
EXPLAIN SELECT i<3 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i < 3\).*
|
||||
|
||||
# range joins
|
||||
# we again join two tables with i:[1, 3] on the left, and i:[2, 4] on the right
|
||||
# but now on i2.i<i1.i
|
||||
# the statistics are now: i1.i: [2,3], i2.i: [2, 3]
|
||||
# so we can prune i=4
|
||||
query II
|
||||
EXPLAIN SELECT i2.i=4 FROM integers i1 JOIN integers2 i2 ON (i2.i<i1.i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i = 4\).*
|
||||
|
||||
# or i=1
|
||||
query II
|
||||
EXPLAIN SELECT i1.i=1 FROM integers i1 JOIN integers2 i2 ON (i2.i<i1.i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i = 1\).*
|
||||
|
||||
# but not i=3
|
||||
query II
|
||||
EXPLAIN SELECT i2.i=3 FROM integers i1 JOIN integers2 i2 ON (i2.i<i1.i);
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i = 3\).*
|
||||
|
||||
# or i=2
|
||||
query II
|
||||
EXPLAIN SELECT i1.i=2 FROM integers i1 JOIN integers2 i2 ON (i2.i<i1.i);
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i = 2\).*
|
||||
|
||||
|
||||
query I
|
||||
SELECT i=1 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
0
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i=4 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
0
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i>3 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
0
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i<2 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
0
|
||||
0
|
||||
|
||||
query I rowsort
|
||||
SELECT i>2 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
0
|
||||
1
|
||||
|
||||
query I rowsort
|
||||
SELECT i<3 FROM integers JOIN integers2 USING (i);
|
||||
----
|
||||
0
|
||||
1
|
||||
|
||||
query I
|
||||
SELECT i2.i=4 FROM integers i1 JOIN integers2 i2 ON (i2.i<i1.i);
|
||||
----
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i1.i=1 FROM integers i1 JOIN integers2 i2 ON (i2.i<i1.i);
|
||||
----
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i2.i=3 FROM integers i1 JOIN integers2 i2 ON (i2.i<i1.i);
|
||||
----
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i1.i=2 FROM integers i1 JOIN integers2 i2 ON (i2.i<i1.i);
|
||||
----
|
||||
0
|
||||
139
external/duckdb/test/optimizer/statistics/statistics_is_null.test
vendored
Normal file
139
external/duckdb/test/optimizer/statistics/statistics_is_null.test
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
# name: test/optimizer/statistics/statistics_is_null.test
|
||||
# description: Test filter propagation in IS NULL/IS NOT NULL operands
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
SET default_null_order='nulls_first';
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers2 AS SELECT * FROM (VALUES (4), (5), (NULL)) tbl(i);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# we can statically determine IS NULL/IS NOT NULL are false, if there are no null values for this column
|
||||
query II
|
||||
EXPLAIN SELECT i IS NULL FROM integers;
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS NULL.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i IS NOT NULL FROM integers;
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS NOT NULL.*
|
||||
|
||||
# if there are null values, however, we have to execute the operator
|
||||
query II
|
||||
EXPLAIN SELECT i IS NULL FROM integers2;
|
||||
----
|
||||
logical_opt <REGEX>:.*IS NULL.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i IS NOT NULL FROM integers2;
|
||||
----
|
||||
logical_opt <REGEX>:.*IS NOT NULL.*
|
||||
|
||||
# filters remove null values, so even if the base column contains null values, we don't need to check IS NULL here
|
||||
query II
|
||||
EXPLAIN SELECT i IS NULL FROM integers2 WHERE i>0;
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS NULL.*
|
||||
|
||||
# left/right outer joins with false condition can convert to cross product with constant NULL value,
|
||||
# so we don't need to check IS NULL here, since it's always NULL
|
||||
query II
|
||||
EXPLAIN SELECT i2.i IS NULL FROM integers i1 LEFT JOIN integers i2 ON (false);
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS NULL.*
|
||||
|
||||
# full outer joins can introduce nulls, even if the base tables do not contain them
|
||||
query II
|
||||
EXPLAIN SELECT i1.i IS NULL FROM integers i1 FULL OUTER JOIN integers i2 ON (false);
|
||||
----
|
||||
logical_opt <REGEX>:.*IS NULL.*
|
||||
|
||||
# verify that all these queries produce the correct results
|
||||
query I
|
||||
SELECT i IS NULL FROM integers;
|
||||
----
|
||||
0
|
||||
0
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i IS NOT NULL FROM integers;
|
||||
----
|
||||
1
|
||||
1
|
||||
1
|
||||
|
||||
query I
|
||||
SELECT i IS NULL FROM integers2;
|
||||
----
|
||||
0
|
||||
0
|
||||
1
|
||||
|
||||
query I
|
||||
SELECT i IS NOT NULL FROM integers2;
|
||||
----
|
||||
1
|
||||
1
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i IS NULL FROM integers2 WHERE i>0;
|
||||
----
|
||||
0
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i2.i IS NULL FROM integers i1 LEFT JOIN integers i2 ON (false);
|
||||
----
|
||||
1
|
||||
1
|
||||
1
|
||||
|
||||
query I
|
||||
SELECT i1.i IS NULL FROM integers i1 FULL OUTER JOIN integers i2 ON (false) ORDER BY i1.i;
|
||||
----
|
||||
1
|
||||
1
|
||||
1
|
||||
0
|
||||
0
|
||||
0
|
||||
|
||||
# FIXME: we don't yet correctly track when columns don't contain valid values
|
||||
mode skip
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers3 AS SELECT * FROM (VALUES (NULL), (NULL), (NULL)) tbl(i);
|
||||
|
||||
# we can statically determine IS NULL/IS NOT NULL are true, if there are no valid values for this column
|
||||
query II
|
||||
EXPLAIN SELECT i IS NULL FROM integers3;
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS NULL.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i IS NOT NULL FROM integers3;
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS NOT NULL.*
|
||||
|
||||
query I
|
||||
SELECT i IS NULL FROM integers3;
|
||||
----
|
||||
true
|
||||
true
|
||||
true
|
||||
|
||||
query I
|
||||
SELECT i IS NOT NULL FROM integers3;
|
||||
----
|
||||
false
|
||||
false
|
||||
false
|
||||
184
external/duckdb/test/optimizer/statistics/statistics_join.test
vendored
Normal file
184
external/duckdb/test/optimizer/statistics/statistics_join.test
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
# name: test/optimizer/statistics/statistics_join.test
|
||||
# description: Statistics propagation test with joins
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers2 AS SELECT * FROM (VALUES (4), (5), (6)) tbl(i);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# inner join
|
||||
# join cannot match
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i=i2.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i>i2.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i>=i2.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i<i1.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i<=i1.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# join is guaranteed to match
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i<i2.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*CROSS_PRODUCT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i<=i2.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*CROSS_PRODUCT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i>i1.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*CROSS_PRODUCT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i>=i1.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*CROSS_PRODUCT.*
|
||||
|
||||
# left join
|
||||
# join cannot match
|
||||
# note that the result is not actually empty here; only the RHS is set to the empty result
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 LEFT JOIN integers2 i2 ON i1.i=i2.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# semi join
|
||||
# join cannot match: replaced with empty result
|
||||
query II
|
||||
explain select * from integers where i > any(select * from integers2) order by 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# join is guaranteed to match: entire join is stripped away
|
||||
query II
|
||||
explain select * from integers where i < any(select * from integers2) order by 1;
|
||||
----
|
||||
logical_opt <!REGEX>:.*JOIN.*
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i=i2.i ORDER BY 1;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i>i2.i ORDER BY 1;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i>=i2.i ORDER BY 1;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i<i1.i ORDER BY 1;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i<=i1.i ORDER BY 1;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i<i2.i ORDER BY 1;
|
||||
----
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
2
|
||||
3
|
||||
3
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i<=i2.i ORDER BY 1;
|
||||
----
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
2
|
||||
3
|
||||
3
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i>i1.i ORDER BY 1;
|
||||
----
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
2
|
||||
3
|
||||
3
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i>=i1.i ORDER BY 1;
|
||||
----
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
2
|
||||
3
|
||||
3
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 LEFT JOIN integers2 i2 ON i1.i=i2.i ORDER BY 1;
|
||||
----
|
||||
1
|
||||
2
|
||||
3
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 LEFT JOIN integers2 i2 ON i1.i<i2.i ORDER BY 1;
|
||||
----
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
2
|
||||
3
|
||||
3
|
||||
3
|
||||
|
||||
query I
|
||||
select * from integers where i > any(select * from integers2) order by 1;
|
||||
----
|
||||
|
||||
query I
|
||||
select * from integers where i < any(select * from integers2) order by 1;
|
||||
----
|
||||
1
|
||||
2
|
||||
3
|
||||
42
external/duckdb/test/optimizer/statistics/statistics_join_multicolumn.test
vendored
Normal file
42
external/duckdb/test/optimizer/statistics/statistics_join_multicolumn.test
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# name: test/optimizer/statistics/statistics_join_multicolumn.test
|
||||
# description: Statistics propagation through joins on multiple columns
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (1), (2), (10)) tbl(i);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers2 AS SELECT * FROM (VALUES (2, 5), (3, 6), (4, 7)) tbl(i, j);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# inner join
|
||||
# integers.i has [1, 10] as min max
|
||||
# integers2.i is [2, 4], integers2.j [5, 7]
|
||||
# we compare integers.i = integers2.i AND integers.i = integers2.j
|
||||
# these sets are disjoint, so we get an empty result
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON (i1.i=i2.i AND i1.i=i2.j);
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON (i1.i=i2.i AND i1.i>i2.j);
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# when we do i1.i < i2.j, the sets are no longer disjoint, because the set [2, 4] is smaller than the set [5, 7]
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON (i1.i=i2.i AND i1.i<i2.j);
|
||||
----
|
||||
logical_opt <!REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON (i1.i=i2.i AND i1.i=i2.j);
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON (i1.i=i2.i AND i1.i<i2.j);
|
||||
----
|
||||
2
|
||||
79
external/duckdb/test/optimizer/statistics/statistics_join_null.test
vendored
Normal file
79
external/duckdb/test/optimizer/statistics/statistics_join_null.test
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
# name: test/optimizer/statistics/statistics_join_null.test
|
||||
# description: Statistics propagation test with joins and null values
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (1), (2), (NULL)) tbl(i);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers2 AS SELECT * FROM (VALUES (4), (5), (NULL)) tbl(i);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# inner join
|
||||
# join cannot match: prune result
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i=i2.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
|
||||
# join is guaranteed to match... except there are null values!
|
||||
# we CANNOT convert to a cross product
|
||||
# (well... we could, if we would push a x IS NOT NULL filter on both sides)
|
||||
# (but that is for another day)
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i<i2.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <!REGEX>:.*CROSS_PRODUCT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i<=i2.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <!REGEX>:.*CROSS_PRODUCT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i>i1.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <!REGEX>:.*CROSS_PRODUCT.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i>=i1.i ORDER BY 1;
|
||||
----
|
||||
logical_opt <!REGEX>:.*CROSS_PRODUCT.*
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i=i2.i ORDER BY 1;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i<i2.i ORDER BY 1;
|
||||
----
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i1.i<=i2.i ORDER BY 1;
|
||||
----
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i>i1.i ORDER BY 1;
|
||||
----
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
|
||||
query I
|
||||
SELECT i1.i FROM integers i1 JOIN integers2 i2 ON i2.i>=i1.i ORDER BY 1;
|
||||
----
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
94
external/duckdb/test/optimizer/statistics/statistics_null_comparison.test
vendored
Normal file
94
external/duckdb/test/optimizer/statistics/statistics_null_comparison.test
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
# name: test/optimizer/statistics/statistics_null_comparison.test
|
||||
# description: Statistics propagation with comparisons and null values
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (10, 1), (20, 2), (30, NULL)) tbl(i, j);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers2 AS SELECT * FROM (VALUES (1), (2), (NULL)) tbl(i);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE t1 AS SELECT * FROM (VALUES (1)) tbl(c0);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE t2 AS SELECT * FROM (VALUES (NULL)) tbl(c0);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# this is statically false, but there are null values NOT in a filter, so we can't optimize it away
|
||||
# instead the comparison is replaced by a CONSTANT OR NULL
|
||||
query II
|
||||
EXPLAIN SELECT i=j FROM integers ORDER BY i;
|
||||
----
|
||||
logical_opt <REGEX>:.*constant_or_null.*
|
||||
|
||||
# if we put the same expression in a where clause, however, we CAN prune it
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i=j ORDER BY i;
|
||||
----
|
||||
logical_opt <!REGEX>:.*constant_or_null.*
|
||||
|
||||
# this is statically true, but there are null values, so we can't optimize it away
|
||||
query II
|
||||
EXPLAIN SELECT i>j FROM integers ORDER BY i;
|
||||
----
|
||||
logical_opt <REGEX>:.*constant_or_null.*
|
||||
|
||||
# if we put it in the where clause, we STILL can't prune it
|
||||
query II
|
||||
EXPLAIN SELECT * FROM integers WHERE i>j ORDER BY i;
|
||||
----
|
||||
logical_opt <REGEX>:.*constant_or_null.*
|
||||
|
||||
# now verify that the results are correct
|
||||
query I
|
||||
SELECT i=j FROM integers ORDER BY i;
|
||||
----
|
||||
0
|
||||
0
|
||||
NULL
|
||||
|
||||
query II
|
||||
SELECT * FROM integers WHERE i=j ORDER BY i;
|
||||
----
|
||||
|
||||
query I
|
||||
SELECT j=i FROM integers ORDER BY i;
|
||||
----
|
||||
0
|
||||
0
|
||||
NULL
|
||||
|
||||
query I
|
||||
SELECT i>j FROM integers ORDER BY i;
|
||||
----
|
||||
1
|
||||
1
|
||||
NULL
|
||||
|
||||
query II
|
||||
SELECT * FROM integers WHERE i>j ORDER BY i;
|
||||
----
|
||||
10 1
|
||||
20 2
|
||||
|
||||
# relate issue 17338
|
||||
query II
|
||||
SELECT * FROM t1 INNER JOIN t2 ON ((t2.c0)>=(t2.c0));
|
||||
----
|
||||
|
||||
statement ok
|
||||
INSERT INTO t2 VALUES(1);
|
||||
|
||||
# t2.c0>=t2.c0 means always true or null which is equals to is not null
|
||||
query II
|
||||
EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON ((t2.c0)>=(t2.c0));
|
||||
----
|
||||
logical_opt <REGEX>:.*IS NOT NULL.*
|
||||
|
||||
query II
|
||||
SELECT * FROM t1 INNER JOIN t2 ON ((t2.c0)>=(t2.c0));
|
||||
----
|
||||
1 1
|
||||
102
external/duckdb/test/optimizer/statistics/statistics_numeric.test
vendored
Normal file
102
external/duckdb/test/optimizer/statistics/statistics_numeric.test
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
# name: test/optimizer/statistics/statistics_numeric.test
|
||||
# description: Statistics propagation of numeric functions
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers(i INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers VALUES (1), (10);
|
||||
|
||||
# abs with only positive values
|
||||
query I
|
||||
SELECT ABS(i) FROM integers ORDER BY i
|
||||
----
|
||||
1
|
||||
10
|
||||
|
||||
query I
|
||||
SELECT STATS(ABS(i)) FROM integers LIMIT 1
|
||||
----
|
||||
<REGEX>:.*1.*10.*
|
||||
|
||||
# verify that the call to abs gets removed by the optimizer out
|
||||
query II
|
||||
EXPLAIN SELECT ABS(i) FROM integers ORDER BY i;
|
||||
----
|
||||
logical_opt <!REGEX>:.*abs.*
|
||||
|
||||
|
||||
# mix of positive and negative values
|
||||
statement ok
|
||||
INSERT INTO integers VALUES (-5)
|
||||
|
||||
query I
|
||||
SELECT STATS(ABS(i)) FROM integers LIMIT 1
|
||||
----
|
||||
<REGEX>:.*0.*10.*
|
||||
|
||||
query I
|
||||
SELECT ABS(i) FROM integers ORDER BY i
|
||||
----
|
||||
5
|
||||
1
|
||||
10
|
||||
|
||||
# the call to abs can no longer be removed
|
||||
query II
|
||||
EXPLAIN SELECT ABS(i) FROM integers ORDER BY i;
|
||||
----
|
||||
logical_opt <REGEX>:.*abs.*
|
||||
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers VALUES (-15)
|
||||
|
||||
query I
|
||||
SELECT STATS(ABS(i)) FROM integers LIMIT 1
|
||||
----
|
||||
<REGEX>:.*0.*15.*
|
||||
|
||||
query I
|
||||
SELECT ABS(i) FROM integers ORDER BY i
|
||||
----
|
||||
15
|
||||
5
|
||||
1
|
||||
10
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers VALUES (0)
|
||||
|
||||
query I
|
||||
SELECT STATS(ABS(i)) FROM integers LIMIT 1
|
||||
----
|
||||
<REGEX>:.*0.*15.*
|
||||
|
||||
query I
|
||||
SELECT ABS(i) FROM integers ORDER BY i
|
||||
----
|
||||
15
|
||||
5
|
||||
0
|
||||
1
|
||||
10
|
||||
|
||||
# only negative values
|
||||
statement ok
|
||||
DROP TABLE integers
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers(i INTEGER);
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers VALUES (-1), (-10);
|
||||
|
||||
query I
|
||||
SELECT STATS(ABS(i)) FROM integers LIMIT 1
|
||||
----
|
||||
<REGEX>:.*1.*10.*
|
||||
143
external/duckdb/test/optimizer/statistics/statistics_setop.test
vendored
Normal file
143
external/duckdb/test/optimizer/statistics/statistics_setop.test
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
# name: test/optimizer/statistics/statistics_setop.test
|
||||
# description: Statistics propagation test with set operations
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT * FROM (VALUES (1), (2), (3)) tbl(i);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers2 AS SELECT * FROM (VALUES (4), (5), (6)) tbl(i);
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers3 AS SELECT * FROM (VALUES (4), (5), (NULL)) tbl(i);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# union all
|
||||
# total min/max after union all is [1, 6]: 7 is out of bounds, so i=7 can be optimized away
|
||||
query II
|
||||
EXPLAIN SELECT i=7 FROM (SELECT * FROM integers UNION ALL SELECT * FROM integers2) tbl(i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i = 7\).*
|
||||
|
||||
# 5 is in bounds, so this cannot be optimized away
|
||||
query II
|
||||
EXPLAIN SELECT i=5 FROM (SELECT * FROM integers UNION ALL SELECT * FROM integers2) tbl(i);
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i = 5\).*
|
||||
|
||||
# neither integers nor integers2 has null values, so this is false
|
||||
query II
|
||||
EXPLAIN SELECT i IS NULL FROM (SELECT * FROM integers UNION ALL SELECT * FROM integers2) tbl(i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS NULL.*
|
||||
|
||||
# integers3 has null values, so once we include integers3 we need to execute the IS_NULL predicate
|
||||
query II
|
||||
EXPLAIN SELECT i IS NULL FROM (SELECT * FROM integers UNION ALL SELECT * FROM integers2 UNION ALL SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
logical_opt <REGEX>:.*IS NULL.*
|
||||
|
||||
# except
|
||||
# except has the same stats as the LHS (as in the worst case, nothing is filtered out)
|
||||
# in this case the LHS stats are [4, 6] without null values
|
||||
query II
|
||||
EXPLAIN SELECT i=7 FROM (SELECT * FROM integers2 EXCEPT SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i = 7\).*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i=5 FROM (SELECT * FROM integers2 EXCEPT SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i = 5\).*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i IS NULL FROM (SELECT * FROM integers2 EXCEPT SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS NULL.*
|
||||
|
||||
# intersect
|
||||
# intersect has as stats the intersection of the LHS with the RHS
|
||||
# in this case that would be [4, 5] with no null values
|
||||
# however, we don't actually intersect the stats yet, so limit our testing to the stats of the LHS
|
||||
query II
|
||||
EXPLAIN SELECT i=7 FROM (SELECT * FROM integers2 INTERSECT SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
logical_opt <!REGEX>:.*\(i = 7\).*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i=5 FROM (SELECT * FROM integers2 INTERSECT SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
logical_opt <REGEX>:.*\(i = 5\).*
|
||||
|
||||
# now check the results of all these queries
|
||||
query I
|
||||
SELECT i=7 FROM (SELECT * FROM integers UNION ALL SELECT * FROM integers2) tbl(i);
|
||||
----
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i=5 FROM (SELECT * FROM integers UNION ALL SELECT * FROM integers2) tbl(i);
|
||||
----
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
1
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i IS NULL FROM (SELECT * FROM integers UNION ALL SELECT * FROM integers2) tbl(i);
|
||||
----
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i IS NULL FROM (SELECT * FROM integers UNION ALL SELECT * FROM integers2 UNION ALL SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
1
|
||||
|
||||
query I
|
||||
SELECT i=7 FROM (SELECT * FROM integers2 EXCEPT SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i=5 FROM (SELECT * FROM integers2 EXCEPT SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i IS NULL FROM (SELECT * FROM integers2 EXCEPT SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i=7 FROM (SELECT * FROM integers2 INTERSECT SELECT * FROM integers3) tbl(i);
|
||||
----
|
||||
0
|
||||
0
|
||||
|
||||
query I
|
||||
SELECT i=5 FROM (SELECT * FROM integers2 INTERSECT SELECT * FROM integers3) tbl(i) ORDER BY i;
|
||||
----
|
||||
0
|
||||
1
|
||||
27
external/duckdb/test/optimizer/statistics/statistics_struct.test
vendored
Normal file
27
external/duckdb/test/optimizer/statistics/statistics_struct.test
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# name: test/optimizer/statistics/statistics_struct.test
|
||||
# description: Statistics propagation test with structs
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE structs AS SELECT {'i': i} c FROM range(4) tbl(i);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# we can statically determine IS NULL/IS NOT NULL are false, if there are no null values for this column
|
||||
query II
|
||||
EXPLAIN SELECT c IS NULL FROM structs;
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS_NULL.*
|
||||
|
||||
# the same applies to c['i']
|
||||
query II
|
||||
EXPLAIN SELECT c['i'] IS NULL FROM structs;
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS_NULL.*
|
||||
|
||||
# filter is out of range
|
||||
query II
|
||||
EXPLAIN SELECT * FROM structs WHERE c['i']=4;
|
||||
----
|
||||
logical_opt <REGEX>:.*EMPTY_RESULT.*
|
||||
60
external/duckdb/test/optimizer/statistics/statistics_try_cast.test
vendored
Normal file
60
external/duckdb/test/optimizer/statistics/statistics_try_cast.test
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
# name: test/optimizer/statistics/statistics_try_cast.test
|
||||
# description: Statistics with try cast
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers AS SELECT range i FROM range(5)
|
||||
|
||||
query I
|
||||
SELECT i::TINYINT IS NULL FROM integers
|
||||
----
|
||||
False
|
||||
False
|
||||
False
|
||||
False
|
||||
False
|
||||
|
||||
query I
|
||||
SELECT TRY_CAST(i AS TINYINT) IS NULL FROM integers
|
||||
----
|
||||
False
|
||||
False
|
||||
False
|
||||
False
|
||||
False
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT i::TINYINT IS NULL FROM integers
|
||||
----
|
||||
logical_opt <!REGEX>:.*IS.*NULL.*
|
||||
|
||||
query II
|
||||
EXPLAIN SELECT (TRY_CAST(i AS TINYINT)) IS NULL FROM integers
|
||||
----
|
||||
logical_opt <REGEX>:.*IS.*NULL.*
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers VALUES (255)
|
||||
|
||||
query I
|
||||
SELECT TRY_CAST(i AS TINYINT) FROM integers
|
||||
----
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
NULL
|
||||
|
||||
query I
|
||||
SELECT TRY_CAST(i AS TINYINT) IS NULL FROM integers
|
||||
----
|
||||
False
|
||||
False
|
||||
False
|
||||
False
|
||||
False
|
||||
True
|
||||
74
external/duckdb/test/optimizer/statistics/statistics_varchar.test
vendored
Normal file
74
external/duckdb/test/optimizer/statistics/statistics_varchar.test
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
# name: test/optimizer/statistics/statistics_varchar.test
|
||||
# description: Statistics propagation test with varchars
|
||||
# group: [statistics]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE varchars AS SELECT * FROM (VALUES ('Mark'), ('Hannes'), ('World')) tbl(v);
|
||||
|
||||
statement ok
|
||||
PRAGMA explain_output = OPTIMIZED_ONLY;
|
||||
|
||||
# no unicode
|
||||
query II
|
||||
SELECT LENGTH(v), STRLEN(v) FROM varchars
|
||||
----
|
||||
4 4
|
||||
6 6
|
||||
5 5
|
||||
|
||||
query I
|
||||
SELECT STRPOS(v, 'e') FROM varchars
|
||||
----
|
||||
0
|
||||
5
|
||||
0
|
||||
|
||||
query II
|
||||
SELECT UPPER(v), LOWER(v) FROM varchars
|
||||
----
|
||||
MARK mark
|
||||
HANNES hannes
|
||||
WORLD world
|
||||
|
||||
query I
|
||||
SELECT SUBSTR(v, 2, 2) FROM varchars
|
||||
----
|
||||
ar
|
||||
an
|
||||
or
|
||||
|
||||
# unicode
|
||||
statement ok
|
||||
INSERT INTO varchars VALUES ('Mühleisen');
|
||||
|
||||
query II
|
||||
SELECT LENGTH(v), STRLEN(v) FROM varchars
|
||||
----
|
||||
4 4
|
||||
6 6
|
||||
5 5
|
||||
9 10
|
||||
|
||||
query I
|
||||
SELECT STRPOS(v, 'e') FROM varchars
|
||||
----
|
||||
0
|
||||
5
|
||||
0
|
||||
5
|
||||
|
||||
query II
|
||||
SELECT UPPER(v), LOWER(v) FROM varchars
|
||||
----
|
||||
MARK mark
|
||||
HANNES hannes
|
||||
WORLD world
|
||||
MÜHLEISEN mühleisen
|
||||
|
||||
query I
|
||||
SELECT SUBSTR(v, 2, 2) FROM varchars
|
||||
----
|
||||
ar
|
||||
an
|
||||
or
|
||||
üh
|
||||
Reference in New Issue
Block a user