File: statistics_between.test

package info (click to toggle)
duckdb 1.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 299,196 kB
  • sloc: cpp: 865,414; ansic: 57,292; python: 18,871; sql: 12,663; lisp: 11,751; yacc: 7,412; lex: 1,682; sh: 747; makefile: 558
file content (191 lines) | stat: -rw-r--r-- 4,798 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
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