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:
13: set testdir [file dirname $argv0]
14: source $testdir/tester.tcl
15:
16: set 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:
28: proc det {args} { uplevel do_eqp_test $args }
29:
30: do_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:
38: do_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: }
45: do_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: }
52: do_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: }
57: do_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: }
63: do_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: }
68: do_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:
76: do_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: }
82: do_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: }
89: do_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: }
97: do_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:
106: do_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: #
118: drop_all_tables
119: do_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:
126: det 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: }
132: det 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: }
137: det 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: }
141: det 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: }
146: det 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: }
152: det 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:
157: det 2.3.1 "SELECT max(x) FROM t2" {
158: 0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1 (~1 rows)}
159: }
160: det 2.3.2 "SELECT min(x) FROM t2" {
161: 0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1 (~1 rows)}
162: }
163: det 2.3.3 "SELECT min(x), max(x) FROM t2" {
164: 0 0 0 {SCAN TABLE t2 (~1000000 rows)}
165: }
166:
167: det 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: #
176: do_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: }
183: do_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: }
190: do_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: }
198: do_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:
206: det 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: }
214: det 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:
228: det 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: }
235: det 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: }
242: det 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: #
253: do_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: }
260: do_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: }
269: do_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: }
278: do_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: }
287: do_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:
297: do_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: }
305: do_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: }
314: do_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: }
323: do_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:
333: do_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:
341: do_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: }
350: do_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: #
366: drop_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)
370: do_execsql_test 5.1.0 { CREATE TABLE t1(a, b) }
371: det 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)
378: do_execsql_test 5.2.0 { CREATE INDEX i1 ON t1(a) }
379: det 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)
386: do_execsql_test 5.3.0 { CREATE INDEX i2 ON t1(a, b) }
387: det 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)
395: do_execsql_test 5.4.0 {CREATE TABLE t2(c, d)}
396: det 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)
405: det 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)
414: do_execsql_test 5.5.0 {CREATE INDEX i3 ON t1(b)}
415: det 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
423: det 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)
431: do_execsql_test 5.8.0 {CREATE INDEX i4 ON t2(c)}
432: det 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)
442: det 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
456: det 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)
467: det 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)
476: det 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)
487: det 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: #
500: set 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.
513: proc 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:
526: do_peqp_test 6.1 {
527: SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1
528: } [string trimleft {
529: 1 0 0 SCAN TABLE t1 USING COVERING INDEX i2 (~1000000 rows)
530: 2 0 0 SCAN TABLE t2 (~1000000 rows)
531: 2 0 0 USE TEMP B-TREE FOR ORDER BY
532: 0 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: #
539: drop_all_tables
540:
541: do_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:
547: det 7.1 "SELECT count(*) FROM t1" {
548: 0 0 0 {SCAN TABLE t1 (~1000000 rows)}
549: }
550:
551: det 7.2 "SELECT count(*) FROM t2" {
552: 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1(~1000000 rows)}
553: }
554:
555: do_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:
566: db close
567: sqlite3 db test.db
568:
569: det 7.4 "SELECT count(*) FROM t1" {
570: 0 0 0 {SCAN TABLE t1 (~2 rows)}
571: }
572:
573: det 7.5 "SELECT count(*) FROM t2" {
574: 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1(~3 rows)}
575: }
576:
577:
578: finish_test
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>