blob: 30fcdf287fe329f94857f60a68a24fa6094f4345 [file] [log] [blame]
dan2ce22452010-11-08 19:01:16 +00001# 2010 November 6
2#
3# The author disclaims copyright to this source code. In place of
4# a legal notice, here is a blessing:
5#
6# May you do good and not evil.
7# May you find forgiveness for yourself and forgive others.
8# May you share freely, never taking more than you give.
9#
10#***********************************************************************
11#
12
13set testdir [file dirname $argv0]
14source $testdir/tester.tcl
15
dan2f56da32012-02-13 10:00:35 +000016ifcapable !compound {
17 finish_test
18 return
19}
20
dan2ce22452010-11-08 19:01:16 +000021set testprefix eqp
22
23#-------------------------------------------------------------------------
24#
25# eqp-1.*: Assorted tests.
26# eqp-2.*: Tests for single select statements.
27# eqp-3.*: Select statements that execute sub-selects.
28# eqp-4.*: Compound select statements.
danef7075d2011-02-21 17:49:49 +000029# ...
30# eqp-7.*: "SELECT count(*) FROM tbl" statements (VDBE code OP_Count).
dan2ce22452010-11-08 19:01:16 +000031#
32
dan4a07e3d2010-11-09 14:48:59 +000033proc det {args} { uplevel do_eqp_test $args }
dan2ce22452010-11-08 19:01:16 +000034
35do_execsql_test 1.1 {
drhd9e3cad2013-10-04 02:36:19 +000036 CREATE TABLE t1(a INT, b INT, ex TEXT);
dan2ce22452010-11-08 19:01:16 +000037 CREATE INDEX i1 ON t1(a);
38 CREATE INDEX i2 ON t1(b);
drhd9e3cad2013-10-04 02:36:19 +000039 CREATE TABLE t2(a INT, b INT, ex TEXT);
40 CREATE TABLE t3(a INT, b INT, ex TEXT);
dan2ce22452010-11-08 19:01:16 +000041}
42
43do_eqp_test 1.2 {
44 SELECT * FROM t2, t1 WHERE t1.a=1 OR t1.b=2;
45} {
drh5822d6f2013-06-10 23:30:09 +000046 0 0 1 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
47 0 0 1 {SEARCH TABLE t1 USING INDEX i2 (b=?)}
48 0 1 0 {SCAN TABLE t2}
dan2ce22452010-11-08 19:01:16 +000049}
50do_eqp_test 1.3 {
51 SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=1 OR t1.b=2;
52} {
drh5822d6f2013-06-10 23:30:09 +000053 0 0 0 {SCAN TABLE t2}
54 0 1 1 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
55 0 1 1 {SEARCH TABLE t1 USING INDEX i2 (b=?)}
dan2ce22452010-11-08 19:01:16 +000056}
57do_eqp_test 1.3 {
58 SELECT a FROM t1 ORDER BY a
59} {
drh5822d6f2013-06-10 23:30:09 +000060 0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
dan2ce22452010-11-08 19:01:16 +000061}
62do_eqp_test 1.4 {
63 SELECT a FROM t1 ORDER BY +a
64} {
drh5822d6f2013-06-10 23:30:09 +000065 0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
dan2ce22452010-11-08 19:01:16 +000066 0 0 0 {USE TEMP B-TREE FOR ORDER BY}
67}
68do_eqp_test 1.5 {
69 SELECT a FROM t1 WHERE a=4
70} {
drh5822d6f2013-06-10 23:30:09 +000071 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
dan2ce22452010-11-08 19:01:16 +000072}
73do_eqp_test 1.6 {
74 SELECT DISTINCT count(*) FROM t3 GROUP BY a;
75} {
drh5822d6f2013-06-10 23:30:09 +000076 0 0 0 {SCAN TABLE t3}
dan2ce22452010-11-08 19:01:16 +000077 0 0 0 {USE TEMP B-TREE FOR GROUP BY}
78 0 0 0 {USE TEMP B-TREE FOR DISTINCT}
79}
80
drh95aa47b2010-11-16 02:49:15 +000081do_eqp_test 1.7 {
82 SELECT * FROM t3 JOIN (SELECT 1)
83} {
drh5822d6f2013-06-10 23:30:09 +000084 0 0 1 {SCAN SUBQUERY 1}
85 0 1 0 {SCAN TABLE t3}
drh95aa47b2010-11-16 02:49:15 +000086}
87do_eqp_test 1.8 {
88 SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
89} {
90 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
drh5822d6f2013-06-10 23:30:09 +000091 0 0 1 {SCAN SUBQUERY 1}
92 0 1 0 {SCAN TABLE t3}
drh95aa47b2010-11-16 02:49:15 +000093}
94do_eqp_test 1.9 {
95 SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
96} {
drh5822d6f2013-06-10 23:30:09 +000097 3 0 0 {SCAN TABLE t3}
drh95aa47b2010-11-16 02:49:15 +000098 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (EXCEPT)}
drh5822d6f2013-06-10 23:30:09 +000099 0 0 1 {SCAN SUBQUERY 1}
100 0 1 0 {SCAN TABLE t3}
drh95aa47b2010-11-16 02:49:15 +0000101}
102do_eqp_test 1.10 {
103 SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
104} {
drh5822d6f2013-06-10 23:30:09 +0000105 3 0 0 {SCAN TABLE t3}
drh95aa47b2010-11-16 02:49:15 +0000106 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (INTERSECT)}
drh5822d6f2013-06-10 23:30:09 +0000107 0 0 1 {SCAN SUBQUERY 1}
108 0 1 0 {SCAN TABLE t3}
drh95aa47b2010-11-16 02:49:15 +0000109}
110
111do_eqp_test 1.11 {
112 SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17)
113} {
drh5822d6f2013-06-10 23:30:09 +0000114 3 0 0 {SCAN TABLE t3}
drh95aa47b2010-11-16 02:49:15 +0000115 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)}
drh5822d6f2013-06-10 23:30:09 +0000116 0 0 1 {SCAN SUBQUERY 1}
117 0 1 0 {SCAN TABLE t3}
drh95aa47b2010-11-16 02:49:15 +0000118}
119
dan2ce22452010-11-08 19:01:16 +0000120#-------------------------------------------------------------------------
121# Test cases eqp-2.* - tests for single select statements.
122#
123drop_all_tables
124do_execsql_test 2.1 {
drhd9e3cad2013-10-04 02:36:19 +0000125 CREATE TABLE t1(x INT, y INT, ex TEXT);
dan2ce22452010-11-08 19:01:16 +0000126
drhd9e3cad2013-10-04 02:36:19 +0000127 CREATE TABLE t2(x INT, y INT, ex TEXT);
dan2ce22452010-11-08 19:01:16 +0000128 CREATE INDEX t2i1 ON t2(x);
129}
130
dan4a07e3d2010-11-09 14:48:59 +0000131det 2.2.1 "SELECT DISTINCT min(x), max(x) FROM t1 GROUP BY x ORDER BY 1" {
drh5822d6f2013-06-10 23:30:09 +0000132 0 0 0 {SCAN TABLE t1}
dan2ce22452010-11-08 19:01:16 +0000133 0 0 0 {USE TEMP B-TREE FOR GROUP BY}
134 0 0 0 {USE TEMP B-TREE FOR DISTINCT}
135 0 0 0 {USE TEMP B-TREE FOR ORDER BY}
136}
dan4a07e3d2010-11-09 14:48:59 +0000137det 2.2.2 "SELECT DISTINCT min(x), max(x) FROM t2 GROUP BY x ORDER BY 1" {
drh5822d6f2013-06-10 23:30:09 +0000138 0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
dan2ce22452010-11-08 19:01:16 +0000139 0 0 0 {USE TEMP B-TREE FOR DISTINCT}
140 0 0 0 {USE TEMP B-TREE FOR ORDER BY}
141}
dan4a07e3d2010-11-09 14:48:59 +0000142det 2.2.3 "SELECT DISTINCT * FROM t1" {
drh5822d6f2013-06-10 23:30:09 +0000143 0 0 0 {SCAN TABLE t1}
dan4a07e3d2010-11-09 14:48:59 +0000144 0 0 0 {USE TEMP B-TREE FOR DISTINCT}
145}
146det 2.2.4 "SELECT DISTINCT * FROM t1, t2" {
drh5822d6f2013-06-10 23:30:09 +0000147 0 0 0 {SCAN TABLE t1}
148 0 1 1 {SCAN TABLE t2}
dan4a07e3d2010-11-09 14:48:59 +0000149 0 0 0 {USE TEMP B-TREE FOR DISTINCT}
150}
151det 2.2.5 "SELECT DISTINCT * FROM t1, t2 ORDER BY t1.x" {
drh5822d6f2013-06-10 23:30:09 +0000152 0 0 0 {SCAN TABLE t1}
153 0 1 1 {SCAN TABLE t2}
dan4a07e3d2010-11-09 14:48:59 +0000154 0 0 0 {USE TEMP B-TREE FOR DISTINCT}
155 0 0 0 {USE TEMP B-TREE FOR ORDER BY}
156}
157det 2.2.6 "SELECT DISTINCT t2.x FROM t1, t2 ORDER BY t2.x" {
drh5822d6f2013-06-10 23:30:09 +0000158 0 0 1 {SCAN TABLE t2 USING COVERING INDEX t2i1}
159 0 1 0 {SCAN TABLE t1}
dan4a07e3d2010-11-09 14:48:59 +0000160}
161
162det 2.3.1 "SELECT max(x) FROM t2" {
drh5822d6f2013-06-10 23:30:09 +0000163 0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1}
dan4a07e3d2010-11-09 14:48:59 +0000164}
165det 2.3.2 "SELECT min(x) FROM t2" {
drh5822d6f2013-06-10 23:30:09 +0000166 0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1}
dan4a07e3d2010-11-09 14:48:59 +0000167}
168det 2.3.3 "SELECT min(x), max(x) FROM t2" {
drh5822d6f2013-06-10 23:30:09 +0000169 0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
dan4a07e3d2010-11-09 14:48:59 +0000170}
171
172det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {
drh5822d6f2013-06-10 23:30:09 +0000173 0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)}
dan4a07e3d2010-11-09 14:48:59 +0000174}
175
176
dan2ce22452010-11-08 19:01:16 +0000177
178#-------------------------------------------------------------------------
179# Test cases eqp-3.* - tests for select statements that use sub-selects.
180#
181do_eqp_test 3.1.1 {
182 SELECT (SELECT x FROM t1 AS sub) FROM t1;
183} {
drh5822d6f2013-06-10 23:30:09 +0000184 0 0 0 {SCAN TABLE t1}
dan4a07e3d2010-11-09 14:48:59 +0000185 0 0 0 {EXECUTE SCALAR SUBQUERY 1}
drh5822d6f2013-06-10 23:30:09 +0000186 1 0 0 {SCAN TABLE t1 AS sub}
dan4a07e3d2010-11-09 14:48:59 +0000187}
188do_eqp_test 3.1.2 {
189 SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
190} {
dan4a07e3d2010-11-09 14:48:59 +0000191 0 0 0 {EXECUTE SCALAR SUBQUERY 1}
drh5822d6f2013-06-10 23:30:09 +0000192 1 0 0 {SCAN TABLE t1 AS sub}
danc456a762017-06-22 16:51:16 +0000193 0 0 0 {SCAN TABLE t1}
dan4a07e3d2010-11-09 14:48:59 +0000194}
195do_eqp_test 3.1.3 {
196 SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y);
197} {
dan4a07e3d2010-11-09 14:48:59 +0000198 0 0 0 {EXECUTE SCALAR SUBQUERY 1}
drh5822d6f2013-06-10 23:30:09 +0000199 1 0 0 {SCAN TABLE t1 AS sub}
dan4a07e3d2010-11-09 14:48:59 +0000200 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
danc456a762017-06-22 16:51:16 +0000201 0 0 0 {SCAN TABLE t1}
dan4a07e3d2010-11-09 14:48:59 +0000202}
203do_eqp_test 3.1.4 {
204 SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x);
205} {
dan4a07e3d2010-11-09 14:48:59 +0000206 0 0 0 {EXECUTE SCALAR SUBQUERY 1}
drh5822d6f2013-06-10 23:30:09 +0000207 1 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
danc456a762017-06-22 16:51:16 +0000208 0 0 0 {SCAN TABLE t1}
dan4a07e3d2010-11-09 14:48:59 +0000209}
210
211det 3.2.1 {
212 SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY y LIMIT 5
213} {
drh5822d6f2013-06-10 23:30:09 +0000214 1 0 0 {SCAN TABLE t1}
dan4a07e3d2010-11-09 14:48:59 +0000215 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
drh5822d6f2013-06-10 23:30:09 +0000216 0 0 0 {SCAN SUBQUERY 1}
dan4a07e3d2010-11-09 14:48:59 +0000217 0 0 0 {USE TEMP B-TREE FOR ORDER BY}
218}
219det 3.2.2 {
220 SELECT * FROM
221 (SELECT * FROM t1 ORDER BY x LIMIT 10) AS x1,
222 (SELECT * FROM t2 ORDER BY x LIMIT 10) AS x2
223 ORDER BY x2.y LIMIT 5
224} {
drh5822d6f2013-06-10 23:30:09 +0000225 1 0 0 {SCAN TABLE t1}
dan4a07e3d2010-11-09 14:48:59 +0000226 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
drh5822d6f2013-06-10 23:30:09 +0000227 2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
228 0 0 0 {SCAN SUBQUERY 1 AS x1}
229 0 1 1 {SCAN SUBQUERY 2 AS x2}
dan4a07e3d2010-11-09 14:48:59 +0000230 0 0 0 {USE TEMP B-TREE FOR ORDER BY}
dan2ce22452010-11-08 19:01:16 +0000231}
232
dan47eb16d2010-11-11 10:36:25 +0000233det 3.3.1 {
234 SELECT * FROM t1 WHERE y IN (SELECT y FROM t2)
235} {
drh5822d6f2013-06-10 23:30:09 +0000236 0 0 0 {SCAN TABLE t1}
dan47eb16d2010-11-11 10:36:25 +0000237 0 0 0 {EXECUTE LIST SUBQUERY 1}
drh5822d6f2013-06-10 23:30:09 +0000238 1 0 0 {SCAN TABLE t2}
dan47eb16d2010-11-11 10:36:25 +0000239}
240det 3.3.2 {
241 SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x)
242} {
drh5822d6f2013-06-10 23:30:09 +0000243 0 0 0 {SCAN TABLE t1}
dan47eb16d2010-11-11 10:36:25 +0000244 0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1}
drh5822d6f2013-06-10 23:30:09 +0000245 1 0 0 {SCAN TABLE t2}
dan47eb16d2010-11-11 10:36:25 +0000246}
247det 3.3.3 {
248 SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x)
249} {
drh5822d6f2013-06-10 23:30:09 +0000250 0 0 0 {SCAN TABLE t1}
dan47eb16d2010-11-11 10:36:25 +0000251 0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 1}
drh5822d6f2013-06-10 23:30:09 +0000252 1 0 0 {SCAN TABLE t2}
dan47eb16d2010-11-11 10:36:25 +0000253}
254
dan2ce22452010-11-08 19:01:16 +0000255#-------------------------------------------------------------------------
dan4a07e3d2010-11-09 14:48:59 +0000256# Test cases eqp-4.* - tests for composite select statements.
dan2ce22452010-11-08 19:01:16 +0000257#
258do_eqp_test 4.1.1 {
259 SELECT * FROM t1 UNION ALL SELECT * FROM t2
260} {
drh5822d6f2013-06-10 23:30:09 +0000261 1 0 0 {SCAN TABLE t1}
262 2 0 0 {SCAN TABLE t2}
dan30969d32010-11-11 17:48:51 +0000263 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
dan2ce22452010-11-08 19:01:16 +0000264}
265do_eqp_test 4.1.2 {
266 SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 2
267} {
drh5822d6f2013-06-10 23:30:09 +0000268 1 0 0 {SCAN TABLE t1}
dan2ce22452010-11-08 19:01:16 +0000269 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
drh5822d6f2013-06-10 23:30:09 +0000270 2 0 0 {SCAN TABLE t2}
dan2ce22452010-11-08 19:01:16 +0000271 2 0 0 {USE TEMP B-TREE FOR ORDER BY}
dan30969d32010-11-11 17:48:51 +0000272 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
dan2ce22452010-11-08 19:01:16 +0000273}
274do_eqp_test 4.1.3 {
275 SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 2
276} {
drh5822d6f2013-06-10 23:30:09 +0000277 1 0 0 {SCAN TABLE t1}
dan2ce22452010-11-08 19:01:16 +0000278 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
drh5822d6f2013-06-10 23:30:09 +0000279 2 0 0 {SCAN TABLE t2}
dan2ce22452010-11-08 19:01:16 +0000280 2 0 0 {USE TEMP B-TREE FOR ORDER BY}
dan30969d32010-11-11 17:48:51 +0000281 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)}
dan2ce22452010-11-08 19:01:16 +0000282}
283do_eqp_test 4.1.4 {
284 SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 2
285} {
drh5822d6f2013-06-10 23:30:09 +0000286 1 0 0 {SCAN TABLE t1}
dan2ce22452010-11-08 19:01:16 +0000287 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
drh5822d6f2013-06-10 23:30:09 +0000288 2 0 0 {SCAN TABLE t2}
dan2ce22452010-11-08 19:01:16 +0000289 2 0 0 {USE TEMP B-TREE FOR ORDER BY}
dan30969d32010-11-11 17:48:51 +0000290 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)}
dan2ce22452010-11-08 19:01:16 +0000291}
292do_eqp_test 4.1.5 {
293 SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 2
294} {
drh5822d6f2013-06-10 23:30:09 +0000295 1 0 0 {SCAN TABLE t1}
dan2ce22452010-11-08 19:01:16 +0000296 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
drh5822d6f2013-06-10 23:30:09 +0000297 2 0 0 {SCAN TABLE t2}
dan2ce22452010-11-08 19:01:16 +0000298 2 0 0 {USE TEMP B-TREE FOR ORDER BY}
dan30969d32010-11-11 17:48:51 +0000299 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
dan2ce22452010-11-08 19:01:16 +0000300}
301
302do_eqp_test 4.2.2 {
303 SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 1
304} {
drh5822d6f2013-06-10 23:30:09 +0000305 1 0 0 {SCAN TABLE t1}
dan2ce22452010-11-08 19:01:16 +0000306 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
drh5822d6f2013-06-10 23:30:09 +0000307 2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
dan30969d32010-11-11 17:48:51 +0000308 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
dan2ce22452010-11-08 19:01:16 +0000309}
dan2ce22452010-11-08 19:01:16 +0000310do_eqp_test 4.2.3 {
311 SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 1
312} {
drh5822d6f2013-06-10 23:30:09 +0000313 1 0 0 {SCAN TABLE t1}
dan2ce22452010-11-08 19:01:16 +0000314 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
dan75525cb2014-04-30 14:53:21 +0000315 2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
316 2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
dan30969d32010-11-11 17:48:51 +0000317 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)}
dan2ce22452010-11-08 19:01:16 +0000318}
319do_eqp_test 4.2.4 {
320 SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 1
321} {
drh5822d6f2013-06-10 23:30:09 +0000322 1 0 0 {SCAN TABLE t1}
dan2ce22452010-11-08 19:01:16 +0000323 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
dan75525cb2014-04-30 14:53:21 +0000324 2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
325 2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
dan30969d32010-11-11 17:48:51 +0000326 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)}
dan2ce22452010-11-08 19:01:16 +0000327}
328do_eqp_test 4.2.5 {
329 SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 1
330} {
drh5822d6f2013-06-10 23:30:09 +0000331 1 0 0 {SCAN TABLE t1}
dan2ce22452010-11-08 19:01:16 +0000332 1 0 0 {USE TEMP B-TREE FOR ORDER BY}
dan75525cb2014-04-30 14:53:21 +0000333 2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
334 2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
dan30969d32010-11-11 17:48:51 +0000335 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
dan2ce22452010-11-08 19:01:16 +0000336}
337
dan4a07e3d2010-11-09 14:48:59 +0000338do_eqp_test 4.3.1 {
339 SELECT x FROM t1 UNION SELECT x FROM t2
340} {
drh5822d6f2013-06-10 23:30:09 +0000341 1 0 0 {SCAN TABLE t1}
342 2 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
dan30969d32010-11-11 17:48:51 +0000343 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
dan7f61e922010-11-11 16:46:40 +0000344}
345
346do_eqp_test 4.3.2 {
347 SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1
348} {
drh5822d6f2013-06-10 23:30:09 +0000349 2 0 0 {SCAN TABLE t1}
350 3 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
dan30969d32010-11-11 17:48:51 +0000351 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
drh5822d6f2013-06-10 23:30:09 +0000352 4 0 0 {SCAN TABLE t1}
dan30969d32010-11-11 17:48:51 +0000353 0 0 0 {COMPOUND SUBQUERIES 1 AND 4 USING TEMP B-TREE (UNION)}
dan7f61e922010-11-11 16:46:40 +0000354}
355do_eqp_test 4.3.3 {
356 SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER BY 1
357} {
drh5822d6f2013-06-10 23:30:09 +0000358 2 0 0 {SCAN TABLE t1}
dan7f61e922010-11-11 16:46:40 +0000359 2 0 0 {USE TEMP B-TREE FOR ORDER BY}
drh5822d6f2013-06-10 23:30:09 +0000360 3 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
dan30969d32010-11-11 17:48:51 +0000361 1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION)}
drh5822d6f2013-06-10 23:30:09 +0000362 4 0 0 {SCAN TABLE t1}
dan7f61e922010-11-11 16:46:40 +0000363 4 0 0 {USE TEMP B-TREE FOR ORDER BY}
dan30969d32010-11-11 17:48:51 +0000364 0 0 0 {COMPOUND SUBQUERIES 1 AND 4 (UNION)}
dan4a07e3d2010-11-09 14:48:59 +0000365}
dan2ce22452010-11-08 19:01:16 +0000366
danfa00aa22010-11-12 17:41:37 +0000367#-------------------------------------------------------------------------
368# This next block of tests verifies that the examples on the
369# lang_explain.html page are correct.
370#
371drop_all_tables
372
drh39759742013-08-02 23:40:45 +0000373# EVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b
374# FROM t1 WHERE a=1;
375# 0|0|0|SCAN TABLE t1
376#
drhd9e3cad2013-10-04 02:36:19 +0000377do_execsql_test 5.1.0 { CREATE TABLE t1(a INT, b INT, ex TEXT) }
danfa00aa22010-11-12 17:41:37 +0000378det 5.1.1 "SELECT a, b FROM t1 WHERE a=1" {
drh5822d6f2013-06-10 23:30:09 +0000379 0 0 0 {SCAN TABLE t1}
danfa00aa22010-11-12 17:41:37 +0000380}
381
drh39759742013-08-02 23:40:45 +0000382# EVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a);
danfa00aa22010-11-12 17:41:37 +0000383# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
drh39759742013-08-02 23:40:45 +0000384# 0|0|0|SEARCH TABLE t1 USING INDEX i1
385#
danfa00aa22010-11-12 17:41:37 +0000386do_execsql_test 5.2.0 { CREATE INDEX i1 ON t1(a) }
387det 5.2.1 "SELECT a, b FROM t1 WHERE a=1" {
drh5822d6f2013-06-10 23:30:09 +0000388 0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
danfa00aa22010-11-12 17:41:37 +0000389}
390
drh39759742013-08-02 23:40:45 +0000391# EVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b);
danfa00aa22010-11-12 17:41:37 +0000392# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
drh5822d6f2013-06-10 23:30:09 +0000393# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
drh39759742013-08-02 23:40:45 +0000394#
danfa00aa22010-11-12 17:41:37 +0000395do_execsql_test 5.3.0 { CREATE INDEX i2 ON t1(a, b) }
396det 5.3.1 "SELECT a, b FROM t1 WHERE a=1" {
drh5822d6f2013-06-10 23:30:09 +0000397 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
danfa00aa22010-11-12 17:41:37 +0000398}
399
drh39759742013-08-02 23:40:45 +0000400# EVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN
401# SELECT t1.*, t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2;
402# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
403# 0|1|1|SCAN TABLE t2
drh5822d6f2013-06-10 23:30:09 +0000404#
drhd9e3cad2013-10-04 02:36:19 +0000405do_execsql_test 5.4.0 {CREATE TABLE t2(c INT, d INT, ex TEXT)}
406det 5.4.1 "SELECT t1.a, t2.c FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {
drh5822d6f2013-06-10 23:30:09 +0000407 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
408 0 1 1 {SCAN TABLE t2}
danfa00aa22010-11-12 17:41:37 +0000409}
410
drh39759742013-08-02 23:40:45 +0000411# EVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN
412# SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2;
413# 0|0|1|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
414# 0|1|0|SCAN TABLE t2
drh5822d6f2013-06-10 23:30:09 +0000415#
drhd9e3cad2013-10-04 02:36:19 +0000416det 5.5 "SELECT t1.a, t2.c FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {
drh5822d6f2013-06-10 23:30:09 +0000417 0 0 1 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
418 0 1 0 {SCAN TABLE t2}
danfa00aa22010-11-12 17:41:37 +0000419}
420
drh39759742013-08-02 23:40:45 +0000421# EVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b);
danfa00aa22010-11-12 17:41:37 +0000422# sqlite> EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=1 OR b=2;
drh5822d6f2013-06-10 23:30:09 +0000423# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
424# 0|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
drh39759742013-08-02 23:40:45 +0000425#
danfa00aa22010-11-12 17:41:37 +0000426do_execsql_test 5.5.0 {CREATE INDEX i3 ON t1(b)}
drhd9e3cad2013-10-04 02:36:19 +0000427det 5.6.1 "SELECT a, b FROM t1 WHERE a=1 OR b=2" {
drh5822d6f2013-06-10 23:30:09 +0000428 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
429 0 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
danfa00aa22010-11-12 17:41:37 +0000430}
431
drh39759742013-08-02 23:40:45 +0000432# EVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN
433# SELECT c, d FROM t2 ORDER BY c;
434# 0|0|0|SCAN TABLE t2
435# 0|0|0|USE TEMP B-TREE FOR ORDER BY
436#
danfa00aa22010-11-12 17:41:37 +0000437det 5.7 "SELECT c, d FROM t2 ORDER BY c" {
drh5822d6f2013-06-10 23:30:09 +0000438 0 0 0 {SCAN TABLE t2}
danfa00aa22010-11-12 17:41:37 +0000439 0 0 0 {USE TEMP B-TREE FOR ORDER BY}
440}
441
drh39759742013-08-02 23:40:45 +0000442# EVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c);
danfa00aa22010-11-12 17:41:37 +0000443# sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c;
drh5822d6f2013-06-10 23:30:09 +0000444# 0|0|0|SCAN TABLE t2 USING INDEX i4
drh39759742013-08-02 23:40:45 +0000445#
danfa00aa22010-11-12 17:41:37 +0000446do_execsql_test 5.8.0 {CREATE INDEX i4 ON t2(c)}
447det 5.8.1 "SELECT c, d FROM t2 ORDER BY c" {
drh5822d6f2013-06-10 23:30:09 +0000448 0 0 0 {SCAN TABLE t2 USING INDEX i4}
danfa00aa22010-11-12 17:41:37 +0000449}
450
drh39759742013-08-02 23:40:45 +0000451# EVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT
danfa00aa22010-11-12 17:41:37 +0000452# (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2;
drh39759742013-08-02 23:40:45 +0000453# 0|0|0|SCAN TABLE t2
454# 0|0|0|EXECUTE SCALAR SUBQUERY 1
drh5822d6f2013-06-10 23:30:09 +0000455# 1|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
drh39759742013-08-02 23:40:45 +0000456# 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2
457# 2|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
458#
danfa00aa22010-11-12 17:41:37 +0000459det 5.9 {
460 SELECT (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2
461} {
drh5822d6f2013-06-10 23:30:09 +0000462 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
danfa00aa22010-11-12 17:41:37 +0000463 0 0 0 {EXECUTE SCALAR SUBQUERY 1}
drh5822d6f2013-06-10 23:30:09 +0000464 1 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
danfa00aa22010-11-12 17:41:37 +0000465 0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}
drh5822d6f2013-06-10 23:30:09 +0000466 2 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
danfa00aa22010-11-12 17:41:37 +0000467}
468
drh39759742013-08-02 23:40:45 +0000469# EVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN
470# SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x;
471# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
472# 0|0|0|SCAN SUBQUERY 1
473# 0|0|0|USE TEMP B-TREE FOR GROUP BY
474#
danfa00aa22010-11-12 17:41:37 +0000475det 5.10 {
476 SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x
477} {
drh5822d6f2013-06-10 23:30:09 +0000478 1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
479 0 0 0 {SCAN SUBQUERY 1}
danfa00aa22010-11-12 17:41:37 +0000480 0 0 0 {USE TEMP B-TREE FOR GROUP BY}
481}
482
drh39759742013-08-02 23:40:45 +0000483# EVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN
484# SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1;
485# 0|0|0|SEARCH TABLE t2 USING INDEX i4 (c=?)
486# 0|1|1|SCAN TABLE t1
487#
drhd9e3cad2013-10-04 02:36:19 +0000488det 5.11 "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1" {
drh5822d6f2013-06-10 23:30:09 +0000489 0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
490 0 1 1 {SCAN TABLE t1 USING COVERING INDEX i2}
danfa00aa22010-11-12 17:41:37 +0000491}
492
drh39759742013-08-02 23:40:45 +0000493# EVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN
494# SELECT a FROM t1 UNION SELECT c FROM t2;
495# 1|0|0|SCAN TABLE t1
496# 2|0|0|SCAN TABLE t2
497# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)
498#
drh165674d2013-10-04 15:58:59 +0000499det 5.12 "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2" {
drh4fe425a2013-06-12 17:08:06 +0000500 1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
drh5822d6f2013-06-10 23:30:09 +0000501 2 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
danfa00aa22010-11-12 17:41:37 +0000502 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
503}
504
drh39759742013-08-02 23:40:45 +0000505# EVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN
506# SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1;
507# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
508# 2|0|0|SCAN TABLE t2 2|0|0|USE TEMP B-TREE FOR ORDER BY
509# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
510#
danfa00aa22010-11-12 17:41:37 +0000511det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {
drh165674d2013-10-04 15:58:59 +0000512 1 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
drh5822d6f2013-06-10 23:30:09 +0000513 2 0 0 {SCAN TABLE t2}
danfa00aa22010-11-12 17:41:37 +0000514 2 0 0 {USE TEMP B-TREE FOR ORDER BY}
515 0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
516}
517
518
drhaf3906a2016-03-14 17:05:04 +0000519if {![nonzero_reserved_bytes]} {
520 #-------------------------------------------------------------------------
521 # The following tests - eqp-6.* - test that the example C code on
522 # documentation page eqp.html works. The C code is duplicated in test1.c
523 # and wrapped in Tcl command [print_explain_query_plan]
524 #
525 set boilerplate {
526 proc explain_query_plan {db sql} {
527 set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY]
528 print_explain_query_plan $stmt
529 sqlite3_finalize $stmt
530 }
531 sqlite3 db test.db
532 explain_query_plan db {%SQL%}
533 db close
534 exit
dan91da6b82010-11-15 14:51:33 +0000535 }
drhaf3906a2016-03-14 17:05:04 +0000536
537 # Do a "Print Explain Query Plan" test.
538 proc do_peqp_test {tn sql res} {
539 set fd [open script.tcl w]
540 puts $fd [string map [list %SQL% $sql] $::boilerplate]
dan91da6b82010-11-15 14:51:33 +0000541 close $fd
drhaf3906a2016-03-14 17:05:04 +0000542
543 uplevel do_test $tn [list {
544 set fd [open "|[info nameofexec] script.tcl"]
545 set data [read $fd]
546 close $fd
547 set data
548 }] [list $res]
549 }
550
551 do_peqp_test 6.1 {
552 SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
553 } [string trimleft {
drh5822d6f2013-06-10 23:30:09 +00005541 0 0 SCAN TABLE t1 USING COVERING INDEX i2
5552 0 0 SCAN TABLE t2
dan91da6b82010-11-15 14:51:33 +00005562 0 0 USE TEMP B-TREE FOR ORDER BY
5570 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
558}]
drhaf3906a2016-03-14 17:05:04 +0000559}
dan91da6b82010-11-15 14:51:33 +0000560
danef7075d2011-02-21 17:49:49 +0000561#-------------------------------------------------------------------------
562# The following tests - eqp-7.* - test that queries that use the OP_Count
563# optimization return something sensible with EQP.
564#
565drop_all_tables
danfa00aa22010-11-12 17:41:37 +0000566
danef7075d2011-02-21 17:49:49 +0000567do_execsql_test 7.0 {
drh165674d2013-10-04 15:58:59 +0000568 CREATE TABLE t1(a INT, b INT, ex CHAR(100));
569 CREATE TABLE t2(a INT, b INT, ex CHAR(100));
danef7075d2011-02-21 17:49:49 +0000570 CREATE INDEX i1 ON t2(a);
571}
572
573det 7.1 "SELECT count(*) FROM t1" {
drh5822d6f2013-06-10 23:30:09 +0000574 0 0 0 {SCAN TABLE t1}
danef7075d2011-02-21 17:49:49 +0000575}
576
577det 7.2 "SELECT count(*) FROM t2" {
drh8636e9c2013-06-11 01:50:08 +0000578 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1}
danef7075d2011-02-21 17:49:49 +0000579}
580
581do_execsql_test 7.3 {
drh165674d2013-10-04 15:58:59 +0000582 INSERT INTO t1(a,b) VALUES(1, 2);
583 INSERT INTO t1(a,b) VALUES(3, 4);
danef7075d2011-02-21 17:49:49 +0000584
drh165674d2013-10-04 15:58:59 +0000585 INSERT INTO t2(a,b) VALUES(1, 2);
586 INSERT INTO t2(a,b) VALUES(3, 4);
587 INSERT INTO t2(a,b) VALUES(5, 6);
danef7075d2011-02-21 17:49:49 +0000588
589 ANALYZE;
590}
591
592db close
593sqlite3 db test.db
594
595det 7.4 "SELECT count(*) FROM t1" {
drh5822d6f2013-06-10 23:30:09 +0000596 0 0 0 {SCAN TABLE t1}
danef7075d2011-02-21 17:49:49 +0000597}
598
599det 7.5 "SELECT count(*) FROM t2" {
drh8636e9c2013-06-11 01:50:08 +0000600 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1}
danef7075d2011-02-21 17:49:49 +0000601}
danfa00aa22010-11-12 17:41:37 +0000602
dane96f2df2014-05-23 17:17:06 +0000603#-------------------------------------------------------------------------
604# The following tests - eqp-8.* - test that queries that use the OP_Count
605# optimization return something sensible with EQP.
606#
607drop_all_tables
608
609do_execsql_test 8.0 {
610 CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
611 CREATE TABLE t2(a, b, c);
612}
613
614det 8.1.1 "SELECT * FROM t2" {
615 0 0 0 {SCAN TABLE t2}
616}
617
618det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
619 0 0 0 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
620}
621
622det 8.1.3 "SELECT count(*) FROM t2" {
623 0 0 0 {SCAN TABLE t2}
624}
625
626det 8.2.1 "SELECT * FROM t1" {
627 0 0 0 {SCAN TABLE t1}
628}
629
630det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
631 0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=?)}
632}
633
634det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
635 0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)}
636}
637
638det 8.2.4 "SELECT count(*) FROM t1" {
639 0 0 0 {SCAN TABLE t1}
640}
641
642
643
644
645
646
danfa00aa22010-11-12 17:41:37 +0000647
dan2ce22452010-11-08 19:01:16 +0000648finish_test