• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 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
16set testprefix eqp
17
18#-------------------------------------------------------------------------
19#
20# eqp-1.*:        Assorted tests.
21# eqp-2.*:        Tests for single select statements.
22# eqp-3.*:        Select statements that execute sub-selects.
23# eqp-4.*:        Compound select statements.
24# ...
25# eqp-7.*:        "SELECT count(*) FROM tbl" statements (VDBE code OP_Count).
26#
27
28proc det {args} { uplevel do_eqp_test $args }
29
30do_execsql_test 1.1 {
31  CREATE TABLE t1(a, b);
32  CREATE INDEX i1 ON t1(a);
33  CREATE INDEX i2 ON t1(b);
34  CREATE TABLE t2(a, b);
35  CREATE TABLE t3(a, b);
36}
37
38do_eqp_test 1.2 {
39  SELECT * FROM t2, t1 WHERE t1.a=1 OR t1.b=2;
40} {
41  0 0 1 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~10 rows)}
42  0 0 1 {SEARCH TABLE t1 USING INDEX i2 (b=?) (~10 rows)}
43  0 1 0 {SCAN TABLE t2 (~1000000 rows)}
44}
45do_eqp_test 1.3 {
46  SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=1 OR t1.b=2;
47} {
48  0 0 0 {SCAN TABLE t2 (~1000000 rows)}
49  0 1 1 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~10 rows)}
50  0 1 1 {SEARCH TABLE t1 USING INDEX i2 (b=?) (~10 rows)}
51}
52do_eqp_test 1.3 {
53  SELECT a FROM t1 ORDER BY a
54} {
55  0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1 (~1000000 rows)}
56}
57do_eqp_test 1.4 {
58  SELECT a FROM t1 ORDER BY +a
59} {
60  0 0 0 {SCAN TABLE t1 (~1000000 rows)}
61  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
62}
63do_eqp_test 1.5 {
64  SELECT a FROM t1 WHERE a=4
65} {
66  0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) (~10 rows)}
67}
68do_eqp_test 1.6 {
69  SELECT DISTINCT count(*) FROM t3 GROUP BY a;
70} {
71  0 0 0 {SCAN TABLE t3 (~1000000 rows)}
72  0 0 0 {USE TEMP B-TREE FOR GROUP BY}
73  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
74}
75
76do_eqp_test 1.7 {
77  SELECT * FROM t3 JOIN (SELECT 1)
78} {
79  0 0 1 {SCAN SUBQUERY 1 (~1 rows)}
80  0 1 0 {SCAN TABLE t3 (~1000000 rows)}
81}
82do_eqp_test 1.8 {
83  SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
84} {
85  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
86  0 0 1 {SCAN SUBQUERY 1 (~2 rows)}
87  0 1 0 {SCAN TABLE t3 (~1000000 rows)}
88}
89do_eqp_test 1.9 {
90  SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
91} {
92  3 0 0 {SCAN TABLE t3 (~1000000 rows)}
93  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (EXCEPT)}
94  0 0 1 {SCAN SUBQUERY 1 (~17 rows)}
95  0 1 0 {SCAN TABLE t3 (~1000000 rows)}
96}
97do_eqp_test 1.10 {
98  SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
99} {
100  3 0 0 {SCAN TABLE t3 (~1000000 rows)}
101  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (INTERSECT)}
102  0 0 1 {SCAN SUBQUERY 1 (~1 rows)}
103  0 1 0 {SCAN TABLE t3 (~1000000 rows)}
104}
105
106do_eqp_test 1.11 {
107  SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17)
108} {
109  3 0 0 {SCAN TABLE t3 (~1000000 rows)}
110  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)}
111  0 0 1 {SCAN SUBQUERY 1 (~17 rows)}
112  0 1 0 {SCAN TABLE t3 (~1000000 rows)}
113}
114
115#-------------------------------------------------------------------------
116# Test cases eqp-2.* - tests for single select statements.
117#
118drop_all_tables
119do_execsql_test 2.1 {
120  CREATE TABLE t1(x, y);
121
122  CREATE TABLE t2(x, y);
123  CREATE INDEX t2i1 ON t2(x);
124}
125
126det 2.2.1 "SELECT DISTINCT min(x), max(x) FROM t1 GROUP BY x ORDER BY 1" {
127  0 0 0 {SCAN TABLE t1 (~1000000 rows)}
128  0 0 0 {USE TEMP B-TREE FOR GROUP BY}
129  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
130  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
131}
132det 2.2.2 "SELECT DISTINCT min(x), max(x) FROM t2 GROUP BY x ORDER BY 1" {
133  0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1 (~1000000 rows)}
134  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
135  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
136}
137det 2.2.3 "SELECT DISTINCT * FROM t1" {
138  0 0 0 {SCAN TABLE t1 (~1000000 rows)}
139  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
140}
141det 2.2.4 "SELECT DISTINCT * FROM t1, t2" {
142  0 0 0 {SCAN TABLE t1 (~1000000 rows)}
143  0 1 1 {SCAN TABLE t2 (~1000000 rows)}
144  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
145}
146det 2.2.5 "SELECT DISTINCT * FROM t1, t2 ORDER BY t1.x" {
147  0 0 0 {SCAN TABLE t1 (~1000000 rows)}
148  0 1 1 {SCAN TABLE t2 (~1000000 rows)}
149  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
150  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
151}
152det 2.2.6 "SELECT DISTINCT t2.x FROM t1, t2 ORDER BY t2.x" {
153  0 0 1 {SCAN TABLE t2 USING COVERING INDEX t2i1 (~1000000 rows)}
154  0 1 0 {SCAN TABLE t1 (~1000000 rows)}
155}
156
157det 2.3.1 "SELECT max(x) FROM t2" {
158  0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1 (~1 rows)}
159}
160det 2.3.2 "SELECT min(x) FROM t2" {
161  0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1 (~1 rows)}
162}
163det 2.3.3 "SELECT min(x), max(x) FROM t2" {
164  0 0 0 {SCAN TABLE t2 (~1000000 rows)}
165}
166
167det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {
168  0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}
169}
170
171
172
173#-------------------------------------------------------------------------
174# Test cases eqp-3.* - tests for select statements that use sub-selects.
175#
176do_eqp_test 3.1.1 {
177  SELECT (SELECT x FROM t1 AS sub) FROM t1;
178} {
179  0 0 0 {SCAN TABLE t1 (~1000000 rows)}
180  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
181  1 0 0 {SCAN TABLE t1 AS sub (~1000000 rows)}
182}
183do_eqp_test 3.1.2 {
184  SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
185} {
186  0 0 0 {SCAN TABLE t1 (~1000000 rows)}
187  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
188  1 0 0 {SCAN TABLE t1 AS sub (~1000000 rows)}
189}
190do_eqp_test 3.1.3 {
191  SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y);
192} {
193  0 0 0 {SCAN TABLE t1 (~1000000 rows)}
194  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
195  1 0 0 {SCAN TABLE t1 AS sub (~1000000 rows)}
196  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
197}
198do_eqp_test 3.1.4 {
199  SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x);
200} {
201  0 0 0 {SCAN TABLE t1 (~1000000 rows)}
202  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
203  1 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1 (~1000000 rows)}
204}
205
206det 3.2.1 {
207  SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY y LIMIT 5
208} {
209  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
210  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
211  0 0 0 {SCAN SUBQUERY 1 (~10 rows)}
212  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
213}
214det 3.2.2 {
215  SELECT * FROM
216    (SELECT * FROM t1 ORDER BY x LIMIT 10) AS x1,
217    (SELECT * FROM t2 ORDER BY x LIMIT 10) AS x2
218  ORDER BY x2.y LIMIT 5
219} {
220  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
221  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
222  2 0 0 {SCAN TABLE t2 USING INDEX t2i1 (~1000000 rows)}
223  0 0 0 {SCAN SUBQUERY 1 AS x1 (~10 rows)}
224  0 1 1 {SCAN SUBQUERY 2 AS x2 (~10 rows)}
225  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
226}
227
228det 3.3.1 {
229  SELECT * FROM t1 WHERE y IN (SELECT y FROM t2)
230} {
231  0 0 0 {SCAN TABLE t1 (~100000 rows)}
232  0 0 0 {EXECUTE LIST SUBQUERY 1}
233  1 0 0 {SCAN TABLE t2 (~1000000 rows)}
234}
235det 3.3.2 {
236  SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x)
237} {
238  0 0 0 {SCAN TABLE t1 (~500000 rows)}
239  0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1}
240  1 0 0 {SCAN TABLE t2 (~500000 rows)}
241}
242det 3.3.3 {
243  SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x)
244} {
245  0 0 0 {SCAN TABLE t1 (~500000 rows)}
246  0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 1}
247  1 0 0 {SCAN TABLE t2 (~500000 rows)}
248}
249
250#-------------------------------------------------------------------------
251# Test cases eqp-4.* - tests for composite select statements.
252#
253do_eqp_test 4.1.1 {
254  SELECT * FROM t1 UNION ALL SELECT * FROM t2
255} {
256  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
257  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
258  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
259}
260do_eqp_test 4.1.2 {
261  SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 2
262} {
263  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
264  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
265  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
266  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
267  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
268}
269do_eqp_test 4.1.3 {
270  SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 2
271} {
272  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
273  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
274  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
275  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
276  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)}
277}
278do_eqp_test 4.1.4 {
279  SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 2
280} {
281  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
282  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
283  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
284  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
285  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)}
286}
287do_eqp_test 4.1.5 {
288  SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 2
289} {
290  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
291  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
292  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
293  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
294  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
295}
296
297do_eqp_test 4.2.2 {
298  SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 1
299} {
300  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
301  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
302  2 0 0 {SCAN TABLE t2 USING INDEX t2i1 (~1000000 rows)}
303  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
304}
305do_eqp_test 4.2.3 {
306  SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 1
307} {
308  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
309  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
310  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
311  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
312  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)}
313}
314do_eqp_test 4.2.4 {
315  SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 1
316} {
317  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
318  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
319  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
320  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
321  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)}
322}
323do_eqp_test 4.2.5 {
324  SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 1
325} {
326  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
327  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
328  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
329  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
330  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
331}
332
333do_eqp_test 4.3.1 {
334  SELECT x FROM t1 UNION SELECT x FROM t2
335} {
336  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
337  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
338  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
339}
340
341do_eqp_test 4.3.2 {
342  SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1
343} {
344  2 0 0 {SCAN TABLE t1 (~1000000 rows)}
345  3 0 0 {SCAN TABLE t2 (~1000000 rows)}
346  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
347  4 0 0 {SCAN TABLE t1 (~1000000 rows)}
348  0 0 0 {COMPOUND SUBQUERIES 1 AND 4 USING TEMP B-TREE (UNION)}
349}
350do_eqp_test 4.3.3 {
351  SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER BY 1
352} {
353  2 0 0 {SCAN TABLE t1 (~1000000 rows)}
354  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
355  3 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1 (~1000000 rows)}
356  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION)}
357  4 0 0 {SCAN TABLE t1 (~1000000 rows)}
358  4 0 0 {USE TEMP B-TREE FOR ORDER BY}
359  0 0 0 {COMPOUND SUBQUERIES 1 AND 4 (UNION)}
360}
361
362#-------------------------------------------------------------------------
363# This next block of tests verifies that the examples on the
364# lang_explain.html page are correct.
365#
366drop_all_tables
367
368# EVIDENCE-OF: R-64208-08323 sqlite> EXPLAIN QUERY PLAN SELECT a, b
369# FROM t1 WHERE a=1; 0|0|0|SCAN TABLE t1 (~100000 rows)
370do_execsql_test 5.1.0 { CREATE TABLE t1(a, b) }
371det 5.1.1 "SELECT a, b FROM t1 WHERE a=1" {
372  0 0 0 {SCAN TABLE t1 (~100000 rows)}
373}
374
375# EVIDENCE-OF: R-09022-44606 sqlite> CREATE INDEX i1 ON t1(a);
376# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
377# 0|0|0|SEARCH TABLE t1 USING INDEX i1 (a=?) (~10 rows)
378do_execsql_test 5.2.0 { CREATE INDEX i1 ON t1(a) }
379det 5.2.1 "SELECT a, b FROM t1 WHERE a=1" {
380  0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~10 rows)}
381}
382
383# EVIDENCE-OF: R-62228-34103 sqlite> CREATE INDEX i2 ON t1(a, b);
384# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
385# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) (~10 rows)
386do_execsql_test 5.3.0 { CREATE INDEX i2 ON t1(a, b) }
387det 5.3.1 "SELECT a, b FROM t1 WHERE a=1" {
388  0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) (~10 rows)}
389}
390
391# EVIDENCE-OF: R-22253-05302 sqlite> EXPLAIN QUERY PLAN SELECT t1.*,
392# t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2; 0|0|0|SEARCH TABLE t1
393# USING COVERING INDEX i2 (a=? AND b>?) (~3 rows) 0|1|1|SCAN TABLE t2
394# (~1000000 rows)
395do_execsql_test 5.4.0 {CREATE TABLE t2(c, d)}
396det 5.4.1 "SELECT t1.*, t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {
397  0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?) (~2 rows)}
398  0 1 1 {SCAN TABLE t2 (~1000000 rows)}
399}
400
401# EVIDENCE-OF: R-21040-07025 sqlite> EXPLAIN QUERY PLAN SELECT t1.*,
402# t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2; 0|0|1|SEARCH TABLE t1
403# USING COVERING INDEX i2 (a=? AND b>?) (~3 rows) 0|1|0|SCAN TABLE t2
404# (~1000000 rows)
405det 5.5 "SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {
406  0 0 1 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?) (~2 rows)}
407  0 1 0 {SCAN TABLE t2 (~1000000 rows)}
408}
409
410# EVIDENCE-OF: R-39007-61103 sqlite> CREATE INDEX i3 ON t1(b);
411# sqlite> EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=1 OR b=2;
412# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) (~10 rows)
413# 0|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?) (~10 rows)
414do_execsql_test 5.5.0 {CREATE INDEX i3 ON t1(b)}
415det 5.6.1 "SELECT * FROM t1 WHERE a=1 OR b=2" {
416  0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) (~10 rows)}
417  0 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?) (~10 rows)}
418}
419
420# EVIDENCE-OF: R-33025-54904 sqlite> EXPLAIN QUERY PLAN SELECT c, d
421# FROM t2 ORDER BY c; 0|0|0|SCAN TABLE t2 (~1000000 rows) 0|0|0|USE TEMP
422# B-TREE FOR ORDER BY
423det 5.7 "SELECT c, d FROM t2 ORDER BY c" {
424  0 0 0 {SCAN TABLE t2 (~1000000 rows)}
425  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
426}
427
428# EVIDENCE-OF: R-38854-22809 sqlite> CREATE INDEX i4 ON t2(c);
429# sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c;
430# 0|0|0|SCAN TABLE t2 USING INDEX i4 (~1000000 rows)
431do_execsql_test 5.8.0 {CREATE INDEX i4 ON t2(c)}
432det 5.8.1 "SELECT c, d FROM t2 ORDER BY c" {
433  0 0 0 {SCAN TABLE t2 USING INDEX i4 (~1000000 rows)}
434}
435
436# EVIDENCE-OF: R-29884-43993 sqlite> EXPLAIN QUERY PLAN SELECT
437# (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2;
438# 0|0|0|SCAN TABLE t2 (~1000000 rows) 0|0|0|EXECUTE SCALAR SUBQUERY 1
439# 1|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) (~10 rows)
440# 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2 2|0|0|SEARCH TABLE t1 USING
441# INDEX i3 (b=?) (~10 rows)
442det 5.9 {
443  SELECT (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2
444} {
445  0 0 0 {SCAN TABLE t2 (~1000000 rows)}
446  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
447  1 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) (~10 rows)}
448  0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}
449  2 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?) (~10 rows)}
450}
451
452# EVIDENCE-OF: R-17911-16445 sqlite> EXPLAIN QUERY PLAN SELECT
453# count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x;
454# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2 (~1000000 rows) 0|0|0|SCAN
455# SUBQUERY 1 (~1000000 rows) 0|0|0|USE TEMP B-TREE FOR GROUP BY
456det 5.10 {
457  SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x
458} {
459  1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2 (~1000000 rows)}
460  0 0 0 {SCAN SUBQUERY 1 (~100 rows)}
461  0 0 0 {USE TEMP B-TREE FOR GROUP BY}
462}
463
464# EVIDENCE-OF: R-18544-33103 sqlite> EXPLAIN QUERY PLAN SELECT * FROM
465# (SELECT * FROM t2 WHERE c=1), t1; 0|0|0|SEARCH TABLE t2 USING INDEX i4
466# (c=?) (~10 rows) 0|1|1|SCAN TABLE t1 (~1000000 rows)
467det 5.11 "SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1" {
468  0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?) (~10 rows)}
469  0 1 1 {SCAN TABLE t1 (~1000000 rows)}
470}
471
472# EVIDENCE-OF: R-40701-42164 sqlite> EXPLAIN QUERY PLAN SELECT a FROM
473# t1 UNION SELECT c FROM t2; 1|0|0|SCAN TABLE t1 (~1000000 rows)
474# 2|0|0|SCAN TABLE t2 (~1000000 rows) 0|0|0|COMPOUND SUBQUERIES 1 AND 2
475# USING TEMP B-TREE (UNION)
476det 5.12 "SELECT a FROM t1 UNION SELECT c FROM t2" {
477  1 0 0 {SCAN TABLE t1 (~1000000 rows)}
478  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
479  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
480}
481
482# EVIDENCE-OF: R-61538-24748 sqlite> EXPLAIN QUERY PLAN SELECT a FROM
483# t1 EXCEPT SELECT d FROM t2 ORDER BY 1; 1|0|0|SCAN TABLE t1 USING
484# COVERING INDEX i2 (~1000000 rows) 2|0|0|SCAN TABLE t2 (~1000000 rows)
485# 2|0|0|USE TEMP B-TREE FOR ORDER BY 0|0|0|COMPOUND SUBQUERIES 1 AND 2
486# (EXCEPT)
487det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {
488  1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2 (~1000000 rows)}
489  2 0 0 {SCAN TABLE t2 (~1000000 rows)}
490  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
491  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
492}
493
494
495#-------------------------------------------------------------------------
496# The following tests - eqp-6.* - test that the example C code on
497# documentation page eqp.html works. The C code is duplicated in test1.c
498# and wrapped in Tcl command [print_explain_query_plan]
499#
500set boilerplate {
501  proc explain_query_plan {db sql} {
502    set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY]
503    print_explain_query_plan $stmt
504    sqlite3_finalize $stmt
505  }
506  sqlite3 db test.db
507  explain_query_plan db {%SQL%}
508  db close
509  exit
510}
511
512# Do a "Print Explain Query Plan" test.
513proc do_peqp_test {tn sql res} {
514  set fd [open script.tcl w]
515  puts $fd [string map [list %SQL% $sql] $::boilerplate]
516  close $fd
517
518  uplevel do_test $tn [list {
519    set fd [open "|[info nameofexec] script.tcl"]
520    set data [read $fd]
521    close $fd
522    set data
523  }] [list $res]
524}
525
526do_peqp_test 6.1 {
527  SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1
528} [string trimleft {
5291 0 0 SCAN TABLE t1 USING COVERING INDEX i2 (~1000000 rows)
5302 0 0 SCAN TABLE t2 (~1000000 rows)
5312 0 0 USE TEMP B-TREE FOR ORDER BY
5320 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
533}]
534
535#-------------------------------------------------------------------------
536# The following tests - eqp-7.* - test that queries that use the OP_Count
537# optimization return something sensible with EQP.
538#
539drop_all_tables
540
541do_execsql_test 7.0 {
542  CREATE TABLE t1(a, b);
543  CREATE TABLE t2(a, b);
544  CREATE INDEX i1 ON t2(a);
545}
546
547det 7.1 "SELECT count(*) FROM t1" {
548  0 0 0 {SCAN TABLE t1 (~1000000 rows)}
549}
550
551det 7.2 "SELECT count(*) FROM t2" {
552  0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1(~1000000 rows)}
553}
554
555do_execsql_test 7.3 {
556  INSERT INTO t1 VALUES(1, 2);
557  INSERT INTO t1 VALUES(3, 4);
558
559  INSERT INTO t2 VALUES(1, 2);
560  INSERT INTO t2 VALUES(3, 4);
561  INSERT INTO t2 VALUES(5, 6);
562
563  ANALYZE;
564}
565
566db close
567sqlite3 db test.db
568
569det 7.4 "SELECT count(*) FROM t1" {
570  0 0 0 {SCAN TABLE t1 (~2 rows)}
571}
572
573det 7.5 "SELECT count(*) FROM t2" {
574  0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1(~3 rows)}
575}
576
577
578finish_test
579