CoolFace
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
eqp.test904 linesDownload Raw Back to test
1# 2010 November 62#3# The author disclaims copyright to this source code.  In place of4# 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.tcl15 16ifcapable !compound {17  finish_test18  return19}20 21set testprefix eqp22 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.29# ...30# eqp-7.*:        "SELECT count(*) FROM tbl" statements (VDBE code OP_Count).31#32 33proc det {args} { uplevel do_eqp_test $args }34 35do_execsql_test 1.1 {36  CREATE TABLE t1(a INT, b INT, ex TEXT);37  CREATE INDEX i1 ON t1(a);38  CREATE INDEX i2 ON t1(b);39  CREATE TABLE t2(a INT, b INT, ex TEXT);40  CREATE TABLE t3(a INT, b INT, ex TEXT);41}42 43do_eqp_test 1.2 {44  SELECT * FROM t2, t1 WHERE t1.a=1 OR t1.b=2;45} {46  QUERY PLAN47  |--MULTI-INDEX OR48  |  |--INDEX 149  |  |  `--SEARCH t1 USING INDEX i1 (a=?)50  |  `--INDEX 251  |     `--SEARCH t1 USING INDEX i2 (b=?)52  `--SCAN t253}54do_eqp_test 1.3 {55  SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=1 OR t1.b=2;56} {57  QUERY PLAN58  |--SCAN t259  `--MULTI-INDEX OR60     |--INDEX 161     |  `--SEARCH t1 USING INDEX i1 (a=?)62     `--INDEX 263        `--SEARCH t1 USING INDEX i2 (b=?)64}65do_eqp_test 1.3 {66  SELECT a FROM t1 ORDER BY a67} {68  QUERY PLAN69  `--SCAN t1 USING COVERING INDEX i170}71do_eqp_test 1.4 {72  SELECT a FROM t1 ORDER BY +a73} {74  QUERY PLAN75  |--SCAN t1 USING COVERING INDEX i176  `--USE TEMP B-TREE FOR ORDER BY77}78do_eqp_test 1.5 {79  SELECT a FROM t1 WHERE a=480} {81  QUERY PLAN82  `--SEARCH t1 USING COVERING INDEX i1 (a=?)83}84do_eqp_test 1.6 {85  SELECT DISTINCT count(*) FROM t3 GROUP BY a;86} {87  QUERY PLAN88  |--SCAN t389  |--USE TEMP B-TREE FOR GROUP BY90  `--USE TEMP B-TREE FOR DISTINCT91}92 93do_eqp_test 1.7.1 {94  SELECT * FROM t3 JOIN (SELECT 1)95} {96  QUERY PLAN97  |--CO-ROUTINE (subquery-xxxxxx)98  |  `--SCAN CONSTANT ROW99  |--SCAN (subquery-xxxxxx)100  `--SCAN t3101}102do_eqp_test 1.7.2 {103  SELECT * FROM t3 JOIN (SELECT 1) AS v1104} {105  QUERY PLAN106  |--CO-ROUTINE v1107  |  `--SCAN CONSTANT ROW108  |--SCAN v1109  `--SCAN t3110}111do_eqp_test 1.7.3 {112  SELECT * FROM t3 AS xx JOIN (SELECT 1) AS yy113} {114  QUERY PLAN115  |--CO-ROUTINE yy116  |  `--SCAN CONSTANT ROW117  |--SCAN yy118  `--SCAN xx119}120 121 122do_eqp_test 1.8 {123  SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)124} {125  QUERY PLAN126  |--CO-ROUTINE (subquery-xxxxxx)127  |  `--COMPOUND QUERY128  |     |--LEFT-MOST SUBQUERY129  |     |  `--SCAN CONSTANT ROW130  |     `--UNION USING TEMP B-TREE131  |        `--SCAN CONSTANT ROW132  |--SCAN (subquery-xxxxxx)133  `--SCAN t3134}135do_eqp_test 1.9 {136  SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17) AS abc137} {138  QUERY PLAN139  |--CO-ROUTINE abc140  |  `--COMPOUND QUERY141  |     |--LEFT-MOST SUBQUERY142  |     |  `--SCAN CONSTANT ROW143  |     `--EXCEPT USING TEMP B-TREE144  |        `--SCAN t3145  |--SCAN abc146  `--SCAN t3147}148do_eqp_test 1.10 {149  SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17) AS abc150} {151  QUERY PLAN152  |--CO-ROUTINE abc153  |  `--COMPOUND QUERY154  |     |--LEFT-MOST SUBQUERY155  |     |  `--SCAN CONSTANT ROW156  |     `--INTERSECT USING TEMP B-TREE157  |        `--SCAN t3158  |--SCAN abc159  `--SCAN t3160}161 162do_eqp_test 1.11 {163  SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17) abc164} {165  QUERY PLAN166  |--CO-ROUTINE abc167  |  `--COMPOUND QUERY168  |     |--LEFT-MOST SUBQUERY169  |     |  `--SCAN CONSTANT ROW170  |     `--UNION ALL171  |        `--SCAN t3172  |--SCAN abc173  `--SCAN t3174}175 176#-------------------------------------------------------------------------177# Test cases eqp-2.* - tests for single select statements.178#179drop_all_tables180do_execsql_test 2.1 {181  CREATE TABLE t1(x INT, y INT, ex TEXT);182 183  CREATE TABLE t2(x INT, y INT, ex TEXT);184  CREATE INDEX t2i1 ON t2(x);185}186 187det 2.2.1 "SELECT DISTINCT min(x), max(x) FROM t1 GROUP BY x ORDER BY 1" {188  QUERY PLAN189  |--SCAN t1190  |--USE TEMP B-TREE FOR GROUP BY191  |--USE TEMP B-TREE FOR DISTINCT192  `--USE TEMP B-TREE FOR ORDER BY193}194det 2.2.2 "SELECT DISTINCT min(x), max(x) FROM t2 GROUP BY x ORDER BY 1" {195  QUERY PLAN196  |--SCAN t2 USING COVERING INDEX t2i1197  |--USE TEMP B-TREE FOR DISTINCT198  `--USE TEMP B-TREE FOR ORDER BY199}200det 2.2.3 "SELECT DISTINCT * FROM t1" {201  QUERY PLAN202  |--SCAN t1203  `--USE TEMP B-TREE FOR DISTINCT204}205det 2.2.4 "SELECT DISTINCT * FROM t1, t2" {206  QUERY PLAN207  |--SCAN t1208  |--SCAN t2209  `--USE TEMP B-TREE FOR DISTINCT210}211det 2.2.5 "SELECT DISTINCT * FROM t1, t2 ORDER BY t1.x" {212  QUERY PLAN213  |--SCAN t1214  |--SCAN t2215  |--USE TEMP B-TREE FOR DISTINCT216  `--USE TEMP B-TREE FOR ORDER BY217}218det 2.2.6 "SELECT DISTINCT t2.x FROM t1, t2 ORDER BY t2.x" {219  QUERY PLAN220  |--SCAN t2 USING COVERING INDEX t2i1221  `--SCAN t1222}223 224det 2.3.1 "SELECT max(x) FROM t2" {225  QUERY PLAN226  `--SEARCH t2 USING COVERING INDEX t2i1227}228det 2.3.2 "SELECT min(x) FROM t2" {229  QUERY PLAN230  `--SEARCH t2 USING COVERING INDEX t2i1231}232det 2.3.3 "SELECT min(x), max(x) FROM t2" {233  QUERY PLAN234  `--SCAN t2 USING COVERING INDEX t2i1235}236 237det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {238  QUERY PLAN239  `--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)240}241 242 243 244#-------------------------------------------------------------------------245# Test cases eqp-3.* - tests for select statements that use sub-selects.246#247do_eqp_test 3.1.1 {248  SELECT (SELECT x FROM t1 AS sub) FROM t1;249} {250  QUERY PLAN251  |--SCAN t1252  `--SCALAR SUBQUERY xxxxxx253     `--SCAN sub254}255do_eqp_test 3.1.2 {256  SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);257} {258  QUERY PLAN259  |--SCAN t1260  `--SCALAR SUBQUERY xxxxxx261     `--SCAN sub262}263do_eqp_test 3.1.3 {264  SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y);265} {266  QUERY PLAN267  |--SCAN t1268  `--SCALAR SUBQUERY xxxxxx269     |--SCAN sub270     `--USE TEMP B-TREE FOR ORDER BY271}272do_eqp_test 3.1.4 {273  SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x);274} {275  QUERY PLAN276  |--SCAN t1277  `--SCALAR SUBQUERY xxxxxx278     `--SCAN t2 USING COVERING INDEX t2i1279}280 281det 3.2.1 {282  SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY y LIMIT 5283} {284  QUERY PLAN285  |--CO-ROUTINE (subquery-xxxxxx)286  |  |--SCAN t1287  |  `--USE TEMP B-TREE FOR ORDER BY288  |--SCAN (subquery-xxxxxx)289  `--USE TEMP B-TREE FOR ORDER BY290}291 292det 3.2.2 {293  SELECT * FROM 294    (SELECT * FROM t1 ORDER BY x LIMIT 10) AS x1,295    (SELECT * FROM t2 ORDER BY x LIMIT 10) AS x2296  ORDER BY x2.y LIMIT 5297} {298  QUERY PLAN299  |--CO-ROUTINE x1300  |  |--SCAN t1301  |  `--USE TEMP B-TREE FOR ORDER BY302  |--MATERIALIZE x2303  |  `--SCAN t2 USING INDEX t2i1304  |--SCAN x1305  |--SCAN x2306  `--USE TEMP B-TREE FOR ORDER BY307}308 309det 3.2.3 {310  SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY x LIMIT 5311} {312  QUERY PLAN313  |--CO-ROUTINE (subquery-xxxxxx)314  |  |--SCAN t1315  |  `--USE TEMP B-TREE FOR ORDER BY316  `--SCAN (subquery-xxxxxx)317}318 319det 3.3.1 {320  SELECT * FROM t1 WHERE y IN (SELECT y FROM t2)321} {322  QUERY PLAN323  |--SCAN t1324  `--LIST SUBQUERY xxxxxx325     |--SCAN t2326     `--CREATE BLOOM FILTER327}328det 3.3.2 {329  SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x)330} {331  QUERY PLAN332  |--SCAN t1333  `--CORRELATED LIST SUBQUERY xxxxxx334     `--SCAN t2335}336det 3.3.3 {337  SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x)338} {339  QUERY PLAN340  |--SCAN t1341  `--SCAN t2 EXISTS342}343 344#-------------------------------------------------------------------------345# Test cases eqp-4.* - tests for composite select statements.346#347do_eqp_test 4.1.1 {348  SELECT * FROM t1 UNION ALL SELECT * FROM t2349} {350  QUERY PLAN351  `--COMPOUND QUERY352     |--LEFT-MOST SUBQUERY353     |  `--SCAN t1354     `--UNION ALL355        `--SCAN t2356}357do_eqp_test 4.1.2 {358  SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 2359} {360  QUERY PLAN361  `--MERGE (UNION ALL)362     |--LEFT363     |  |--SCAN t1364     |  `--USE TEMP B-TREE FOR ORDER BY365     `--RIGHT366        |--SCAN t2367        `--USE TEMP B-TREE FOR ORDER BY368}369do_eqp_test 4.1.3 {370  SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 2371} {372  QUERY PLAN373  `--MERGE (UNION)374     |--LEFT375     |  |--SCAN t1376     |  `--USE TEMP B-TREE FOR ORDER BY377     `--RIGHT378        |--SCAN t2379        `--USE TEMP B-TREE FOR ORDER BY380}381do_eqp_test 4.1.4 {382  SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 2383} {384  QUERY PLAN385  `--MERGE (INTERSECT)386     |--LEFT387     |  |--SCAN t1388     |  `--USE TEMP B-TREE FOR ORDER BY389     `--RIGHT390        |--SCAN t2391        `--USE TEMP B-TREE FOR ORDER BY392}393do_eqp_test 4.1.5 {394  SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 2395} {396  QUERY PLAN397  `--MERGE (EXCEPT)398     |--LEFT399     |  |--SCAN t1400     |  `--USE TEMP B-TREE FOR ORDER BY401     `--RIGHT402        |--SCAN t2403        `--USE TEMP B-TREE FOR ORDER BY404}405 406do_eqp_test 4.2.2 {407  SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 1408} {409  QUERY PLAN410  `--MERGE (UNION ALL)411     |--LEFT412     |  |--SCAN t1413     |  `--USE TEMP B-TREE FOR ORDER BY414     `--RIGHT415        `--SCAN t2 USING INDEX t2i1416}417do_eqp_test 4.2.3 {418  SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 1419} {420  QUERY PLAN421  `--MERGE (UNION)422     |--LEFT423     |  |--SCAN t1424     |  `--USE TEMP B-TREE FOR ORDER BY425     `--RIGHT426        |--SCAN t2 USING INDEX t2i1427        `--USE TEMP B-TREE FOR LAST 2 TERMS OF ORDER BY428}429do_eqp_test 4.2.4 {430  SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 1431} {432  QUERY PLAN433  `--MERGE (INTERSECT)434     |--LEFT435     |  |--SCAN t1436     |  `--USE TEMP B-TREE FOR ORDER BY437     `--RIGHT438        |--SCAN t2 USING INDEX t2i1439        `--USE TEMP B-TREE FOR LAST 2 TERMS OF ORDER BY440}441do_eqp_test 4.2.5 {442  SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 1443} {444  QUERY PLAN445  `--MERGE (EXCEPT)446     |--LEFT447     |  |--SCAN t1448     |  `--USE TEMP B-TREE FOR ORDER BY449     `--RIGHT450        |--SCAN t2 USING INDEX t2i1451        `--USE TEMP B-TREE FOR LAST 2 TERMS OF ORDER BY452}453 454do_eqp_test 4.3.1 {455  SELECT x FROM t1 UNION SELECT x FROM t2456} {457  QUERY PLAN458  `--COMPOUND QUERY459     |--LEFT-MOST SUBQUERY460     |  `--SCAN t1461     `--UNION USING TEMP B-TREE462        `--SCAN t2 USING COVERING INDEX t2i1463}464 465do_eqp_test 4.3.2 {466  SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1467} {468  QUERY PLAN469  `--COMPOUND QUERY470     |--LEFT-MOST SUBQUERY471     |  `--SCAN t1472     |--UNION USING TEMP B-TREE473     |  `--SCAN t2 USING COVERING INDEX t2i1474     `--UNION USING TEMP B-TREE475        `--SCAN t1476}477do_eqp_test 4.3.3 {478  SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER BY 1479} {480  QUERY PLAN481  `--MERGE (UNION)482     |--LEFT483     |  `--MERGE (UNION)484     |     |--LEFT485     |     |  |--SCAN t1486     |     |  `--USE TEMP B-TREE FOR ORDER BY487     |     `--RIGHT488     |        `--SCAN t2 USING COVERING INDEX t2i1489     `--RIGHT490        |--SCAN t1491        `--USE TEMP B-TREE FOR ORDER BY492}493 494if 0 {495#-------------------------------------------------------------------------496# This next block of tests verifies that the examples on the 497# lang_explain.html page are correct.498#499drop_all_tables500 501# XVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b502# FROM t1 WHERE a=1;503# 0|0|0|SCAN t1504#505do_execsql_test 5.1.0 { CREATE TABLE t1(a INT, b INT, ex TEXT) }506det 5.1.1 "SELECT a, b FROM t1 WHERE a=1" {507  0 0 0 {SCAN t1}508}509 510# XVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a);511# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;512# 0|0|0|SEARCH t1 USING INDEX i1513#514do_execsql_test 5.2.0 { CREATE INDEX i1 ON t1(a) }515det 5.2.1 "SELECT a, b FROM t1 WHERE a=1" {516  0 0 0 {SEARCH t1 USING INDEX i1 (a=?)}517}518 519# XVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b);520# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;521# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)522#523do_execsql_test 5.3.0 { CREATE INDEX i2 ON t1(a, b) }524det 5.3.1 "SELECT a, b FROM t1 WHERE a=1" {525  0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}526}527 528# XVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN529# SELECT t1.*, t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2;530# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)531# 0|1|1|SCAN t2532#533do_execsql_test 5.4.0 {CREATE TABLE t2(c INT, d INT, ex TEXT)}534det 5.4.1 "SELECT t1.a, t2.c FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {535  0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)}536  0 1 1 {SCAN t2}537}538 539# XVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN540# SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2;541# 0|0|1|SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)542# 0|1|0|SCAN t2543#544det 5.5 "SELECT t1.a, t2.c FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {545  0 0 1 {SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)}546  0 1 0 {SCAN t2}547}548 549# XVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b);550# sqlite> EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=1 OR b=2;551# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)552# 0|0|0|SEARCH t1 USING INDEX i3 (b=?)553#554do_execsql_test 5.5.0 {CREATE INDEX i3 ON t1(b)}555det 5.6.1 "SELECT a, b FROM t1 WHERE a=1 OR b=2" {556  0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}557  0 0 0 {SEARCH t1 USING INDEX i3 (b=?)}558}559 560# XVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN561# SELECT c, d FROM t2 ORDER BY c;562# 0|0|0|SCAN t2563# 0|0|0|USE TEMP B-TREE FOR ORDER BY564#565det 5.7 "SELECT c, d FROM t2 ORDER BY c" {566  0 0 0 {SCAN t2}567  0 0 0 {USE TEMP B-TREE FOR ORDER BY}568}569 570# XVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c);571# sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c;572# 0|0|0|SCAN t2 USING INDEX i4573#574do_execsql_test 5.8.0 {CREATE INDEX i4 ON t2(c)}575det 5.8.1 "SELECT c, d FROM t2 ORDER BY c" {576  0 0 0 {SCAN t2 USING INDEX i4}577}578 579# XVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT580# (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2;581# 0|0|0|SCAN t2582# 0|0|0|EXECUTE SCALAR SUBQUERY 1583# 1|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)584# 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2585# 2|0|0|SEARCH t1 USING INDEX i3 (b=?)586#587det 5.9 {588  SELECT (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2589} {590  0 0 0 {SCAN t2 USING COVERING INDEX i4}591  0 0 0 {EXECUTE SCALAR SUBQUERY 1}592  1 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}593  0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}594  2 0 0 {SEARCH t1 USING INDEX i3 (b=?)}595}596 597# XVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN598# SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x;599# 1|0|0|SCAN t1 USING COVERING INDEX i2600# 0|0|0|SCAN SUBQUERY 1601# 0|0|0|USE TEMP B-TREE FOR GROUP BY602#603det 5.10 {604  SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x605} {606  1 0 0 {SCAN t1 USING COVERING INDEX i2}607  0 0 0 {SCAN SUBQUERY 1}608  0 0 0 {USE TEMP B-TREE FOR GROUP BY}609}610 611# XVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN612# SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1;613# 0|0|0|SEARCH t2 USING INDEX i4 (c=?)614# 0|1|1|SCAN t1615#616det 5.11 "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1" {617  0 0 0 {SEARCH t2 USING INDEX i4 (c=?)}618  0 1 1 {SCAN t1 USING COVERING INDEX i2}619}620 621# XVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN622# SELECT a FROM t1 UNION SELECT c FROM t2;623# 1|0|0|SCAN t1624# 2|0|0|SCAN t2625# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)626#627det 5.12 "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2" {628  1 0 0 {SCAN t1 USING COVERING INDEX i2}629  2 0 0 {SCAN t2 USING COVERING INDEX i4}630  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}631}632 633# XVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN634# SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1;635# 1|0|0|SCAN t1 USING COVERING INDEX i2636# 2|0|0|SCAN t2 2|0|0|USE TEMP B-TREE FOR ORDER BY637# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)638#639det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {640  1 0 0 {SCAN t1 USING COVERING INDEX i1}641  2 0 0 {SCAN t2}642  2 0 0 {USE TEMP B-TREE FOR ORDER BY}643  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}644}645 646if {![nonzero_reserved_bytes]} {647  #-------------------------------------------------------------------------648  # The following tests - eqp-6.* - test that the example C code on 649  # documentation page eqp.html works. The C code is duplicated in test1.c650  # and wrapped in Tcl command [print_explain_query_plan] 651  #652  set boilerplate {653    proc explain_query_plan {db sql} {654      set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY]655      print_explain_query_plan $stmt656      sqlite3_finalize $stmt657    }658    sqlite3 db test.db659    explain_query_plan db {%SQL%}660    db close661    exit662  }663  664  # Do a "Print Explain Query Plan" test.665  proc do_peqp_test {tn sql res} {666    set fd [open script.tcl w]667    puts $fd [string map [list %SQL% $sql] $::boilerplate]668    close $fd669  670    uplevel do_test $tn [list {671      set fd [open "|[info nameofexec] script.tcl"]672      set data [read $fd]673      close $fd674      set data675    }] [list $res]676  }677  678  do_peqp_test 6.1 {679    SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1680  } [string trimleft {6811 0 0 SCAN t1 USING COVERING INDEX i26822 0 0 SCAN t26832 0 0 USE TEMP B-TREE FOR ORDER BY6840 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)685}]686}687}688 689#-------------------------------------------------------------------------690# The following tests - eqp-7.* - test that queries that use the OP_Count691# optimization return something sensible with EQP.692#693drop_all_tables694 695do_execsql_test 7.0 {696  CREATE TABLE t1(a INT, b INT, ex CHAR(100));697  CREATE TABLE t2(a INT, b INT, ex CHAR(100));698  CREATE INDEX i1 ON t2(a);699}700 701det 7.1 "SELECT count(*) FROM t1" {702  QUERY PLAN703  `--SCAN t1704}705 706det 7.2 "SELECT count(*) FROM t2" {707  QUERY PLAN708  `--SCAN t2 USING COVERING INDEX i1709}710 711do_execsql_test 7.3 {712  INSERT INTO t1(a,b) VALUES(1, 2);713  INSERT INTO t1(a,b) VALUES(3, 4);714 715  INSERT INTO t2(a,b) VALUES(1, 2);716  INSERT INTO t2(a,b) VALUES(3, 4);717  INSERT INTO t2(a,b) VALUES(5, 6);718 719  ANALYZE;720}721 722db close723sqlite3 db test.db724 725det 7.4 "SELECT count(*) FROM t1" {726  QUERY PLAN727  `--SCAN t1728}729 730det 7.5 "SELECT count(*) FROM t2" {731  QUERY PLAN732  `--SCAN t2 USING COVERING INDEX i1733}734 735#-------------------------------------------------------------------------736# The following tests - eqp-8.* - test that queries that use the OP_Count737# optimization return something sensible with EQP.738#739drop_all_tables740 741do_execsql_test 8.0 {742  CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;743  CREATE TABLE t2(a, b, c);744}745 746det 8.1.1 "SELECT * FROM t2" {747  QUERY PLAN748  `--SCAN t2749}750 751det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {752  QUERY PLAN753  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)754}755 756det 8.1.3 "SELECT count(*) FROM t2" {757  QUERY PLAN758  `--SCAN t2759}760 761det 8.2.1 "SELECT * FROM t1" {762  QUERY PLAN763  `--SCAN t1764}765 766det 8.2.2 "SELECT * FROM t1 WHERE b=?" {767  QUERY PLAN768  `--SEARCH t1 USING PRIMARY KEY (b=?)769}770 771det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {772  QUERY PLAN773  `--SEARCH t1 USING PRIMARY KEY (b=? AND c=?)774}775 776det 8.2.4 "SELECT count(*) FROM t1" {777  QUERY PLAN778  `--SCAN t1779}780 781# 2018-08-16:  While working on Fossil I discovered that EXPLAIN QUERY PLAN782# did not describe IN operators implemented using a ROWID lookup.  These783# test cases ensure that problem as been fixed.784#785do_execsql_test 9.0 {786  -- Schema from Fossil 2018-08-16787  CREATE TABLE forumpost(788    fpid INTEGER PRIMARY KEY,789    froot INT,790    fprev INT,791    firt INT,792    fmtime REAL793  );794  CREATE INDEX forumthread ON forumpost(froot,fmtime);795  CREATE TABLE blob(796    rid INTEGER PRIMARY KEY,797    rcvid INTEGER,798    size INTEGER,799    uuid TEXT UNIQUE NOT NULL,800    content BLOB,801    CHECK( length(uuid)>=40 AND rid>0 )802  );803  CREATE TABLE event(804    type TEXT,805    mtime DATETIME,806    objid INTEGER PRIMARY KEY,807    tagid INTEGER,808    uid INTEGER REFERENCES user,809    bgcolor TEXT,810    euser TEXT,811    user TEXT,812    ecomment TEXT,813    comment TEXT,814    brief TEXT,815    omtime DATETIME816  );817  CREATE INDEX event_i1 ON event(mtime);818  CREATE TABLE private(rid INTEGER PRIMARY KEY);819}820optimization_control db order-by-subquery off821do_eqp_test 9.1 {822  WITH thread(age,duration,cnt,root,last) AS (823    SELECT824      julianday('now') - max(fmtime) AS age,825      max(fmtime) - min(fmtime) AS duration,826      sum(fprev IS NULL) AS msg_count,827      froot,828      (SELECT fpid FROM forumpost829        WHERE froot=x.froot830          AND fpid NOT IN private831        ORDER BY fmtime DESC LIMIT 1)832    FROM forumpost AS x833    WHERE fpid NOT IN private  --- Ensure this table mentioned in EQP output!834    GROUP BY froot835    ORDER BY 1 LIMIT 26 OFFSET 5836  )837  SELECT838    thread.age,839    thread.duration,840    thread.cnt,841    blob.uuid,842    substr(event.comment,instr(event.comment,':')+1)843  FROM thread, blob, event844  WHERE blob.rid=thread.last845    AND event.objid=thread.last846  ORDER BY 1;847} {848  QUERY PLAN849  |--CO-ROUTINE thread850  |  |--SCAN x USING INDEX forumthread851  |  |--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR852  |  |--CORRELATED SCALAR SUBQUERY xxxxxx853  |  |  |--SEARCH forumpost USING COVERING INDEX forumthread (froot=?)854  |  |  `--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR855  |  `--USE TEMP B-TREE FOR ORDER BY856  |--SCAN thread857  |--SEARCH blob USING INTEGER PRIMARY KEY (rowid=?)858  |--SEARCH event USING INTEGER PRIMARY KEY (rowid=?)859  `--USE TEMP B-TREE FOR ORDER BY860}861optimization_control db all on862db cache flush863do_eqp_test 9.2 {864  WITH thread(age,duration,cnt,root,last) AS (865    SELECT866      julianday('now') - max(fmtime) AS age,867      max(fmtime) - min(fmtime) AS duration,868      sum(fprev IS NULL) AS msg_count,869      froot,870      (SELECT fpid FROM forumpost871        WHERE froot=x.froot872          AND fpid NOT IN private873        ORDER BY fmtime DESC LIMIT 1)874    FROM forumpost AS x875    WHERE fpid NOT IN private  --- Ensure this table mentioned in EQP output!876    GROUP BY froot877    ORDER BY 1 LIMIT 26 OFFSET 5878  )879  SELECT880    thread.age,881    thread.duration,882    thread.cnt,883    blob.uuid,884    substr(event.comment,instr(event.comment,':')+1)885  FROM thread, blob, event886  WHERE blob.rid=thread.last887    AND event.objid=thread.last888  ORDER BY 1;889} {890  QUERY PLAN891  |--CO-ROUTINE thread892  |  |--SCAN x USING INDEX forumthread893  |  |--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR894  |  |--CORRELATED SCALAR SUBQUERY xxxxxx895  |  |  |--SEARCH forumpost USING COVERING INDEX forumthread (froot=?)896  |  |  `--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR897  |  `--USE TEMP B-TREE FOR ORDER BY898  |--SCAN thread899  |--SEARCH blob USING INTEGER PRIMARY KEY (rowid=?)900  `--SEARCH event USING INTEGER PRIMARY KEY (rowid=?)901}902 903finish_test904