/ Check-in [9650f71b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge enhancements from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | cell-overwrite-prototype
Files: files | file ages | folders
SHA3-256: 9650f71b82ca1b3759e776bbd8a2e8ca61c51f80038e37c9c9a675a8c13b0b06
User & Date: drh 2018-05-04 19:18:27
Context
2018-05-07
11:29
Fix harmless compiler warnings in the cell-overwrite logic. Closed-Leaf check-in: 3e11dc31 user: drh tags: cell-overwrite-prototype
2018-05-04
19:18
Merge enhancements from trunk. check-in: 9650f71b user: drh tags: cell-overwrite-prototype
18:32
Fix requirements marks. No code changes. check-in: 7fdad122 user: drh tags: trunk
2018-05-03
16:56
Fix various error handling conditions on the cell overwrite optimization. Fix a test case so that it works with the new optimization. check-in: f89b54f4 user: drh tags: cell-overwrite-prototype
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to autoconf/Makefile.am.

     1      1   
     2         -AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
            2  +AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE @DEBUG_FLAGS@
     3      3   
     4      4   lib_LTLIBRARIES = libsqlite3.la
     5      5   libsqlite3_la_SOURCES = sqlite3.c
     6      6   libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
     7      7   
     8      8   bin_PROGRAMS = sqlite3
     9      9   sqlite3_SOURCES = shell.c sqlite3.h

Changes to autoconf/configure.ac.

   111    111   AC_SUBST(DYNAMIC_EXTENSION_FLAGS)
   112    112   #-----------------------------------------------------------------------
   113    113   
   114    114   #-----------------------------------------------------------------------
   115    115   #   --enable-fts5
   116    116   #
   117    117   AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
   118         -  [--enable-fts5], [include fts5 support [default=no]])], 
   119         -  [], [enable_fts5=no])
          118  +  [--enable-fts5], [include fts5 support [default=yes]])], 
          119  +  [], [enable_fts5=yes])
   120    120   if test x"$enable_fts5" = "xyes"; then
   121    121     AC_SEARCH_LIBS(log, m)
   122    122     FTS5_FLAGS=-DSQLITE_ENABLE_FTS5
   123    123   fi
   124    124   AC_SUBST(FTS5_FLAGS)
   125    125   #-----------------------------------------------------------------------
   126    126   
   127    127   #-----------------------------------------------------------------------
   128    128   #   --enable-json1
   129    129   #
   130    130   AC_ARG_ENABLE(json1, [AS_HELP_STRING(
   131         -  [--enable-json1], [include json1 support [default=no]])], 
   132         -  [], [enable_json1=no])
          131  +  [--enable-json1], [include json1 support [default=yes]])], 
          132  +  [], [enable_json1=yes])
   133    133   if test x"$enable_json1" = "xyes"; then
   134    134     JSON1_FLAGS=-DSQLITE_ENABLE_JSON1
   135    135   fi
   136    136   AC_SUBST(JSON1_FLAGS)
   137    137   #-----------------------------------------------------------------------
   138    138   
   139    139   #-----------------------------------------------------------------------
................................................................................
   143    143     [--enable-session], [enable the session extension [default=no]])], 
   144    144     [], [enable_session=no])
   145    145   if test x"$enable_session" = "xyes"; then
   146    146     SESSION_FLAGS="-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
   147    147   fi
   148    148   AC_SUBST(SESSION_FLAGS)
   149    149   #-----------------------------------------------------------------------
          150  +
          151  +#-----------------------------------------------------------------------
          152  +#   --enable-debug
          153  +#
          154  +AC_ARG_ENABLE(debug, [AS_HELP_STRING(
          155  +  [--enable-debug], [build with debugging features enabled [default=no]])], 
          156  +  [], [enable_session=no])
          157  +if test x"$enable_debug" = "xyes"; then
          158  +  DEBUG_FLAGS="-DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
          159  +fi
          160  +AC_SUBST(DEBUG_FLAGS)
          161  +#-----------------------------------------------------------------------
   150    162   
   151    163   #-----------------------------------------------------------------------
   152    164   #   --enable-static-shell
   153    165   #
   154    166   AC_ARG_ENABLE(static-shell, [AS_HELP_STRING(
   155    167     [--enable-static-shell], 
   156    168     [statically link libsqlite3 into shell tool [default=yes]])], 

Changes to ext/expert/expert1.test.

    91     91     eval $setup
    92     92   
    93     93   
    94     94   do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } {
    95     95     SELECT * FROM t1
    96     96   } {
    97     97     (no new indexes)
    98         -  0|0|0|SCAN TABLE t1
           98  +  SCAN TABLE t1
    99     99   }
   100    100   
   101    101   do_setup_rec_test $tn.2 {
   102    102     CREATE TABLE t1(a, b, c);
   103    103   } {
   104    104     SELECT * FROM t1 WHERE b>?;
   105    105   } {
   106    106     CREATE INDEX t1_idx_00000062 ON t1(b);
   107         -  0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
          107  +  SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
   108    108   }
   109    109   
   110    110   do_setup_rec_test $tn.3 {
   111    111     CREATE TABLE t1(a, b, c);
   112    112   } {
   113    113     SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ?
   114    114   } {
   115    115     CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE);
   116         -  0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
          116  +  SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
   117    117   }
   118    118   
   119    119   do_setup_rec_test $tn.4 {
   120    120     CREATE TABLE t1(a, b, c);
   121    121   } {
   122    122     SELECT a FROM t1 ORDER BY b;
   123    123   } {
   124    124     CREATE INDEX t1_idx_00000062 ON t1(b);
   125         -  0|0|0|SCAN TABLE t1 USING INDEX t1_idx_00000062
          125  +  SCAN TABLE t1 USING INDEX t1_idx_00000062
   126    126   }
   127    127   
   128    128   do_setup_rec_test $tn.5 {
   129    129     CREATE TABLE t1(a, b, c);
   130    130   } {
   131    131     SELECT a FROM t1 WHERE a=? ORDER BY b;
   132    132   } {
   133    133     CREATE INDEX t1_idx_000123a7 ON t1(a, b);
   134         -  0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
          134  +  SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
   135    135   }
   136    136   
   137    137   do_setup_rec_test $tn.6 {
   138    138     CREATE TABLE t1(a, b, c);
   139    139   } {
   140    140     SELECT min(a) FROM t1
   141    141   } {
   142    142     CREATE INDEX t1_idx_00000061 ON t1(a);
   143         -  0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
          143  +  SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
   144    144   }
   145    145   
   146    146   do_setup_rec_test $tn.7 {
   147    147     CREATE TABLE t1(a, b, c);
   148    148   } {
   149    149     SELECT * FROM t1 ORDER BY a, b, c;
   150    150   } {
   151    151     CREATE INDEX t1_idx_033e95fe ON t1(a, b, c);
   152         -  0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
          152  +  SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
   153    153   }
   154    154   
   155    155   #do_setup_rec_test $tn.1.8 {
   156    156   #  CREATE TABLE t1(a, b, c);
   157    157   #} {
   158    158   #  SELECT * FROM t1 ORDER BY a ASC, b COLLATE nocase DESC, c ASC;
   159    159   #} {
................................................................................
   163    163   
   164    164   do_setup_rec_test $tn.8.1 {
   165    165     CREATE TABLE t1(a COLLATE NOCase, b, c);
   166    166   } {
   167    167     SELECT * FROM t1 WHERE a=?
   168    168   } {
   169    169     CREATE INDEX t1_idx_00000061 ON t1(a);
   170         -  0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
          170  +  SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
   171    171   }
   172    172   do_setup_rec_test $tn.8.2 {
   173    173     CREATE TABLE t1(a, b COLLATE nocase, c);
   174    174   } {
   175    175     SELECT * FROM t1 ORDER BY a ASC, b DESC, c ASC;
   176    176   } {
   177    177     CREATE INDEX t1_idx_5cb97285 ON t1(a, b DESC, c);
   178         -  0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_5cb97285
          178  +  SCAN TABLE t1 USING COVERING INDEX t1_idx_5cb97285
   179    179   }
   180    180   
   181    181   
   182    182   # Tables with names that require quotes.
   183    183   #
   184    184   do_setup_rec_test $tn.9.1 {
   185    185     CREATE TABLE "t t"(a, b, c);
   186    186   } {
   187    187     SELECT * FROM "t t" WHERE a=?
   188    188   } {
   189    189     CREATE INDEX 't t_idx_00000061' ON 't t'(a);
   190         -  0|0|0|SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?) 
          190  +  SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?) 
   191    191   }
   192    192   
   193    193   do_setup_rec_test $tn.9.2 {
   194    194     CREATE TABLE "t t"(a, b, c);
   195    195   } {
   196    196     SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
   197    197   } {
   198    198     CREATE INDEX 't t_idx_00000062' ON 't t'(b);
   199         -  0|0|0|SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b<?)
          199  +  SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b<?)
   200    200   }
   201    201   
   202    202   # Columns with names that require quotes.
   203    203   #
   204    204   do_setup_rec_test $tn.10.1 {
   205    205     CREATE TABLE t3(a, "b b", c);
   206    206   } {
   207    207     SELECT * FROM t3 WHERE "b b" = ?
   208    208   } {
   209    209     CREATE INDEX t3_idx_00050c52 ON t3('b b');
   210         -  0|0|0|SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
          210  +  SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
   211    211   }
   212    212   
   213    213   do_setup_rec_test $tn.10.2 {
   214    214     CREATE TABLE t3(a, "b b", c);
   215    215   } {
   216    216     SELECT * FROM t3 ORDER BY "b b"
   217    217   } {
   218    218     CREATE INDEX t3_idx_00050c52 ON t3('b b');
   219         -  0|0|0|SCAN TABLE t3 USING INDEX t3_idx_00050c52
          219  +  SCAN TABLE t3 USING INDEX t3_idx_00050c52
   220    220   }
   221    221   
   222    222   # Transitive constraints
   223    223   #
   224    224   do_setup_rec_test $tn.11.1 {
   225    225     CREATE TABLE t5(a, b);
   226    226     CREATE TABLE t6(c, d);
   227    227   } {
   228    228     SELECT * FROM t5, t6 WHERE a=? AND b=c AND c=?
   229    229   } {
   230    230     CREATE INDEX t5_idx_000123a7 ON t5(a, b);
   231    231     CREATE INDEX t6_idx_00000063 ON t6(c);
   232         -  0|0|1|SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?) 
   233         -  0|1|0|SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
          232  +  SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?) 
          233  +  SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
   234    234   }
   235    235   
   236    236   # OR terms.
   237    237   #
   238    238   do_setup_rec_test $tn.12.1 {
   239    239     CREATE TABLE t7(a, b);
   240    240   } {
   241    241     SELECT * FROM t7 WHERE a=? OR b=?
   242    242   } {
   243    243     CREATE INDEX t7_idx_00000062 ON t7(b);
   244    244     CREATE INDEX t7_idx_00000061 ON t7(a);
   245         -  0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?) 
   246         -  0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
          245  +  MULTI-INDEX OR
          246  +    SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?) 
          247  +    SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
   247    248   }
   248    249   
   249    250   # rowid terms.
   250    251   #
   251    252   do_setup_rec_test $tn.13.1 {
   252    253     CREATE TABLE t8(a, b);
   253    254   } {
   254    255     SELECT * FROM t8 WHERE rowid=?
   255    256   } {
   256    257     (no new indexes)
   257         -  0|0|0|SEARCH TABLE t8 USING INTEGER PRIMARY KEY (rowid=?)
          258  +  SEARCH TABLE t8 USING INTEGER PRIMARY KEY (rowid=?)
   258    259   }
   259    260   do_setup_rec_test $tn.13.2 {
   260    261     CREATE TABLE t8(a, b);
   261    262   } {
   262    263     SELECT * FROM t8 ORDER BY rowid
   263    264   } {
   264    265     (no new indexes)
   265         -  0|0|0|SCAN TABLE t8
          266  +  SCAN TABLE t8
   266    267   }
   267    268   do_setup_rec_test $tn.13.3 {
   268    269     CREATE TABLE t8(a, b);
   269    270   } {
   270    271     SELECT * FROM t8 WHERE a=? ORDER BY rowid
   271    272   } {
   272    273     CREATE INDEX t8_idx_00000061 ON t8(a); 
   273         -  0|0|0|SEARCH TABLE t8 USING INDEX t8_idx_00000061 (a=?)
          274  +  SEARCH TABLE t8 USING INDEX t8_idx_00000061 (a=?)
   274    275   }
   275    276   
   276    277   # Triggers
   277    278   #
   278    279   do_setup_rec_test $tn.14 {
   279    280     CREATE TABLE t9(a, b, c);
   280    281     CREATE TABLE t10(a, b, c);
................................................................................
   281    282     CREATE TRIGGER t9t AFTER INSERT ON t9 BEGIN
   282    283       UPDATE t10 SET a=new.a WHERE b = new.b;
   283    284     END;
   284    285   } {
   285    286     INSERT INTO t9 VALUES(?, ?, ?);
   286    287   } {
   287    288     CREATE INDEX t10_idx_00000062 ON t10(b); 
   288         -  0|1|0|-- TRIGGER t9t
   289         -  0|0|0|SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
          289  +  -- TRIGGER t9t
          290  +  SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
   290    291   }
   291    292   
   292    293   do_setup_rec_test $tn.15 {
   293    294     CREATE TABLE t1(a, b);
   294    295     CREATE TABLE t2(c, d);
   295    296   
   296    297     WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
................................................................................
   298    299   
   299    300     WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
   300    301     INSERT INTO t2 SELECT (i-1)/20, (i-1)/5 FROM s;
   301    302   } {
   302    303     SELECT * FROM t2, t1 WHERE b=? AND d=? AND t2.rowid=t1.rowid
   303    304   } {
   304    305     CREATE INDEX t2_idx_00000064 ON t2(d);
   305         -  0|0|0|SEARCH TABLE t2 USING INDEX t2_idx_00000064 (d=?) 
   306         -  0|1|1|SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
          306  +  SEARCH TABLE t2 USING INDEX t2_idx_00000064 (d=?) 
          307  +  SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
   307    308   }
   308    309   
   309    310   do_setup_rec_test $tn.16 {
   310    311     CREATE TABLE t1(a, b);
   311    312   } {
   312    313     SELECT * FROM t1 WHERE b IS NOT NULL;
   313    314   } {
   314    315     (no new indexes)
   315         -  0|0|0|SCAN TABLE t1
          316  +  SCAN TABLE t1
   316    317   }
   317    318   
   318    319   }
   319    320   
   320    321   proc do_candidates_test {tn sql res} {
   321    322     set res [squish [string trim $res]]
   322    323   

Changes to ext/expert/sqlite3expert.c.

  1119   1119       IdxHashEntry *pEntry;
  1120   1120       sqlite3_stmt *pExplain = 0;
  1121   1121       idxHashClear(&hIdx);
  1122   1122       rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,
  1123   1123           "EXPLAIN QUERY PLAN %s", pStmt->zSql
  1124   1124       );
  1125   1125       while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
  1126         -      int iSelectid = sqlite3_column_int(pExplain, 0);
  1127         -      int iOrder = sqlite3_column_int(pExplain, 1);
  1128         -      int iFrom = sqlite3_column_int(pExplain, 2);
         1126  +      /* int iId = sqlite3_column_int(pExplain, 0); */
         1127  +      /* int iParent = sqlite3_column_int(pExplain, 1); */
         1128  +      /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
  1129   1129         const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
  1130   1130         int nDetail = STRLEN(zDetail);
  1131   1131         int i;
  1132   1132   
  1133   1133         for(i=0; i<nDetail; i++){
  1134   1134           const char *zIdx = 0;
  1135   1135           if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
................................................................................
  1148   1148               idxHashAdd(&rc, &hIdx, zSql, 0);
  1149   1149               if( rc ) goto find_indexes_out;
  1150   1150             }
  1151   1151             break;
  1152   1152           }
  1153   1153         }
  1154   1154   
  1155         -      pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%d|%d|%d|%s\n", 
  1156         -          iSelectid, iOrder, iFrom, zDetail
  1157         -      );
         1155  +      pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
  1158   1156       }
  1159   1157   
  1160   1158       for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
  1161   1159         pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey);
  1162   1160       }
  1163   1161   
  1164   1162       idxFinalize(&rc, pExplain);

Changes to ext/fts5/test/fts5plan.test.

    25     25     CREATE TABLE t1(x, y);
    26     26     CREATE VIRTUAL TABLE f1 USING fts5(ff);
    27     27   }
    28     28   
    29     29   do_eqp_test 1.1 {
    30     30     SELECT * FROM t1, f1 WHERE f1 MATCH t1.x
    31     31   } {
    32         -  0 0 0 {SCAN TABLE t1} 
    33         -  0 1 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:}
           32  +  QUERY PLAN
           33  +  |--SCAN TABLE t1
           34  +  `--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:
    34     35   }
    35     36   
    36     37   do_eqp_test 1.2 {
    37     38     SELECT * FROM t1, f1 WHERE f1 > t1.x
    38     39   } {
    39         -  0 0 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:}
    40         -  0 1 0 {SCAN TABLE t1} 
           40  +  QUERY PLAN
           41  +  |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
           42  +  `--SCAN TABLE t1
    41     43   }
    42     44   
    43     45   do_eqp_test 1.3 {
    44     46     SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
    45     47   } {
    46         -  0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:}
    47         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
           48  +  QUERY PLAN
           49  +  |--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:
           50  +  `--USE TEMP B-TREE FOR ORDER BY
    48     51   }
    49     52   
    50     53   do_eqp_test 1.4 {
    51     54     SELECT * FROM f1 ORDER BY rank
    52     55   } {
    53         -  0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:}
    54         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
           56  +  QUERY PLAN
           57  +  |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
           58  +  `--USE TEMP B-TREE FOR ORDER BY
    55     59   }
    56     60   
    57     61   do_eqp_test 1.5 {
    58     62     SELECT * FROM f1 WHERE rank MATCH ?
    59         -} {
    60         -  0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:}
    61         -}
    62         -
    63         -
    64         -
           63  +} {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:}
    65     64   
    66     65   finish_test

Changes to ext/rtree/rtree6.test.

    70     70   do_test rtree6-1.5 {
    71     71     rtree_strategy {SELECT * FROM t1,t2 WHERE k=+ii AND x1<10}
    72     72   } {C0}
    73     73   
    74     74   do_eqp_test rtree6.2.1 {
    75     75     SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
    76     76   } {
    77         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0} 
    78         -  0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
           77  +  QUERY PLAN
           78  +  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
           79  +  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
    79     80   }
    80     81   
    81     82   do_eqp_test rtree6.2.2 {
    82     83     SELECT * FROM t1,t2 WHERE k=ii AND x1<10
    83     84   } {
    84         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0} 
    85         -  0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
           85  +  QUERY PLAN
           86  +  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
           87  +  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
    86     88   }
    87     89   
    88     90   do_eqp_test rtree6.2.3 {
    89     91     SELECT * FROM t1,t2 WHERE k=ii
    90     92   } {
    91         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:} 
    92         -  0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
           93  +  QUERY PLAN
           94  +  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
           95  +  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
    93     96   }
    94     97   
    95     98   do_eqp_test rtree6.2.4.1 {
    96     99     SELECT * FROM t1,t2 WHERE v=+ii and x1<10 and x2>10
    97    100   } {
    98         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1} 
    99         -  0 1 1 {SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)}
          101  +  QUERY PLAN
          102  +  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
          103  +  `--SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)
   100    104   }
   101    105   do_eqp_test rtree6.2.4.2 {
   102    106     SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
   103    107   } {
   104         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1} 
   105         -  0 1 1 {SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)}
          108  +  QUERY PLAN
          109  +  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
          110  +  `--SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
   106    111   }
   107    112   
   108    113   do_eqp_test rtree6.2.5 {
   109    114     SELECT * FROM t1,t2 WHERE k=ii AND x1<v
   110    115   } {
   111         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:} 
   112         -  0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
          116  +  QUERY PLAN
          117  +  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
          118  +  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
   113    119   }
   114    120   
   115    121   do_execsql_test rtree6-3.1 {
   116    122     CREATE VIRTUAL TABLE t3 USING rtree(id, x1, x2, y1, y2);
   117    123     INSERT INTO t3 VALUES(NULL, 1, 1, 2, 2);
   118    124     SELECT * FROM t3 WHERE 
   119    125       x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 

Changes to ext/rtree/rtreeC.test.

    25     25     CREATE TABLE t(x, y);
    26     26   }
    27     27   
    28     28   do_eqp_test 1.1 {
    29     29     SELECT * FROM r_tree, t 
    30     30     WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
    31     31   } {
    32         -  0 0 1 {SCAN TABLE t}
    33         -  0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
           32  +  QUERY PLAN
           33  +  |--SCAN TABLE t
           34  +  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
    34     35   }
    35     36   
    36     37   do_eqp_test 1.2 {
    37     38     SELECT * FROM t, r_tree
    38     39     WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
    39     40   } {
    40         -  0 0 0 {SCAN TABLE t}
    41         -  0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
           41  +  QUERY PLAN
           42  +  |--SCAN TABLE t
           43  +  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
    42     44   }
    43     45   
    44     46   do_eqp_test 1.3 {
    45     47     SELECT * FROM t, r_tree
    46     48     WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
    47     49   } {
    48         -  0 0 0 {SCAN TABLE t}
    49         -  0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
           50  +  QUERY PLAN
           51  +  |--SCAN TABLE t
           52  +  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
    50     53   }
    51     54   
    52     55   do_eqp_test 1.5 {
    53     56     SELECT * FROM t, r_tree
    54     57   } {
    55         -  0 0 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:}
    56         -  0 1 0 {SCAN TABLE t} 
           58  +  QUERY PLAN
           59  +  |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
           60  +  `--SCAN TABLE t
    57     61   }
    58     62   
    59     63   do_execsql_test 2.0 {
    60     64     INSERT INTO t VALUES(0, 0);
    61     65     INSERT INTO t VALUES(0, 1);
    62     66     INSERT INTO t VALUES(0, 2);
    63     67     INSERT INTO t VALUES(0, 3);
................................................................................
    78     82   db close
    79     83   sqlite3 db test.db
    80     84   
    81     85   do_eqp_test 2.1 {
    82     86     SELECT * FROM r_tree, t 
    83     87     WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
    84     88   } {
    85         -  0 0 1 {SCAN TABLE t}
    86         -  0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
           89  +  QUERY PLAN
           90  +  |--SCAN TABLE t
           91  +  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
    87     92   }
    88     93   
    89     94   do_eqp_test 2.2 {
    90     95     SELECT * FROM t, r_tree
    91     96     WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
    92     97   } {
    93         -  0 0 0 {SCAN TABLE t}
    94         -  0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
           98  +  QUERY PLAN
           99  +  |--SCAN TABLE t
          100  +  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
    95    101   }
    96    102   
    97    103   do_eqp_test 2.3 {
    98    104     SELECT * FROM t, r_tree
    99    105     WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
   100    106   } {
   101         -  0 0 0 {SCAN TABLE t}
   102         -  0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
          107  +  QUERY PLAN
          108  +  |--SCAN TABLE t
          109  +  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
   103    110   }
   104    111   
   105    112   do_eqp_test 2.5 {
   106    113     SELECT * FROM t, r_tree
   107    114   } {
   108         -  0 0 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:}
   109         -  0 1 0 {SCAN TABLE t} 
          115  +  QUERY PLAN
          116  +  |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
          117  +  `--SCAN TABLE t
   110    118   }
   111    119   
   112    120   #-------------------------------------------------------------------------
   113    121   # Test that the special CROSS JOIN handling works with rtree tables.
   114    122   #
   115    123   do_execsql_test 3.1 {
   116    124     CREATE TABLE t1(x);
   117    125     CREATE TABLE t2(y);
   118    126     CREATE VIRTUAL TABLE t3 USING rtree(z, x1,x2, y1,y2);
   119    127   }
   120    128   
   121    129   do_eqp_test 3.2.1 { SELECT * FROM t1 CROSS JOIN t2 } {
   122         -  0 0 0 {SCAN TABLE t1} 
   123         -  0 1 1 {SCAN TABLE t2}
          130  +  QUERY PLAN
          131  +  |--SCAN TABLE t1
          132  +  `--SCAN TABLE t2
   124    133   }
   125    134   do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } {
   126         -  0 0 0 {SCAN TABLE t2} 0 1 1 {SCAN TABLE t1}
          135  +  QUERY PLAN
          136  +  |--SCAN TABLE t2
          137  +  `--SCAN TABLE t1
   127    138   }
   128    139   
   129    140   do_eqp_test 3.3.1 { SELECT * FROM t1 CROSS JOIN t3 } {
   130         -  0 0 0 {SCAN TABLE t1}
   131         -  0 1 1 {SCAN TABLE t3 VIRTUAL TABLE INDEX 2:} 
          141  +  QUERY PLAN
          142  +  |--SCAN TABLE t1
          143  +  `--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
   132    144   }
   133    145   do_eqp_test 3.3.2 { SELECT * FROM t3 CROSS JOIN t1 } {
   134         -  0 0 0 {SCAN TABLE t3 VIRTUAL TABLE INDEX 2:} 
   135         -  0 1 1 {SCAN TABLE t1}
          146  +  QUERY PLAN
          147  +  |--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
          148  +  `--SCAN TABLE t1
   136    149   }
   137    150   
   138    151   #--------------------------------------------------------------------
   139    152   # Test that LEFT JOINs are not reordered if the right-hand-side is
   140    153   # a virtual table.
   141    154   #
   142    155   reset_db
................................................................................
   185    198   
   186    199   # First test a query with no ANALYZE data at all. The outer loop is
   187    200   # real table "t1".
   188    201   #
   189    202   do_eqp_test 5.2 {
   190    203     SELECT * FROM t1, rt WHERE x==id;
   191    204   } {
   192         -  0 0 0 {SCAN TABLE t1} 
   193         -  0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
          205  +  QUERY PLAN
          206  +  |--SCAN TABLE t1
          207  +  `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
   194    208   }
   195    209   
   196    210   # Now create enough ANALYZE data to tell SQLite that virtual table "rt"
   197    211   # contains very few rows. This causes it to move "rt" to the outer loop.
   198    212   #
   199    213   do_execsql_test 5.3 {
   200    214     ANALYZE;
................................................................................
   201    215     DELETE FROM sqlite_stat1 WHERE tbl='t1';
   202    216   }
   203    217   db close
   204    218   sqlite3 db test.db
   205    219   do_eqp_test 5.4 {
   206    220     SELECT * FROM t1, rt WHERE x==id;
   207    221   } {
   208         -  0 0 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:} 
   209         -  0 1 0 {SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)}
          222  +  QUERY PLAN
          223  +  |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:
          224  +  `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
   210    225   }
   211    226   
   212    227   # Delete the ANALYZE data. "t1" should be the outer loop again.
   213    228   #
   214    229   do_execsql_test 5.5 { DROP TABLE sqlite_stat1; }
   215    230   db close
   216    231   sqlite3 db test.db
   217    232   do_eqp_test 5.6 {
   218    233     SELECT * FROM t1, rt WHERE x==id;
   219    234   } {
   220         -  0 0 0 {SCAN TABLE t1} 
   221         -  0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
          235  +  QUERY PLAN
          236  +  |--SCAN TABLE t1
          237  +  `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
   222    238   }
   223    239   
   224    240   # This time create and attach a database that contains ANALYZE data for
   225    241   # tables of the same names as those used internally by virtual table
   226    242   # "rt". Check that the rtree module is not fooled into using this data.
   227    243   # Table "t1" should remain the outer loop.
   228    244   #
................................................................................
   237    253     db close
   238    254     sqlite3 db test.db
   239    255     execsql { ATTACH 'test.db2' AS aux; }
   240    256   } {}
   241    257   do_eqp_test 5.8 {
   242    258     SELECT * FROM t1, rt WHERE x==id;
   243    259   } {
   244         -  0 0 0 {SCAN TABLE t1} 
   245         -  0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
          260  +  QUERY PLAN
          261  +  |--SCAN TABLE t1
          262  +  `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
   246    263   }
   247    264   
   248    265   #--------------------------------------------------------------------
   249    266   # Test that having a second connection drop the sqlite_stat1 table
   250    267   # before it is required by rtreeConnect() does not cause problems.
   251    268   #
   252    269   ifcapable rtree {
................................................................................
   295    312     INSERT INTO rt VALUES(1, 2, 7, 12, 14);      -- Not a hit
   296    313     INSERT INTO rt VALUES(2, 2, 7, 8, 12);       -- A hit!
   297    314     INSERT INTO rt VALUES(3, 7, 11, 8, 12);      -- Not a hit!
   298    315     INSERT INTO rt VALUES(4, 5, 5, 10, 10);      -- A hit!
   299    316   
   300    317   }
   301    318   
   302         -proc do_eqp_execsql_test {tn sql res} {
   303         -  set query "EXPLAIN QUERY PLAN $sql ; $sql "
   304         -  uplevel [list do_execsql_test $tn $query $res]
          319  +proc do_eqp_execsql_test {tn sql res1 res2} {
          320  +  do_eqp_test $tn.1 $sql $res1
          321  +  do_execsql_test $tn.2 $sql $res2
   305    322   }
   306    323   
   307    324   do_eqp_execsql_test 7.1 {
   308    325     SELECT id FROM xdir, rt, ydir 
   309    326     ON (y1 BETWEEN ymin AND ymax)
   310    327     WHERE (x1 BETWEEN xmin AND xmax);
   311    328   } {
   312         -  0 0 0 {SCAN TABLE xdir} 
   313         -  0 1 2 {SCAN TABLE ydir} 
   314         -  0 2 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1}
          329  +  QUERY PLAN
          330  +  |--SCAN TABLE xdir
          331  +  |--SCAN TABLE ydir
          332  +  `--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1
          333  +} {
   315    334     2 4
   316    335   }
   317    336   
   318    337   do_eqp_execsql_test 7.2 {
   319    338     SELECT * FROM xdir, rt LEFT JOIN ydir 
   320    339     ON (y1 BETWEEN ymin AND ymax)
   321    340     WHERE (x1 BETWEEN xmin AND xmax);
   322    341   } {
   323         -  0 0 0 {SCAN TABLE xdir} 
   324         -  0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
   325         -  0 2 2 {SCAN TABLE ydir} 
   326         -
          342  +  QUERY PLAN
          343  +  |--SCAN TABLE xdir
          344  +  |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
          345  +  `--SCAN TABLE ydir
          346  +} {
   327    347     5 1 2 7 12 14 {}
   328    348     5 2 2 7  8 12 10
   329    349     5 4 5 5 10 10 10
   330    350   }
   331    351   
   332    352   do_eqp_execsql_test 7.3 {
   333    353     SELECT id FROM xdir, rt CROSS JOIN ydir 
   334    354     ON (y1 BETWEEN ymin AND ymax)
   335    355     WHERE (x1 BETWEEN xmin AND xmax);
   336    356   } {
   337         -  0 0 0 {SCAN TABLE xdir} 
   338         -  0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
   339         -  0 2 2 {SCAN TABLE ydir} 
          357  +  QUERY PLAN
          358  +  |--SCAN TABLE xdir
          359  +  |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
          360  +  `--SCAN TABLE ydir
          361  +} {
   340    362     2 4
   341    363   }
   342    364   
   343    365   do_eqp_execsql_test 7.4 {
   344    366     SELECT id FROM rt, xdir CROSS JOIN ydir 
   345    367     ON (y1 BETWEEN ymin AND ymax)
   346    368     WHERE (x1 BETWEEN xmin AND xmax);
   347    369   } {
   348         -  0 0 1 {SCAN TABLE xdir} 
   349         -  0 1 0 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
   350         -  0 2 2 {SCAN TABLE ydir} 
          370  +  QUERY PLAN
          371  +  |--SCAN TABLE xdir
          372  +  |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
          373  +  `--SCAN TABLE ydir
          374  +} {
   351    375     2 4
   352    376   }
   353    377   
   354    378   finish_test

Changes to src/expr.c.

  2406   2406               if( aiMap ) aiMap[i] = j;
  2407   2407             }
  2408   2408     
  2409   2409             assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) );
  2410   2410             if( colUsed==(MASKBIT(nExpr)-1) ){
  2411   2411               /* If we reach this point, that means the index pIdx is usable */
  2412   2412               int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
  2413         -#ifndef SQLITE_OMIT_EXPLAIN
  2414         -            sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0,
  2415         -              sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName),
  2416         -              P4_DYNAMIC);
  2417         -#endif
         2413  +            ExplainQueryPlan((pParse, 0,
         2414  +                              "USING INDEX %s FOR IN-OPERATOR",pIdx->zName));
  2418   2415               sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
  2419   2416               sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
  2420   2417               VdbeComment((v, "%s", pIdx->zName));
  2421   2418               assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
  2422   2419               eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
  2423   2420     
  2424   2421               if( prRhsHasNull ){
................................................................................
  2642   2639           **
  2643   2640           ** Generate code to write the results of the select into the temporary
  2644   2641           ** table allocated and opened above.
  2645   2642           */
  2646   2643           Select *pSelect = pExpr->x.pSelect;
  2647   2644           ExprList *pEList = pSelect->pEList;
  2648   2645   
  2649         -#ifndef SQLITE_OMIT_EXPLAIN
  2650         -        if( pParse->explain==2 ){
  2651         -          char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %sLIST SUBQUERY %d",
  2652         -            jmpIfDynamic>=0?"":"CORRELATED ",
  2653         -            pParse->iNextSelectId
  2654         -          );
  2655         -          sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg,
  2656         -                            P4_DYNAMIC);
  2657         -        }
  2658         -#endif
  2659         -
         2646  +        ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY",
         2647  +            jmpIfDynamic>=0?"":"CORRELATED "
         2648  +        ));
  2660   2649           assert( !isRowid );
  2661   2650           /* If the LHS and RHS of the IN operator do not match, that
  2662   2651           ** error will have been caught long before we reach this point. */
  2663   2652           if( ALWAYS(pEList->nExpr==nVal) ){
  2664   2653             SelectDest dest;
  2665   2654             int i;
  2666   2655             sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
................................................................................
  2773   2762         Expr *pLimit;                         /* New limit expression */
  2774   2763   
  2775   2764         testcase( pExpr->op==TK_EXISTS );
  2776   2765         testcase( pExpr->op==TK_SELECT );
  2777   2766         assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
  2778   2767         assert( ExprHasProperty(pExpr, EP_xIsSelect) );
  2779   2768   
  2780         -#ifndef SQLITE_OMIT_EXPLAIN
  2781         -      if( pParse->explain==2 ){
  2782         -        char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %sSCALAR SUBQUERY %d",
  2783         -            jmpIfDynamic>=0?"":"CORRELATED ",
  2784         -            pParse->iNextSelectId
  2785         -        );
  2786         -        sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg,
  2787         -                          P4_DYNAMIC);
  2788         -      }
  2789         -#endif
  2790         -
  2791   2769         pSel = pExpr->x.pSelect;
         2770  +      ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY",
         2771  +            jmpIfDynamic>=0?"":"CORRELATED "));
  2792   2772         nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1;
  2793   2773         sqlite3SelectDestInit(&dest, 0, pParse->nMem+1);
  2794   2774         pParse->nMem += nReg;
  2795   2775         if( pExpr->op==TK_SELECT ){
  2796   2776           dest.eDest = SRT_Mem;
  2797   2777           dest.iSdst = dest.iSDParm;
  2798   2778           dest.nSdst = nReg;

Changes to src/prepare.c.

   612    612     }
   613    613     rc = sParse.rc;
   614    614   
   615    615   #ifndef SQLITE_OMIT_EXPLAIN
   616    616     if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
   617    617       static const char * const azColName[] = {
   618    618          "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
   619         -       "selectid", "order", "from", "detail"
          619  +       "id", "parent", "notused", "detail"
   620    620       };
   621    621       int iFirst, mx;
   622    622       if( sParse.explain==2 ){
   623    623         sqlite3VdbeSetNumCols(sParse.pVdbe, 4);
   624    624         iFirst = 8;
   625    625         mx = 12;
   626    626       }else{

Changes to src/select.c.

    17     17   /*
    18     18   ** Trace output macros
    19     19   */
    20     20   #if SELECTTRACE_ENABLED
    21     21   /***/ int sqlite3SelectTrace = 0;
    22     22   # define SELECTTRACE(K,P,S,X)  \
    23     23     if(sqlite3SelectTrace&(K))   \
    24         -    sqlite3DebugPrintf("%s/%d/%p: ",(S)->zSelName,(P)->iSelectId,(S)),\
           24  +    sqlite3DebugPrintf("%s/%d/%p: ",(S)->zSelName,(P)->addrExplain,(S)),\
    25     25       sqlite3DebugPrintf X
    26     26   #else
    27     27   # define SELECTTRACE(K,P,S,X)
    28     28   #endif
    29     29   
    30     30   
    31     31   /*
................................................................................
    74     74     u8 nDefer;            /* Number of valid entries in aDefer[] */
    75     75     struct DeferredCsr {
    76     76       Table *pTab;        /* Table definition */
    77     77       int iCsr;           /* Cursor number for table */
    78     78       int nKey;           /* Number of PK columns for table pTab (>=1) */
    79     79     } aDefer[4];
    80     80   #endif
           81  +  struct RowLoadInfo *pDeferredRowLoad;  /* Deferred row loading info or NULL */
    81     82   };
    82     83   #define SORTFLAG_UseSorter  0x01   /* Use SorterOpen instead of OpenEphemeral */
    83     84   
    84     85   /*
    85     86   ** Delete all the content of a Select structure.  Deallocate the structure
    86     87   ** itself only if bFree is true.
    87     88   */
................................................................................
   531    532   /* Forward reference */
   532    533   static KeyInfo *keyInfoFromExprList(
   533    534     Parse *pParse,       /* Parsing context */
   534    535     ExprList *pList,     /* Form the KeyInfo object from this ExprList */
   535    536     int iStart,          /* Begin with this column of pList */
   536    537     int nExtra           /* Add this many extra columns to the end */
   537    538   );
          539  +
          540  +/*
          541  +** An instance of this object holds information (beyond pParse and pSelect)
          542  +** needed to load the next result row that is to be added to the sorter.
          543  +*/
          544  +typedef struct RowLoadInfo RowLoadInfo;
          545  +struct RowLoadInfo {
          546  +  int regResult;               /* Store results in array of registers here */
          547  +  u8 ecelFlags;                /* Flag argument to ExprCodeExprList() */
          548  +#ifdef SQLITE_ENABLE_SORTER_REFERENCES
          549  +  ExprList *pExtra;            /* Extra columns needed by sorter refs */
          550  +  int regExtraResult;          /* Where to load the extra columns */
          551  +#endif
          552  +};
          553  +
          554  +/*
          555  +** This routine does the work of loading query data into an array of
          556  +** registers so that it can be added to the sorter.
          557  +*/
          558  +static void innerLoopLoadRow(
          559  +  Parse *pParse,             /* Statement under construction */
          560  +  Select *pSelect,           /* The query being coded */
          561  +  RowLoadInfo *pInfo         /* Info needed to complete the row load */
          562  +){
          563  +  sqlite3ExprCodeExprList(pParse, pSelect->pEList, pInfo->regResult,
          564  +                          0, pInfo->ecelFlags);
          565  +#ifdef SQLITE_ENABLE_SORTER_REFERENCES
          566  +  if( pInfo->pExtra ){
          567  +    sqlite3ExprCodeExprList(pParse, pInfo->pExtra, pInfo->regExtraResult, 0, 0);
          568  +    sqlite3ExprListDelete(pParse->db, pInfo->pExtra);
          569  +  }
          570  +#endif
          571  +}
          572  +
          573  +/*
          574  +** Code the OP_MakeRecord instruction that generates the entry to be
          575  +** added into the sorter.
          576  +**
          577  +** Return the register in which the result is stored.
          578  +*/
          579  +static int makeSorterRecord(
          580  +  Parse *pParse,
          581  +  SortCtx *pSort,
          582  +  Select *pSelect,
          583  +  int regBase,
          584  +  int nBase
          585  +){
          586  +  int nOBSat = pSort->nOBSat;
          587  +  Vdbe *v = pParse->pVdbe;
          588  +  int regOut = ++pParse->nMem;
          589  +  if( pSort->pDeferredRowLoad ){
          590  +    innerLoopLoadRow(pParse, pSelect, pSort->pDeferredRowLoad);
          591  +  }
          592  +  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regOut);
          593  +  return regOut;
          594  +}
   538    595   
   539    596   /*
   540    597   ** Generate code that will push the record in registers regData
   541    598   ** through regData+nData-1 onto the sorter.
   542    599   */
   543    600   static void pushOntoSorter(
   544    601     Parse *pParse,         /* Parser context */
   545    602     SortCtx *pSort,        /* Information about the ORDER BY clause */
   546    603     Select *pSelect,       /* The whole SELECT statement */
   547    604     int regData,           /* First register holding data to be sorted */
   548    605     int regOrigData,       /* First register holding data before packing */
   549         -  int nData,             /* Number of elements in the data array */
          606  +  int nData,             /* Number of elements in the regData data array */
   550    607     int nPrefixReg         /* No. of reg prior to regData available for use */
   551    608   ){
   552    609     Vdbe *v = pParse->pVdbe;                         /* Stmt under construction */
   553    610     int bSeq = ((pSort->sortFlags & SORTFLAG_UseSorter)==0);
   554    611     int nExpr = pSort->pOrderBy->nExpr;              /* No. of ORDER BY terms */
   555    612     int nBase = nExpr + bSeq + nData;                /* Fields in sorter record */
   556    613     int regBase;                                     /* Regs for sorter record */
   557         -  int regRecord = ++pParse->nMem;                  /* Assembled sorter record */
          614  +  int regRecord = 0;                               /* Assembled sorter record */
   558    615     int nOBSat = pSort->nOBSat;                      /* ORDER BY terms to skip */
   559    616     int op;                            /* Opcode to add sorter record to sorter */
   560    617     int iLimit;                        /* LIMIT counter */
          618  +  int iSkip = 0;                     /* End of the sorter insert loop */
   561    619   
   562    620     assert( bSeq==0 || bSeq==1 );
          621  +
          622  +  /* Three cases:
          623  +  **   (1) The data to be sorted has already been packed into a Record
          624  +  **       by a prior OP_MakeRecord.  In this case nData==1 and regData
          625  +  **       will be completely unrelated to regOrigData.
          626  +  **   (2) All output columns are included in the sort record.  In that
          627  +  **       case regData==regOrigData.
          628  +  **   (3) Some output columns are omitted from the sort record due to
          629  +  **       the SQLITE_ENABLE_SORTER_REFERENCE optimization, or due to the
          630  +  **       SQLITE_ECEL_OMITREF optimization.  In that case, regOrigData==0
          631  +  **       to prevent this routine from trying to copy values that might
          632  +  **       not exist.
          633  +  */
   563    634     assert( nData==1 || regData==regOrigData || regOrigData==0 );
          635  +
   564    636     if( nPrefixReg ){
   565    637       assert( nPrefixReg==nExpr+bSeq );
   566         -    regBase = regData - nExpr - bSeq;
          638  +    regBase = regData - nPrefixReg;
   567    639     }else{
   568    640       regBase = pParse->nMem + 1;
   569    641       pParse->nMem += nBase;
   570    642     }
   571    643     assert( pSelect->iOffset==0 || pSelect->iLimit!=0 );
   572    644     iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
   573    645     pSort->labelDone = sqlite3VdbeMakeLabel(v);
................................................................................
   583    655       int regPrevKey;   /* The first nOBSat columns of the previous row */
   584    656       int addrFirst;    /* Address of the OP_IfNot opcode */
   585    657       int addrJmp;      /* Address of the OP_Jump opcode */
   586    658       VdbeOp *pOp;      /* Opcode that opens the sorter */
   587    659       int nKey;         /* Number of sorting key columns, including OP_Sequence */
   588    660       KeyInfo *pKI;     /* Original KeyInfo on the sorter table */
   589    661   
   590         -    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat,regRecord);
          662  +    regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase);
   591    663       regPrevKey = pParse->nMem+1;
   592    664       pParse->nMem += pSort->nOBSat;
   593    665       nKey = nExpr - pSort->nOBSat + bSeq;
   594    666       if( bSeq ){
   595    667         addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); 
   596    668       }else{
   597    669         addrFirst = sqlite3VdbeAddOp1(v, OP_SequenceTest, pSort->iECursor);
................................................................................
   634    706       ** If the new record does not need to be inserted into the sorter,
   635    707       ** jump to the next iteration of the loop. Or, if the
   636    708       ** pSort->bOrderedInnerLoop flag is set to indicate that the inner
   637    709       ** loop delivers items in sorted order, jump to the next iteration
   638    710       ** of the outer loop.
   639    711       */
   640    712       int iCsr = pSort->iECursor;
   641         -    int iJmp = sqlite3VdbeCurrentAddr(v)+5+(nOBSat<=0)+pSort->bOrderedInnerLoop;
   642         -    assert( pSort->bOrderedInnerLoop==0 || pSort->bOrderedInnerLoop==1 );
   643    713       sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4);
   644    714       VdbeCoverage(v);
   645    715       sqlite3VdbeAddOp2(v, OP_Last, iCsr, 0);
   646         -    sqlite3VdbeAddOp4Int(v, OP_IdxLE, iCsr, iJmp, regBase+nOBSat, nExpr-nOBSat);
          716  +    iSkip = sqlite3VdbeAddOp4Int(v, OP_IdxLE,
          717  +                                 iCsr, 0, regBase+nOBSat, nExpr-nOBSat);
   647    718       VdbeCoverage(v);
   648    719       sqlite3VdbeAddOp1(v, OP_Delete, iCsr);
   649    720     }
   650         -  if( nOBSat<=0 ){
   651         -    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat,regRecord);
          721  +  if( regRecord==0 ){
          722  +    regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase);
   652    723     }
   653    724     if( pSort->sortFlags & SORTFLAG_UseSorter ){
   654    725       op = OP_SorterInsert;
   655    726     }else{
   656    727       op = OP_IdxInsert;
   657    728     }
   658    729     sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord,
   659    730                          regBase+nOBSat, nBase-nOBSat);
          731  +  if( iSkip ){
          732  +    assert( pSort->bOrderedInnerLoop==0 || pSort->bOrderedInnerLoop==1 );
          733  +    sqlite3VdbeChangeP2(v, iSkip,
          734  +         sqlite3VdbeCurrentAddr(v) + pSort->bOrderedInnerLoop);
          735  +  }
   660    736   }
   661    737   
   662    738   /*
   663    739   ** Add code to implement the OFFSET
   664    740   */
   665    741   static void codeOffset(
   666    742     Vdbe *v,          /* Generate code into this VM */
................................................................................
   738    814     for(i=0; i<pEList->nExpr; i++){
   739    815       struct ExprList_item *pItem = &pEList->a[i];
   740    816       if( pItem->u.x.iOrderByCol==0 ){
   741    817         Expr *pExpr = pItem->pExpr;
   742    818         Table *pTab = pExpr->pTab;
   743    819         if( pExpr->op==TK_COLUMN && pTab && !IsVirtual(pTab)
   744    820          && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
   745         -#if 0
   746         -          && pTab->pSchema && pTab->pSelect==0 && !IsVirtual(pTab)
   747         -#endif
   748    821         ){
   749    822           int j;
   750    823           for(j=0; j<nDefer; j++){
   751    824             if( pSort->aDefer[j].iCsr==pExpr->iTable ) break;
   752    825           }
   753    826           if( j==nDefer ){
   754    827             if( nDefer==ArraySize(pSort->aDefer) ){
................................................................................
   807    880     Vdbe *v = pParse->pVdbe;
   808    881     int i;
   809    882     int hasDistinct;            /* True if the DISTINCT keyword is present */
   810    883     int eDest = pDest->eDest;   /* How to dispose of results */
   811    884     int iParm = pDest->iSDParm; /* First argument to disposal method */
   812    885     int nResultCol;             /* Number of result columns */
   813    886     int nPrefixReg = 0;         /* Number of extra registers before regResult */
          887  +  RowLoadInfo sRowLoadInfo;   /* Info for deferred row loading */
   814    888   
   815    889     /* Usually, regResult is the first cell in an array of memory cells
   816    890     ** containing the current result row. In this case regOrig is set to the
   817    891     ** same value. However, if the results are being sent to the sorter, the
   818    892     ** values for any expressions that are also part of the sort-key are omitted
   819    893     ** from this array. In this case regOrig is set to zero.  */
   820    894     int regResult;              /* Start of memory holding current results */
................................................................................
   859    933     }else if( eDest!=SRT_Exists ){
   860    934   #ifdef SQLITE_ENABLE_SORTER_REFERENCES
   861    935       ExprList *pExtra = 0;
   862    936   #endif
   863    937       /* If the destination is an EXISTS(...) expression, the actual
   864    938       ** values returned by the SELECT are not required.
   865    939       */
   866         -    u8 ecelFlags;
          940  +    u8 ecelFlags;    /* "ecel" is an abbreviation of "ExprCodeExprList" */
          941  +    ExprList *pEList;
   867    942       if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){
   868    943         ecelFlags = SQLITE_ECEL_DUP;
   869    944       }else{
   870    945         ecelFlags = 0;
   871    946       }
   872    947       if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){
   873    948         /* For each expression in p->pEList that is a copy of an expression in
   874    949         ** the ORDER BY clause (pSort->pOrderBy), set the associated 
   875    950         ** iOrderByCol value to one more than the index of the ORDER BY 
   876    951         ** expression within the sort-key that pushOntoSorter() will generate.
   877    952         ** This allows the p->pEList field to be omitted from the sorted record,
   878    953         ** saving space and CPU cycles.  */
   879    954         ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF);
          955  +
   880    956         for(i=pSort->nOBSat; i<pSort->pOrderBy->nExpr; i++){
   881    957           int j;
   882    958           if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){
   883    959             p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat;
   884    960           }
   885    961         }
   886    962   #ifdef SQLITE_ENABLE_SORTER_REFERENCES
................................................................................
   893    969           ** composite primary keys in the SortCtx.aDefer[] array.  */
   894    970           VdbeOp *pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
   895    971           pOp->p2 += (pExtra->nExpr - pSort->nDefer);
   896    972           pOp->p4.pKeyInfo->nAllField += (pExtra->nExpr - pSort->nDefer);
   897    973           pParse->nMem += pExtra->nExpr;
   898    974         }
   899    975   #endif
   900         -      regOrig = 0;
          976  +
          977  +      /* Adjust nResultCol to account for columns that are omitted
          978  +      ** from the sorter by the optimizations in this branch */
          979  +      pEList = p->pEList;
          980  +      for(i=0; i<pEList->nExpr; i++){
          981  +        if( pEList->a[i].u.x.iOrderByCol>0
          982  +#ifdef SQLITE_ENABLE_SORTER_REFERENCES
          983  +         || pEList->a[i].bSorterRef
          984  +#endif
          985  +        ){
          986  +          nResultCol--;
          987  +          regOrig = 0;
          988  +        }
          989  +      }
          990  +
          991  +      testcase( regOrig );
          992  +      testcase( eDest==SRT_Set );
          993  +      testcase( eDest==SRT_Mem );
          994  +      testcase( eDest==SRT_Coroutine );
          995  +      testcase( eDest==SRT_Output );
   901    996         assert( eDest==SRT_Set || eDest==SRT_Mem 
   902    997              || eDest==SRT_Coroutine || eDest==SRT_Output );
   903    998       }
   904         -    nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult,
   905         -                                         0,ecelFlags);
          999  +    sRowLoadInfo.regResult = regResult;
         1000  +    sRowLoadInfo.ecelFlags = ecelFlags;
   906   1001   #ifdef SQLITE_ENABLE_SORTER_REFERENCES
   907         -    if( pExtra ){
   908         -      nResultCol += sqlite3ExprCodeExprList(
   909         -          pParse, pExtra, regResult + nResultCol, 0, 0
   910         -      );
   911         -      sqlite3ExprListDelete(pParse->db, pExtra);
         1002  +    sRowLoadInfo.pExtra = pExtra;
         1003  +    sRowLoadInfo.regExtraResult = regResult + nResultCol;
         1004  +    if( pExtra ) nResultCol += pExtra->nExpr;
         1005  +#endif
         1006  +    if( p->iLimit
         1007  +     && (ecelFlags & SQLITE_ECEL_OMITREF)!=0 
         1008  +     && nPrefixReg>0
         1009  +    ){
         1010  +      assert( pSort!=0 );
         1011  +      assert( hasDistinct==0 );
         1012  +      pSort->pDeferredRowLoad = &sRowLoadInfo;
         1013  +    }else{
         1014  +      innerLoopLoadRow(pParse, p, &sRowLoadInfo);
   912   1015       }
   913         -#endif
   914   1016     }
   915   1017   
   916   1018     /* If the DISTINCT keyword was present on the SELECT statement
   917   1019     ** and this row has been seen before, then do not make this row
   918   1020     ** part of the result.
   919   1021     */
   920   1022     if( hasDistinct ){
................................................................................
  1022   1124           sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0);
  1023   1125           VdbeCoverage(v);
  1024   1126           sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol);
  1025   1127           assert( pSort==0 );
  1026   1128         }
  1027   1129   #endif
  1028   1130         if( pSort ){
  1029         -        pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg);
         1131  +        assert( regResult==regOrig );
         1132  +        pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, regOrig, 1, nPrefixReg);
  1030   1133         }else{
  1031   1134           int r2 = sqlite3GetTempReg(pParse);
  1032   1135           sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
  1033   1136           sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
  1034   1137           sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
  1035   1138           sqlite3ReleaseTempReg(pParse, r2);
  1036   1139         }
................................................................................
  1289   1392   **
  1290   1393   **   "USE TEMP B-TREE FOR xxx"
  1291   1394   **
  1292   1395   ** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which
  1293   1396   ** is determined by the zUsage argument.
  1294   1397   */
  1295   1398   static void explainTempTable(Parse *pParse, const char *zUsage){
  1296         -  if( pParse->explain==2 ){
  1297         -    Vdbe *v = pParse->pVdbe;
  1298         -    char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage);
  1299         -    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  1300         -  }
         1399  +  ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s", zUsage));
  1301   1400   }
  1302   1401   
  1303   1402   /*
  1304   1403   ** Assign expression b to lvalue a. A second, no-op, version of this macro
  1305   1404   ** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code
  1306   1405   ** in sqlite3Select() to assign values to structure member variables that
  1307   1406   ** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the
................................................................................
  1311   1410   
  1312   1411   #else
  1313   1412   /* No-op versions of the explainXXX() functions and macros. */
  1314   1413   # define explainTempTable(y,z)
  1315   1414   # define explainSetInteger(y,z)
  1316   1415   #endif
  1317   1416   
  1318         -#if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT)
  1319         -/*
  1320         -** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
  1321         -** is a no-op. Otherwise, it adds a single row of output to the EQP result,
  1322         -** where the caption is of one of the two forms:
  1323         -**
  1324         -**   "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)"
  1325         -**   "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)"
  1326         -**
  1327         -** where iSub1 and iSub2 are the integers passed as the corresponding
  1328         -** function parameters, and op is the text representation of the parameter
  1329         -** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT,
  1330         -** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is 
  1331         -** false, or the second form if it is true.
  1332         -*/
  1333         -static void explainComposite(
  1334         -  Parse *pParse,                  /* Parse context */
  1335         -  int op,                         /* One of TK_UNION, TK_EXCEPT etc. */
  1336         -  int iSub1,                      /* Subquery id 1 */
  1337         -  int iSub2,                      /* Subquery id 2 */
  1338         -  int bUseTmp                     /* True if a temp table was used */
  1339         -){
  1340         -  assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL );
  1341         -  if( pParse->explain==2 ){
  1342         -    Vdbe *v = pParse->pVdbe;
  1343         -    char *zMsg = sqlite3MPrintf(
  1344         -        pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2,
  1345         -        bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op)
  1346         -    );
  1347         -    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  1348         -  }
  1349         -}
  1350         -#else
  1351         -/* No-op versions of the explainXXX() functions and macros. */
  1352         -# define explainComposite(v,w,x,y,z)
  1353         -#endif
  1354   1417   
  1355   1418   /*
  1356   1419   ** If the inner loop was generated using a non-null pOrderBy argument,
  1357   1420   ** then the results were placed in a sorter.  After the loop is terminated
  1358   1421   ** we need to run the sorter and output the results.  The following
  1359   1422   ** routine generates the code needed to do that.
  1360   1423   */
................................................................................
  1796   1859   #ifndef SQLITE_OMIT_EXPLAIN
  1797   1860     /* If this is an EXPLAIN, skip this step */
  1798   1861     if( pParse->explain ){
  1799   1862       return;
  1800   1863     }
  1801   1864   #endif
  1802   1865   
  1803         -  if( pParse->colNamesSet || db->mallocFailed ) return;
         1866  +  if( pParse->colNamesSet ) return;
  1804   1867     /* Column names are determined by the left-most term of a compound select */
  1805   1868     while( pSelect->pPrior ) pSelect = pSelect->pPrior;
  1806   1869     SELECTTRACE(1,pParse,pSelect,("generating column names\n"));
  1807   1870     pTabList = pSelect->pSrc;
  1808   1871     pEList = pSelect->pEList;
  1809   1872     assert( v!=0 );
  1810   1873     assert( pTabList!=0 );
................................................................................
  2323   2386     }
  2324   2387   
  2325   2388     /* Detach the ORDER BY clause from the compound SELECT */
  2326   2389     p->pOrderBy = 0;
  2327   2390   
  2328   2391     /* Store the results of the setup-query in Queue. */
  2329   2392     pSetup->pNext = 0;
         2393  +  ExplainQueryPlan((pParse, 1, "SETUP"));
  2330   2394     rc = sqlite3Select(pParse, pSetup, &destQueue);
  2331   2395     pSetup->pNext = p;
  2332   2396     if( rc ) goto end_of_recursive_query;
  2333   2397   
  2334   2398     /* Find the next row in the Queue and output that row */
  2335   2399     addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); VdbeCoverage(v);
  2336   2400   
................................................................................
  2357   2421     /* Execute the recursive SELECT taking the single row in Current as
  2358   2422     ** the value for the recursive-table. Store the results in the Queue.
  2359   2423     */
  2360   2424     if( p->selFlags & SF_Aggregate ){
  2361   2425       sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
  2362   2426     }else{
  2363   2427       p->pPrior = 0;
         2428  +    ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
  2364   2429       sqlite3Select(pParse, p, &destQueue);
  2365   2430       assert( p->pPrior==0 );
  2366   2431       p->pPrior = pSetup;
  2367   2432     }
  2368   2433   
  2369   2434     /* Keep running the loop until the Queue is empty */
  2370   2435     sqlite3VdbeGoto(v, addrTop);
................................................................................
  2402   2467   ** Since the limit is exactly 1, we only need to evalutes the left-most VALUES.
  2403   2468   */
  2404   2469   static int multiSelectValues(
  2405   2470     Parse *pParse,        /* Parsing context */
  2406   2471     Select *p,            /* The right-most of SELECTs to be coded */
  2407   2472     SelectDest *pDest     /* What to do with query results */
  2408   2473   ){
  2409         -  Select *pPrior;
  2410         -  Select *pRightmost = p;
  2411   2474     int nRow = 1;
  2412   2475     int rc = 0;
         2476  +  int bShowAll = p->pLimit==0;
  2413   2477     assert( p->selFlags & SF_MultiValue );
  2414   2478     do{
  2415   2479       assert( p->selFlags & SF_Values );
  2416   2480       assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
  2417   2481       assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
  2418   2482       if( p->pPrior==0 ) break;
  2419   2483       assert( p->pPrior->pNext==p );
  2420   2484       p = p->pPrior;
  2421         -    nRow++;
         2485  +    nRow += bShowAll;
  2422   2486     }while(1);
         2487  +  ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROW%s", nRow,
         2488  +                    nRow==1 ? "" : "S"));
  2423   2489     while( p ){
  2424         -    pPrior = p->pPrior;
  2425         -    p->pPrior = 0;
  2426         -    rc = sqlite3Select(pParse, p, pDest);
  2427         -    p->pPrior = pPrior;
  2428         -    if( rc || pRightmost->pLimit ) break;
         2490  +    selectInnerLoop(pParse, p, -1, 0, 0, pDest, 1, 1);
         2491  +    if( !bShowAll ) break;
  2429   2492       p->nSelectRow = nRow;
  2430   2493       p = p->pNext;
  2431   2494     }
  2432   2495     return rc;
  2433   2496   }
  2434   2497   
  2435   2498   /*
................................................................................
  2470   2533   ){
  2471   2534     int rc = SQLITE_OK;   /* Success code from a subroutine */
  2472   2535     Select *pPrior;       /* Another SELECT immediately to our left */
  2473   2536     Vdbe *v;              /* Generate code to this VDBE */
  2474   2537     SelectDest dest;      /* Alternative data destination */
  2475   2538     Select *pDelete = 0;  /* Chain of simple selects to delete */
  2476   2539     sqlite3 *db;          /* Database connection */
  2477         -#ifndef SQLITE_OMIT_EXPLAIN
  2478         -  int iSub1 = 0;        /* EQP id of left-hand query */
  2479         -  int iSub2 = 0;        /* EQP id of right-hand query */
  2480         -#endif
  2481   2540   
  2482   2541     /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
  2483   2542     ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
  2484   2543     */
  2485   2544     assert( p && p->pPrior );  /* Calling function guarantees this much */
  2486   2545     assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION );
  2487   2546     db = pParse->db;
................................................................................
  2524   2583     }else
  2525   2584   #endif
  2526   2585   
  2527   2586     /* Compound SELECTs that have an ORDER BY clause are handled separately.
  2528   2587     */
  2529   2588     if( p->pOrderBy ){
  2530   2589       return multiSelectOrderBy(pParse, p, pDest);
  2531         -  }else
  2532         -
  2533         -  /* Generate code for the left and right SELECT statements.
  2534         -  */
  2535         -  switch( p->op ){
  2536         -    case TK_ALL: {
  2537         -      int addr = 0;
  2538         -      int nLimit;
  2539         -      assert( !pPrior->pLimit );
  2540         -      pPrior->iLimit = p->iLimit;
  2541         -      pPrior->iOffset = p->iOffset;
  2542         -      pPrior->pLimit = p->pLimit;
  2543         -      explainSetInteger(iSub1, pParse->iNextSelectId);
  2544         -      rc = sqlite3Select(pParse, pPrior, &dest);
  2545         -      p->pLimit = 0;
  2546         -      if( rc ){
  2547         -        goto multi_select_end;
  2548         -      }
  2549         -      p->pPrior = 0;
  2550         -      p->iLimit = pPrior->iLimit;
  2551         -      p->iOffset = pPrior->iOffset;
  2552         -      if( p->iLimit ){
  2553         -        addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
  2554         -        VdbeComment((v, "Jump ahead if LIMIT reached"));
  2555         -        if( p->iOffset ){
  2556         -          sqlite3VdbeAddOp3(v, OP_OffsetLimit,
  2557         -                            p->iLimit, p->iOffset+1, p->iOffset);
  2558         -        }
  2559         -      }
  2560         -      explainSetInteger(iSub2, pParse->iNextSelectId);
  2561         -      rc = sqlite3Select(pParse, p, &dest);
  2562         -      testcase( rc!=SQLITE_OK );
  2563         -      pDelete = p->pPrior;
  2564         -      p->pPrior = pPrior;
  2565         -      p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
  2566         -      if( pPrior->pLimit
  2567         -       && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
  2568         -       && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) 
  2569         -      ){
  2570         -        p->nSelectRow = sqlite3LogEst((u64)nLimit);
  2571         -      }
  2572         -      if( addr ){
  2573         -        sqlite3VdbeJumpHere(v, addr);
  2574         -      }
  2575         -      break;
  2576         -    }
  2577         -    case TK_EXCEPT:
  2578         -    case TK_UNION: {
  2579         -      int unionTab;    /* Cursor number of the temporary table holding result */
  2580         -      u8 op = 0;       /* One of the SRT_ operations to apply to self */
  2581         -      int priorOp;     /* The SRT_ operation to apply to prior selects */
  2582         -      Expr *pLimit;    /* Saved values of p->nLimit  */
  2583         -      int addr;
  2584         -      SelectDest uniondest;
  2585         -
  2586         -      testcase( p->op==TK_EXCEPT );
  2587         -      testcase( p->op==TK_UNION );
  2588         -      priorOp = SRT_Union;
  2589         -      if( dest.eDest==priorOp ){
  2590         -        /* We can reuse a temporary table generated by a SELECT to our
  2591         -        ** right.
         2590  +  }else{
         2591  +
         2592  +#ifndef SQLITE_OMIT_EXPLAIN
         2593  +    if( pPrior->pPrior==0 ){
         2594  +      ExplainQueryPlan((pParse, 1, "COMPOUND QUERY"));
         2595  +      ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY"));
         2596  +    }
         2597  +#endif
         2598  +
         2599  +    /* Generate code for the left and right SELECT statements.
         2600  +    */
         2601  +    switch( p->op ){
         2602  +      case TK_ALL: {
         2603  +        int addr = 0;
         2604  +        int nLimit;
         2605  +        assert( !pPrior->pLimit );
         2606  +        pPrior->iLimit = p->iLimit;
         2607  +        pPrior->iOffset = p->iOffset;
         2608  +        pPrior->pLimit = p->pLimit;
         2609  +        rc = sqlite3Select(pParse, pPrior, &dest);
         2610  +        p->pLimit = 0;
         2611  +        if( rc ){
         2612  +          goto multi_select_end;
         2613  +        }
         2614  +        p->pPrior = 0;
         2615  +        p->iLimit = pPrior->iLimit;
         2616  +        p->iOffset = pPrior->iOffset;
         2617  +        if( p->iLimit ){
         2618  +          addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
         2619  +          VdbeComment((v, "Jump ahead if LIMIT reached"));
         2620  +          if( p->iOffset ){
         2621  +            sqlite3VdbeAddOp3(v, OP_OffsetLimit,
         2622  +                              p->iLimit, p->iOffset+1, p->iOffset);
         2623  +          }
         2624  +        }
         2625  +        ExplainQueryPlan((pParse, 1, "UNION ALL"));
         2626  +        rc = sqlite3Select(pParse, p, &dest);
         2627  +        testcase( rc!=SQLITE_OK );
         2628  +        pDelete = p->pPrior;
         2629  +        p->pPrior = pPrior;
         2630  +        p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
         2631  +        if( pPrior->pLimit
         2632  +         && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
         2633  +         && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) 
         2634  +        ){
         2635  +          p->nSelectRow = sqlite3LogEst((u64)nLimit);
         2636  +        }
         2637  +        if( addr ){
         2638  +          sqlite3VdbeJumpHere(v, addr);
         2639  +        }
         2640  +        break;
         2641  +      }
         2642  +      case TK_EXCEPT:
         2643  +      case TK_UNION: {
         2644  +        int unionTab;    /* Cursor number of the temp table holding result */
         2645  +        u8 op = 0;       /* One of the SRT_ operations to apply to self */
         2646  +        int priorOp;     /* The SRT_ operation to apply to prior selects */
         2647  +        Expr *pLimit;    /* Saved values of p->nLimit  */
         2648  +        int addr;
         2649  +        SelectDest uniondest;
         2650  +  
         2651  +        testcase( p->op==TK_EXCEPT );
         2652  +        testcase( p->op==TK_UNION );
         2653  +        priorOp = SRT_Union;
         2654  +        if( dest.eDest==priorOp ){
         2655  +          /* We can reuse a temporary table generated by a SELECT to our
         2656  +          ** right.
         2657  +          */
         2658  +          assert( p->pLimit==0 );      /* Not allowed on leftward elements */
         2659  +          unionTab = dest.iSDParm;
         2660  +        }else{
         2661  +          /* We will need to create our own temporary table to hold the
         2662  +          ** intermediate results.
         2663  +          */
         2664  +          unionTab = pParse->nTab++;
         2665  +          assert( p->pOrderBy==0 );
         2666  +          addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
         2667  +          assert( p->addrOpenEphm[0] == -1 );
         2668  +          p->addrOpenEphm[0] = addr;
         2669  +          findRightmost(p)->selFlags |= SF_UsesEphemeral;
         2670  +          assert( p->pEList );
         2671  +        }
         2672  +  
         2673  +        /* Code the SELECT statements to our left
         2674  +        */
         2675  +        assert( !pPrior->pOrderBy );
         2676  +        sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
         2677  +        rc = sqlite3Select(pParse, pPrior, &uniondest);
         2678  +        if( rc ){
         2679  +          goto multi_select_end;
         2680  +        }
         2681  +  
         2682  +        /* Code the current SELECT statement
         2683  +        */
         2684  +        if( p->op==TK_EXCEPT ){
         2685  +          op = SRT_Except;
         2686  +        }else{
         2687  +          assert( p->op==TK_UNION );
         2688  +          op = SRT_Union;
         2689  +        }
         2690  +        p->pPrior = 0;
         2691  +        pLimit = p->pLimit;
         2692  +        p->pLimit = 0;
         2693  +        uniondest.eDest = op;
         2694  +        ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
         2695  +                          selectOpName(p->op)));
         2696  +        rc = sqlite3Select(pParse, p, &uniondest);
         2697  +        testcase( rc!=SQLITE_OK );
         2698  +        /* Query flattening in sqlite3Select() might refill p->pOrderBy.
         2699  +        ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
         2700  +        sqlite3ExprListDelete(db, p->pOrderBy);
         2701  +        pDelete = p->pPrior;
         2702  +        p->pPrior = pPrior;
         2703  +        p->pOrderBy = 0;
         2704  +        if( p->op==TK_UNION ){
         2705  +          p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
         2706  +        }
         2707  +        sqlite3ExprDelete(db, p->pLimit);
         2708  +        p->pLimit = pLimit;
         2709  +        p->iLimit = 0;
         2710  +        p->iOffset = 0;
         2711  +  
         2712  +        /* Convert the data in the temporary table into whatever form
         2713  +        ** it is that we currently need.
         2714  +        */
         2715  +        assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
         2716  +        if( dest.eDest!=priorOp ){
         2717  +          int iCont, iBreak, iStart;
         2718  +          assert( p->pEList );
         2719  +          iBreak = sqlite3VdbeMakeLabel(v);
         2720  +          iCont = sqlite3VdbeMakeLabel(v);
         2721  +          computeLimitRegisters(pParse, p, iBreak);
         2722  +          sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
         2723  +          iStart = sqlite3VdbeCurrentAddr(v);
         2724  +          selectInnerLoop(pParse, p, unionTab,
         2725  +                          0, 0, &dest, iCont, iBreak);
         2726  +          sqlite3VdbeResolveLabel(v, iCont);
         2727  +          sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
         2728  +          sqlite3VdbeResolveLabel(v, iBreak);
         2729  +          sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
         2730  +        }
         2731  +        break;
         2732  +      }
         2733  +      default: assert( p->op==TK_INTERSECT ); {
         2734  +        int tab1, tab2;
         2735  +        int iCont, iBreak, iStart;
         2736  +        Expr *pLimit;
         2737  +        int addr;
         2738  +        SelectDest intersectdest;
         2739  +        int r1;
         2740  +  
         2741  +        /* INTERSECT is different from the others since it requires
         2742  +        ** two temporary tables.  Hence it has its own case.  Begin
         2743  +        ** by allocating the tables we will need.
  2592   2744           */
  2593         -        assert( p->pLimit==0 );      /* Not allowed on leftward elements */
  2594         -        unionTab = dest.iSDParm;
  2595         -      }else{
  2596         -        /* We will need to create our own temporary table to hold the
  2597         -        ** intermediate results.
  2598         -        */
  2599         -        unionTab = pParse->nTab++;
         2745  +        tab1 = pParse->nTab++;
         2746  +        tab2 = pParse->nTab++;
  2600   2747           assert( p->pOrderBy==0 );
  2601         -        addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
         2748  +  
         2749  +        addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
  2602   2750           assert( p->addrOpenEphm[0] == -1 );
  2603   2751           p->addrOpenEphm[0] = addr;
  2604   2752           findRightmost(p)->selFlags |= SF_UsesEphemeral;
  2605   2753           assert( p->pEList );
  2606         -      }
  2607         -
  2608         -      /* Code the SELECT statements to our left
  2609         -      */
  2610         -      assert( !pPrior->pOrderBy );
  2611         -      sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
  2612         -      explainSetInteger(iSub1, pParse->iNextSelectId);
  2613         -      rc = sqlite3Select(pParse, pPrior, &uniondest);
  2614         -      if( rc ){
  2615         -        goto multi_select_end;
  2616         -      }
  2617         -
  2618         -      /* Code the current SELECT statement
  2619         -      */
  2620         -      if( p->op==TK_EXCEPT ){
  2621         -        op = SRT_Except;
  2622         -      }else{
  2623         -        assert( p->op==TK_UNION );
  2624         -        op = SRT_Union;
  2625         -      }
  2626         -      p->pPrior = 0;
  2627         -      pLimit = p->pLimit;
  2628         -      p->pLimit = 0;
  2629         -      uniondest.eDest = op;
  2630         -      explainSetInteger(iSub2, pParse->iNextSelectId);
  2631         -      rc = sqlite3Select(pParse, p, &uniondest);
  2632         -      testcase( rc!=SQLITE_OK );
  2633         -      /* Query flattening in sqlite3Select() might refill p->pOrderBy.
  2634         -      ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
  2635         -      sqlite3ExprListDelete(db, p->pOrderBy);
  2636         -      pDelete = p->pPrior;
  2637         -      p->pPrior = pPrior;
  2638         -      p->pOrderBy = 0;
  2639         -      if( p->op==TK_UNION ){
  2640         -        p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
  2641         -      }
  2642         -      sqlite3ExprDelete(db, p->pLimit);
  2643         -      p->pLimit = pLimit;
  2644         -      p->iLimit = 0;
  2645         -      p->iOffset = 0;
  2646         -
  2647         -      /* Convert the data in the temporary table into whatever form
  2648         -      ** it is that we currently need.
  2649         -      */
  2650         -      assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
  2651         -      if( dest.eDest!=priorOp ){
  2652         -        int iCont, iBreak, iStart;
         2754  +  
         2755  +        /* Code the SELECTs to our left into temporary table "tab1".
         2756  +        */
         2757  +        sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
         2758  +        rc = sqlite3Select(pParse, pPrior, &intersectdest);
         2759  +        if( rc ){
         2760  +          goto multi_select_end;
         2761  +        }
         2762  +  
         2763  +        /* Code the current SELECT into temporary table "tab2"
         2764  +        */
         2765  +        addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
         2766  +        assert( p->addrOpenEphm[1] == -1 );
         2767  +        p->addrOpenEphm[1] = addr;
         2768  +        p->pPrior = 0;
         2769  +        pLimit = p->pLimit;
         2770  +        p->pLimit = 0;
         2771  +        intersectdest.iSDParm = tab2;
         2772  +        ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
         2773  +                          selectOpName(p->op)));
         2774  +        rc = sqlite3Select(pParse, p, &intersectdest);
         2775  +        testcase( rc!=SQLITE_OK );
         2776  +        pDelete = p->pPrior;
         2777  +        p->pPrior = pPrior;
         2778  +        if( p->nSelectRow>pPrior->nSelectRow ){
         2779  +          p->nSelectRow = pPrior->nSelectRow;
         2780  +        }
         2781  +        sqlite3ExprDelete(db, p->pLimit);
         2782  +        p->pLimit = pLimit;
         2783  +  
         2784  +        /* Generate code to take the intersection of the two temporary
         2785  +        ** tables.
         2786  +        */
  2653   2787           assert( p->pEList );
  2654   2788           iBreak = sqlite3VdbeMakeLabel(v);
  2655   2789           iCont = sqlite3VdbeMakeLabel(v);
  2656   2790           computeLimitRegisters(pParse, p, iBreak);
  2657         -        sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
  2658         -        iStart = sqlite3VdbeCurrentAddr(v);
  2659         -        selectInnerLoop(pParse, p, unionTab,
         2791  +        sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
         2792  +        r1 = sqlite3GetTempReg(pParse);
         2793  +        iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
         2794  +        sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
         2795  +        VdbeCoverage(v);
         2796  +        sqlite3ReleaseTempReg(pParse, r1);
         2797  +        selectInnerLoop(pParse, p, tab1,
  2660   2798                           0, 0, &dest, iCont, iBreak);
  2661   2799           sqlite3VdbeResolveLabel(v, iCont);
  2662         -        sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
         2800  +        sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v);
  2663   2801           sqlite3VdbeResolveLabel(v, iBreak);
  2664         -        sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
  2665         -      }
  2666         -      break;
  2667         -    }
  2668         -    default: assert( p->op==TK_INTERSECT ); {
  2669         -      int tab1, tab2;
  2670         -      int iCont, iBreak, iStart;
  2671         -      Expr *pLimit;
  2672         -      int addr;
  2673         -      SelectDest intersectdest;
  2674         -      int r1;
  2675         -
  2676         -      /* INTERSECT is different from the others since it requires
  2677         -      ** two temporary tables.  Hence it has its own case.  Begin
  2678         -      ** by allocating the tables we will need.
  2679         -      */
  2680         -      tab1 = pParse->nTab++;
  2681         -      tab2 = pParse->nTab++;
  2682         -      assert( p->pOrderBy==0 );
  2683         -
  2684         -      addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
  2685         -      assert( p->addrOpenEphm[0] == -1 );
  2686         -      p->addrOpenEphm[0] = addr;
  2687         -      findRightmost(p)->selFlags |= SF_UsesEphemeral;
  2688         -      assert( p->pEList );
  2689         -
  2690         -      /* Code the SELECTs to our left into temporary table "tab1".
  2691         -      */
  2692         -      sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
  2693         -      explainSetInteger(iSub1, pParse->iNextSelectId);
  2694         -      rc = sqlite3Select(pParse, pPrior, &intersectdest);
  2695         -      if( rc ){
  2696         -        goto multi_select_end;
  2697         -      }
  2698         -
  2699         -      /* Code the current SELECT into temporary table "tab2"
  2700         -      */
  2701         -      addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
  2702         -      assert( p->addrOpenEphm[1] == -1 );
  2703         -      p->addrOpenEphm[1] = addr;
  2704         -      p->pPrior = 0;
  2705         -      pLimit = p->pLimit;
  2706         -      p->pLimit = 0;
  2707         -      intersectdest.iSDParm = tab2;
  2708         -      explainSetInteger(iSub2, pParse->iNextSelectId);
  2709         -      rc = sqlite3Select(pParse, p, &intersectdest);
  2710         -      testcase( rc!=SQLITE_OK );
  2711         -      pDelete = p->pPrior;
  2712         -      p->pPrior = pPrior;
  2713         -      if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
  2714         -      sqlite3ExprDelete(db, p->pLimit);
  2715         -      p->pLimit = pLimit;
  2716         -
  2717         -      /* Generate code to take the intersection of the two temporary
  2718         -      ** tables.
  2719         -      */
  2720         -      assert( p->pEList );
  2721         -      iBreak = sqlite3VdbeMakeLabel(v);
  2722         -      iCont = sqlite3VdbeMakeLabel(v);
  2723         -      computeLimitRegisters(pParse, p, iBreak);
  2724         -      sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
  2725         -      r1 = sqlite3GetTempReg(pParse);
  2726         -      iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
  2727         -      sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v);
  2728         -      sqlite3ReleaseTempReg(pParse, r1);
  2729         -      selectInnerLoop(pParse, p, tab1,
  2730         -                      0, 0, &dest, iCont, iBreak);
  2731         -      sqlite3VdbeResolveLabel(v, iCont);
  2732         -      sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v);
  2733         -      sqlite3VdbeResolveLabel(v, iBreak);
  2734         -      sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
  2735         -      sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
  2736         -      break;
  2737         -    }
  2738         -  }
  2739         -
  2740         -  explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL);
  2741         -
         2802  +        sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
         2803  +        sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
         2804  +        break;
         2805  +      }
         2806  +    }
         2807  +  
         2808  +  #ifndef SQLITE_OMIT_EXPLAIN
         2809  +    if( p->pNext==0 ){
         2810  +      ExplainQueryPlanPop(pParse);
         2811  +    }
         2812  +  #endif
         2813  +  }
         2814  +  
  2742   2815     /* Compute collating sequences used by 
  2743   2816     ** temporary tables needed to implement the compound select.
  2744   2817     ** Attach the KeyInfo structure to all temporary tables.
  2745   2818     **
  2746   2819     ** This section is run by the right-most SELECT statement only.
  2747   2820     ** SELECT statements to the left always skip this part.  The right-most
  2748   2821     ** SELECT might also skip this part if it has no ORDER BY clause and
................................................................................
  3072   3145     int op;               /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
  3073   3146     KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */
  3074   3147     KeyInfo *pKeyMerge;   /* Comparison information for merging rows */
  3075   3148     sqlite3 *db;          /* Database connection */
  3076   3149     ExprList *pOrderBy;   /* The ORDER BY clause */
  3077   3150     int nOrderBy;         /* Number of terms in the ORDER BY clause */
  3078   3151     int *aPermute;        /* Mapping from ORDER BY terms to result set columns */
  3079         -#ifndef SQLITE_OMIT_EXPLAIN
  3080         -  int iSub1;            /* EQP id of left-hand query */
  3081         -  int iSub2;            /* EQP id of right-hand query */
  3082         -#endif
  3083   3152   
  3084   3153     assert( p->pOrderBy!=0 );
  3085   3154     assert( pKeyDup==0 ); /* "Managed" code needs this.  Ticket #3382. */
  3086   3155     db = pParse->db;
  3087   3156     v = pParse->pVdbe;
  3088   3157     assert( v!=0 );       /* Already thrown the error if VDBE alloc failed */
  3089   3158     labelEnd = sqlite3VdbeMakeLabel(v);
................................................................................
  3195   3264     regAddrA = ++pParse->nMem;
  3196   3265     regAddrB = ++pParse->nMem;
  3197   3266     regOutA = ++pParse->nMem;
  3198   3267     regOutB = ++pParse->nMem;
  3199   3268     sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
  3200   3269     sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
  3201   3270   
         3271  +  ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op)));
         3272  +
  3202   3273     /* Generate a coroutine to evaluate the SELECT statement to the
  3203   3274     ** left of the compound operator - the "A" select.
  3204   3275     */
  3205   3276     addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
  3206   3277     addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
  3207   3278     VdbeComment((v, "left SELECT"));
  3208   3279     pPrior->iLimit = regLimitA;
  3209         -  explainSetInteger(iSub1, pParse->iNextSelectId);
         3280  +  ExplainQueryPlan((pParse, 1, "LEFT"));
  3210   3281     sqlite3Select(pParse, pPrior, &destA);
  3211   3282     sqlite3VdbeEndCoroutine(v, regAddrA);
  3212   3283     sqlite3VdbeJumpHere(v, addr1);
  3213   3284   
  3214   3285     /* Generate a coroutine to evaluate the SELECT statement on 
  3215   3286     ** the right - the "B" select
  3216   3287     */
................................................................................
  3217   3288     addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
  3218   3289     addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
  3219   3290     VdbeComment((v, "right SELECT"));
  3220   3291     savedLimit = p->iLimit;
  3221   3292     savedOffset = p->iOffset;
  3222   3293     p->iLimit = regLimitB;
  3223   3294     p->iOffset = 0;  
  3224         -  explainSetInteger(iSub2, pParse->iNextSelectId);
         3295  +  ExplainQueryPlan((pParse, 1, "RIGHT"));
  3225   3296     sqlite3Select(pParse, p, &destB);
  3226   3297     p->iLimit = savedLimit;
  3227   3298     p->iOffset = savedOffset;
  3228   3299     sqlite3VdbeEndCoroutine(v, regAddrB);
  3229   3300   
  3230   3301     /* Generate a subroutine that outputs the current row of the A
  3231   3302     ** select as the next output row of the compound select.
................................................................................
  3329   3400       sqlite3SelectDelete(db, p->pPrior);
  3330   3401     }
  3331   3402     p->pPrior = pPrior;
  3332   3403     pPrior->pNext = p;
  3333   3404   
  3334   3405     /*** TBD:  Insert subroutine calls to close cursors on incomplete
  3335   3406     **** subqueries ****/
  3336         -  explainComposite(pParse, p->op, iSub1, iSub2, 0);
         3407  +  ExplainQueryPlanPop(pParse);
  3337   3408     return pParse->nErr!=0;
  3338   3409   }
  3339   3410   #endif
  3340   3411   
  3341   3412   #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  3342   3413   
  3343   3414   /* An instance of the SubstContext object describes an substitution edit
................................................................................
  5117   5188   static void explainSimpleCount(
  5118   5189     Parse *pParse,                  /* Parse context */
  5119   5190     Table *pTab,                    /* Table being queried */
  5120   5191     Index *pIdx                     /* Index used to optimize scan, or NULL */
  5121   5192   ){
  5122   5193     if( pParse->explain==2 ){
  5123   5194       int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
  5124         -    char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
         5195  +    sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s",
  5125   5196           pTab->zName,
  5126   5197           bCover ? " USING COVERING INDEX " : "",
  5127   5198           bCover ? pIdx->zName : ""
  5128   5199       );
  5129         -    sqlite3VdbeAddOp4(
  5130         -        pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
  5131         -    );
  5132   5200     }
  5133   5201   }
  5134   5202   #else
  5135   5203   # define explainSimpleCount(a,b,c)
  5136   5204   #endif
  5137   5205   
  5138   5206   /*
................................................................................
  5337   5405     SortCtx sSort;         /* Info on how to code the ORDER BY clause */
  5338   5406     AggInfo sAggInfo;      /* Information used by aggregate queries */
  5339   5407     int iEnd;              /* Address of the end of the query */
  5340   5408     sqlite3 *db;           /* The database connection */
  5341   5409     ExprList *pMinMaxOrderBy = 0;  /* Added ORDER BY for min/max queries */
  5342   5410     u8 minMaxFlag;                 /* Flag for min/max queries */
  5343   5411   
  5344         -#ifndef SQLITE_OMIT_EXPLAIN
  5345         -  int iRestoreSelectId = pParse->iSelectId;
  5346         -  pParse->iSelectId = pParse->iNextSelectId++;
  5347         -#endif
  5348         -
  5349   5412     db = pParse->db;
         5413  +  v = sqlite3GetVdbe(pParse);
  5350   5414     if( p==0 || db->mallocFailed || pParse->nErr ){
  5351   5415       return 1;
  5352   5416     }
  5353   5417     if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
  5354   5418     memset(&sAggInfo, 0, sizeof(sAggInfo));
  5355   5419   #if SELECTTRACE_ENABLED
  5356         -#ifndef SQLITE_OMIT_EXPLAIN
  5357         -  p->iSelectId = pParse->iSelectId;
  5358         -#endif
  5359         -  SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->iSelectId));
         5420  +  SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
  5360   5421     if( sqlite3SelectTrace & 0x100 ){
  5361   5422       sqlite3TreeViewSelect(0, p, 0);
  5362   5423     }
  5363   5424   #endif
  5364   5425   
  5365   5426     assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
  5366   5427     assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
................................................................................
  5389   5450   #if SELECTTRACE_ENABLED
  5390   5451     if( sqlite3SelectTrace & 0x104 ){
  5391   5452       SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
  5392   5453       sqlite3TreeViewSelect(0, p, 0);
  5393   5454     }
  5394   5455   #endif
  5395   5456   
  5396         -  /* Get a pointer the VDBE under construction, allocating a new VDBE if one
  5397         -  ** does not already exist */
  5398         -  v = sqlite3GetVdbe(pParse);
  5399         -  if( v==0 ) goto select_end;
  5400   5457     if( pDest->eDest==SRT_Output ){
  5401   5458       generateColumnNames(pParse, p);
  5402   5459     }
  5403   5460   
  5404   5461     /* Try to various optimizations (flattening subqueries, and strength
  5405   5462     ** reduction of join operators) in the FROM clause up into the main query
  5406   5463     */
................................................................................
  5487   5544     /* Handle compound SELECT statements using the separate multiSelect()
  5488   5545     ** procedure.
  5489   5546     */
  5490   5547     if( p->pPrior ){
  5491   5548       rc = multiSelect(pParse, p, pDest);
  5492   5549   #if SELECTTRACE_ENABLED
  5493   5550       SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
  5494         -    if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x2000)!=0 ){
         5551  +    if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
  5495   5552         sqlite3TreeViewSelect(0, p, 0);
  5496   5553       }
  5497   5554   #endif
  5498         -    explainSetInteger(pParse->iSelectId, iRestoreSelectId);
         5555  +    if( p->pNext==0 ) ExplainQueryPlanPop(pParse);
  5499   5556       return rc;
  5500   5557     }
  5501   5558   #endif
  5502   5559   
  5503   5560     /* For each term in the FROM clause, do two things:
  5504   5561     ** (1) Authorized unreferenced tables
  5505   5562     ** (2) Generate code for all sub-queries
................................................................................
  5603   5660         int addrTop = sqlite3VdbeCurrentAddr(v)+1;
  5604   5661        
  5605   5662         pItem->regReturn = ++pParse->nMem;
  5606   5663         sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
  5607   5664         VdbeComment((v, "%s", pItem->pTab->zName));
  5608   5665         pItem->addrFillSub = addrTop;
  5609   5666         sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
  5610         -      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
         5667  +      ExplainQueryPlan((pParse, 1, "CO-ROUTINE 0x%p", pSub));
  5611   5668         sqlite3Select(pParse, pSub, &dest);
  5612   5669         pItem->pTab->nRowLogEst = pSub->nSelectRow;
  5613   5670         pItem->fg.viaCoroutine = 1;
  5614   5671         pItem->regResult = dest.iSdst;
  5615   5672         sqlite3VdbeEndCoroutine(v, pItem->regReturn);
  5616   5673         sqlite3VdbeJumpHere(v, addrTop-1);
  5617   5674         sqlite3ClearTempRegCache(pParse);
................................................................................
  5638   5695           VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
  5639   5696         }else{
  5640   5697           VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
  5641   5698         }
  5642   5699         pPrior = isSelfJoinView(pTabList, pItem);
  5643   5700         if( pPrior ){
  5644   5701           sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
  5645         -        explainSetInteger(pItem->iSelectId, pPrior->iSelectId);
  5646   5702           assert( pPrior->pSelect!=0 );
  5647   5703           pSub->nSelectRow = pPrior->pSelect->nSelectRow;
  5648   5704         }else{
  5649   5705           sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
  5650         -        explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
         5706  +        ExplainQueryPlan((pParse, 1, "MATERIALIZE 0x%p", pSub));
  5651   5707           sqlite3Select(pParse, pSub, &dest);
  5652   5708         }
  5653   5709         pItem->pTab->nRowLogEst = pSub->nSelectRow;
  5654   5710         if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
  5655   5711         retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
  5656   5712         VdbeComment((v, "end %s", pItem->pTab->zName));
  5657   5713         sqlite3VdbeChangeP1(v, topAddr, retAddr);
................................................................................
  6281   6337     */
  6282   6338   select_end:
  6283   6339     sqlite3ExprListDelete(db, pMinMaxOrderBy);
  6284   6340     sqlite3DbFree(db, sAggInfo.aCol);
  6285   6341     sqlite3DbFree(db, sAggInfo.aFunc);
  6286   6342   #if SELECTTRACE_ENABLED
  6287   6343     SELECTTRACE(0x1,pParse,p,("end processing\n"));
  6288         -  if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x2000)!=0 ){
         6344  +  if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
  6289   6345       sqlite3TreeViewSelect(0, p, 0);
  6290   6346     }
  6291   6347   #endif
  6292         -  explainSetInteger(pParse->iSelectId, iRestoreSelectId);
         6348  +  ExplainQueryPlanPop(pParse);
  6293   6349     return rc;
  6294   6350   }

Changes to src/shell.c.in.

   977    977     sqlite3expert *pExpert;
   978    978     int bVerbose;
   979    979   };
   980    980   
   981    981   /* A single line in the EQP output */
   982    982   typedef struct EQPGraphRow EQPGraphRow;
   983    983   struct EQPGraphRow {
   984         -  int iSelectId;        /* The SelectID for this row */
          984  +  int iEqpId;           /* ID for this row */
          985  +  int iParentId;        /* ID of the parent row */
   985    986     EQPGraphRow *pNext;   /* Next row in sequence */
   986    987     char zText[1];        /* Text to display for this row */
   987    988   };
   988    989   
   989    990   /* All EQP output is collected into an instance of the following */
   990    991   typedef struct EQPGraph EQPGraph;
   991    992   struct EQPGraph {
................................................................................
   999   1000   ** instance of the following structure.
  1000   1001   */
  1001   1002   typedef struct ShellState ShellState;
  1002   1003   struct ShellState {
  1003   1004     sqlite3 *db;           /* The database */
  1004   1005     u8 autoExplain;        /* Automatically turn on .explain mode */
  1005   1006     u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
         1007  +  u8 autoEQPtest;        /* autoEQP is in test mode */
  1006   1008     u8 statsOn;            /* True to display memory stats before each finalize */
  1007   1009     u8 scanstatsOn;        /* True to display scan stats before each finalize */
  1008   1010     u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
  1009   1011     u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
  1010   1012     u8 nEqpLevel;          /* Depth of the EQP output graph */
  1011   1013     unsigned mEqpLines;    /* Mask of veritical lines in the EQP output graph */
  1012   1014     int outCount;          /* Revert to stdout when reaching zero */
................................................................................
  1049   1051   #endif
  1050   1052     ExpertInfo expert;        /* Valid if previous command was ".expert OPT..." */
  1051   1053   };
  1052   1054   
  1053   1055   
  1054   1056   /* Allowed values for ShellState.autoEQP
  1055   1057   */
  1056         -#define AUTOEQP_off      0
  1057         -#define AUTOEQP_on       1
  1058         -#define AUTOEQP_trigger  2
  1059         -#define AUTOEQP_full     3
         1058  +#define AUTOEQP_off      0           /* Automatic EXPLAIN QUERY PLAN is off */
         1059  +#define AUTOEQP_on       1           /* Automatic EQP is on */
         1060  +#define AUTOEQP_trigger  2           /* On and also show plans for triggers */
         1061  +#define AUTOEQP_full     3           /* Show full EXPLAIN */
  1060   1062   
  1061   1063   /* Allowed values for ShellState.openMode
  1062   1064   */
  1063   1065   #define SHELL_OPEN_UNSPEC     0      /* No open-mode specified */
  1064   1066   #define SHELL_OPEN_NORMAL     1      /* Normal database file */
  1065   1067   #define SHELL_OPEN_APPENDVFS  2      /* Use appendvfs */
  1066   1068   #define SHELL_OPEN_ZIPFILE    3      /* Use the zipfile virtual table */
................................................................................
  1663   1665     }
  1664   1666     return 1;
  1665   1667   }
  1666   1668   
  1667   1669   /*
  1668   1670   ** Add a new entry to the EXPLAIN QUERY PLAN data
  1669   1671   */
  1670         -static void eqp_append(ShellState *p, int iSelectId, const char *zText){
         1672  +static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
  1671   1673     EQPGraphRow *pNew;
  1672   1674     int nText = strlen30(zText);
         1675  +  if( p->autoEQPtest ){
         1676  +    utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
         1677  +  }
  1673   1678     pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
  1674   1679     if( pNew==0 ) shell_out_of_memory();
  1675         -  pNew->iSelectId = iSelectId;
         1680  +  pNew->iEqpId = iEqpId;
         1681  +  pNew->iParentId = p2;
  1676   1682     memcpy(pNew->zText, zText, nText+1);
  1677   1683     pNew->pNext = 0;
  1678   1684     if( p->sGraph.pLast ){
  1679   1685       p->sGraph.pLast->pNext = pNew;
  1680   1686     }else{
  1681   1687       p->sGraph.pRow = pNew;
  1682   1688     }
................................................................................
  1692   1698     for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
  1693   1699       pNext = pRow->pNext;
  1694   1700       sqlite3_free(pRow);
  1695   1701     }
  1696   1702     memset(&p->sGraph, 0, sizeof(p->sGraph));
  1697   1703   }
  1698   1704   
  1699         -/* Return the next EXPLAIN QUERY PLAN line with iSelectId that occurs after
         1705  +/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
  1700   1706   ** pOld, or return the first such line if pOld is NULL
  1701   1707   */
  1702         -static EQPGraphRow *eqp_next_row(ShellState *p, int iSelectId, EQPGraphRow *pOld){
         1708  +static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
  1703   1709     EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
  1704         -  while( pRow && pRow->iSelectId!=iSelectId ) pRow = pRow->pNext;
         1710  +  while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
  1705   1711     return pRow;
  1706   1712   }
  1707   1713   
  1708         -/* Render a single level of the graph shell having iSelectId.  Called
         1714  +/* Render a single level of the graph that has iEqpId as its parent.  Called
  1709   1715   ** recursively to render sublevels.
  1710   1716   */
  1711         -static void eqp_render_level(ShellState *p, int iSelectId){
         1717  +static void eqp_render_level(ShellState *p, int iEqpId){
  1712   1718     EQPGraphRow *pRow, *pNext;
  1713         -  int i;
  1714   1719     int n = strlen30(p->sGraph.zPrefix);
  1715   1720     char *z;
  1716         -  for(pRow = eqp_next_row(p, iSelectId, 0); pRow; pRow = pNext){
  1717         -    pNext = eqp_next_row(p, iSelectId, pRow);
         1721  +  for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
         1722  +    pNext = eqp_next_row(p, iEqpId, pRow);
  1718   1723       z = pRow->zText;
  1719   1724       utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);
  1720         -    if( n<sizeof(p->sGraph.zPrefix)-7 && (z = strstr(z, " SUBQUER"))!=0 ){
         1725  +    if( n<sizeof(p->sGraph.zPrefix)-7 ){
  1721   1726         memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
  1722         -      if( strncmp(z, " SUBQUERY ", 9)==0 && (i = atoi(z+10))>iSelectId ){
  1723         -        eqp_render_level(p, i);
  1724         -      }else if( strncmp(z, " SUBQUERIES ", 12)==0 ){
  1725         -        i = atoi(z+12);
  1726         -        if( i>iSelectId ){
  1727         -          utf8_printf(p->out, "%s|--SUBQUERY %d\n", p->sGraph.zPrefix, i);
  1728         -          memcpy(&p->sGraph.zPrefix[n+3],"|  ",4);
  1729         -          eqp_render_level(p, i);
  1730         -        }
  1731         -        z = strstr(z, " AND ");
  1732         -        if( z && (i = atoi(z+5))>iSelectId ){
  1733         -          p->sGraph.zPrefix[n+3] = 0;
  1734         -          utf8_printf(p->out, "%s`--SUBQUERY %d\n", p->sGraph.zPrefix, i);
  1735         -          memcpy(&p->sGraph.zPrefix[n+3],"   ",4);
  1736         -          eqp_render_level(p, i);
  1737         -        }
  1738         -      }
         1727  +      eqp_render_level(p, pRow->iEqpId);
  1739   1728         p->sGraph.zPrefix[n] = 0;
  1740   1729       }
  1741   1730     }
  1742   1731   }
  1743   1732   
  1744   1733   /*
  1745   1734   ** Display and reset the EXPLAIN QUERY PLAN data
................................................................................
  2110   2099           if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
  2111   2100           utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
  2112   2101         }
  2113   2102         utf8_printf(p->out, "%s", p->rowSeparator);
  2114   2103         break;
  2115   2104       }
  2116   2105       case MODE_EQP: {
  2117         -      eqp_append(p, atoi(azArg[0]), azArg[3]);
         2106  +      eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
  2118   2107         break;
  2119   2108       }
  2120   2109     }
  2121   2110     return 0;
  2122   2111   }
  2123   2112   
  2124   2113   /*
................................................................................
  2952   2941             sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
  2953   2942           }
  2954   2943           zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
  2955   2944           rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
  2956   2945           if( rc==SQLITE_OK ){
  2957   2946             while( sqlite3_step(pExplain)==SQLITE_ROW ){
  2958   2947               const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
  2959         -            int iSelectId = sqlite3_column_int(pExplain, 0);
         2948  +            int iEqpId = sqlite3_column_int(pExplain, 0);
         2949  +            int iParentId = sqlite3_column_int(pExplain, 1);
  2960   2950               if( zEQPLine[0]=='-' ) eqp_render(pArg);
  2961         -            eqp_append(pArg, iSelectId, zEQPLine);
         2951  +            eqp_append(pArg, iEqpId, iParentId, zEQPLine);
  2962   2952             }
  2963   2953             eqp_render(pArg);
  2964   2954           }
  2965   2955           sqlite3_finalize(pExplain);
  2966   2956           sqlite3_free(zEQP);
  2967   2957           if( pArg->autoEQP>=AUTOEQP_full ){
  2968   2958             /* Also do an EXPLAIN for ".eqp full" mode */
................................................................................
  5910   5900         raw_printf(stderr, "Usage: .echo on|off\n");
  5911   5901         rc = 1;
  5912   5902       }
  5913   5903     }else
  5914   5904   
  5915   5905     if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
  5916   5906       if( nArg==2 ){
         5907  +      p->autoEQPtest = 0;
  5917   5908         if( strcmp(azArg[1],"full")==0 ){
  5918   5909           p->autoEQP = AUTOEQP_full;
  5919   5910         }else if( strcmp(azArg[1],"trigger")==0 ){
  5920   5911           p->autoEQP = AUTOEQP_trigger;
         5912  +      }else if( strcmp(azArg[1],"test")==0 ){
         5913  +        p->autoEQP = AUTOEQP_on;
         5914  +        p->autoEQPtest = 1;
  5921   5915         }else{
  5922   5916           p->autoEQP = (u8)booleanValue(azArg[1]);
  5923   5917         }
  5924   5918       }else{
  5925   5919         raw_printf(stderr, "Usage: .eqp off|on|trigger|full\n");
  5926   5920         rc = 1;
  5927   5921       }

Changes to src/sqliteInt.h.

  2605   2605         unsigned notIndexed :1;    /* True if there is a NOT INDEXED clause */
  2606   2606         unsigned isIndexedBy :1;   /* True if there is an INDEXED BY clause */
  2607   2607         unsigned isTabFunc :1;     /* True if table-valued-function syntax */
  2608   2608         unsigned isCorrelated :1;  /* True if sub-query is correlated */
  2609   2609         unsigned viaCoroutine :1;  /* Implemented as a co-routine */
  2610   2610         unsigned isRecursive :1;   /* True for recursive reference in WITH */
  2611   2611       } fg;
  2612         -#ifndef SQLITE_OMIT_EXPLAIN
  2613         -    u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
  2614         -#endif
  2615   2612       int iCursor;      /* The VDBE cursor number used to access this table */
  2616   2613       Expr *pOn;        /* The ON clause of a join */
  2617   2614       IdList *pUsing;   /* The USING clause of a join */
  2618   2615       Bitmask colUsed;  /* Bit N (1<<N) set if column N of pTab is used */
  2619   2616       union {
  2620   2617         char *zIndexedBy;    /* Identifier from "INDEXED BY <zIndex>" clause */
  2621   2618         ExprList *pFuncArg;  /* Arguments to table-valued-function */
................................................................................
  2755   2752     int iIdxCur;              /* Index of the first index cursor */
  2756   2753   };
  2757   2754   
  2758   2755   /*
  2759   2756   ** An instance of the following structure contains all information
  2760   2757   ** needed to generate code for a single SELECT statement.
  2761   2758   **
  2762         -** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
  2763         -** If there is a LIMIT clause, the parser sets nLimit to the value of the
  2764         -** limit and nOffset to the value of the offset (or 0 if there is not
  2765         -** offset).  But later on, nLimit and nOffset become the memory locations
  2766         -** in the VDBE that record the limit and offset counters.
         2759  +** See the header comment on the computeLimitRegisters() routine for a
         2760  +** detailed description of the meaning of the iLimit and iOffset fields.
  2767   2761   **
  2768   2762   ** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
  2769   2763   ** These addresses must be stored so that we can go back and fill in
  2770   2764   ** the P4_KEYINFO and P2 parameters later.  Neither the KeyInfo nor
  2771   2765   ** the number of columns in P2 can be computed at the same time
  2772   2766   ** as the OP_OpenEphm instruction is coded because not
  2773   2767   ** enough information about the compound query is known at that point.
................................................................................
  2779   2773     ExprList *pEList;      /* The fields of the result */
  2780   2774     u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
  2781   2775     LogEst nSelectRow;     /* Estimated number of result rows */
  2782   2776     u32 selFlags;          /* Various SF_* values */
  2783   2777     int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
  2784   2778   #if SELECTTRACE_ENABLED
  2785   2779     char zSelName[12];     /* Symbolic name of this SELECT use for debugging */
  2786         -  u32 iSelectId;         /* EXPLAIN QUERY PLAN select ID */
  2787   2780   #endif
  2788   2781     int addrOpenEphm[2];   /* OP_OpenEphem opcodes related to this select */
  2789   2782     SrcList *pSrc;         /* The FROM clause */
  2790   2783     Expr *pWhere;          /* The WHERE clause */
  2791   2784     ExprList *pGroupBy;    /* The GROUP BY clause */
  2792   2785     Expr *pHaving;         /* The HAVING clause */
  2793   2786     ExprList *pOrderBy;    /* The ORDER BY clause */
................................................................................
  2820   2813   #define SF_NestedFrom     0x00800  /* Part of a parenthesized FROM clause */
  2821   2814   #define SF_MinMaxAgg      0x01000  /* Aggregate containing min() or max() */
  2822   2815   #define SF_Recursive      0x02000  /* The recursive part of a recursive CTE */
  2823   2816   #define SF_FixedLimit     0x04000  /* nSelectRow set by a constant LIMIT */
  2824   2817   #define SF_MaybeConvert   0x08000  /* Need convertCompoundSelectToSubquery() */
  2825   2818   #define SF_Converted      0x10000  /* By convertCompoundSelectToSubquery() */
  2826   2819   #define SF_IncludeHidden  0x20000  /* Include hidden columns in output */
  2827         -#define SF_ComplexResult  0x40000  /* Result set contains subquery or function */
  2828         -
         2820  +#define SF_ComplexResult  0x40000  /* Result contains subquery or function */
  2829   2821   
  2830   2822   /*
  2831   2823   ** The results of a SELECT can be distributed in several ways, as defined
  2832   2824   ** by one of the following macros.  The "SRT" prefix means "SELECT Result
  2833   2825   ** Type".
  2834   2826   **
  2835   2827   **     SRT_Union       Store results as a key in a temporary index
................................................................................
  3091   3083     u8 explain;               /* True if the EXPLAIN flag is found on the query */
  3092   3084   #ifndef SQLITE_OMIT_VIRTUALTABLE
  3093   3085     u8 declareVtab;           /* True if inside sqlite3_declare_vtab() */
  3094   3086     int nVtabLock;            /* Number of virtual tables to lock */
  3095   3087   #endif
  3096   3088     int nHeight;              /* Expression tree height of current sub-select */
  3097   3089   #ifndef SQLITE_OMIT_EXPLAIN
  3098         -  int iSelectId;            /* ID of current select for EXPLAIN output */
  3099         -  int iNextSelectId;        /* Next available select ID for EXPLAIN output */
         3090  +  int addrExplain;          /* Address of current OP_Explain opcode */
  3100   3091   #endif
  3101   3092     VList *pVList;            /* Mapping between variable names and numbers */
  3102   3093     Vdbe *pReprepare;         /* VM being reprepared (sqlite3Reprepare()) */
  3103   3094     const char *zTail;        /* All SQL text past the last semicolon parsed */
  3104   3095     Table *pNewTable;         /* A table being constructed by CREATE TABLE */
  3105   3096     Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
  3106   3097     const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */

Changes to src/treeview.c.

   137    137       sqlite3TreeViewWith(pView, p->pWith, 1);
   138    138       cnt = 1;
   139    139       sqlite3TreeViewPush(pView, 1);
   140    140     }
   141    141     do{
   142    142   #if SELECTTRACE_ENABLED
   143    143       sqlite3TreeViewLine(pView,
   144         -      "SELECT%s%s (%s/%d/%p) selFlags=0x%x nSelectRow=%d",
          144  +      "SELECT%s%s (%s/%p) selFlags=0x%x nSelectRow=%d",
   145    145         ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
   146    146         ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
   147         -      p->zSelName, p->iSelectId, p, p->selFlags,
          147  +      p->zSelName, p, p->selFlags,
   148    148         (int)p->nSelectRow
   149    149       );
   150    150   #else
   151    151       sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d",
   152    152         ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
   153    153         ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags,
   154    154         (int)p->nSelectRow

Changes to src/vacuum.c.

    35     35   
    36     36     /* printf("SQL: [%s]\n", zSql); fflush(stdout); */
    37     37     rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
    38     38     if( rc!=SQLITE_OK ) return rc;
    39     39     while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
    40     40       const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0);
    41     41       assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 );
    42         -    assert( sqlite3_strnicmp(zSubSql,"SELECT",6)!=0 || CORRUPT_DB );
    43         -    if( zSubSql && zSubSql[0]!='S' ){
           42  +    /* The secondary SQL must be one of CREATE TABLE, CREATE INDEX,
           43  +    ** or INSERT.  Historically there have been attacks that first
           44  +    ** corrupt the sqlite_master.sql field with other kinds of statements
           45  +    ** then run VACUUM to get those statements to execute at inappropriate
           46  +    ** times. */
           47  +    if( zSubSql
           48  +     && (strncmp(zSubSql,"CRE",3)==0 || strncmp(zSubSql,"INS",3)==0)
           49  +    ){
    44     50         rc = execSql(db, pzErrMsg, zSubSql);
    45     51         if( rc!=SQLITE_OK ) break;
    46     52       }
    47     53     }
    48     54     assert( rc!=SQLITE_ROW );
    49     55     if( rc==SQLITE_DONE ) rc = SQLITE_OK;
    50     56     if( rc ){
................................................................................
   243    249     /* Query the schema of the main database. Create a mirror schema
   244    250     ** in the temporary database.
   245    251     */
   246    252     db->init.iDb = nDb; /* force new CREATE statements into vacuum_db */
   247    253     rc = execSqlF(db, pzErrMsg,
   248    254         "SELECT sql FROM \"%w\".sqlite_master"
   249    255         " WHERE type='table'AND name<>'sqlite_sequence'"
   250         -      " AND coalesce(rootpage,1)>0 AND sql LIKE 'CREATE%%'",
          256  +      " AND coalesce(rootpage,1)>0",
   251    257         zDbMain
   252    258     );
   253    259     if( rc!=SQLITE_OK ) goto end_of_vacuum;
   254    260     rc = execSqlF(db, pzErrMsg,
   255    261         "SELECT sql FROM \"%w\".sqlite_master"
   256         -      " WHERE type='index' AND length(sql)>10",
          262  +      " WHERE type='index'",
   257    263         zDbMain
   258    264     );
   259    265     if( rc!=SQLITE_OK ) goto end_of_vacuum;
   260    266     db->init.iDb = 0;
   261    267   
   262    268     /* Loop through the tables in the main database. For each, do
   263    269     ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy

Changes to src/vdbe.h.

   193    193   #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
   194    194     void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
   195    195     void sqlite3VdbeVerifyNoResultRow(Vdbe *p);
   196    196   #else
   197    197   # define sqlite3VdbeVerifyNoMallocRequired(A,B)
   198    198   # define sqlite3VdbeVerifyNoResultRow(A)
   199    199   #endif
   200         -VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
          200  +VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
          201  +#ifndef SQLITE_OMIT_EXPLAIN
          202  +  void sqlite3VdbeExplain(Parse*,u8,const char*,...);
          203  +  void sqlite3VdbeExplainPop(Parse*);
          204  +  int sqlite3VdbeExplainParent(Parse*);
          205  +# define ExplainQueryPlan(P)        sqlite3VdbeExplain P
          206  +# define ExplainQueryPlanPop(P)     sqlite3VdbeExplainPop(P)
          207  +# define ExplainQueryPlanParent(P)  sqlite3VdbeExplainParent(P)
          208  +#else
          209  +# define ExplainQueryPlan(P)
          210  +# define ExplainQueryPlanPop(P)
          211  +# define ExplainQueryPlanParent(P) 0
          212  +#endif
   201    213   void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
   202    214   void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
   203    215   void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
   204    216   void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
   205    217   void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
   206    218   void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
   207    219   void sqlite3VdbeJumpHere(Vdbe*, int addr);

Changes to src/vdbeaux.c.

   299    299     int p4type          /* P4 operand type */
   300    300   ){
   301    301     char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8);
   302    302     if( p4copy ) memcpy(p4copy, zP4, 8);
   303    303     return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type);
   304    304   }
   305    305   
          306  +#ifndef SQLITE_OMIT_EXPLAIN
          307  +/*
          308  +** Return the address of the current EXPLAIN QUERY PLAN baseline.
          309  +** 0 means "none".
          310  +*/
          311  +int sqlite3VdbeExplainParent(Parse *pParse){
          312  +  VdbeOp *pOp;
          313  +  if( pParse->addrExplain==0 ) return 0;
          314  +  pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain);
          315  +  return pOp->p2;
          316  +}
          317  +
          318  +/*
          319  +** Add a new OP_Explain opcode.
          320  +**
          321  +** If the bPush flag is true, then make this opcode the parent for
          322  +** subsequent Explains until sqlite3VdbeExplainPop() is called.
          323  +*/
          324  +void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
          325  +  if( pParse->explain==2 ){
          326  +    char *zMsg;
          327  +    Vdbe *v = pParse->pVdbe;
          328  +    va_list ap;
          329  +    int iThis;
          330  +    va_start(ap, zFmt);
          331  +    zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap);
          332  +    va_end(ap);
          333  +    v = pParse->pVdbe;
          334  +    iThis = v->nOp;
          335  +    sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0,
          336  +                      zMsg, P4_DYNAMIC);
          337  +    if( bPush) pParse->addrExplain = iThis;
          338  +  }
          339  +}
          340  +
          341  +/*
          342  +** Pop the EXPLAIN QUERY PLAN stack one level.
          343  +*/
          344  +void sqlite3VdbeExplainPop(Parse *pParse){
          345  +  pParse->addrExplain = sqlite3VdbeExplainParent(pParse);
          346  +}
          347  +#endif /* SQLITE_OMIT_EXPLAIN */
          348  +
   306    349   /*
   307    350   ** Add an OP_ParseSchema opcode.  This routine is broken out from
   308    351   ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
   309    352   ** as having been used.
   310    353   **
   311    354   ** The zWhere string must have been obtained from sqlite3_malloc().
   312    355   ** This routine will take ownership of the allocated memory.

Changes to src/where.c.

  4588   4588     /* Special case: No FROM clause
  4589   4589     */
  4590   4590     if( nTabList==0 ){
  4591   4591       if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr;
  4592   4592       if( wctrlFlags & WHERE_WANT_DISTINCT ){
  4593   4593         pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
  4594   4594       }
         4595  +    ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
  4595   4596     }else{
  4596   4597       /* Assign a bit from the bitmask to every term in the FROM clause.
  4597   4598       **
  4598   4599       ** The N-th term of the FROM clause is assigned a bitmask of 1<<N.
  4599   4600       **
  4600   4601       ** The rule of the previous sentence ensures thta if X is the bitmask for
  4601   4602       ** a table T, then X-1 is the bitmask for all other tables to the left of T.

Changes to src/wherecode.c.

   130    130   #if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
   131    131     if( sqlite3ParseToplevel(pParse)->explain==2 )
   132    132   #endif
   133    133     {
   134    134       struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
   135    135       Vdbe *v = pParse->pVdbe;      /* VM being constructed */
   136    136       sqlite3 *db = pParse->db;     /* Database handle */
   137         -    int iId = pParse->iSelectId;  /* Select id (left-most output column) */
   138    137       int isSearch;                 /* True for a SEARCH. False for SCAN. */
   139    138       WhereLoop *pLoop;             /* The controlling WhereLoop object */
   140    139       u32 flags;                    /* Flags that describe this loop */
   141    140       char *zMsg;                   /* Text to add to EQP output */
   142    141       StrAccum str;                 /* EQP output string */
   143    142       char zBuf[100];               /* Initial space for EQP output string */
   144    143   
................................................................................
   149    148       isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
   150    149               || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
   151    150               || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
   152    151   
   153    152       sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
   154    153       sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN");
   155    154       if( pItem->pSelect ){
   156         -      sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId);
          155  +      sqlite3XPrintf(&str, " SUBQUERY 0x%p", pItem->pSelect);
   157    156       }else{
   158    157         sqlite3XPrintf(&str, " TABLE %s", pItem->zName);
   159    158       }
   160    159   
   161    160       if( pItem->zAlias ){
   162    161         sqlite3XPrintf(&str, " AS %s", pItem->zAlias);
   163    162       }
................................................................................
   210    209       if( pLoop->nOut>=10 ){
   211    210         sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut));
   212    211       }else{
   213    212         sqlite3StrAccumAppend(&str, " (~1 row)", 9);
   214    213       }
   215    214   #endif
   216    215       zMsg = sqlite3StrAccumFinish(&str);
   217         -    ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC);
          216  +    ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
          217  +                            pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
   218    218     }
   219    219     return ret;
   220    220   }
   221    221   #endif /* SQLITE_OMIT_EXPLAIN */
   222    222   
   223    223   #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
   224    224   /*
................................................................................
  1930   1930       }
  1931   1931   
  1932   1932       /* Run a separate WHERE clause for each term of the OR clause.  After
  1933   1933       ** eliminating duplicates from other WHERE clauses, the action for each
  1934   1934       ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
  1935   1935       */
  1936   1936       wctrlFlags =  WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE);
         1937  +    ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
  1937   1938       for(ii=0; ii<pOrWc->nTerm; ii++){
  1938   1939         WhereTerm *pOrTerm = &pOrWc->a[ii];
  1939   1940         if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
  1940   1941           WhereInfo *pSubWInfo;           /* Info for single OR-term scan */
  1941   1942           Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
  1942   1943           int jmp1 = 0;                   /* Address of jump operation */
  1943   1944           assert( (pTabItem[0].fg.jointype & JT_LEFT)==0 
................................................................................
  2050   2051             }
  2051   2052   
  2052   2053             /* Finish the loop through table entries that match term pOrTerm. */
  2053   2054             sqlite3WhereEnd(pSubWInfo);
  2054   2055           }
  2055   2056         }
  2056   2057       }
         2058  +    ExplainQueryPlanPop(pParse);
  2057   2059       pLevel->u.pCovidx = pCov;
  2058   2060       if( pCov ) pLevel->iIdxCur = iCovCur;
  2059   2061       if( pAndExpr ){
  2060   2062         pAndExpr->pLeft = 0;
  2061   2063         sqlite3ExprDelete(db, pAndExpr);
  2062   2064       }
  2063   2065       sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));

Changes to test/analyze3.test.

   114    114   
   115    115   # The first of the following two SELECT statements visits 99 rows. So
   116    116   # it is better to use the index. But the second visits every row in 
   117    117   # the table (1000 in total) so it is better to do a full-table scan.
   118    118   #
   119    119   do_eqp_test analyze3-1.1.2 {
   120    120     SELECT sum(y) FROM t1 WHERE x>200 AND x<300
   121         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
          121  +} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
   122    122   do_eqp_test analyze3-1.1.3 {
   123    123     SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 
   124         -} {0 0 0 {SCAN TABLE t1}}
          124  +} {SCAN TABLE t1}
   125    125   
   126    126   # 2017-06-26:  Verify that the SQLITE_DBCONFIG_ENABLE_QPSG setting disables
   127    127   # the use of bound parameters by STAT4
   128    128   #
   129    129   db cache flush
   130    130   unset -nocomplain l
   131    131   unset -nocomplain u
   132    132   do_eqp_test analyze3-1.1.3.100 {
   133    133     SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
   134         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
          134  +} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
   135    135   set l 200
   136    136   set u 300
   137    137   do_eqp_test analyze3-1.1.3.101 {
   138    138     SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
   139         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
          139  +} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
   140    140   set l 0
   141    141   set u 1100
   142    142   do_eqp_test analyze3-1.1.3.102 {
   143    143     SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
   144         -} {0 0 0 {SCAN TABLE t1}}
          144  +} {SCAN TABLE t1}
   145    145   db cache flush
   146    146   sqlite3_db_config db ENABLE_QPSG 1
   147    147   do_eqp_test analyze3-1.1.3.103 {
   148    148     SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
   149         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
          149  +} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
   150    150   db cache flush
   151    151   sqlite3_db_config db ENABLE_QPSG 0
   152    152   do_eqp_test analyze3-1.1.3.104 {
   153    153     SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
   154         -} {0 0 0 {SCAN TABLE t1}}
          154  +} {SCAN TABLE t1}
   155    155   
   156    156   do_test analyze3-1.1.4 {
   157    157     sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
   158    158   } {199 0 14850}
   159    159   do_test analyze3-1.1.5 {
   160    160     set l [string range "200" 0 end]
   161    161     set u [string range "300" 0 end]
................................................................................
   197    197   } {}
   198    198   do_execsql_test analyze3-2.1.x {
   199    199     SELECT count(*) FROM t2 WHERE x>1 AND x<2;
   200    200     SELECT count(*) FROM t2 WHERE x>0 AND x<99;
   201    201   } {200 990}
   202    202   do_eqp_test analyze3-1.2.2 {
   203    203     SELECT sum(y) FROM t2 WHERE x>1 AND x<2
   204         -} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}}
          204  +} {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}
   205    205   do_eqp_test analyze3-1.2.3 {
   206    206     SELECT sum(y) FROM t2 WHERE x>0 AND x<99
   207         -} {0 0 0 {SCAN TABLE t2}}
          207  +} {SCAN TABLE t2}
   208    208   
   209    209   do_test analyze3-1.2.4 {
   210    210     sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
   211    211   } {161 0 4760}
   212    212   do_test analyze3-1.2.5 {
   213    213     set l [string range "12" 0 end]
   214    214     set u [string range "20" 0 end]
................................................................................
   249    249   } {}
   250    250   do_execsql_test analyze3-1.3.x {
   251    251     SELECT count(*) FROM t3 WHERE x>200 AND x<300;
   252    252     SELECT count(*) FROM t3 WHERE x>0 AND x<1100
   253    253   } {99 1000}
   254    254   do_eqp_test analyze3-1.3.2 {
   255    255     SELECT sum(y) FROM t3 WHERE x>200 AND x<300
   256         -} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}}
          256  +} {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}
   257    257   do_eqp_test analyze3-1.3.3 {
   258    258     SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
   259         -} {0 0 0 {SCAN TABLE t3}}
          259  +} {SCAN TABLE t3}
   260    260   
   261    261   do_test analyze3-1.3.4 {
   262    262     sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
   263    263   } {199 0 14850}
   264    264   do_test analyze3-1.3.5 {
   265    265     set l [string range "200" 0 end]
   266    266     set u [string range "300" 0 end]
................................................................................
   304    304       append t [lindex {a b c d e f g h i j} [expr ($i%10)]]
   305    305       execsql { INSERT INTO t1 VALUES($i, $t) }
   306    306     }
   307    307     execsql COMMIT
   308    308   } {}
   309    309   do_eqp_test analyze3-2.2 {
   310    310     SELECT count(a) FROM t1 WHERE b LIKE 'a%'
   311         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?)}}
          311  +} {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?)}
   312    312   do_eqp_test analyze3-2.3 {
   313    313     SELECT count(a) FROM t1 WHERE b LIKE '%a'
   314         -} {0 0 0 {SCAN TABLE t1}}
          314  +} {SCAN TABLE t1}
   315    315   
   316    316   # Return the first argument if like_match_blobs is true (the default)
   317    317   # or the second argument if not
   318    318   #
   319    319   proc ilmb {a b} {
   320    320     ifcapable like_match_blobs {return $a}
   321    321     return $b
................................................................................
   694    694     }
   695    695     execsql COMMIT
   696    696     execsql ANALYZE
   697    697   } {}
   698    698   
   699    699   do_eqp_test analyze3-6-3 {
   700    700     SELECT * FROM t1 WHERE a = 5 AND c = 13;
   701         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
          701  +} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
   702    702   
   703    703   do_eqp_test analyze3-6-2 {
   704    704     SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
   705         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
          705  +} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
   706    706   
   707    707   #-----------------------------------------------------------------------------
   708    708   # 2015-04-20.
   709    709   # Memory leak in sqlite3Stat4ProbeFree().  (Discovered while fuzzing.)
   710    710   #
   711    711   do_execsql_test analyze-7.1 {
   712    712     DROP TABLE IF EXISTS t1;

Changes to test/analyze4.test.

    34     34       INSERT INTO t1 SELECT a+32, b FROM t1;
    35     35       INSERT INTO t1 SELECT a+64, b FROM t1;
    36     36       ANALYZE;
    37     37     }
    38     38   
    39     39     # Should choose the t1a index since it is more specific than t1b.
    40     40     db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL}
    41         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
           41  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
    42     42   
    43     43   # Verify that the t1b index shows that it does not narrow down the
    44     44   # search any at all.
    45     45   #
    46     46   do_test analyze4-1.1 {
    47     47     db eval {
    48     48       SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t1' ORDER BY idx;

Changes to test/analyze6.test.

    57     57   # The lowest cost plan is to scan CAT and for each integer there, do a single
    58     58   # lookup of the first corresponding entry in EV then read off the equal values
    59     59   # in EV.  (Prior to the 2011-03-04 enhancement to where.c, this query would
    60     60   # have used EV for the outer loop instead of CAT - which was about 3x slower.)
    61     61   #
    62     62   do_test analyze6-1.1 {
    63     63     eqp {SELECT count(*) FROM ev, cat WHERE x=y}
    64         -} {0 0 1 {SCAN TABLE cat USING COVERING INDEX catx} 0 1 0 {SEARCH TABLE ev USING COVERING INDEX evy (y=?)}}
           64  +} {/*SCAN TABLE cat USING COVERING INDEX catx*SEARCH TABLE ev USING COVERING INDEX evy (y=?)*/}
    65     65   
    66     66   # The same plan is chosen regardless of the order of the tables in the
    67     67   # FROM clause.
    68     68   #
    69         -do_test analyze6-1.2 {
    70         -  eqp {SELECT count(*) FROM cat, ev WHERE x=y}
    71         -} {0 0 0 {SCAN TABLE cat USING COVERING INDEX catx} 0 1 1 {SEARCH TABLE ev USING COVERING INDEX evy (y=?)}}
           69  +do_eqp_test analyze6-1.2 {
           70  +  SELECT count(*) FROM cat, ev WHERE x=y
           71  +} {
           72  +  QUERY PLAN
           73  +  |--SCAN TABLE cat USING COVERING INDEX catx
           74  +  `--SEARCH TABLE ev USING COVERING INDEX evy (y=?)
           75  +}
    72     76   
    73     77   
    74     78   # Ticket [83ea97620bd3101645138b7b0e71c12c5498fe3d] 2011-03-30
    75     79   # If ANALYZE is run on an empty table, make sure indices are used
    76     80   # on the table.
    77     81   #
    78     82   do_test analyze6-2.1 {
    79     83     execsql {
    80     84       CREATE TABLE t201(x INTEGER PRIMARY KEY, y UNIQUE, z);
    81     85       CREATE INDEX t201z ON t201(z);
    82     86       ANALYZE;
    83     87     }
    84     88     eqp {SELECT * FROM t201 WHERE z=5}
    85         -} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}}
           89  +} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
    86     90   do_test analyze6-2.2 {
    87     91     eqp {SELECT * FROM t201 WHERE y=5}
    88         -} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}}
           92  +} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
    89     93   do_test analyze6-2.3 {
    90     94     eqp {SELECT * FROM t201 WHERE x=5}
    91         -} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}}
           95  +} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
    92     96   do_test analyze6-2.4 {
    93     97     execsql {
    94     98       INSERT INTO t201 VALUES(1,2,3),(2,3,4),(3,4,5);
    95     99       ANALYZE t201;
    96    100     }
    97    101     eqp {SELECT * FROM t201 WHERE z=5}
    98         -} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}}
          102  +} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
    99    103   do_test analyze6-2.5 {
   100    104     eqp {SELECT * FROM t201 WHERE y=5}
   101         -} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}}
          105  +} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
   102    106   do_test analyze6-2.6 {
   103    107     eqp {SELECT * FROM t201 WHERE x=5}
   104         -} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}}
          108  +} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
   105    109   do_test analyze6-2.7 {
   106    110     execsql {
   107    111       INSERT INTO t201 VALUES(4,5,7);
   108    112       INSERT INTO t201 SELECT x+100, y+100, z+100 FROM t201;
   109    113       INSERT INTO t201 SELECT x+200, y+200, z+200 FROM t201;
   110    114       INSERT INTO t201 SELECT x+400, y+400, z+400 FROM t201;
   111    115       ANALYZE t201;
   112    116     }
   113    117     eqp {SELECT * FROM t201 WHERE z=5}
   114         -} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}}
          118  +} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
   115    119   do_test analyze6-2.8 {
   116    120     eqp {SELECT * FROM t201 WHERE y=5}
   117         -} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}}
          121  +} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
   118    122   do_test analyze6-2.9 {
   119    123     eqp {SELECT * FROM t201 WHERE x=5}
   120         -} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}}
          124  +} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
   121    125   
   122    126   finish_test

Changes to test/analyze7.test.

    33     33       CREATE INDEX t1b ON t1(b);
    34     34       CREATE INDEX t1cd ON t1(c,d);
    35     35       CREATE VIRTUAL TABLE nums USING wholenumber;
    36     36       INSERT INTO t1 SELECT value, value, value/100, value FROM nums
    37     37                       WHERE value BETWEEN 1 AND 256;
    38     38       EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;
    39     39     }
    40         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
           40  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
    41     41   do_test analyze7-1.1 {
    42     42     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
    43         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
           43  +} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
    44     44   do_test analyze7-1.2 {
    45     45     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
    46         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
           46  +} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
    47     47   
    48     48   # Run an analyze on one of the three indices.  Verify that this
    49     49   # effects the row-count estimate on the one query that uses that
    50     50   # one index.
    51     51   #
    52     52   do_test analyze7-2.0 {
    53     53     execsql {ANALYZE t1a;}
    54     54     db cache flush
    55     55     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
    56         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
           56  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
    57     57   do_test analyze7-2.1 {
    58     58     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
    59         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
           59  +} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
    60     60   do_test analyze7-2.2 {
    61     61     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
    62         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
           62  +} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
    63     63   
    64     64   # Verify that since the query planner now things that t1a is more
    65     65   # selective than t1b, it prefers to use t1a.
    66     66   #
    67     67   do_test analyze7-2.3 {
    68     68     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
    69         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
           69  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
    70     70   
    71     71   # Run an analysis on another of the three indices.  Verify  that this
    72     72   # new analysis works and does not disrupt the previous analysis.
    73     73   #
    74     74   do_test analyze7-3.0 {
    75     75     execsql {ANALYZE t1cd;}
    76     76     db cache flush;
    77     77     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
    78         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
           78  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
    79     79   do_test analyze7-3.1 {
    80     80     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
    81         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
           81  +} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
    82     82   do_test analyze7-3.2.1 {
    83     83     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;}
    84         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
           84  +} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
    85     85   ifcapable stat4||stat3 {
    86     86     # If ENABLE_STAT4 is defined, SQLite comes up with a different estimated
    87     87     # row count for (c=2) than it does for (c=?).
    88     88     do_test analyze7-3.2.2 {
    89     89       execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
    90         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
           90  +  } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
    91     91   } else {
    92     92     # If ENABLE_STAT4 is not defined, the expected row count for (c=2) is the
    93     93     # same as that for (c=?).
    94     94     do_test analyze7-3.2.3 {
    95     95       execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
    96         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
           96  +  } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
    97     97   }
    98     98   do_test analyze7-3.3 {
    99     99     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
   100         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
          100  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
   101    101   
   102    102   ifcapable {!stat4 && !stat3} {
   103    103     do_test analyze7-3.4 {
   104    104       execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
   105         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
          105  +  } {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
   106    106     do_test analyze7-3.5 {
   107    107       execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
   108         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
          108  +  } {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
   109    109   }
   110    110   do_test analyze7-3.6 {
   111    111     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123}
   112         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)}}
          112  +} {/*SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)*/}
   113    113   
   114    114   finish_test

Changes to test/analyze8.test.

    57     57   # with a==100.  And so for those cases, choose the t1b index.
    58     58   #
    59     59   # Buf ro a==99 and a==101, there are far fewer rows so choose
    60     60   # the t1a index.
    61     61   #
    62     62   do_test 1.1 {
    63     63     eqp {SELECT * FROM t1 WHERE a=100 AND b=55}
    64         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
           64  +} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
    65     65   do_test 1.2 {
    66     66     eqp {SELECT * FROM t1 WHERE a=99 AND b=55}
    67         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
           67  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
    68     68   do_test 1.3 {
    69     69     eqp {SELECT * FROM t1 WHERE a=101 AND b=55}
    70         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
           70  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
    71     71   do_test 1.4 {
    72     72     eqp {SELECT * FROM t1 WHERE a=100 AND b=56}
    73         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
           73  +} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
    74     74   do_test 1.5 {
    75     75     eqp {SELECT * FROM t1 WHERE a=99 AND b=56}
    76         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
           76  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
    77     77   do_test 1.6 {
    78     78     eqp {SELECT * FROM t1 WHERE a=101 AND b=56}
    79         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
           79  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
    80     80   do_test 2.1 {
    81     81     eqp {SELECT * FROM t1 WHERE a=100 AND b BETWEEN 50 AND 54}
    82         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
           82  +} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)*/}
    83     83   
    84     84   # There are many more values of c between 0 and 100000 than there are
    85     85   # between 800000 and 900000.  So t1c is more selective for the latter
    86     86   # range.
    87     87   # 
    88     88   # Test 3.2 is a little unstable. It depends on the planner estimating
    89     89   # that (b BETWEEN 30 AND 34) will match more rows than (c BETWEEN
................................................................................
    95     95   do_execsql_test 3.0 {
    96     96     SELECT count(*) FROM t1 WHERE b BETWEEN 30 AND 34;
    97     97     SELECT count(*) FROM t1 WHERE c BETWEEN 0 AND 100000;
    98     98     SELECT count(*) FROM t1 WHERE c BETWEEN 800000 AND 900000;
    99     99   } {50 376 32}
   100    100   do_test 3.1 {
   101    101     eqp {SELECT * FROM t1 WHERE b BETWEEN 30 AND 34 AND c BETWEEN 0 AND 100000}
   102         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
          102  +} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)*/}
   103    103   do_test 3.2 {
   104    104     eqp {SELECT * FROM t1
   105    105          WHERE b BETWEEN 30 AND 34 AND c BETWEEN 800000 AND 900000}
   106         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
          106  +} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)*/}
   107    107   do_test 3.3 {
   108    108     eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 0 AND 100000}
   109         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
          109  +} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
   110    110   do_test 3.4 {
   111    111     eqp {SELECT * FROM t1
   112    112          WHERE a=100 AND c BETWEEN 800000 AND 900000}
   113         -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
          113  +} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)*/}
   114    114   
   115    115   finish_test

Changes to test/analyze9.test.

   983    983   } {/*USING INTEGER PRIMARY KEY*/}
   984    984   
   985    985   #-------------------------------------------------------------------------
   986    986   #
   987    987   reset_db
   988    988   do_execsql_test 22.0 {
   989    989     CREATE TABLE t3(a, b, c, d, PRIMARY KEY(a, b)) WITHOUT ROWID;
   990         -}
          990  +  SELECT * FROM t3;
          991  +} {}
   991    992   do_execsql_test 22.1 {
   992    993     WITH r(x) AS (
   993    994       SELECT 1
   994    995       UNION ALL
   995    996       SELECT x+1 FROM r WHERE x<=100
   996    997     )
   997    998   
................................................................................
  1051   1052   
  1052   1053   do_eqp_test 23.1 {
  1053   1054     SELECT * FROM t4 WHERE 
  1054   1055       (e=1 AND b='xyz' AND c='zyx' AND a<'AEA') AND f<300
  1055   1056     -- Formerly used index i41.  But i41 is not a covering index whereas
  1056   1057     -- the PRIMARY KEY is a covering index, and so as of 2017-10-15, the
  1057   1058     -- PRIMARY KEY is preferred.
  1058         -} {
  1059         -  0 0 0 {SEARCH TABLE t4 USING PRIMARY KEY (c=? AND b=? AND a<?)}
  1060         -}
         1059  +} {SEARCH TABLE t4 USING PRIMARY KEY (c=? AND b=? AND a<?)}
  1061   1060   do_eqp_test 23.2 {
  1062   1061     SELECT * FROM t4 WHERE 
  1063   1062       (e=1 AND b='xyz' AND c='zyx' AND a<'JJJ') AND f<300
  1064         -} {
  1065         -  0 0 0 {SEARCH TABLE t4 USING INDEX i42 (f<?)}
  1066         -}
         1063  +} {SEARCH TABLE t4 USING INDEX i42 (f<?)}
  1067   1064   
  1068   1065   do_execsql_test 24.0 {
  1069   1066     CREATE TABLE t5(c, d, b, e, a, PRIMARY KEY(a, b, c)) WITHOUT ROWID;
  1070   1067     WITH data(a, b, c, d, e) AS (
  1071   1068       SELECT 'z', 'y', 0, 0, 0
  1072   1069       UNION ALL
  1073   1070       SELECT 
................................................................................
  1104   1101       CREATE INDEX aa ON t6(a);
  1105   1102       CREATE INDEX bb ON t6(b);
  1106   1103       ANALYZE;
  1107   1104     }
  1108   1105   
  1109   1106     # Term (b<?) is estimated at 25%. Better than (a<30) but not as
  1110   1107     # good as (a<20).
  1111         -  do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b<? } {
  1112         -    0 0 0 {SEARCH TABLE t6 USING INDEX bb (b<?)}
  1113         -  }
  1114         -  do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } {
  1115         -    0 0 0 {SEARCH TABLE t6 USING INDEX aa (a<?)}
  1116         -  }
         1108  +  do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b<? } \
         1109  +    {SEARCH TABLE t6 USING INDEX bb (b<?)}
         1110  +  do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } \
         1111  +    {SEARCH TABLE t6 USING INDEX aa (a<?)}
  1117   1112   
  1118   1113     # Term (b BETWEEN ? AND ?) is estimated at 1/64.
  1119   1114     do_eqp_test 25.3.1 { 
  1120   1115       SELECT * FROM t6 WHERE a BETWEEN 5 AND 10 AND b BETWEEN ? AND ? 
  1121         -  } {
  1122         -    0 0 0 {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
  1123         -  }
         1116  +  } {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
  1124   1117     
  1125   1118     # Term (b BETWEEN ? AND 60) is estimated to return roughly 15 rows -
  1126   1119     # 60 from (b<=60) multiplied by 0.25 for the b>=? term. Better than
  1127   1120     # (a<20) but not as good as (a<10).
  1128   1121     do_eqp_test 25.4.1 { 
  1129   1122       SELECT * FROM t6 WHERE a < 10 AND (b BETWEEN ? AND 60)
  1130         -  } {
  1131         -    0 0 0 {SEARCH TABLE t6 USING INDEX aa (a<?)}
  1132         -  }
         1123  +  } {SEARCH TABLE t6 USING INDEX aa (a<?)}
         1124  +
  1133   1125     do_eqp_test 25.4.2 { 
  1134   1126       SELECT * FROM t6 WHERE a < 20 AND (b BETWEEN ? AND 60)
  1135         -  } {
  1136         -    0 0 0 {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
  1137         -  }
         1127  +  } {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
  1138   1128   }
  1139   1129   
  1140   1130   #-------------------------------------------------------------------------
  1141   1131   # Check that a problem in they way stat4 data is used has been 
  1142   1132   # resolved (see below).
  1143   1133   #
  1144   1134   reset_db
................................................................................
  1186   1176   # no more than that. Guessing less than 20 is therefore unreasonable.
  1187   1177   #
  1188   1178   # At one point though, due to a problem in whereKeyStats(), the planner was
  1189   1179   # estimating that (x=10000 AND y<50) would match only 2 rows.
  1190   1180   #
  1191   1181   do_eqp_test 26.1.4 {
  1192   1182     SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444;
  1193         -} {
  1194         -  0 0 0 {SEARCH TABLE t1 USING INDEX t1z (z=?)}
  1195         -}
         1183  +} {SEARCH TABLE t1 USING INDEX t1z (z=?)}
  1196   1184   
  1197   1185   
  1198   1186   # This test - 26.2.* - tests that another manifestation of the same problem
  1199   1187   # is no longer present in the library. Assuming:
  1200   1188   # 
  1201   1189   #   CREATE INDEX t1xy ON t1(x, y)
  1202   1190   #
................................................................................
  1237   1225       UPDATE t1 SET z = (rowid / 95);
  1238   1226       ANALYZE;
  1239   1227     COMMIT;
  1240   1228   }
  1241   1229   
  1242   1230   do_eqp_test 26.2.2 {
  1243   1231     SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?;
  1244         -} {
  1245         -  0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
  1246         -}
         1232  +} {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
  1247   1233   
  1248   1234   
  1249   1235   finish_test

Changes to test/analyzeA.test.

   132    132     do_execsql_test 1.$tn.2.1 { SELECT count(*) FROM t1 WHERE b=31 } 1
   133    133     do_execsql_test 1.$tn.2.2 { SELECT count(*) FROM t1 WHERE c=0  } 49
   134    134     do_execsql_test 1.$tn.2.3 { SELECT count(*) FROM t1 WHERE b=125  } 49
   135    135     do_execsql_test 1.$tn.2.4 { SELECT count(*) FROM t1 WHERE c=16  } 1
   136    136   
   137    137     do_eqp_test 1.$tn.2.5 {
   138    138       SELECT * FROM t1 WHERE b = 31 AND c = 0;
   139         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
          139  +  } {SEARCH TABLE t1 USING INDEX t1b (b=?)}
   140    140     do_eqp_test 1.$tn.2.6 {
   141    141       SELECT * FROM t1 WHERE b = 125 AND c = 16;
   142         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c=?)}}
          142  +  } {SEARCH TABLE t1 USING INDEX t1c (c=?)}
   143    143   
   144    144     do_execsql_test 1.$tn.3.1 { 
   145    145       SELECT count(*) FROM t1 WHERE b BETWEEN 0 AND 50
   146    146     } {6}
   147    147     do_execsql_test 1.$tn.3.2 { 
   148    148       SELECT count(*) FROM t1 WHERE c BETWEEN 0 AND 50
   149    149     } {90}
................................................................................
   152    152     } {90}
   153    153     do_execsql_test 1.$tn.3.4 { 
   154    154       SELECT count(*) FROM t1 WHERE c BETWEEN 75 AND 125
   155    155     } {6}
   156    156   
   157    157     do_eqp_test 1.$tn.3.5 {
   158    158       SELECT * FROM t1 WHERE b BETWEEN 0 AND 50 AND c BETWEEN 0 AND 50
   159         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
          159  +  } {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
   160    160   
   161    161     do_eqp_test 1.$tn.3.6 {
   162    162       SELECT * FROM t1 WHERE b BETWEEN 75 AND 125 AND c BETWEEN 75 AND 125
   163         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
          163  +  } {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}
   164    164   
   165    165     do_eqp_test 1.$tn.3.7 {
   166    166       SELECT * FROM t1 WHERE b BETWEEN +0 AND +50 AND c BETWEEN +0 AND +50
   167         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
          167  +  } {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
   168    168   
   169    169     do_eqp_test 1.$tn.3.8 {
   170    170       SELECT * FROM t1
   171    171        WHERE b BETWEEN cast('0' AS int) AND cast('50.0' AS real)
   172    172          AND c BETWEEN cast('0' AS numeric) AND cast('50.0' AS real)
   173         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
          173  +  } {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
   174    174   
   175    175     do_eqp_test 1.$tn.3.9 {
   176    176       SELECT * FROM t1 WHERE b BETWEEN +75 AND +125 AND c BETWEEN +75 AND +125
   177         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
          177  +  } {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}
   178    178   
   179    179     do_eqp_test 1.$tn.3.10 {
   180    180       SELECT * FROM t1
   181    181        WHERE b BETWEEN cast('75' AS int) AND cast('125.0' AS real)
   182    182          AND c BETWEEN cast('75' AS numeric) AND cast('125.0' AS real)
   183         -  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
          183  +  } {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}
   184    184   }
   185    185   
   186    186   finish_test

Changes to test/analyzeD.test.

    59     59   } {}
    60     60   
    61     61   # With full ANALYZE data, SQLite sees that c=150 (5 rows) is better than
    62     62   # a=3001 (7 rows).
    63     63   #
    64     64   do_eqp_test 1.2 {
    65     65     SELECT * FROM t1 WHERE a=3001 AND c=150;
    66         -} {
    67         -  0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
    68         -}
           66  +} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
    69     67   
    70     68   do_test 1.3 {
    71     69     execsql { DELETE FROM sqlite_stat1 }
    72     70     db close
    73     71     sqlite3 db test.db
    74     72   } {}
    75     73   
................................................................................
    76     74   # Without stat1, because 3001 is larger than all samples in the stat4
    77     75   # table, SQLite thinks that a=3001 matches just 1 row. So it (incorrectly)
    78     76   # chooses it over the c=150 index (5 rows). Even with stat1 data, things
    79     77   # worked this way before commit [e6f7f97dbc].
    80     78   #
    81     79   do_eqp_test 1.4 {
    82     80     SELECT * FROM t1 WHERE a=3001 AND c=150;
    83         -} {
    84         -  0 0 0 {SEARCH TABLE t1 USING INDEX t1_ab (a=?)}
    85         -}
           81  +} {SEARCH TABLE t1 USING INDEX t1_ab (a=?)}
    86     82   
    87     83   do_test 1.5 {
    88     84     execsql { 
    89     85       UPDATE t1 SET a=13 WHERE a = 3001;
    90     86       ANALYZE;
    91     87     }
    92     88   } {}
    93     89   
    94     90   do_eqp_test 1.6 {
    95     91     SELECT * FROM t1 WHERE a=13 AND c=150;
    96         -} {
    97         -  0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
    98         -}
           92  +} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
    99     93   
   100     94   do_test 1.7 {
   101     95     execsql { DELETE FROM sqlite_stat1 }
   102     96     db close
   103     97     sqlite3 db test.db
   104     98   } {}
   105     99   
   106    100   # Same test as 1.4, except this time the 7 rows that match the a=? condition 
   107    101   # do not feature larger values than all rows in the stat4 table. So SQLite
   108    102   # gets this right, even without stat1 data.
   109    103   do_eqp_test 1.8 {
   110    104     SELECT * FROM t1 WHERE a=13 AND c=150;
   111         -} {
   112         -  0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
   113         -}
          105  +} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
   114    106   
   115    107   finish_test

Changes to test/analyzeF.test.

    58     58   
    59     59     9  "x = str('19') AND y = str('4')" {t1y (y=?)}
    60     60     10 "x = str('4') AND y = str('19')" {t1y (y=?)}
    61     61   
    62     62     11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)}
    63     63     12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)}
    64     64   } {
    65         -  set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
           65  +  set res "SEARCH TABLE t1 USING INDEX $idx"
    66     66     do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res
    67     67   }
    68     68   
    69     69   # Test that functions that do not exist - "func()" - do not cause an error.
    70     70   #
    71     71   do_catchsql_test 2.1 {
    72     72     SELECT * FROM t1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
................................................................................
    88     88   foreach {tn where idx} {
    89     89     1 "x = det4() AND y = det19()"     {t1x (x=?)}
    90     90     2 "x = det19() AND y = det4()"     {t1y (y=?)}
    91     91   
    92     92     3 "x = nondet4() AND y = nondet19()"     {t1y (y=?)}
    93     93     4 "x = nondet19() AND y = nondet4()"     {t1y (y=?)}
    94     94   } {
    95         -  set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
           95  +  set res "SEARCH TABLE t1 USING INDEX $idx"
    96     96     do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
    97     97   }
    98     98   
    99     99   
   100    100   execsql { DELETE FROM t1 }
   101    101   
   102    102   proc throw_error {err} { error $err }

Changes to test/autoindex1.test.

   173    173   #
   174    174   do_execsql_test autoindex1-500 {
   175    175     CREATE TABLE t501(a INTEGER PRIMARY KEY, b);
   176    176     CREATE TABLE t502(x INTEGER PRIMARY KEY, y);
   177    177     INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t501',null,'1000000');
   178    178     INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t502',null,'1000');
   179    179     ANALYZE sqlite_master;
   180         -  EXPLAIN QUERY PLAN
          180  +}
          181  +do_eqp_test autoindex1-500.1 {
   181    182     SELECT b FROM t501
   182    183      WHERE t501.a IN (SELECT x FROM t502 WHERE y=?);
   183    184   } {
   184         -  0 0 0 {SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)} 
   185         -  0 0 0 {EXECUTE LIST SUBQUERY 1} 
   186         -  1 0 0 {SCAN TABLE t502}
          185  +  QUERY PLAN
          186  +  |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
          187  +  `--LIST SUBQUERY
          188  +     `--SCAN TABLE t502
   187    189   }
   188         -do_execsql_test autoindex1-501 {
   189         -  EXPLAIN QUERY PLAN
          190  +do_eqp_test autoindex1-501 {
   190    191     SELECT b FROM t501
   191    192      WHERE t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
   192    193   } {
   193         -  0 0 0 {SCAN TABLE t501} 
   194         -  0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1} 
   195         -  1 0 0 {SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)}
          194  +  QUERY PLAN
          195  +  |--SCAN TABLE t501
          196  +  `--CORRELATED LIST SUBQUERY
          197  +     `--SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)
   196    198   }
   197         -do_execsql_test autoindex1-502 {
   198         -  EXPLAIN QUERY PLAN
          199  +do_eqp_test autoindex1-502 {
   199    200     SELECT b FROM t501
   200    201      WHERE t501.a=123
   201    202        AND t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
   202    203   } {
   203         -  0 0 0 {SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)} 
   204         -  0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1} 
   205         -  1 0 0 {SCAN TABLE t502}
          204  +  QUERY PLAN
          205  +  |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
          206  +  `--CORRELATED LIST SUBQUERY
          207  +     `--SCAN TABLE t502
   206    208   }
   207         -
   208    209   
   209    210   # The following code checks a performance regression reported on the
   210    211   # mailing list on 2010-10-19.  The problem is that the nRowEst field
   211    212   # of ephermeral tables was not being initialized correctly and so no
   212    213   # automatic index was being created for the emphemeral table when it was
   213    214   # used as part of a join.
   214    215   #
................................................................................
   253    254                 ON flock_owner (owner_change_date);
   254    255     CREATE INDEX fo_owner_person_id_index  
   255    256                 ON flock_owner (owner_person_id);
   256    257     CREATE INDEX sheep_org_flock_index  
   257    258              ON sheep (originating_flock);
   258    259     CREATE INDEX sheep_reg_flock_index  
   259    260              ON sheep (registering_flock);
   260         -  EXPLAIN QUERY PLAN
          261  +}
          262  +do_eqp_test autoindex1-600a {
   261    263     SELECT x.sheep_no, x.registering_flock, x.date_of_registration
   262    264      FROM sheep x LEFT JOIN
   263    265          (SELECT s.sheep_no, prev.flock_no, prev.owner_person_id,
   264    266          s.date_of_registration, prev.owner_change_date
   265    267          FROM sheep s JOIN flock_owner prev ON s.registering_flock =
   266    268      prev.flock_no
   267    269          AND (prev.owner_change_date <= s.date_of_registration || ' 00:00:00')
................................................................................
   270    272              WHERE prev.flock_no = later.flock_no
   271    273              AND later.owner_change_date > prev.owner_change_date
   272    274              AND later.owner_change_date <= s.date_of_registration||' 00:00:00')
   273    275          ) y ON x.sheep_no = y.sheep_no
   274    276      WHERE y.sheep_no IS NULL
   275    277      ORDER BY x.registering_flock;
   276    278   } {
   277         -  1 0 0 {SCAN TABLE sheep AS s} 
   278         -  1 1 1 {SEARCH TABLE flock_owner AS prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date<?)} 
   279         -  1 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2} 
   280         -  2 0 0 {SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)} 
   281         -  0 0 0 {SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index} 
   282         -  0 1 1 {SEARCH SUBQUERY 1 AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)}
          279  +  QUERY PLAN
          280  +  |--MATERIALIZE xxxxxx
          281  +  |  |--SCAN TABLE sheep AS s
          282  +  |  |--SEARCH TABLE flock_owner AS prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date<?)
          283  +  |  `--CORRELATED SCALAR SUBQUERY
          284  +  |     `--SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)
          285  +  |--SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index
          286  +  `--SEARCH SUBQUERY xxxxxx AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)
   283    287   }
   284    288   
   285    289   
   286    290   do_execsql_test autoindex1-700 {
   287    291     CREATE TABLE t5(a, b, c);
   288         -  EXPLAIN QUERY PLAN SELECT a FROM t5 WHERE b=10 ORDER BY c;
          292  +}
          293  +do_eqp_test autoindex1-700a {
          294  +  SELECT a FROM t5 WHERE b=10 ORDER BY c;
   289    295   } {
   290         -  0 0 0 {SCAN TABLE t5} 
   291         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          296  +  QUERY PLAN
          297  +  |--SCAN TABLE t5
          298  +  `--USE TEMP B-TREE FOR ORDER BY
   292    299   }
   293    300   
   294    301   # The following checks a performance issue reported on the sqlite-dev
   295    302   # mailing list on 2013-01-10
   296    303   #
   297    304   do_execsql_test autoindex1-800 {
   298    305     CREATE TABLE accounts(

Changes to test/autoindex3.test.

    80     80   # on the basis that the real index "uab" must be better than the automatic
    81     81   # index. This is not right - a skip-scan is not necessarily better than an
    82     82   # automatic index scan.
    83     83   #
    84     84   do_eqp_test 220 {
    85     85     select count(*) from u, v where u.b = v.b and v.e > 34;
    86     86   } {
    87         -  0 0 1 {SEARCH TABLE v USING INDEX ve (e>?)} 
    88         -  0 1 0 {SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?)}
           87  +  QUERY PLAN
           88  +  |--SEARCH TABLE v USING INDEX ve (e>?)
           89  +  `--SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?)
    89     90   }
    90     91   
    91     92   
    92     93   finish_test

Changes to test/autoindex5.test.

    80     80                 AND debian_bugs.note = package_notes.id
    81     81                 ORDER BY debian_bugs.bug;
    82     82   } {}
    83     83   
    84     84   # The following query should use an automatic index for the view
    85     85   # in FROM clause of the subquery of the second result column.
    86     86   #
    87         -do_execsql_test autoindex5-1.1 {
    88         -  EXPLAIN QUERY PLAN
           87  +do_eqp_test autoindex5-1.1 {
    89     88     SELECT
    90     89       st.bug_name,
    91     90       (SELECT ALL debian_cve.bug FROM debian_cve
    92     91         WHERE debian_cve.bug_name = st.bug_name
    93     92         ORDER BY debian_cve.bug),
    94     93       sp.release
    95     94     FROM
................................................................................
    99     98     WHERE
   100     99        sp.rowid = st.package
   101    100        AND st.bug_name = bugs.name
   102    101        AND ( st.bug_name LIKE 'CVE-%' OR st.bug_name LIKE 'TEMP-%' )
   103    102        AND ( sp.release = 'sid' OR sp.release = 'stretch' OR sp.release = 'jessie'
   104    103               OR sp.release = 'wheezy' OR sp.release = 'squeeze' )
   105    104     ORDER BY sp.name, st.bug_name, sp.release, sp.subrelease;
   106         -} {/SEARCH SUBQUERY 2 USING AUTOMATIC COVERING INDEX .bug_name=/}
          105  +} {SEARCH SUBQUERY * USING AUTOMATIC COVERING INDEX (bug_name=?)}
   107    106   
   108    107   #-------------------------------------------------------------------------
   109    108   # Test that ticket [8a2adec1] has been fixed.
   110    109   #
   111    110   do_execsql_test 2.1 {
   112    111     CREATE TABLE one(o);
   113    112     INSERT INTO one DEFAULT VALUES;

Changes to test/bestindex1.test.

    47     47   
    48     48   do_execsql_test 1.0 {
    49     49     CREATE VIRTUAL TABLE x1 USING tcl(vtab_command);
    50     50   } {}
    51     51   
    52     52   do_eqp_test 1.1 {
    53     53     SELECT * FROM x1 WHERE a = 'abc'
    54         -} {
    55         -  0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
    56         -}
           54  +} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
    57     55   
    58     56   do_eqp_test 1.2 {
    59     57     SELECT * FROM x1 WHERE a IN ('abc', 'def');
    60         -} {
    61         -  0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
    62         -}
           58  +} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
    63     59   
    64     60   #-------------------------------------------------------------------------
    65     61   #
    66     62   reset_db
    67     63   register_tcl_module db
    68     64   
    69     65   # Parameter $mode may be one of:
................................................................................
   140    136     do_execsql_test 2.2.$mode.4 {SELECT rowid FROM t1 WHERE a='two'} {2} 
   141    137   
   142    138     do_execsql_test 2.2.$mode.5 {
   143    139       SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
   144    140     } {1 4} 
   145    141   
   146    142     set plan(use) {
   147         -    0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'}
   148         -    0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          143  +    QUERY PLAN
          144  +    |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
          145  +    `--USE TEMP B-TREE FOR ORDER BY
   149    146     }
   150    147     set plan(omit) {
   151         -    0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'}
   152         -    0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          148  +    QUERY PLAN
          149  +    |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
          150  +    `--USE TEMP B-TREE FOR ORDER BY
   153    151     }
   154    152     set plan(use2) {
   155         -    0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x}
   156         -    0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          153  +    QUERY PLAN
          154  +    |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x
          155  +    `--USE TEMP B-TREE FOR ORDER BY
   157    156     }
   158    157   
   159    158     do_eqp_test 2.2.$mode.6 { 
   160    159       SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
   161         -  } $plan($mode)
          160  +  } [string map {"\n  " "\n"} $plan($mode)]
   162    161   }
   163    162   
   164    163   # 2016-04-09.
   165    164   # Demonstrate a register overwrite problem when using two virtual
   166    165   # tables where the outer loop uses the IN operator.
   167    166   #
   168    167   set G(collist) [list PrimaryKey flagA columnA]

Changes to test/bestindex2.test.

    85     85     CREATE VIRTUAL TABLE t1 USING tcl("vtab_cmd t1 {a b}");
    86     86     CREATE VIRTUAL TABLE t2 USING tcl("vtab_cmd t2 {c d}");
    87     87     CREATE VIRTUAL TABLE t3 USING tcl("vtab_cmd t3 {e f}");
    88     88   }
    89     89   
    90     90   do_eqp_test 1.1 {
    91     91     SELECT * FROM t1 WHERE a='abc'
    92         -} {
    93         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
    94         -}
           92  +} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
           93  +
    95     94   do_eqp_test 1.2 {
    96     95     SELECT * FROM t1 WHERE a='abc' AND b='def'
    97         -} {
    98         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
    99         -}
           96  +} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
           97  +
   100     98   do_eqp_test 1.3 {
   101     99     SELECT * FROM t1 WHERE a='abc' AND a='def'
   102         -} {
   103         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
   104         -}
          100  +} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
          101  +
   105    102   do_eqp_test 1.4 {
   106    103     SELECT * FROM t1,t2 WHERE c=a
   107    104   } {
   108         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} 
   109         -  0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
          105  +  QUERY PLAN
          106  +  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
          107  +  `--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
   110    108   }
   111    109   
   112    110   do_eqp_test 1.5 {
   113    111     SELECT * FROM t1, t2 CROSS JOIN t3 WHERE t2.c = +t1.b AND t3.e=t2.d
   114    112   } {
   115         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} 
   116         -  0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} 
   117         -  0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
          113  +  QUERY PLAN
          114  +  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
          115  +  |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
          116  +  `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
   118    117   }
   119    118   
   120    119   do_eqp_test 1.6 {
   121    120     SELECT * FROM t1, t2, t3 WHERE t2.c = +t1.b AND t3.e = t2.d
   122    121   } {
   123         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:} 
   124         -  0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} 
   125         -  0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
          122  +  QUERY PLAN
          123  +  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
          124  +  |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
          125  +  `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
   126    126   }
   127    127   
   128    128   do_execsql_test 1.7.1 {
   129    129     CREATE TABLE x1(a, b);
   130    130   }
   131    131   do_eqp_test 1.7.2 {
   132    132     SELECT * FROM x1 CROSS JOIN t1, t2, t3 
   133    133       WHERE t1.a = t2.c AND t1.b = t3.e
   134    134   } {
   135         -  0 0 0 {SCAN TABLE x1} 
   136         -  0 1 1 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
   137         -  0 2 2 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} 
   138         -  0 3 3 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
          135  +  QUERY PLAN
          136  +  |--SCAN TABLE x1
          137  +  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
          138  +  |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
          139  +  `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
   139    140   }
   140    141   
   141    142   finish_test

Changes to test/bestindex3.test.

    75     75   
    76     76   do_execsql_test 1.0 {
    77     77     CREATE VIRTUAL TABLE t1 USING tcl("vtab_cmd 0");
    78     78   }
    79     79   
    80     80   do_eqp_test 1.1 {
    81     81     SELECT * FROM t1 WHERE a LIKE 'abc';
    82         -} {
    83         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
    84         -}
           82  +} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
    85     83   
    86     84   do_eqp_test 1.2 {
    87     85     SELECT * FROM t1 WHERE a = 'abc';
    88         -} {
    89         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
    90         -}
           86  +} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
    91     87   
    92     88   do_eqp_test 1.3 {
    93     89     SELECT * FROM t1 WHERE a = 'abc' OR b = 'def';
    94     90   } {
    95         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
    96         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?}
           91  +  QUERY PLAN
           92  +  `--MULTI-INDEX OR
           93  +     |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?
           94  +     `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
    97     95   }
    98     96   
    99     97   do_eqp_test 1.4 {
   100     98     SELECT * FROM t1 WHERE a LIKE 'abc%' OR b = 'def';
   101     99   } {
   102         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
   103         -  0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?}
          100  +  QUERY PLAN
          101  +  `--MULTI-INDEX OR
          102  +     |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?
          103  +     `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
   104    104   }
   105    105   
   106    106   do_execsql_test 1.5 {
   107    107     CREATE TABLE ttt(a, b, c);
   108    108   
   109    109     INSERT INTO ttt VALUES(1, 'two',   'three');
   110    110     INSERT INTO ttt VALUES(2, 'one',   'two');
................................................................................
   143    143       CREATE TABLE t2(x TEXT COLLATE nocase, y TEXT);
   144    144       CREATE INDEX t2x ON t2(x COLLATE nocase);
   145    145       CREATE INDEX t2y ON t2(y);
   146    146     }
   147    147   
   148    148     do_eqp_test 2.2 {
   149    149       SELECT * FROM t2 WHERE x LIKE 'abc%' OR y = 'def'
   150         -  } {
   151         -    0 0 0 {SEARCH TABLE t2 USING INDEX t2x (x>? AND x<?)}
   152         -    0 0 0 {SEARCH TABLE t2 USING INDEX t2y (y=?)}
   153         -  }
          150  +  } [string map {"\n  " \n} {
          151  +    QUERY PLAN
          152  +    `--MULTI-INDEX OR
          153  +       |--SEARCH TABLE t2 USING INDEX t2x (x>? AND x<?)
          154  +       `--SEARCH TABLE t2 USING INDEX t2y (y=?)
          155  +  }]
   154    156   }
   155    157   
   156    158   #-------------------------------------------------------------------------
   157    159   # Test that any PRIMARY KEY within a sqlite3_decl_vtab() CREATE TABLE 
   158    160   # statement is currently ignored.
   159    161   #
   160    162   proc vvv_command {method args} {

Changes to test/bigmmap.test.

    88     88         ORDER BY b, c;
    89     89       " {}
    90     90       
    91     91       do_eqp_test 2.$i.$t.3 "
    92     92         SELECT * FROM t$t AS o WHERE 
    93     93           NOT EXISTS( SELECT * FROM t$t AS i WHERE a=o.a AND +b=o.b AND +c=o.c )
    94     94         ORDER BY b, c;
    95         -    " "
    96         -      0 0 0 {SCAN TABLE t$t AS o USING COVERING INDEX sqlite_autoindex_t${t}_1}
    97         -      0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 1}
    98         -      1 0 0 {SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)}
    99         -    "
           95  +    " [string map {"\n    " "\n"} "
           96  +      QUERY PLAN
           97  +      |--SCAN TABLE t$t AS o USING COVERING INDEX sqlite_autoindex_t${t}_1
           98  +      `--CORRELATED SCALAR SUBQUERY
           99  +         `--SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)
          100  +    "]
   100    101     }
   101    102   }
   102    103   
   103    104   finish_test
   104         -

Changes to test/cost.test.

    20     20     CREATE TABLE t4(c, d, e);
    21     21     CREATE UNIQUE INDEX i3 ON t3(b);
    22     22     CREATE UNIQUE INDEX i4 ON t4(c, d);
    23     23   }
    24     24   do_eqp_test 1.2 {
    25     25     SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d;
    26     26   } {
    27         -  0 0 0 {SCAN TABLE t3 USING COVERING INDEX i3} 
    28         -  0 1 1 {SEARCH TABLE t4 USING INDEX i4 (c=?)}
           27  +  QUERY PLAN
           28  +  |--SCAN TABLE t3 USING COVERING INDEX i3
           29  +  `--SEARCH TABLE t4 USING INDEX i4 (c=?)
    29     30   }
    30     31   
    31     32   
    32     33   do_execsql_test 2.1 {
    33     34     CREATE TABLE t1(a, b);
    34     35     CREATE INDEX i1 ON t1(a);
    35     36   }
    36     37   
    37     38   # It is better to use an index for ORDER BY than sort externally, even 
    38     39   # if the index is a non-covering index.
    39     40   do_eqp_test 2.2 {
    40     41     SELECT * FROM t1 ORDER BY a;
    41         -} {
    42         -  0 0 0 {SCAN TABLE t1 USING INDEX i1}
    43         -}
           42  +} {SCAN TABLE t1 USING INDEX i1}
    44     43   
    45     44   do_execsql_test 3.1 {
    46     45     CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
    47     46     CREATE INDEX t5b ON t5(b);
    48     47     CREATE INDEX t5c ON t5(c);
    49     48     CREATE INDEX t5d ON t5(d);
    50     49     CREATE INDEX t5e ON t5(e);
................................................................................
    53     52   }
    54     53   
    55     54   do_eqp_test 3.2 {
    56     55     SELECT a FROM t5 
    57     56     WHERE b IS NULL OR c IS NULL OR d IS NULL 
    58     57     ORDER BY a;
    59     58   } {
    60         -  0 0 0 {SEARCH TABLE t5 USING INDEX t5b (b=?)} 
    61         -  0 0 0 {SEARCH TABLE t5 USING INDEX t5c (c=?)} 
    62         -  0 0 0 {SEARCH TABLE t5 USING INDEX t5d (d=?)} 
    63         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
           59  +  QUERY PLAN
           60  +  |--MULTI-INDEX OR
           61  +  |  |--SEARCH TABLE t5 USING INDEX t5b (b=?)
           62  +  |  |--SEARCH TABLE t5 USING INDEX t5c (c=?)
           63  +  |  `--SEARCH TABLE t5 USING INDEX t5d (d=?)
           64  +  `--USE TEMP B-TREE FOR ORDER BY
    64     65   }
    65     66   
    66     67   #-------------------------------------------------------------------------
    67     68   # If there is no likelihood() or stat3 data, SQLite assumes that a closed
    68     69   # range scan (e.g. one constrained by "col BETWEEN ? AND ?" constraint)
    69     70   # visits 1/64 of the rows in a table.
    70     71   #
................................................................................
    75     76   do_execsql_test 4.1 {
    76     77     CREATE TABLE t1(a, b);
    77     78     CREATE INDEX i1 ON t1(a);
    78     79     CREATE INDEX i2 ON t1(b);
    79     80   }
    80     81   do_eqp_test 4.2 {
    81     82     SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?;
    82         -} {
    83         -  0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
    84         -}
           83  +} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
           84  +
    85     85   do_eqp_test 4.3 {
    86     86     SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?;
    87         -} {
    88         -  0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b>? AND b<?)}
    89         -}
           87  +} {SEARCH TABLE t1 USING INDEX i2 (b>? AND b<?)}
    90     88   
    91     89   
    92     90   #-------------------------------------------------------------------------
    93     91   #
    94     92   reset_db
    95     93   do_execsql_test 5.1 {
    96     94     CREATE TABLE t2(x, y);
    97     95     CREATE INDEX t2i1 ON t2(x);
    98     96   }
    99     97   
   100     98   do_eqp_test 5.2 {
   101     99     SELECT * FROM t2 ORDER BY x, y;
   102    100   } {
   103         -  0 0 0 {SCAN TABLE t2 USING INDEX t2i1} 
   104         -  0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
          101  +  QUERY PLAN
          102  +  |--SCAN TABLE t2 USING INDEX t2i1
          103  +  `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
   105    104   }
   106    105   
   107    106   do_eqp_test 5.3 {
   108    107     SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid;
   109    108   } {
   110         -  0 0 0 {SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x<?)} 
   111         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          109  +  QUERY PLAN
          110  +  |--SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x<?)
          111  +  `--USE TEMP B-TREE FOR ORDER BY
   112    112   }
   113    113   
   114    114   # where7.test, where8.test:
   115    115   #
   116    116   do_execsql_test 6.1 {
   117    117     CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c);
   118    118     CREATE INDEX t3i1 ON t3(b);
   119    119     CREATE INDEX t3i2 ON t3(c);
   120    120   }
   121    121   
   122    122   do_eqp_test 6.2 {
   123    123     SELECT a FROM t3 WHERE (b BETWEEN 2 AND 4) OR c=100 ORDER BY a
   124    124   } {
   125         -  0 0 0 {SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b<?)} 
   126         -  0 0 0 {SEARCH TABLE t3 USING INDEX t3i2 (c=?)}
   127         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          125  +  QUERY PLAN
          126  +  |--MULTI-INDEX OR
          127  +  |  |--SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b<?)
          128  +  |  `--SEARCH TABLE t3 USING INDEX t3i2 (c=?)
          129  +  `--USE TEMP B-TREE FOR ORDER BY
   128    130   }
   129    131   
   130    132   #-------------------------------------------------------------------------
   131    133   #
   132    134   reset_db
   133    135   do_execsql_test 7.1 {
   134    136     CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
................................................................................
   141    143   }
   142    144   
   143    145   do_eqp_test 7.2 {
   144    146     SELECT a FROM t1
   145    147        WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL)
   146    148     ORDER BY a
   147    149   } {
   148         -  0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)} 
   149         -  0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)} 
   150         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          150  +  QUERY PLAN
          151  +  |--MULTI-INDEX OR
          152  +  |  |--SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)
          153  +  |  `--SEARCH TABLE t1 USING INDEX t1b (b=?)
          154  +  `--USE TEMP B-TREE FOR ORDER BY
   151    155   }
   152    156   
   153    157   do_eqp_test 7.3 {
   154    158     SELECT rowid FROM t1
   155    159     WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL)
   156    160           OR (b NOT NULL AND c IS NULL AND d NOT NULL)
   157    161           OR (b NOT NULL AND c NOT NULL AND d IS NULL)
   158         -} {
   159         -  0 0 0 {SCAN TABLE t1}
   160         -}
          162  +} {SCAN TABLE t1}
   161    163   
   162    164   do_eqp_test 7.4 {
   163    165     SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
   164         -} {
   165         -  0 0 0 {SCAN TABLE t1}
   166         -}
          166  +} {SCAN TABLE t1}
   167    167   
   168    168   #-------------------------------------------------------------------------
   169    169   #
   170    170   reset_db
   171    171   do_execsql_test 8.1 {
   172    172     CREATE TABLE composer(
   173    173       cid INTEGER PRIMARY KEY,
................................................................................
   190    190   do_eqp_test 8.2 {
   191    191     SELECT DISTINCT aname
   192    192       FROM album, composer, track
   193    193      WHERE cname LIKE '%bach%'
   194    194        AND unlikely(composer.cid=track.cid)
   195    195        AND unlikely(album.aid=track.aid);
   196    196   } {
   197         -  0 0 2 {SCAN TABLE track} 
   198         -  0 1 0 {SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)}
   199         -  0 2 1 {SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)}
   200         -  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
          197  +  QUERY PLAN
          198  +  |--SCAN TABLE track
          199  +  |--SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)
          200  +  |--SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)
          201  +  `--USE TEMP B-TREE FOR DISTINCT
   201    202   }
   202    203   
   203    204   #-------------------------------------------------------------------------
   204    205   #
   205    206   do_execsql_test 9.1 {
   206    207     CREATE TABLE t1(
   207    208       a,b,c,d,e, f,g,h,i,j,
................................................................................
   259    260         execsql { INSERT INTO t6 VALUES($i%4, 'xyz', $i%8) }
   260    261       }
   261    262       execsql ANALYZE
   262    263     } {}
   263    264   
   264    265     do_eqp_test 10.3 {
   265    266       SELECT rowid FROM t6 WHERE a=0 AND c=0
   266         -  } {
   267         -    0 0 0 {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
   268         -  }
          267  +  } {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
   269    268   
   270    269     do_eqp_test 10.4 {
   271    270       SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0
   272         -  } {
   273         -    0 0 0 {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
   274         -  }
          271  +  } {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
   275    272   
   276    273     do_eqp_test 10.5 {
   277    274       SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND c=0
   278         -  } {
   279         -    0 0 0 {SEARCH TABLE t6 USING INDEX t6i1 (a=?)}
   280         -  }
          275  +  } {SEARCH TABLE t6 USING INDEX t6i1 (a=?)}
   281    276   
   282    277     do_eqp_test 10.6 {
   283    278       SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND b='xyz' AND c=0
   284         -  } {
   285         -    0 0 0 {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)}
   286         -  }
          279  +  } {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)}
   287    280   }
   288    281   
   289    282   finish_test

Changes to test/coveridxscan.test.

   105    105   
   106    106     CREATE TABLE t2(i INTEGER PRIMARY KEY, $cols);
   107    107     CREATE INDEX i2 ON t2($cols);
   108    108   "
   109    109   
   110    110   do_eqp_test 5.1.1 {
   111    111     SELECT * FROM t1 ORDER BY c1, c2;
   112         -} {
   113         -  0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
   114         -}
          112  +} {SCAN TABLE t1 USING COVERING INDEX i1}
   115    113   
   116    114   do_eqp_test 5.1.2 {
   117    115     SELECT * FROM t2 ORDER BY c1, c2;
   118         -} {
   119         -  0 0 0 {SCAN TABLE t2 USING COVERING INDEX i2}
   120         -}
   121         -
          116  +} {SCAN TABLE t2 USING COVERING INDEX i2}
   122    117   
   123    118   
   124    119   finish_test

Changes to test/e_createtable.test.

   652    652     1    "CREATE TABLE x1 AS SELECT * FROM t1"                     {a b c}
   653    653     2    "CREATE TABLE x1 AS SELECT c, b, a FROM t1"               {c b a}
   654    654     3    "CREATE TABLE x1 AS SELECT * FROM t1, t2"                 {a b c d e f}
   655    655     4    "CREATE TABLE x1 AS SELECT count(*) FROM t1"              {count(*)}
   656    656     5    "CREATE TABLE x1 AS SELECT count(a) AS a, max(b) FROM t1" {a max(b)}
   657    657   }
   658    658   
   659         -# EVIDENCE-OF: R-37111-22855 The declared type of each column is
          659  +# EVIDENCE-OF: R-55407-45319 The declared type of each column is
   660    660   # determined by the expression affinity of the corresponding expression
   661    661   # in the result set of the SELECT statement, as follows: Expression
   662    662   # Affinity Column Declared Type TEXT "TEXT" NUMERIC "NUM" INTEGER "INT"
   663         -# REAL "REAL" NONE "" (empty string)
          663  +# REAL "REAL" BLOB (a.k.a "NONE") "" (empty string)
   664    664   #
   665    665   do_createtable_tests 2.2 -tclquery {
   666    666     table_column_decltypes x1
   667    667   } -repair {
   668    668     catchsql { DROP TABLE x1 }
   669    669   } {
   670    670     1    "CREATE TABLE x1 AS SELECT a FROM t1"     {""}
................................................................................
  1381   1381   #
  1382   1382   do_execsql_test 4.10.0 {
  1383   1383     CREATE TABLE t1(a, b PRIMARY KEY);
  1384   1384     CREATE TABLE t2(a, b, c, UNIQUE(b, c));
  1385   1385   }
  1386   1386   do_createtable_tests 4.10 {
  1387   1387     1    "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 5" 
  1388         -       {0 0 0 {SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (b=?)}}
         1388  +       {/*SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (b=?)*/}
  1389   1389   
  1390   1390     2    "EXPLAIN QUERY PLAN SELECT * FROM t2 ORDER BY b, c"
  1391         -       {0 0 0 {SCAN TABLE t2 USING INDEX sqlite_autoindex_t2_1}}
         1391  +       {/*SCAN TABLE t2 USING INDEX sqlite_autoindex_t2_1*/}
  1392   1392   
  1393   1393     3    "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE b=10 AND c>10"
  1394         -       {0 0 0 {SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)}}
         1394  +       {/*SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)*/}
  1395   1395   }
  1396   1396   
  1397   1397   # EVIDENCE-OF: R-45493-35653 A CHECK constraint may be attached to a
  1398   1398   # column definition or specified as a table constraint. In practice it
  1399   1399   # makes no difference.
  1400   1400   #
  1401   1401   #   All the tests that deal with CHECK constraints below (4.11.* and 

Changes to test/eqp.test.

    39     39     CREATE TABLE t2(a INT, b INT, ex TEXT);
    40     40     CREATE TABLE t3(a INT, b INT, ex TEXT);
    41     41   }
    42     42   
    43     43   do_eqp_test 1.2 {
    44     44     SELECT * FROM t2, t1 WHERE t1.a=1 OR t1.b=2;
    45     45   } {
    46         -  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}
           46  +  QUERY PLAN
           47  +  |--MULTI-INDEX OR
           48  +  |  |--SEARCH TABLE t1 USING INDEX i1 (a=?)
           49  +  |  `--SEARCH TABLE t1 USING INDEX i2 (b=?)
           50  +  `--SCAN TABLE t2
    49     51   }
    50     52   do_eqp_test 1.3 {
    51     53     SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=1 OR t1.b=2;
    52     54   } {
    53         -  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=?)} 
           55  +  QUERY PLAN
           56  +  |--SCAN TABLE t2
           57  +  `--MULTI-INDEX OR
           58  +     |--SEARCH TABLE t1 USING INDEX i1 (a=?)
           59  +     `--SEARCH TABLE t1 USING INDEX i2 (b=?)
    56     60   }
    57     61   do_eqp_test 1.3 {
    58     62     SELECT a FROM t1 ORDER BY a
    59     63   } {
    60         -  0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
           64  +  QUERY PLAN
           65  +  `--SCAN TABLE t1 USING COVERING INDEX i1
    61     66   }
    62     67   do_eqp_test 1.4 {
    63     68     SELECT a FROM t1 ORDER BY +a
    64     69   } {
    65         -  0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
    66         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
           70  +  QUERY PLAN
           71  +  |--SCAN TABLE t1 USING COVERING INDEX i1
           72  +  `--USE TEMP B-TREE FOR ORDER BY
    67     73   }
    68     74   do_eqp_test 1.5 {
    69     75     SELECT a FROM t1 WHERE a=4
    70     76   } {
    71         -  0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
           77  +  QUERY PLAN
           78  +  `--SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)
    72     79   }
    73     80   do_eqp_test 1.6 {
    74     81     SELECT DISTINCT count(*) FROM t3 GROUP BY a;
    75     82   } {
    76         -  0 0 0 {SCAN TABLE t3}
    77         -  0 0 0 {USE TEMP B-TREE FOR GROUP BY}
    78         -  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
           83  +  QUERY PLAN
           84  +  |--SCAN TABLE t3
           85  +  |--USE TEMP B-TREE FOR GROUP BY
           86  +  `--USE TEMP B-TREE FOR DISTINCT
    79     87   }
    80     88   
    81     89   do_eqp_test 1.7 {
    82     90     SELECT * FROM t3 JOIN (SELECT 1)
    83     91   } {
    84         -  0 0 1 {SCAN SUBQUERY 1}
    85         -  0 1 0 {SCAN TABLE t3}
           92  +  QUERY PLAN
           93  +  |--MATERIALIZE xxxxxx
           94  +  |  `--SCAN CONSTANT ROW
           95  +  |--SCAN SUBQUERY xxxxxx
           96  +  `--SCAN TABLE t3
    86     97   }
    87     98   do_eqp_test 1.8 {
    88     99     SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
    89    100   } {
    90         -  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
    91         -  0 0 1 {SCAN SUBQUERY 1}
    92         -  0 1 0 {SCAN TABLE t3}
          101  +  QUERY PLAN
          102  +  |--MATERIALIZE xxxxxx
          103  +  |  `--COMPOUND QUERY
          104  +  |     |--LEFT-MOST SUBQUERY
          105  +  |     |  `--SCAN CONSTANT ROW
          106  +  |     `--UNION USING TEMP B-TREE
          107  +  |        `--SCAN CONSTANT ROW
          108  +  |--SCAN SUBQUERY xxxxxx
          109  +  `--SCAN TABLE t3
    93    110   }
    94    111   do_eqp_test 1.9 {
    95    112     SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
    96    113   } {
    97         -  3 0 0 {SCAN TABLE t3}
    98         -  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (EXCEPT)}
    99         -  0 0 1 {SCAN SUBQUERY 1}
   100         -  0 1 0 {SCAN TABLE t3}
          114  +  QUERY PLAN
          115  +  |--MATERIALIZE xxxxxx
          116  +  |  `--COMPOUND QUERY
          117  +  |     |--LEFT-MOST SUBQUERY
          118  +  |     |  `--SCAN CONSTANT ROW
          119  +  |     `--EXCEPT USING TEMP B-TREE
          120  +  |        `--SCAN TABLE t3
          121  +  |--SCAN SUBQUERY xxxxxx
          122  +  `--SCAN TABLE t3
   101    123   }
   102    124   do_eqp_test 1.10 {
   103    125     SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
   104    126   } {
   105         -  3 0 0 {SCAN TABLE t3}
   106         -  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (INTERSECT)}
   107         -  0 0 1 {SCAN SUBQUERY 1}
   108         -  0 1 0 {SCAN TABLE t3}
          127  +  QUERY PLAN
          128  +  |--MATERIALIZE xxxxxx
          129  +  |  `--COMPOUND QUERY
          130  +  |     |--LEFT-MOST SUBQUERY
          131  +  |     |  `--SCAN CONSTANT ROW
          132  +  |     `--INTERSECT USING TEMP B-TREE
          133  +  |        `--SCAN TABLE t3
          134  +  |--SCAN SUBQUERY xxxxxx
          135  +  `--SCAN TABLE t3
   109    136   }
   110    137   
   111    138   do_eqp_test 1.11 {
   112    139     SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17)
   113    140   } {
   114         -  3 0 0 {SCAN TABLE t3}
   115         -  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)}
   116         -  0 0 1 {SCAN SUBQUERY 1}
   117         -  0 1 0 {SCAN TABLE t3}
          141  +  QUERY PLAN
          142  +  |--MATERIALIZE xxxxxx
          143  +  |  `--COMPOUND QUERY
          144  +  |     |--LEFT-MOST SUBQUERY
          145  +  |     |  `--SCAN CONSTANT ROW
          146  +  |     `--UNION ALL
          147  +  |        `--SCAN TABLE t3
          148  +  |--SCAN SUBQUERY xxxxxx
          149  +  `--SCAN TABLE t3
   118    150   }
   119    151   
   120    152   #-------------------------------------------------------------------------
   121    153   # Test cases eqp-2.* - tests for single select statements.
   122    154   #
   123    155   drop_all_tables
   124    156   do_execsql_test 2.1 {
................................................................................
   125    157     CREATE TABLE t1(x INT, y INT, ex TEXT);
   126    158   
   127    159     CREATE TABLE t2(x INT, y INT, ex TEXT);
   128    160     CREATE INDEX t2i1 ON t2(x);
   129    161   }
   130    162   
   131    163   det 2.2.1 "SELECT DISTINCT min(x), max(x) FROM t1 GROUP BY x ORDER BY 1" {
   132         -  0 0 0 {SCAN TABLE t1}
   133         -  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}
          164  +  QUERY PLAN
          165  +  |--SCAN TABLE t1
          166  +  |--USE TEMP B-TREE FOR GROUP BY
          167  +  |--USE TEMP B-TREE FOR DISTINCT
          168  +  `--USE TEMP B-TREE FOR ORDER BY
   136    169   }
   137    170   det 2.2.2 "SELECT DISTINCT min(x), max(x) FROM t2 GROUP BY x ORDER BY 1" {
   138         -  0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
   139         -  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
   140         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          171  +  QUERY PLAN
          172  +  |--SCAN TABLE t2 USING COVERING INDEX t2i1
          173  +  |--USE TEMP B-TREE FOR DISTINCT
          174  +  `--USE TEMP B-TREE FOR ORDER BY
   141    175   }
   142    176   det 2.2.3 "SELECT DISTINCT * FROM t1" {
   143         -  0 0 0 {SCAN TABLE t1}
   144         -  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
          177  +  QUERY PLAN
          178  +  |--SCAN TABLE t1
          179  +  `--USE TEMP B-TREE FOR DISTINCT
   145    180   }
   146    181   det 2.2.4 "SELECT DISTINCT * FROM t1, t2" {
   147         -  0 0 0 {SCAN TABLE t1}
   148         -  0 1 1 {SCAN TABLE t2}
   149         -  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
          182  +  QUERY PLAN
          183  +  |--SCAN TABLE t1
          184  +  |--SCAN TABLE t2
          185  +  `--USE TEMP B-TREE FOR DISTINCT
   150    186   }
   151    187   det 2.2.5 "SELECT DISTINCT * FROM t1, t2 ORDER BY t1.x" {
   152         -  0 0 0 {SCAN TABLE t1}
   153         -  0 1 1 {SCAN TABLE t2}
   154         -  0 0 0 {USE TEMP B-TREE FOR DISTINCT}
   155         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          188  +  QUERY PLAN
          189  +  |--SCAN TABLE t1
          190  +  |--SCAN TABLE t2
          191  +  |--USE TEMP B-TREE FOR DISTINCT
          192  +  `--USE TEMP B-TREE FOR ORDER BY
   156    193   }
   157    194   det 2.2.6 "SELECT DISTINCT t2.x FROM t1, t2 ORDER BY t2.x" {
   158         -  0 0 1 {SCAN TABLE t2 USING COVERING INDEX t2i1}
   159         -  0 1 0 {SCAN TABLE t1}
          195  +  QUERY PLAN
          196  +  |--SCAN TABLE t2 USING COVERING INDEX t2i1
          197  +  `--SCAN TABLE t1
   160    198   }
   161    199   
   162    200   det 2.3.1 "SELECT max(x) FROM t2" {
   163         -  0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1}
          201  +  QUERY PLAN
          202  +  `--SEARCH TABLE t2 USING COVERING INDEX t2i1
   164    203   }
   165    204   det 2.3.2 "SELECT min(x) FROM t2" {
   166         -  0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2i1}
          205  +  QUERY PLAN
          206  +  `--SEARCH TABLE t2 USING COVERING INDEX t2i1
   167    207   }
   168    208   det 2.3.3 "SELECT min(x), max(x) FROM t2" {
   169         -  0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
          209  +  QUERY PLAN
          210  +  `--SCAN TABLE t2 USING COVERING INDEX t2i1
   170    211   }
   171    212   
   172    213   det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {
   173         -  0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)}
          214  +  QUERY PLAN
          215  +  `--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
   174    216   }
   175    217   
   176    218   
   177    219   
   178    220   #-------------------------------------------------------------------------
   179    221   # Test cases eqp-3.* - tests for select statements that use sub-selects.
   180    222   #
   181    223   do_eqp_test 3.1.1 {
   182    224     SELECT (SELECT x FROM t1 AS sub) FROM t1;
   183    225   } {
   184         -  0 0 0 {SCAN TABLE t1}
   185         -  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
   186         -  1 0 0 {SCAN TABLE t1 AS sub}
          226  +  QUERY PLAN
          227  +  |--SCAN TABLE t1
          228  +  `--SCALAR SUBQUERY
          229  +     `--SCAN TABLE t1 AS sub
   187    230   }
   188    231   do_eqp_test 3.1.2 {
   189    232     SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
   190    233   } {
   191         -  0 0 0 {SCAN TABLE t1}
   192         -  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
   193         -  1 0 0 {SCAN TABLE t1 AS sub}
          234  +  QUERY PLAN
          235  +  |--SCAN TABLE t1
          236  +  `--SCALAR SUBQUERY
          237  +     `--SCAN TABLE t1 AS sub
   194    238   }
   195    239   do_eqp_test 3.1.3 {
   196    240     SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y);
   197    241   } {
   198         -  0 0 0 {SCAN TABLE t1}
   199         -  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
   200         -  1 0 0 {SCAN TABLE t1 AS sub}
   201         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
          242  +  QUERY PLAN
          243  +  |--SCAN TABLE t1
          244  +  `--SCALAR SUBQUERY
          245  +     |--SCAN TABLE t1 AS sub
          246  +     `--USE TEMP B-TREE FOR ORDER BY
   202    247   }
   203    248   do_eqp_test 3.1.4 {
   204    249     SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x);
   205    250   } {
   206         -  0 0 0 {SCAN TABLE t1}
   207         -  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
   208         -  1 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1}
          251  +  QUERY PLAN
          252  +  |--SCAN TABLE t1
          253  +  `--SCALAR SUBQUERY
          254  +     `--SCAN TABLE t2 USING COVERING INDEX t2i1
   209    255   }
   210    256   
   211    257   det 3.2.1 {
   212    258     SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY y LIMIT 5
   213    259   } {
   214         -  1 0 0 {SCAN TABLE t1} 
   215         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY} 
   216         -  0 0 0 {SCAN SUBQUERY 1} 
   217         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          260  +  QUERY PLAN
          261  +  |--CO-ROUTINE xxxxxx
          262  +  |  |--SCAN TABLE t1
          263  +  |  `--USE TEMP B-TREE FOR ORDER BY
          264  +  |--SCAN SUBQUERY xxxxxx
          265  +  `--USE TEMP B-TREE FOR ORDER BY
   218    266   }
   219    267   det 3.2.2 {
   220    268     SELECT * FROM 
   221    269       (SELECT * FROM t1 ORDER BY x LIMIT 10) AS x1,
   222    270       (SELECT * FROM t2 ORDER BY x LIMIT 10) AS x2
   223    271     ORDER BY x2.y LIMIT 5
   224    272   } {
   225         -  1 0 0 {SCAN TABLE t1} 
   226         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY} 
   227         -  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} 
   230         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          273  +  QUERY PLAN
          274  +  |--MATERIALIZE xxxxxx
          275  +  |  |--SCAN TABLE t1
          276  +  |  `--USE TEMP B-TREE FOR ORDER BY
          277  +  |--MATERIALIZE xxxxxx
          278  +  |  `--SCAN TABLE t2 USING INDEX t2i1
          279  +  |--SCAN SUBQUERY xxxxxx AS x1
          280  +  |--SCAN SUBQUERY xxxxxx AS x2
          281  +  `--USE TEMP B-TREE FOR ORDER BY
   231    282   }
   232    283   
   233    284   det 3.3.1 {
   234    285     SELECT * FROM t1 WHERE y IN (SELECT y FROM t2)
   235    286   } {
   236         -  0 0 0 {SCAN TABLE t1} 
   237         -  0 0 0 {EXECUTE LIST SUBQUERY 1} 
   238         -  1 0 0 {SCAN TABLE t2}
          287  +  QUERY PLAN
          288  +  |--SCAN TABLE t1
          289  +  `--LIST SUBQUERY
          290  +     `--SCAN TABLE t2
   239    291   }
   240    292   det 3.3.2 {
   241    293     SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x)
   242    294   } {
   243         -  0 0 0 {SCAN TABLE t1} 
   244         -  0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1} 
   245         -  1 0 0 {SCAN TABLE t2}
          295  +  QUERY PLAN
          296  +  |--SCAN TABLE t1
          297  +  `--CORRELATED LIST SUBQUERY
          298  +     `--SCAN TABLE t2
   246    299   }
   247    300   det 3.3.3 {
   248    301     SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x)
   249    302   } {
   250         -  0 0 0 {SCAN TABLE t1} 
   251         -  0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 1} 
   252         -  1 0 0 {SCAN TABLE t2}
          303  +  QUERY PLAN
          304  +  |--SCAN TABLE t1
          305  +  `--CORRELATED SCALAR SUBQUERY
          306  +     `--SCAN TABLE t2
   253    307   }
   254    308   
   255    309   #-------------------------------------------------------------------------
   256    310   # Test cases eqp-4.* - tests for composite select statements.
   257    311   #
   258    312   do_eqp_test 4.1.1 {
   259    313     SELECT * FROM t1 UNION ALL SELECT * FROM t2
   260    314   } {
   261         -  1 0 0 {SCAN TABLE t1} 
   262         -  2 0 0 {SCAN TABLE t2} 
   263         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)} 
          315  +  QUERY PLAN
          316  +  `--COMPOUND QUERY
          317  +     |--LEFT-MOST SUBQUERY
          318  +     |  `--SCAN TABLE t1
          319  +     `--UNION ALL
          320  +        `--SCAN TABLE t2
   264    321   }
   265    322   do_eqp_test 4.1.2 {
   266    323     SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 2
   267    324   } {
   268         -  1 0 0 {SCAN TABLE t1} 
   269         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
   270         -  2 0 0 {SCAN TABLE t2} 
   271         -  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
   272         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)} 
          325  +  QUERY PLAN
          326  +  `--MERGE (UNION ALL)
          327  +     |--LEFT
          328  +     |  |--SCAN TABLE t1
          329  +     |  `--USE TEMP B-TREE FOR ORDER BY
          330  +     `--RIGHT
          331  +        |--SCAN TABLE t2
          332  +        `--USE TEMP B-TREE FOR ORDER BY
   273    333   }
   274    334   do_eqp_test 4.1.3 {
   275    335     SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 2
   276    336   } {
   277         -  1 0 0 {SCAN TABLE t1} 
   278         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
   279         -  2 0 0 {SCAN TABLE t2} 
   280         -  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
   281         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)} 
          337  +  QUERY PLAN
          338  +  `--MERGE (UNION)
          339  +     |--LEFT
          340  +     |  |--SCAN TABLE t1
          341  +     |  `--USE TEMP B-TREE FOR ORDER BY
          342  +     `--RIGHT
          343  +        |--SCAN TABLE t2
          344  +        `--USE TEMP B-TREE FOR ORDER BY
   282    345   }
   283    346   do_eqp_test 4.1.4 {
   284    347     SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 2
   285    348   } {
   286         -  1 0 0 {SCAN TABLE t1} 
   287         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
   288         -  2 0 0 {SCAN TABLE t2} 
   289         -  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
   290         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)} 
          349  +  QUERY PLAN
          350  +  `--MERGE (INTERSECT)
          351  +     |--LEFT
          352  +     |  |--SCAN TABLE t1
          353  +     |  `--USE TEMP B-TREE FOR ORDER BY
          354  +     `--RIGHT
          355  +        |--SCAN TABLE t2
          356  +        `--USE TEMP B-TREE FOR ORDER BY
   291    357   }
   292    358   do_eqp_test 4.1.5 {
   293    359     SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 2
   294    360   } {
   295         -  1 0 0 {SCAN TABLE t1} 
   296         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
   297         -  2 0 0 {SCAN TABLE t2} 
   298         -  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
   299         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)} 
          361  +  QUERY PLAN
          362  +  `--MERGE (EXCEPT)
          363  +     |--LEFT
          364  +     |  |--SCAN TABLE t1
          365  +     |  `--USE TEMP B-TREE FOR ORDER BY
          366  +     `--RIGHT
          367  +        |--SCAN TABLE t2
          368  +        `--USE TEMP B-TREE FOR ORDER BY
   300    369   }
   301    370   
   302    371   do_eqp_test 4.2.2 {
   303    372     SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 1
   304    373   } {
   305         -  1 0 0 {SCAN TABLE t1} 
   306         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
   307         -  2 0 0 {SCAN TABLE t2 USING INDEX t2i1} 
   308         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)} 
          374  +  QUERY PLAN
          375  +  `--MERGE (UNION ALL)
          376  +     |--LEFT
          377  +     |  |--SCAN TABLE t1
          378  +     |  `--USE TEMP B-TREE FOR ORDER BY
          379  +     `--RIGHT
          380  +        `--SCAN TABLE t2 USING INDEX t2i1
   309    381   }
   310    382   do_eqp_test 4.2.3 {
   311    383     SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 1
   312    384   } {
   313         -  1 0 0 {SCAN TABLE t1} 
   314         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
   315         -  2 0 0 {SCAN TABLE t2 USING INDEX t2i1} 
   316         -  2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
   317         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)} 
          385  +  QUERY PLAN
          386  +  `--MERGE (UNION)
          387  +     |--LEFT
          388  +     |  |--SCAN TABLE t1
          389  +     |  `--USE TEMP B-TREE FOR ORDER BY
          390  +     `--RIGHT
          391  +        |--SCAN TABLE t2 USING INDEX t2i1
          392  +        `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
   318    393   }
   319    394   do_eqp_test 4.2.4 {
   320    395     SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 1
   321    396   } {
   322         -  1 0 0 {SCAN TABLE t1} 
   323         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
   324         -  2 0 0 {SCAN TABLE t2 USING INDEX t2i1} 
   325         -  2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
   326         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)} 
          397  +  QUERY PLAN
          398  +  `--MERGE (INTERSECT)
          399  +     |--LEFT
          400  +     |  |--SCAN TABLE t1
          401  +     |  `--USE TEMP B-TREE FOR ORDER BY
          402  +     `--RIGHT
          403  +        |--SCAN TABLE t2 USING INDEX t2i1
          404  +        `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
   327    405   }
   328    406   do_eqp_test 4.2.5 {
   329    407     SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 1
   330    408   } {
   331         -  1 0 0 {SCAN TABLE t1} 
   332         -  1 0 0 {USE TEMP B-TREE FOR ORDER BY}
   333         -  2 0 0 {SCAN TABLE t2 USING INDEX t2i1} 
   334         -  2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
   335         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)} 
          409  +  QUERY PLAN
          410  +  `--MERGE (EXCEPT)
          411  +     |--LEFT
          412  +     |  |--SCAN TABLE t1
          413  +     |  `--USE TEMP B-TREE FOR ORDER BY
          414  +     `--RIGHT
          415  +        |--SCAN TABLE t2 USING INDEX t2i1
          416  +        `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
   336    417   }
   337    418   
   338    419   do_eqp_test 4.3.1 {
   339    420     SELECT x FROM t1 UNION SELECT x FROM t2
   340    421   } {
   341         -  1 0 0 {SCAN TABLE t1} 
   342         -  2 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1} 
   343         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)} 
          422  +  QUERY PLAN
          423  +  `--COMPOUND QUERY
          424  +     |--LEFT-MOST SUBQUERY
          425  +     |  `--SCAN TABLE t1
          426  +     `--UNION USING TEMP B-TREE
          427  +        `--SCAN TABLE t2 USING COVERING INDEX t2i1
   344    428   }
   345    429   
   346    430   do_eqp_test 4.3.2 {
   347    431     SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1
   348    432   } {
   349         -  2 0 0 {SCAN TABLE t1} 
   350         -  3 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1} 
   351         -  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
   352         -  4 0 0 {SCAN TABLE t1} 
   353         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 4 USING TEMP B-TREE (UNION)}
          433  +  QUERY PLAN
          434  +  `--COMPOUND QUERY
          435  +     |--LEFT-MOST SUBQUERY
          436  +     |  `--SCAN TABLE t1
          437  +     |--UNION USING TEMP B-TREE
          438  +     |  `--SCAN TABLE t2 USING COVERING INDEX t2i1
          439  +     `--UNION USING TEMP B-TREE
          440  +        `--SCAN TABLE t1
   354    441   }
   355    442   do_eqp_test 4.3.3 {
   356    443     SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER BY 1
   357    444   } {
   358         -  2 0 0 {SCAN TABLE t1} 
   359         -  2 0 0 {USE TEMP B-TREE FOR ORDER BY} 
   360         -  3 0 0 {SCAN TABLE t2 USING COVERING INDEX t2i1} 
   361         -  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION)} 
   362         -  4 0 0 {SCAN TABLE t1} 
   363         -  4 0 0 {USE TEMP B-TREE FOR ORDER BY} 
   364         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 4 (UNION)}
          445  +  QUERY PLAN
          446  +  `--MERGE (UNION)
          447  +     |--LEFT
          448  +     |  `--MERGE (UNION)
          449  +     |     |--LEFT
          450  +     |     |  |--SCAN TABLE t1
          451  +     |     |  `--USE TEMP B-TREE FOR ORDER BY
          452  +     |     `--RIGHT
          453  +     |        `--SCAN TABLE t2 USING COVERING INDEX t2i1
          454  +     `--RIGHT
          455  +        |--SCAN TABLE t1
          456  +        `--USE TEMP B-TREE FOR ORDER BY
   365    457   }
   366    458   
          459  +if 0 {
   367    460   #-------------------------------------------------------------------------
   368    461   # This next block of tests verifies that the examples on the 
   369    462   # lang_explain.html page are correct.
   370    463   #
   371    464   drop_all_tables
   372    465   
   373         -# EVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b
          466  +# XVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b
   374    467   # FROM t1 WHERE a=1;
   375    468   # 0|0|0|SCAN TABLE t1
   376    469   #
   377    470   do_execsql_test 5.1.0 { CREATE TABLE t1(a INT, b INT, ex TEXT) }
   378    471   det 5.1.1 "SELECT a, b FROM t1 WHERE a=1" {
   379    472     0 0 0 {SCAN TABLE t1}
   380    473   }
   381    474   
   382         -# EVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a);
          475  +# XVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a);
   383    476   # sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
   384    477   # 0|0|0|SEARCH TABLE t1 USING INDEX i1
   385    478   #
   386    479   do_execsql_test 5.2.0 { CREATE INDEX i1 ON t1(a) }
   387    480   det 5.2.1 "SELECT a, b FROM t1 WHERE a=1" {
   388    481     0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
   389    482   }
   390    483   
   391         -# EVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b);
          484  +# XVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b);
   392    485   # sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
   393    486   # 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
   394    487   #
   395    488   do_execsql_test 5.3.0 { CREATE INDEX i2 ON t1(a, b) }
   396    489   det 5.3.1 "SELECT a, b FROM t1 WHERE a=1" {
   397    490     0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
   398    491   }
   399    492   
   400         -# EVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN
          493  +# XVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN
   401    494   # SELECT t1.*, t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2;
   402    495   # 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
   403    496   # 0|1|1|SCAN TABLE t2
   404    497   #
   405    498   do_execsql_test 5.4.0 {CREATE TABLE t2(c INT, d INT, ex TEXT)}
   406    499   det 5.4.1 "SELECT t1.a, t2.c FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {
   407    500     0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
   408    501     0 1 1 {SCAN TABLE t2}
   409    502   }
   410    503   
   411         -# EVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN
          504  +# XVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN
   412    505   # SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2;
   413    506   # 0|0|1|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
   414    507   # 0|1|0|SCAN TABLE t2
   415    508   #
   416    509   det 5.5 "SELECT t1.a, t2.c FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {
   417    510     0 0 1 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
   418    511     0 1 0 {SCAN TABLE t2}
   419    512   }
   420    513   
   421         -# EVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b);
          514  +# XVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b);
   422    515   # sqlite> EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=1 OR b=2;
   423    516   # 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
   424    517   # 0|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
   425    518   #
   426    519   do_execsql_test 5.5.0 {CREATE INDEX i3 ON t1(b)}
   427    520   det 5.6.1 "SELECT a, b FROM t1 WHERE a=1 OR b=2" {
   428    521     0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
   429    522     0 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
   430    523   }
   431    524   
   432         -# EVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN
          525  +# XVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN
   433    526   # SELECT c, d FROM t2 ORDER BY c;
   434    527   # 0|0|0|SCAN TABLE t2
   435    528   # 0|0|0|USE TEMP B-TREE FOR ORDER BY
   436    529   #
   437    530   det 5.7 "SELECT c, d FROM t2 ORDER BY c" {
   438    531     0 0 0 {SCAN TABLE t2}
   439    532     0 0 0 {USE TEMP B-TREE FOR ORDER BY}
   440    533   }
   441    534   
   442         -# EVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c);
          535  +# XVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c);
   443    536   # sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c;
   444    537   # 0|0|0|SCAN TABLE t2 USING INDEX i4
   445    538   #
   446    539   do_execsql_test 5.8.0 {CREATE INDEX i4 ON t2(c)}
   447    540   det 5.8.1 "SELECT c, d FROM t2 ORDER BY c" {
   448    541     0 0 0 {SCAN TABLE t2 USING INDEX i4}
   449    542   }
   450    543   
   451         -# EVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT
          544  +# XVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT
   452    545   # (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2;
   453    546   # 0|0|0|SCAN TABLE t2
   454    547   # 0|0|0|EXECUTE SCALAR SUBQUERY 1
   455    548   # 1|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
   456    549   # 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2
   457    550   # 2|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
   458    551   #
................................................................................
   462    555     0 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
   463    556     0 0 0 {EXECUTE SCALAR SUBQUERY 1}
   464    557     1 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
   465    558     0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}
   466    559     2 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
   467    560   }
   468    561   
   469         -# EVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN
          562  +# XVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN
   470    563   # SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x;
   471    564   # 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
   472    565   # 0|0|0|SCAN SUBQUERY 1
   473    566   # 0|0|0|USE TEMP B-TREE FOR GROUP BY
   474    567   #
   475    568   det 5.10 {
   476    569     SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x
   477    570   } {
   478    571     1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
   479    572     0 0 0 {SCAN SUBQUERY 1}
   480    573     0 0 0 {USE TEMP B-TREE FOR GROUP BY}
   481    574   }
   482    575   
   483         -# EVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN
          576  +# XVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN
   484    577   # SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1;
   485    578   # 0|0|0|SEARCH TABLE t2 USING INDEX i4 (c=?)
   486    579   # 0|1|1|SCAN TABLE t1
   487    580   #
   488    581   det 5.11 "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1" {
   489    582     0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
   490    583     0 1 1 {SCAN TABLE t1 USING COVERING INDEX i2}
   491    584   }
   492    585   
   493         -# EVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN
          586  +# XVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN
   494    587   # SELECT a FROM t1 UNION SELECT c FROM t2;
   495    588   # 1|0|0|SCAN TABLE t1
   496    589   # 2|0|0|SCAN TABLE t2
   497    590   # 0|0|0|COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)
   498    591   #
   499    592   det 5.12 "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2" {
   500    593     1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
   501    594     2 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
   502    595     0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
   503    596   }
   504    597   
   505         -# EVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN
          598  +# XVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN
   506    599   # SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1;
   507    600   # 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
   508    601   # 2|0|0|SCAN TABLE t2 2|0|0|USE TEMP B-TREE FOR ORDER BY
   509    602   # 0|0|0|COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
   510    603   #
   511    604   det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {
   512    605     1 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
   513    606     2 0 0 {SCAN TABLE t2}
   514    607     2 0 0 {USE TEMP B-TREE FOR ORDER BY}
   515    608     0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
   516    609   }
   517         -
   518    610   
   519    611   if {![nonzero_reserved_bytes]} {
   520    612     #-------------------------------------------------------------------------
   521    613     # The following tests - eqp-6.* - test that the example C code on 
   522    614     # documentation page eqp.html works. The C code is duplicated in test1.c
   523    615     # and wrapped in Tcl command [print_explain_query_plan] 
   524    616     #
................................................................................
   553    645     } [string trimleft {
   554    646   1 0 0 SCAN TABLE t1 USING COVERING INDEX i2
   555    647   2 0 0 SCAN TABLE t2
   556    648   2 0 0 USE TEMP B-TREE FOR ORDER BY
   557    649   0 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
   558    650   }]
   559    651   }
          652  +}
   560    653   
   561    654   #-------------------------------------------------------------------------
   562    655   # The following tests - eqp-7.* - test that queries that use the OP_Count
   563    656   # optimization return something sensible with EQP.
   564    657   #
   565    658   drop_all_tables
   566    659   
................................................................................
   567    660   do_execsql_test 7.0 {
   568    661     CREATE TABLE t1(a INT, b INT, ex CHAR(100));
   569    662     CREATE TABLE t2(a INT, b INT, ex CHAR(100));
   570    663     CREATE INDEX i1 ON t2(a);
   571    664   }
   572    665   
   573    666   det 7.1 "SELECT count(*) FROM t1" {
   574         -  0 0 0 {SCAN TABLE t1}
          667  +  QUERY PLAN
          668  +  `--SCAN TABLE t1
   575    669   }
   576    670   
   577    671   det 7.2 "SELECT count(*) FROM t2" {
   578         -  0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1}
          672  +  QUERY PLAN
          673  +  `--SCAN TABLE t2 USING COVERING INDEX i1
   579    674   }
   580    675   
   581    676   do_execsql_test 7.3 {
   582    677     INSERT INTO t1(a,b) VALUES(1, 2);
   583    678     INSERT INTO t1(a,b) VALUES(3, 4);
   584    679   
   585    680     INSERT INTO t2(a,b) VALUES(1, 2);
................................................................................
   589    684     ANALYZE;
   590    685   }
   591    686   
   592    687   db close
   593    688   sqlite3 db test.db
   594    689   
   595    690   det 7.4 "SELECT count(*) FROM t1" {
   596         -  0 0 0 {SCAN TABLE t1}
          691  +  QUERY PLAN
          692  +  `--SCAN TABLE t1
   597    693   }
   598    694   
   599    695   det 7.5 "SELECT count(*) FROM t2" {
   600         -  0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1}
          696  +  QUERY PLAN
          697  +  `--SCAN TABLE t2 USING COVERING INDEX i1
   601    698   }
   602    699   
   603    700   #-------------------------------------------------------------------------
   604    701   # The following tests - eqp-8.* - test that queries that use the OP_Count
   605    702   # optimization return something sensible with EQP.
   606    703   #
   607    704   drop_all_tables
................................................................................
   608    705   
   609    706   do_execsql_test 8.0 {
   610    707     CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
   611    708     CREATE TABLE t2(a, b, c);
   612    709   }
   613    710   
   614    711   det 8.1.1 "SELECT * FROM t2" {
   615         -  0 0 0 {SCAN TABLE t2}
          712  +  QUERY PLAN
          713  +  `--SCAN TABLE t2
   616    714   }
   617    715   
   618    716   det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
   619         -  0 0 0 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
          717  +  QUERY PLAN
          718  +  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
   620    719   }
   621    720   
   622    721   det 8.1.3 "SELECT count(*) FROM t2" {
   623         -  0 0 0 {SCAN TABLE t2}
          722  +  QUERY PLAN
          723  +  `--SCAN TABLE t2
   624    724   }
   625    725   
   626    726   det 8.2.1 "SELECT * FROM t1" {
   627         -  0 0 0 {SCAN TABLE t1}
          727  +  QUERY PLAN
          728  +  `--SCAN TABLE t1
   628    729   }
   629    730   
   630    731   det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
   631         -  0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=?)}
          732  +  QUERY PLAN
          733  +  `--SEARCH TABLE t1 USING PRIMARY KEY (b=?)
   632    734   }
   633    735   
   634    736   det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
   635         -  0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)}
          737  +  QUERY PLAN
          738  +  `--SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)
   636    739   }
   637    740   
   638    741   det 8.2.4 "SELECT count(*) FROM t1" {
   639         -  0 0 0 {SCAN TABLE t1}
          742  +  QUERY PLAN
          743  +  `--SCAN TABLE t1
   640    744   }
   641    745   
   642    746   
   643    747   
   644    748   
   645    749   
   646    750   
   647    751   
   648    752   finish_test

Changes to test/fts3aux1.test.

   101    101   db func rec rec
   102    102   
   103    103   # Use EQP to show that the WHERE expression "term='braid'" uses a different
   104    104   # index number (1) than "+term='braid'" (0).
   105    105   #
   106    106   do_execsql_test 2.1.1.1 {
   107    107     EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term='braid'
   108         -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 1:} }
          108  +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 1:*/}
   109    109   do_execsql_test 2.1.1.2 {
   110    110     EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term='braid'
   111         -} {0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}}
          111  +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
   112    112   
   113    113   # Now show that using "term='braid'" means the virtual table returns
   114    114   # only 1 row to SQLite, but "+term='braid'" means all 19 are returned.
   115    115   #
   116    116   do_test 2.1.2.1 {
   117    117     set cnt 0
   118    118     execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND term='braid' }
................................................................................
   150    150   
   151    151   # Special case: term=NULL
   152    152   #
   153    153   do_execsql_test 2.1.5 { SELECT * FROM terms WHERE term=NULL } {}
   154    154   
   155    155   do_execsql_test 2.2.1.1 {
   156    156     EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term>'brain'
   157         -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 2:} }
          157  +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 2:*/}
   158    158   do_execsql_test 2.2.1.2 {
   159    159     EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term>'brain'
   160         -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} }
          160  +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
   161    161   
   162    162   do_execsql_test 2.2.1.3 {
   163    163     EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term<'brain'
   164         -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 4:} }
          164  +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 4:*/}
   165    165   do_execsql_test 2.2.1.4 {
   166    166     EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term<'brain'
   167         -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} }
          167  +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
   168    168   
   169    169   do_execsql_test 2.2.1.5 {
   170    170     EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term BETWEEN 'brags' AND 'brain'
   171         -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 6:} }
          171  +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 6:*/}
   172    172   do_execsql_test 2.2.1.6 {
   173    173     EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term BETWEEN 'brags' AND 'brain'
   174         -} { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} }
          174  +} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
   175    175   
   176    176   do_test 2.2.2.1 {
   177    177     set cnt 0
   178    178     execsql { SELECT * FROM terms WHERE rec('cnt', term) AND term>'brain' }
   179    179     set cnt
   180    180   } {18}
   181    181   do_test 2.2.2.2 {
................................................................................
   331    331     5    1    "ORDER BY documents"
   332    332     6    1    "ORDER BY documents DESC"
   333    333     7    1    "ORDER BY occurrences ASC"
   334    334     8    1    "ORDER BY occurrences"
   335    335     9    1    "ORDER BY occurrences DESC"
   336    336   } {
   337    337   
   338         -  set res [list 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}]
   339         -  if {$sort} { lappend res 0 0 0 {USE TEMP B-TREE FOR ORDER BY} }
          338  +  set res {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}
          339  +  if {$sort} { append res {*USE TEMP B-TREE FOR ORDER BY} }
          340  +  set res "/*$res*/"
   340    341   
   341    342     set sql "SELECT * FROM terms $orderby"
   342    343     do_execsql_test 2.3.1.$tn "EXPLAIN QUERY PLAN $sql" $res
   343    344   }
   344    345   
   345    346   #-------------------------------------------------------------------------
   346    347   # The next set of tests, fts3aux1-3.*, test error conditions in the 
................................................................................
   399    400     INSERT INTO x1 VALUES('f g h i j');
   400    401     INSERT INTO x1 VALUES('k k l l a');
   401    402   
   402    403     INSERT INTO x2 SELECT term FROM terms WHERE col = '*';
   403    404     INSERT INTO x3 SELECT term FROM terms WHERE col = '*';
   404    405   }
   405    406   
   406         -proc do_plansql_test {tn sql r} {
   407         -  uplevel do_execsql_test $tn [list "EXPLAIN QUERY PLAN $sql ; $sql"] [list $r]
          407  +proc do_plansql_test {tn sql r1 r2} {
          408  +  do_eqp_test $tn.eqp $sql $r1
          409  +  do_execsql_test $tn $sql $r2
   408    410   }
   409    411   
   410    412   do_plansql_test 4.2 {
   411    413     SELECT y FROM x2, terms WHERE y = term AND col = '*'
   412    414   } {
   413         -  0 0 0 {SCAN TABLE x2} 
   414         -  0 1 1 {SCAN TABLE terms VIRTUAL TABLE INDEX 1:} 
          415  +  QUERY PLAN
          416  +  |--SCAN TABLE x2
          417  +  `--SCAN TABLE terms VIRTUAL TABLE INDEX 1:
          418  +} {
   415    419     a b c d e f g h i j k l
   416    420   }
   417    421   
   418    422   do_plansql_test 4.3 {
   419    423     SELECT y FROM terms, x2 WHERE y = term AND col = '*'
   420    424   } {
   421         -  0 0 1 {SCAN TABLE x2} 
   422         -  0 1 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 1:} 
          425  +  QUERY PLAN
          426  +  |--SCAN TABLE x2
          427  +  `--SCAN TABLE terms VIRTUAL TABLE INDEX 1:
          428  +} {
   423    429     a b c d e f g h i j k l
   424    430   }
   425    431   
   426    432   do_plansql_test 4.4 {
   427    433     SELECT y FROM x3, terms WHERE y = term AND col = '*'
   428    434   } {
   429         -  0 0 1 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} 
   430         -  0 1 0 {SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)}
          435  +  QUERY PLAN
          436  +  |--SCAN TABLE terms VIRTUAL TABLE INDEX 0:
          437  +  `--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)
          438  +} {
   431    439     a b c d e f g h i j k l
   432    440   }
   433    441   
   434    442   do_plansql_test 4.5 {
   435    443     SELECT y FROM terms, x3 WHERE y = term AND occurrences>1 AND col = '*'
   436    444   } {
   437         -  0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0:} 
   438         -  0 1 1 {SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)}
          445  +  QUERY PLAN
          446  +  |--SCAN TABLE terms VIRTUAL TABLE INDEX 0:
          447  +  `--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)
          448  +} {
   439    449     a k l
   440    450   }
   441    451   
   442    452   #-------------------------------------------------------------------------
   443    453   # The following tests check that fts4aux can handle an fts table with an
   444    454   # odd name (one that requires quoting for use in SQL statements). And that
   445    455   # the argument to the fts4aux constructor is properly dequoted before use.

Changes to test/fts3join.test.

    92     92   
    93     93   do_eqp_test 4.2 {
    94     94     SELECT * FROM t4 LEFT JOIN (
    95     95         SELECT docid, * FROM ft4 WHERE ft4 MATCH ?
    96     96     ) AS rr ON t4.rowid=rr.docid 
    97     97     WHERE t4.y = ?;
    98     98   } {
    99         -  1 0 0 {SCAN TABLE ft4 VIRTUAL TABLE INDEX 3:} 
   100         -  0 0 0 {SCAN TABLE t4}
   101         -  0 1 1 {SEARCH SUBQUERY 1 AS rr USING AUTOMATIC COVERING INDEX (docid=?)}
           99  +  QUERY PLAN
          100  +  |--MATERIALIZE xxxxxx
          101  +  |  `--SCAN TABLE ft4 VIRTUAL TABLE INDEX 3:
          102  +  |--SCAN TABLE t4
          103  +  `--SEARCH SUBQUERY xxxxxx AS rr USING AUTOMATIC COVERING INDEX (docid=?)
   102    104   }
   103    105   
   104    106   finish_test

Changes to test/fts3query.test.

   114    114       CREATE VIRTUAL TABLE ft USING fts3(title);
   115    115       CREATE TABLE bt(title);
   116    116     }
   117    117   } {}
   118    118   do_eqp_test fts3query-4.2 {
   119    119     SELECT t1.number FROM t1, ft WHERE t1.number=ft.rowid ORDER BY t1.date
   120    120   } {
   121         -  0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1} 
   122         -  0 1 1 {SCAN TABLE ft VIRTUAL TABLE INDEX 1:}
          121  +  QUERY PLAN
          122  +  |--SCAN TABLE t1 USING COVERING INDEX i1
          123  +  `--SCAN TABLE ft VIRTUAL TABLE INDEX 1:
   123    124   }
   124    125   do_eqp_test fts3query-4.3 {
   125    126     SELECT t1.number FROM ft, t1 WHERE t1.number=ft.rowid ORDER BY t1.date
   126    127   } {
   127         -  0 0 1 {SCAN TABLE t1 USING COVERING INDEX i1} 
   128         -  0 1 0 {SCAN TABLE ft VIRTUAL TABLE INDEX 1:}
          128  +  QUERY PLAN
          129  +  |--SCAN TABLE t1 USING COVERING INDEX i1
          130  +  `--SCAN TABLE ft VIRTUAL TABLE INDEX 1:
   129    131   }
   130    132   do_eqp_test fts3query-4.4 {
   131    133     SELECT t1.number FROM t1, bt WHERE t1.number=bt.rowid ORDER BY t1.date
   132    134   } {
   133         -  0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1} 
   134         -  0 1 1 {SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)}
          135  +  QUERY PLAN
          136  +  |--SCAN TABLE t1 USING COVERING INDEX i1
          137  +  `--SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)
   135    138   }
   136    139   do_eqp_test fts3query-4.5 {
   137    140     SELECT t1.number FROM bt, t1 WHERE t1.number=bt.rowid ORDER BY t1.date
   138    141   } {
   139         -  0 0 1 {SCAN TABLE t1 USING COVERING INDEX i1} 
   140         -  0 1 0 {SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)}
          142  +  QUERY PLAN
          143  +  |--SCAN TABLE t1 USING COVERING INDEX i1
          144  +  `--SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)
   141    145   }
   142    146   
   143    147   
   144    148   # Test that calling matchinfo() with the wrong number of arguments, or with
   145    149   # an invalid argument returns an error.
   146    150   #
   147    151   do_execsql_test 5.1 {

Changes to test/index6.test.

   314    314     INSERT INTO t8b VALUES('value', 3);
   315    315     INSERT INTO t8b VALUES('dummy', 4);
   316    316   } {}
   317    317   
   318    318   do_eqp_test index6-8.1 {
   319    319     SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
   320    320   } {
   321         -  0 0 0 {SCAN TABLE t8a} 
   322         -  0 1 1 {SEARCH TABLE t8b USING INDEX i8c (y=?)}
          321  +  QUERY PLAN
          322  +  |--SCAN TABLE t8a
          323  +  `--SEARCH TABLE t8b USING INDEX i8c (y=?)
   323    324   }
   324    325   
   325    326   do_execsql_test index6-8.2 {
   326    327     SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
   327    328   } {
   328    329     1 one value 1 
   329    330     2 two {} {} 

Changes to test/index7.test.

   317    317     INSERT INTO t4 VALUES('def', 'xyz');
   318    318     SELECT * FROM v4 WHERE d='xyz' AND c='def'
   319    319   } {
   320    320     def xyz
   321    321   }
   322    322   do_eqp_test index7-6.4 {
   323    323     SELECT * FROM v4 WHERE d='xyz' AND c='def'
   324         -} {
   325         -  0 0 0 {SEARCH TABLE t4 USING INDEX i4 (c=?)}
   326         -}
          324  +} {SEARCH TABLE t4 USING INDEX i4 (c=?)}
          325  +
   327    326   do_catchsql_test index7-6.5 {
   328    327     CREATE INDEX t5a ON t5(a) WHERE a=#1;
   329    328   } {1 {near "#1": syntax error}}
   330    329   
   331    330   
   332    331   finish_test

Changes to test/indexedby.test.

    36     36   #
    37     37   proc EQP {sql} {
    38     38     uplevel "execsql {EXPLAIN QUERY PLAN $sql}"
    39     39   }
    40     40   
    41     41   # These tests are to check that "EXPLAIN QUERY PLAN" is working as expected.
    42     42   #
    43         -do_execsql_test indexedby-1.2 {
    44         -  EXPLAIN QUERY PLAN select * from t1 WHERE a = 10; 
    45         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
    46         -do_execsql_test indexedby-1.3 {
    47         -  EXPLAIN QUERY PLAN select * from t1 ; 
    48         -} {0 0 0 {SCAN TABLE t1}}
    49         -do_execsql_test indexedby-1.4 {
    50         -  EXPLAIN QUERY PLAN select * from t1, t2 WHERE c = 10; 
           43  +do_eqp_test indexedby-1.2 {
           44  +  select * from t1 WHERE a = 10; 
           45  +} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
           46  +do_eqp_test indexedby-1.3 {
           47  +  select * from t1 ; 
           48  +} {SCAN TABLE t1}
           49  +do_eqp_test indexedby-1.4 {
           50  +  select * from t1, t2 WHERE c = 10; 
    51     51   } {
    52         -  0 0 1 {SEARCH TABLE t2 USING INDEX i3 (c=?)} 
    53         -  0 1 0 {SCAN TABLE t1}
           52  +  QUERY PLAN
           53  +  |--SEARCH TABLE t2 USING INDEX i3 (c=?)
           54  +  `--SCAN TABLE t1
    54     55   }
    55     56   
    56     57   # Parser tests. Test that an INDEXED BY or NOT INDEX clause can be 
    57     58   # attached to a table in the FROM clause, but not to a sub-select or
    58     59   # SQL view. Also test that specifying an index that does not exist or
    59     60   # is attached to a different table is detected as an error.
    60     61   #
    61         -# EVIDENCE-OF: R-07004-11522 -- syntax diagram qualified-table-name
           62  +# X-EVIDENCE-OF: R-07004-11522 -- syntax diagram qualified-table-name
    62     63   # 
    63     64   # EVIDENCE-OF: R-58230-57098 The "INDEXED BY index-name" phrase
    64     65   # specifies that the named index must be used in order to look up values
    65     66   # on the preceding table.
    66     67   #
    67     68   do_test indexedby-2.1 {
    68     69     execsql { SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'}
................................................................................
   111    112   #
   112    113   # EVIDENCE-OF: R-37002-28871 The "NOT INDEXED" clause specifies that no
   113    114   # index shall be used when accessing the preceding table, including
   114    115   # implied indices create by UNIQUE and PRIMARY KEY constraints. However,
   115    116   # the rowid can still be used to look up entries even when "NOT INDEXED"
   116    117   # is specified.
   117    118   #
   118         -do_execsql_test indexedby-3.1 {
   119         -  EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a = 'one' AND b = 'two'
          119  +do_eqp_test indexedby-3.1 {
          120  +  SELECT * FROM t1 WHERE a = 'one' AND b = 'two'
   120    121   } {/SEARCH TABLE t1 USING INDEX/}
   121         -do_execsql_test indexedby-3.1.1 {
   122         -  EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
   123         -} {0 0 0 {SCAN TABLE t1}}
   124         -do_execsql_test indexedby-3.1.2 {
   125         -  EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE rowid=1
          122  +do_eqp_test indexedby-3.1.1 {
          123  +  SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
          124  +} {SCAN TABLE t1}
          125  +do_eqp_test indexedby-3.1.2 {
          126  +  SELECT * FROM t1 NOT INDEXED WHERE rowid=1
   126    127   } {/SEARCH TABLE t1 USING INTEGER PRIMARY KEY .rowid=/}
   127    128   
   128    129   
   129         -do_execsql_test indexedby-3.2 {
   130         -  EXPLAIN QUERY PLAN 
          130  +do_eqp_test indexedby-3.2 {
   131    131     SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'
   132         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
   133         -do_execsql_test indexedby-3.3 {
   134         -  EXPLAIN QUERY PLAN 
          132  +} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
          133  +do_eqp_test indexedby-3.3 {
   135    134     SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'
   136         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}}
          135  +} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
   137    136   do_test indexedby-3.4 {
   138    137     catchsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' }
   139    138   } {1 {no query solution}}
   140    139   do_test indexedby-3.5 {
   141    140     catchsql { SELECT * FROM t1 INDEXED BY i2 ORDER BY a }
   142    141   } {1 {no query solution}}
   143    142   do_test indexedby-3.6 {
   144    143     catchsql { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' }
   145    144   } {0 {}}
   146    145   do_test indexedby-3.7 {
   147    146     catchsql { SELECT * FROM t1 INDEXED BY i1 ORDER BY a }
   148    147   } {0 {}}
   149    148   
   150         -do_execsql_test indexedby-3.8 {
   151         -  EXPLAIN QUERY PLAN 
          149  +do_eqp_test indexedby-3.8 {
   152    150     SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 ORDER BY e 
   153         -} {0 0 0 {SCAN TABLE t3 USING INDEX sqlite_autoindex_t3_1}}
   154         -do_execsql_test indexedby-3.9 {
   155         -  EXPLAIN QUERY PLAN 
          151  +} {SCAN TABLE t3 USING INDEX sqlite_autoindex_t3_1}
          152  +do_eqp_test indexedby-3.9 {
   156    153     SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE e = 10 
   157         -} {0 0 0 {SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (e=?)}}
          154  +} {SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (e=?)}
   158    155   do_test indexedby-3.10 {
   159    156     catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE f = 10 }
   160    157   } {1 {no query solution}}
   161    158   do_test indexedby-3.11 {
   162    159     catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_2 WHERE f = 10 }
   163    160   } {1 {no such index: sqlite_autoindex_t3_2}}
   164    161   
   165    162   # Tests for multiple table cases.
   166    163   #
   167         -do_execsql_test indexedby-4.1 {
   168         -  EXPLAIN QUERY PLAN SELECT * FROM t1, t2 WHERE a = c 
          164  +do_eqp_test indexedby-4.1 {
          165  +  SELECT * FROM t1, t2 WHERE a = c 
   169    166   } {
   170         -  0 0 0 {SCAN TABLE t1} 
   171         -  0 1 1 {SEARCH TABLE t2 USING INDEX i3 (c=?)}
          167  +  QUERY PLAN
          168  +  |--SCAN TABLE t1
          169  +  `--SEARCH TABLE t2 USING INDEX i3 (c=?)
   172    170   }
   173         -do_execsql_test indexedby-4.2 {
   174         -  EXPLAIN QUERY PLAN SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c 
          171  +do_eqp_test indexedby-4.2 {
          172  +  SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c 
   175    173   } {
   176         -  0 0 1 {SCAN TABLE t2} 
   177         -  0 1 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
          174  +  QUERY PLAN
          175  +  |--SCAN TABLE t2
          176  +  `--SEARCH TABLE t1 USING INDEX i1 (a=?)
   178    177   }
   179    178   do_test indexedby-4.3 {
   180    179     catchsql {
   181    180       SELECT * FROM t1 INDEXED BY i1, t2 INDEXED BY i3 WHERE a=c
   182    181     }
   183    182   } {1 {no query solution}}
   184    183   do_test indexedby-4.4 {
................................................................................
   190    189   # Test embedding an INDEXED BY in a CREATE VIEW statement. This block
   191    190   # also tests that nothing bad happens if an index refered to by
   192    191   # a CREATE VIEW statement is dropped and recreated.
   193    192   #
   194    193   do_execsql_test indexedby-5.1 {
   195    194     CREATE VIEW v2 AS SELECT * FROM t1 INDEXED BY i1 WHERE a > 5;
   196    195     EXPLAIN QUERY PLAN SELECT * FROM v2 
   197         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}}
          196  +} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/}
   198    197   do_execsql_test indexedby-5.2 {
   199    198     EXPLAIN QUERY PLAN SELECT * FROM v2 WHERE b = 10 
   200         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}}
          199  +} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/}
   201    200   do_test indexedby-5.3 {
   202    201     execsql { DROP INDEX i1 }
   203    202     catchsql { SELECT * FROM v2 }
   204    203   } {1 {no such index: i1}}
   205    204   do_test indexedby-5.4 {
   206    205     # Recreate index i1 in such a way as it cannot be used by the view query.
   207    206     execsql { CREATE INDEX i1 ON t1(b) }
................................................................................
   212    211     # be used by the query.
   213    212     execsql { DROP INDEX i1 ; CREATE INDEX i1 ON t1(a) }
   214    213     catchsql { SELECT * FROM v2 }
   215    214   } {0 {}}
   216    215   
   217    216   # Test that "NOT INDEXED" may use the rowid index, but not others.
   218    217   # 
   219         -do_execsql_test indexedby-6.1 {
   220         -  EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 10 ORDER BY rowid 
   221         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}}
   222         -do_execsql_test indexedby-6.2 {
   223         -  EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid 
   224         -} {0 0 0 {SCAN TABLE t1}}
          218  +do_eqp_test indexedby-6.1 {
          219  +  SELECT * FROM t1 WHERE b = 10 ORDER BY rowid 
          220  +} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
          221  +do_eqp_test indexedby-6.2 {
          222  +  SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid 
          223  +} {SCAN TABLE t1}
   225    224   
   226    225   # EVIDENCE-OF: R-40297-14464 The INDEXED BY phrase forces the SQLite
   227    226   # query planner to use a particular named index on a DELETE, SELECT, or
   228    227   # UPDATE statement.
   229    228   #
   230    229   # Test that "INDEXED BY" can be used in a DELETE statement.
   231    230   # 
   232         -do_execsql_test indexedby-7.1 {
   233         -  EXPLAIN QUERY PLAN DELETE FROM t1 WHERE a = 5 
   234         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
   235         -do_execsql_test indexedby-7.2 {
   236         -  EXPLAIN QUERY PLAN DELETE FROM t1 NOT INDEXED WHERE a = 5 
   237         -} {0 0 0 {SCAN TABLE t1}}
   238         -do_execsql_test indexedby-7.3 {
   239         -  EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i1 WHERE a = 5 
   240         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
   241         -do_execsql_test indexedby-7.4 {
   242         -  EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10
   243         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
   244         -do_execsql_test indexedby-7.5 {
   245         -  EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10
   246         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}}
          231  +do_eqp_test indexedby-7.1 {
          232  +  DELETE FROM t1 WHERE a = 5 
          233  +} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
          234  +do_eqp_test indexedby-7.2 {
          235  +  DELETE FROM t1 NOT INDEXED WHERE a = 5 
          236  +} {SCAN TABLE t1}
          237  +do_eqp_test indexedby-7.3 {
          238  +  DELETE FROM t1 INDEXED BY i1 WHERE a = 5 
          239  +} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
          240  +do_eqp_test indexedby-7.4 {
          241  +  DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10
          242  +} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
          243  +do_eqp_test indexedby-7.5 {
          244  +  DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10
          245  +} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
   247    246   do_test indexedby-7.6 {
   248    247     catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5}
   249    248   } {1 {no query solution}}
   250    249   
   251    250   # Test that "INDEXED BY" can be used in an UPDATE statement.
   252    251   # 
   253         -do_execsql_test indexedby-8.1 {
   254         -  EXPLAIN QUERY PLAN UPDATE t1 SET rowid=rowid+1 WHERE a = 5 
   255         -} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}}
   256         -do_execsql_test indexedby-8.2 {
   257         -  EXPLAIN QUERY PLAN UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 
   258         -} {0 0 0 {SCAN TABLE t1}}
   259         -do_execsql_test indexedby-8.3 {
   260         -  EXPLAIN QUERY PLAN UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 
   261         -} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}}
   262         -do_execsql_test indexedby-8.4 {
   263         -  EXPLAIN QUERY PLAN 
          252  +do_eqp_test indexedby-8.1 {
          253  +  UPDATE t1 SET rowid=rowid+1 WHERE a = 5 
          254  +} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
          255  +do_eqp_test indexedby-8.2 {
          256  +  UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 
          257  +} {SCAN TABLE t1}
          258  +do_eqp_test indexedby-8.3 {
          259  +  UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 
          260  +} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
          261  +do_eqp_test indexedby-8.4 {
   264    262     UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 AND b = 10
   265         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
   266         -do_execsql_test indexedby-8.5 {
   267         -  EXPLAIN QUERY PLAN 
          263  +} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
          264  +do_eqp_test indexedby-8.5 {
   268    265     UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5 AND b = 10
   269         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?)}}
          266  +} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
   270    267   do_test indexedby-8.6 {
   271    268     catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5}
   272    269   } {1 {no query solution}}
   273    270   
   274    271   # Test that bug #3560 is fixed.
   275    272   #
   276    273   do_test indexedby-9.1 {
................................................................................
   337    334     SELECT a,b,rowid FROM x1 INDEXED BY x1i WHERE a=1 AND b=1 AND rowid='3';
   338    335   } {1 1 3}
   339    336   do_execsql_test 11.4 {
   340    337     SELECT a,b,rowid FROM x1 INDEXED BY x1i WHERE a=1 AND b=1 AND rowid='3.0';
   341    338   } {1 1 3}
   342    339   do_eqp_test 11.5 {
   343    340     SELECT a,b,rowid FROM x1 INDEXED BY x1i WHERE a=1 AND b=1 AND rowid='3.0';
   344         -} {0 0 0 {SEARCH TABLE x1 USING COVERING INDEX x1i (a=? AND b=? AND rowid=?)}}
          341  +} {SEARCH TABLE x1 USING COVERING INDEX x1i (a=? AND b=? AND rowid=?)}
   345    342   
   346    343   do_execsql_test 11.6 {
   347    344     CREATE TABLE x2(c INTEGER PRIMARY KEY, a, b TEXT);
   348    345     CREATE INDEX x2i ON x2(a, b);
   349    346     INSERT INTO x2 VALUES(1, 1, 1);
   350    347     INSERT INTO x2 VALUES(2, 1, 1);
   351    348     INSERT INTO x2 VALUES(3, 1, 1);
................................................................................
   358    355     SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3';
   359    356   } {1 1 3}
   360    357   do_execsql_test 11.9 {
   361    358     SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3.0';
   362    359   } {1 1 3}
   363    360   do_eqp_test 11.10 {
   364    361     SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3.0';
   365         -} {0 0 0 {SEARCH TABLE x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}}
          362  +} {SEARCH TABLE x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}
   366    363   
   367    364   #-------------------------------------------------------------------------
   368    365   # Check INDEXED BY works (throws an exception) with partial indexes that 
   369    366   # cannot be used.
   370    367   do_execsql_test 12.1 {
   371    368     CREATE TABLE o1(x INTEGER PRIMARY KEY, y, z);
   372    369     CREATE INDEX p1 ON o1(z);

Changes to test/indexexpr2.test.

    87     87   
    88     88   ifcapable json1 {
    89     89     do_eqp_test 3.3.1 {
    90     90       SELECT json_extract(x, '$.b') FROM t2 
    91     91       WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL 
    92     92       GROUP BY json_extract(x, '$.b') COLLATE nocase
    93     93       ORDER BY json_extract(x, '$.b') COLLATE nocase;
    94         -  } {
    95         -    0 0 0 {SCAN TABLE t2} 
    96         -    0 0 0 {USE TEMP B-TREE FOR GROUP BY}
    97         -  }
           94  +  } [string map {"\n  " \n} {
           95  +    QUERY PLAN
           96  +    |--SCAN TABLE t2
           97  +    `--USE TEMP B-TREE FOR GROUP BY
           98  +  }]
    98     99     
    99    100     do_execsql_test 3.3.2 {
   100    101       CREATE INDEX i3 ON t3(json_extract(x, '$.a'), json_extract(x, '$.b'));
   101    102     } {}
   102    103     
   103    104     do_eqp_test 3.3.3 {
   104    105       SELECT json_extract(x, '$.b') FROM t3 
   105    106       WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL 
   106    107       GROUP BY json_extract(x, '$.b') COLLATE nocase
   107    108       ORDER BY json_extract(x, '$.b') COLLATE nocase;
   108         -  } {
   109         -    0 0 0 {SEARCH TABLE t3 USING INDEX i3 (<expr>=?)} 
   110         -    0 0 0 {USE TEMP B-TREE FOR GROUP BY}
   111         -  }
          109  +  } [string map {"\n  " \n} {
          110  +    QUERY PLAN
          111  +    |--SEARCH TABLE t3 USING INDEX i3 (<expr>=?)
          112  +    `--USE TEMP B-TREE FOR GROUP BY
          113  +  }]
   112    114   }
   113    115   
   114    116   do_execsql_test 3.4.0 {
   115    117     CREATE TABLE t4(a, b);
   116    118     INSERT INTO t4 VALUES('.ABC', 1);
   117    119     INSERT INTO t4 VALUES('.abc', 2);
   118    120     INSERT INTO t4 VALUES('.ABC', 3);

Changes to test/join2.test.

   108    108     CREATE TABLE t3_1(k3 PRIMARY KEY, v3) WITHOUT ROWID;
   109    109     CREATE TABLE t3_2(v3, k3 PRIMARY KEY) WITHOUT ROWID;
   110    110   }
   111    111   
   112    112   do_eqp_test 3.1 {
   113    113     SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_1 USING (k3);
   114    114   } {
   115         -  0 0 0 {SCAN TABLE t1} 
   116         -  0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
          115  +  QUERY PLAN
          116  +  |--SCAN TABLE t1
          117  +  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
   117    118   }
   118    119   
   119    120   do_eqp_test 3.2 {
   120    121     SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_2 USING (k3);
   121    122   } {
   122         -  0 0 0 {SCAN TABLE t1} 
   123         -  0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
          123  +  QUERY PLAN
          124  +  |--SCAN TABLE t1
          125  +  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
   124    126   }
   125    127   
   126    128   #-------------------------------------------------------------------------
   127    129   # Test that tables other than the rightmost can be omitted from a
   128    130   # LEFT JOIN query.
   129    131   #
   130    132   do_execsql_test 4.0 {
................................................................................
   154    156   do_execsql_test 4.1.4 {
   155    157     SELECT v1, v3 FROM c1 LEFT JOIN c2 LEFT JOIN c3 ON (c3.k=v1+1);
   156    158   } {2 v3 2 v3 1112 {} 1112 {}}
   157    159   
   158    160   do_eqp_test 4.1.5 {
   159    161     SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2);
   160    162   } {
   161         -  0 0 0 {SCAN TABLE c1} 
   162         -  0 1 1 {SEARCH TABLE c2 USING INTEGER PRIMARY KEY (rowid=?)}
   163         -  0 2 2 {SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)}
          163  +  QUERY PLAN
          164  +  |--SCAN TABLE c1
          165  +  |--SEARCH TABLE c2 USING INTEGER PRIMARY KEY (rowid=?)
          166  +  `--SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)
   164    167   }
   165    168   do_eqp_test 4.1.6 {
   166    169     SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1);
   167    170   } {
   168         -  0 0 0 {SCAN TABLE c1} 
   169         -  0 1 2 {SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)}
          171  +  QUERY PLAN
          172  +  |--SCAN TABLE c1
          173  +  `--SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)
   170    174   }
   171    175   
   172    176   do_execsql_test 4.2.0 {
   173    177     DROP TABLE c1;
   174    178     DROP TABLE c2;
   175    179     DROP TABLE c3;
   176    180     CREATE TABLE c1(k UNIQUE, v1);
................................................................................
   199    203   do_execsql_test 4.2.4 {
   200    204     SELECT v1, v3 FROM c1 LEFT JOIN c2 LEFT JOIN c3 ON (c3.k=v1+1);
   201    205   } {2 v3 2 v3 1112 {} 1112 {}}
   202    206   
   203    207   do_eqp_test 4.2.5 {
   204    208     SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2);
   205    209   } {
   206         -  0 0 0 {SCAN TABLE c1} 
   207         -  0 1 1 {SEARCH TABLE c2 USING INDEX sqlite_autoindex_c2_1 (k=?)}
   208         -  0 2 2 {SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)}
          210  +  QUERY PLAN
          211  +  |--SCAN TABLE c1
          212  +  |--SEARCH TABLE c2 USING INDEX sqlite_autoindex_c2_1 (k=?)
          213  +  `--SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
   209    214   }
   210    215   do_eqp_test 4.2.6 {
   211    216     SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1);
   212    217   } {
   213         -  0 0 0 {SCAN TABLE c1} 
   214         -  0 1 2 {SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)}
          218  +  QUERY PLAN
          219  +  |--SCAN TABLE c1
          220  +  `--SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
   215    221   }
   216    222   
   217    223   # 2017-11-23 (Thanksgiving day)
   218    224   # OSSFuzz found an assertion fault in the new LEFT JOIN eliminator code.
   219    225   #
   220    226   do_execsql_test 4.3.0 {
   221    227     DROP TABLE IF EXISTS t1;
................................................................................
   241    247     CREATE TABLE s1 (a INTEGER PRIMARY KEY);
   242    248     CREATE TABLE s2 (a INTEGER PRIMARY KEY);
   243    249     CREATE TABLE s3 (a INTEGER);
   244    250     CREATE UNIQUE INDEX ndx on s3(a);
   245    251   }
   246    252   do_eqp_test 5.1 {
   247    253     SELECT s1.a FROM s1 left join s2 using (a);
   248         -} {
   249         -  0 0 0 {SCAN TABLE s1}
   250         -}
          254  +} {SCAN TABLE s1}
          255  +
   251    256   do_eqp_test 5.2 {
   252    257     SELECT s1.a FROM s1 left join s3 using (a);
   253         -} {
   254         -  0 0 0 {SCAN TABLE s1}
   255         -}
          258  +} {SCAN TABLE s1}
   256    259   
   257    260   do_execsql_test 6.0 {
   258    261     CREATE TABLE u1(a INTEGER PRIMARY KEY, b, c);
   259    262     CREATE TABLE u2(a INTEGER PRIMARY KEY, b, c);
   260    263     CREATE INDEX u1ab ON u1(b, c);
   261    264   }
   262    265   do_eqp_test 6.1 {
   263    266     SELECT u2.* FROM u2 LEFT JOIN u1 ON( u1.a=u2.a AND u1.b=u2.b AND u1.c=u2.c );
   264         -} {
   265         -  0 0 0 {SCAN TABLE u2}
   266         -}
          267  +} {SCAN TABLE u2}
   267    268   
   268    269   db close
   269    270   sqlite3 db :memory:
   270    271   do_execsql_test 7.0 {
   271    272     CREATE TABLE t1(a,b);  INSERT INTO t1 VALUES(1,2),(3,4),(5,6);
   272    273     CREATE TABLE t2(c,d);  INSERT INTO t2 VALUES(2,4),(3,6);
   273    274     CREATE TABLE t3(x);    INSERT INTO t3 VALUES(9);

Changes to test/join5.test.

   260    260   }
   261    261   
   262    262   do_eqp_test 7.2 {
   263    263     SELECT * FROM t1 LEFT JOIN t2 ON (
   264    264       t2.x = t1.x AND (t2.y=? OR (t2.y=? AND t2.z IS NOT NULL))
   265    265     );
   266    266   } {
   267         -  0 0 0 {SCAN TABLE t1} 
   268         -  0 1 1 {SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)} 
   269         -  0 1 1 {SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)}
          267  +  QUERY PLAN
          268  +  |--SCAN TABLE t1
          269  +  `--MULTI-INDEX OR
          270  +     |--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)
          271  +     `--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)
   270    272   }
   271    273   
   272    274   do_execsql_test 7.3 {
   273    275     CREATE TABLE t3(x);
   274    276   
   275    277     CREATE TABLE t4(x, y, z);
   276    278     CREATE INDEX t4xy ON t4(x, y);
................................................................................
   281    283   
   282    284     ANALYZE;
   283    285   }
   284    286   
   285    287   do_eqp_test 7.4 {
   286    288     SELECT * FROM t3 LEFT JOIN t4 ON (t4.x = t3.x) WHERE (t4.y = ? OR t4.z = ?);
   287    289   } {
   288         -  0 0 0 {SCAN TABLE t3} 
   289         -  0 1 1 {SEARCH TABLE t4 USING INDEX t4xz (x=?)}
          290  +  QUERY PLAN
          291  +  |--SCAN TABLE t3
          292  +  `--SEARCH TABLE t4 USING INDEX t4xz (x=?)
   290    293   } 
   291    294   
   292    295   finish_test
   293         -

Changes to test/mallocK.test.

   117    117   
   118    118     SELECT 'x' > '.';
   119    119   } {1}
   120    120   
   121    121   ifcapable stat4 {
   122    122     do_eqp_test 6.1 {
   123    123       SELECT DISTINCT c FROM t3 WHERE b BETWEEN '.xx..' AND '.xxxx';
   124         -  } {
   125         -    0 0 0 {SEARCH TABLE t3 USING INDEX i3 (ANY(a) AND b>? AND b<?)} 
   126         -    0 0 0 {USE TEMP B-TREE FOR DISTINCT}
   127         -  }
          124  +  } [string map {"\n  " \n} {
          125  +    QUERY PLAN
          126  +    |--SEARCH TABLE t3 USING INDEX i3 (ANY(a) AND b>? AND b<?)
          127  +    `--USE TEMP B-TREE FOR DISTINCT
          128  +  }]
   128    129   }
   129    130   
   130    131   do_faultsim_test 6 -faults oom* -body {
   131    132     db cache flush
   132    133     db eval { SELECT DISTINCT c FROM t3 WHERE b BETWEEN '.xx..' AND '.xxxx' }
   133    134   } -test {
   134    135     faultsim_test_result {0 {12 13 14 15}} 

Changes to test/orderby1.test.

   450    450       
   451    451       SELECT b, y FROM t41 CROSS JOIN t42 ON x=a ORDER BY b, y;
   452    452     }
   453    453   } {1 13 1 14 1 15 1 16}
   454    454   
   455    455   # No sorting of queries that omit the FROM clause.
   456    456   #
   457         -do_execsql_test 5.0 {
   458         -  EXPLAIN QUERY PLAN SELECT 5 ORDER BY 1
   459         -} {}
          457  +do_eqp_test 5.0 {
          458  +  SELECT 5 ORDER BY 1
          459  +} {
          460  +  QUERY PLAN
          461  +  `--SCAN CONSTANT ROW
          462  +}
   460    463   do_execsql_test 5.1 {
   461    464     EXPLAIN QUERY PLAN SELECT 5 UNION ALL SELECT 3 ORDER BY 1
   462    465   } {~/B-TREE/}
   463    466   do_execsql_test 5.2 {
   464    467     SELECT 5 UNION ALL SELECT 3 ORDER BY 1
   465    468   } {3 5}
   466    469   do_execsql_test 5.3 {
................................................................................
   508    511     CREATE TABLE t1(a, b);
   509    512     CREATE INDEX i1 ON t1(a);
   510    513   }
   511    514   
   512    515   do_eqp_test 8.1 {
   513    516     SELECT * FROM t1 ORDER BY a, b;
   514    517   } {
   515         -  0 0 0 {SCAN TABLE t1 USING INDEX i1} 
   516         -  0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
          518  +  QUERY PLAN
          519  +  |--SCAN TABLE t1 USING INDEX i1
          520  +  `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
   517    521   }
   518    522   
   519    523   do_execsql_test 8.2 {
   520    524     WITH cnt(i) AS (
   521    525       SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000
   522    526     )
   523    527     INSERT INTO t1 SELECT i%2, randomblob(500) FROM cnt;

Changes to test/rollback2.test.

    97     97   }
    98     98   
    99     99   #--------------------------------------------------------------------
   100    100   # Try with some index scans
   101    101   #
   102    102   do_eqp_test 3.1 {
   103    103     SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC;
   104         -} {0 0 0 {SCAN TABLE t1 USING INDEX i1}}
          104  +} {SCAN TABLE t1 USING INDEX i1}
   105    105   do_rollback_test 3.2 -setup {
   106    106     BEGIN;
   107    107       DELETE FROM t1 WHERE (i%2)==1;
   108    108   } -select {
   109    109     SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC;
   110    110   } -result {
   111    111     40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10  8  6  4  2
................................................................................
   127    127   # Now with some index scans that feature overflow keys.
   128    128   #
   129    129   set leader [string repeat "abcdefghij" 70]
   130    130   do_execsql_test 4.1 { UPDATE t1 SET h = $leader || h; }
   131    131   
   132    132   do_eqp_test 4.2 {
   133    133     SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC;
   134         -} {0 0 0 {SCAN TABLE t1 USING INDEX i1}}
          134  +} {SCAN TABLE t1 USING INDEX i1}
   135    135   do_rollback_test 4.3 -setup {
   136    136     BEGIN;
   137    137       DELETE FROM t1 WHERE (i%2)==1;
   138    138   } -select {
   139    139     SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC;
   140    140   } -result {
   141    141     2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40

Changes to test/rowvalue.test.

   171    171     INSERT INTO xy VALUES(3, 3, 3);
   172    172     INSERT INTO xy VALUES(4, 4, 4);
   173    173   }
   174    174   
   175    175   
   176    176   foreach {tn sql res eqp} {
   177    177     1 "SELECT * FROM xy WHERE (i, j) IS (2, 2)" {2 2 2} 
   178         -    "0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid=?)}"
          178  +    "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid=?)"
   179    179   
   180    180     2 "SELECT * FROM xy WHERE (k, j) < (2, 3)" {1 1 1 2 2 2}
   181         -    "0 0 0 {SCAN TABLE xy}"
          181  +    "SCAN TABLE xy"
   182    182   
   183    183     3 "SELECT * FROM xy WHERE (i, j) < (2, 3)" {1 1 1 2 2 2}
   184         -    "0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid<?)}"
          184  +    "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid<?)"
   185    185   
   186    186     4 "SELECT * FROM xy WHERE (i, j) > (2, 1)" {2 2 2 3 3 3 4 4 4}
   187         -    "0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)}"
          187  +    "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)"
   188    188   
   189    189     5 "SELECT * FROM xy WHERE (i, j) > ('2', 1)" {2 2 2 3 3 3 4 4 4}
   190         -    "0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)}"
          190  +    "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)"
   191    191   
   192    192   } {
   193    193     do_eqp_test 7.$tn.1 $sql $eqp
   194    194     do_execsql_test 7.$tn.2 $sql $res
   195    195   }
   196    196   
   197    197   do_execsql_test 8.0 {

Changes to test/rowvalue4.test.

   180    180       INSERT INTO c1(c, d) SELECT a, b FROM c1;
   181    181   
   182    182       CREATE INDEX c1ab ON c1(a, b);
   183    183       CREATE INDEX c1cd ON c1(c, d);
   184    184       ANALYZE;
   185    185     }
   186    186   
   187         -  do_eqp_test 3.1.1 { SELECT * FROM c1 WHERE a=1 AND c=2 } {
   188         -    0 0 0 {SEARCH TABLE c1 USING INDEX c1cd (c=?)}
   189         -  }
   190         -  do_eqp_test 3.1.2 { SELECT * FROM c1 WHERE a=1 AND b>'d' AND c=2 } {
   191         -    0 0 0 {SEARCH TABLE c1 USING INDEX c1cd (c=?)}
   192         -  }
   193         -  do_eqp_test 3.1.3 { SELECT * FROM c1 WHERE a=1 AND b>'l' AND c=2 } {
   194         -    0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=? AND b>?)}
   195         -  }
   196         -
   197         -  do_eqp_test 3.2.1 { SELECT * FROM c1 WHERE a=1 AND c>1 } {
   198         -    0 0 0 {SEARCH TABLE c1 USING INDEX c1cd (c>?)}
   199         -  }
   200         -  do_eqp_test 3.2.2 { SELECT * FROM c1 WHERE a=1 AND c>0 } {
   201         -    0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
   202         -  }
   203         -  do_eqp_test 3.2.3 { SELECT * FROM c1 WHERE a=1 AND c>=1 } {
   204         -    0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
   205         -  }
   206         -  do_eqp_test 3.2.4 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'c') } {
   207         -    0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
   208         -  }
   209         -  do_eqp_test 3.2.5 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'o') } {
   210         -    0 0 0 {SEARCH TABLE c1 USING INDEX c1cd ((c,d)>(?,?))}
   211         -  }
   212         -  do_eqp_test 3.2.6 { SELECT * FROM c1 WHERE a=1 AND (c, +b)>(1, 'c') } {
   213         -    0 0 0 {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
   214         -  }
          187  +  do_eqp_test 3.1.1 { SELECT * FROM c1 WHERE a=1 AND c=2 } \
          188  +     {SEARCH TABLE c1 USING INDEX c1cd (c=?)}
          189  +
          190  +  do_eqp_test 3.1.2 { SELECT * FROM c1 WHERE a=1 AND b>'d' AND c=2 } \
          191  +     {SEARCH TABLE c1 USING INDEX c1cd (c=?)}
          192  +
          193  +  do_eqp_test 3.1.3 { SELECT * FROM c1 WHERE a=1 AND b>'l' AND c=2 } \
          194  +     {SEARCH TABLE c1 USING INDEX c1ab (a=? AND b>?)}
          195  +
          196  +  do_eqp_test 3.2.1 { SELECT * FROM c1 WHERE a=1 AND c>1 } \
          197  +     {SEARCH TABLE c1 USING INDEX c1cd (c>?)}
          198  +
          199  +  do_eqp_test 3.2.2 { SELECT * FROM c1 WHERE a=1 AND c>0 } \
          200  +     {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
          201  +
          202  +  do_eqp_test 3.2.3 { SELECT * FROM c1 WHERE a=1 AND c>=1 } \
          203  +     {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
          204  +
          205  +  do_eqp_test 3.2.4 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'c') } \
          206  +     {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
          207  +
          208  +  do_eqp_test 3.2.5 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'o') } \
          209  +     {SEARCH TABLE c1 USING INDEX c1cd ((c,d)>(?,?))}
          210  +
          211  +  do_eqp_test 3.2.6 { SELECT * FROM c1 WHERE a=1 AND (c, +b)>(1, 'c') } \
          212  +     {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
          213  +
   215    214   }
   216    215   
   217    216   #------------------------------------------------------------------------
   218    217   
   219    218   do_execsql_test 5.0 {
   220    219     CREATE TABLE d1(x, y);
   221    220     CREATE TABLE d2(a, b, c);
................................................................................
   230    229   }
   231    230   
   232    231   do_eqp_test 5.1 {
   233    232     SELECT * FROM d2 WHERE 
   234    233       (a, b) IN (SELECT x, y FROM d1) AND
   235    234       (c) IN (SELECT y FROM d1)
   236    235   } {
   237         -  0 0 0 {SEARCH TABLE d2 USING INDEX d2ab (a=? AND b=?)}
   238         -  0 0 0 {EXECUTE LIST SUBQUERY 1} 
   239         -  1 0 0 {SCAN TABLE d1}
   240         -  0 0 0 {EXECUTE LIST SUBQUERY 2} 
   241         -  2 0 0 {SCAN TABLE d1}
          236  +  QUERY PLAN
          237  +  |--SEARCH TABLE d2 USING INDEX d2ab (a=? AND b=?)
          238  +  |--LIST SUBQUERY
          239  +  |  `--SCAN TABLE d1
          240  +  `--LIST SUBQUERY
          241  +     `--SCAN TABLE d1
   242    242   }
   243    243   
   244    244   do_execsql_test 6.0 {
   245    245     CREATE TABLE e1(a, b, c, d, e);
   246    246     CREATE INDEX e1ab ON e1(a, b);
   247    247     CREATE INDEX e1cde ON e1(c, d, e);
   248    248   }
   249    249   
   250    250   do_eqp_test 6.1 {
   251    251     SELECT * FROM e1 WHERE (a, b) > (?, ?)
   252         -} {
   253         -  0 0 0 {SEARCH TABLE e1 USING INDEX e1ab ((a,b)>(?,?))}
   254         -}
          252  +} {SEARCH TABLE e1 USING INDEX e1ab ((a,b)>(?,?))}
          253  +
   255    254   do_eqp_test 6.2 {
   256    255     SELECT * FROM e1 WHERE (a, b) < (?, ?)
   257         -} {
   258         -  0 0 0 {SEARCH TABLE e1 USING INDEX e1ab ((a,b)<(?,?))}
   259         -}
          256  +} {SEARCH TABLE e1 USING INDEX e1ab ((a,b)<(?,?))}
          257  +
   260    258   do_eqp_test 6.3 {
   261    259     SELECT * FROM e1 WHERE c = ? AND (d, e) > (?, ?)
   262         -} {
   263         -  0 0 0 {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?))}
   264         -}
          260  +} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?))}
          261  +
   265    262   do_eqp_test 6.4 {
   266    263     SELECT * FROM e1 WHERE c = ? AND (d, e) < (?, ?)
   267         -} {
   268         -  0 0 0 {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))}
   269         -}
          264  +} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))}
   270    265   
   271    266   do_eqp_test 6.5 {
   272    267     SELECT * FROM e1 WHERE (d, e) BETWEEN (?, ?) AND (?, ?) AND c = ?
   273         -} {
   274         -  0 0 0 
   275         -  {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))}
   276         -}
          268  +} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))}
   277    269   
   278    270   #-------------------------------------------------------------------------
   279    271   
   280    272   do_execsql_test 7.1 {
   281    273     CREATE TABLE f1(a, b, c);
   282    274     CREATE INDEX f1ab ON f1(a, b);
   283    275   }

Changes to test/scanstatus.test.

   324    324   do_scanstatus_test 5.2.2 { 
   325    325     nLoop 1 nVisit 2 nEst 2.0 zName sqlite_autoindex_t1_1
   326    326     zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
   327    327   }
   328    328   
   329    329   do_eqp_test 5.3.1 {
   330    330     SELECT count(*) FROM t2 WHERE y = 'j';
   331         -} {0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}}
          331  +} {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
   332    332   do_execsql_test 5.3.2 {
   333    333     SELECT count(*) FROM t2 WHERE y = 'j';
   334    334   } {19}
   335    335   do_scanstatus_test 5.3.3 { 
   336    336     nLoop 1 nVisit 19 nEst 56.0 zName t2xy zExplain
   337    337     {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
   338    338   }
   339    339   
   340    340   do_eqp_test 5.4.1 {
   341    341     SELECT count(*) FROM t1, t2 WHERE y = c;
   342    342   } {
   343         -  0 0 0 {SCAN TABLE t1 USING COVERING INDEX t1bc}
   344         -  0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
          343  +  QUERY PLAN
          344  +  |--SCAN TABLE t1 USING COVERING INDEX t1bc
          345  +  `--SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)
   345    346   }
   346    347   do_execsql_test 5.4.2 {
   347    348     SELECT count(*) FROM t1, t2 WHERE y = c;
   348    349   } {200}
   349    350   do_scanstatus_test 5.4.3 { 
   350    351     nLoop 1 nVisit 10 nEst 10.0 zName t1bc 
   351    352     zExplain {SCAN TABLE t1 USING COVERING INDEX t1bc}
................................................................................
   352    353     nLoop 10 nVisit 200 nEst 56.0 zName t2xy 
   353    354     zExplain {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
   354    355   }
   355    356   
   356    357   do_eqp_test 5.5.1 {
   357    358     SELECT count(*) FROM t1, t3 WHERE y = c;
   358    359   } {
   359         -  0 0 1 {SCAN TABLE t3} 
   360         -  0 1 0 {SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)}
          360  +  QUERY PLAN
          361  +  |--SCAN TABLE t3
          362  +  `--SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)
   361    363   }
   362    364   do_execsql_test 5.5.2 {
   363    365     SELECT count(*) FROM t1, t3 WHERE y = c;
   364    366   } {200}
   365    367   do_scanstatus_test 5.5.3 { 
   366    368     nLoop 1 nVisit 501 nEst 480.0 zName t3 zExplain {SCAN TABLE t3}
   367    369     nLoop 501 nVisit 200 nEst 20.0 zName auto-index zExplain

Changes to test/selectA.test.

  1332   1332   
  1333   1333   do_eqp_test 4.1.2 {
  1334   1334     SELECT c, d FROM t5 
  1335   1335     UNION ALL
  1336   1336     SELECT a, b FROM t4 WHERE f()==f()
  1337   1337     ORDER BY 1,2
  1338   1338   } {
  1339         -  1 0 0 {SCAN TABLE t5 USING INDEX i2} 
  1340         -  1 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
  1341         -  2 0 0 {SCAN TABLE t4 USING INDEX i1} 
  1342         -  2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
  1343         -  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
         1339  +  QUERY PLAN
         1340  +  `--MERGE (UNION ALL)
         1341  +     |--LEFT
         1342  +     |  |--SCAN TABLE t5 USING INDEX i2
         1343  +     |  `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
         1344  +     `--RIGHT
         1345  +        |--SCAN TABLE t4 USING INDEX i1
         1346  +        `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
  1344   1347   }
  1345   1348   
  1346   1349   do_execsql_test 4.1.3 {
  1347   1350     SELECT c, d FROM t5 
  1348   1351     UNION ALL
  1349   1352     SELECT a, b FROM t4 WHERE f()==f()
  1350   1353     ORDER BY 1,2

Changes to test/selectD.test.

   165    165     SELECT * 
   166    166      FROM t41
   167    167      LEFT JOIN (SELECT count(*) AS cnt, x1.d
   168    168                   FROM (t42 INNER JOIN t43 ON d=g) AS x1
   169    169                  WHERE x1.d>5
   170    170                  GROUP BY x1.d) AS x2
   171    171                     ON t41.b=x2.d;
   172         -} {/.*SEARCH SUBQUERY 1 AS x2 USING AUTOMATIC.*/}
          172  +} {/*SEARCH SUBQUERY 0x* AS x2 USING AUTOMATIC*/}
   173    173   
   174    174   finish_test

Changes to test/skipscan2.test.

   195    195     for {set i 0} {$i < 1000} {incr i} {
   196    196       execsql { INSERT INTO t3 VALUES($i%2, $i, 'xyz') }
   197    197     }
   198    198     execsql { ANALYZE }
   199    199   } {}
   200    200   do_eqp_test skipscan2-3.3eqp {
   201    201     SELECT * FROM t3 WHERE b=42;
   202         -} {0 0 0 {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}}
          202  +} {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}
   203    203   
   204    204   
   205    205   finish_test

Changes to test/skipscan6.test.

   175    175     t3 t3_ba   {100 20 1 1}
   176    176   }
   177    177   
   178    178   # Use index "t3_a", as (a=?) is expected to match only a single row.
   179    179   #
   180    180   do_eqp_test 3.1 {
   181    181     SELECT * FROM t3 WHERE a = ? AND c = ?
   182         -} {
   183         -  0 0 0 {SEARCH TABLE t3 USING INDEX t3_a (a=?)}
   184         -}
          182  +} {SEARCH TABLE t3 USING INDEX t3_a (a=?)}
   185    183   
   186    184   # The same query on table t2. This should use index "t2_a", for the
   187    185   # same reason. At one point though, it was mistakenly using a skip-scan.
   188    186   #
   189    187   do_eqp_test 3.2 {
   190    188     SELECT * FROM t2 WHERE a = ? AND c = ?
   191         -} {
   192         -  0 0 0 {SEARCH TABLE t2 USING INDEX t2_a (a=?)}
   193         -}
   194         -
   195         -finish_test
   196         -
   197         -
   198         -
          189  +} {SEARCH TABLE t2 USING INDEX t2_a (a=?)}
   199    190   
   200    191   finish_test

Changes to test/tester.tcl.

   955    955     uplevel do_test [list $testname] [list "catchsql {$sql}"] [list $result]
   956    956   }
   957    957   proc do_timed_execsql_test {testname sql {result {}}} {
   958    958     fix_testname testname
   959    959     uplevel do_test [list $testname] [list "execsql_timed {$sql}"]\
   960    960                                      [list [list {*}$result]]
   961    961   }
          962  +
          963  +# Run an EXPLAIN QUERY PLAN $sql in database "db".  Then rewrite the output
          964  +# as an ASCII-art graph and return a string that is that graph.
          965  +#
          966  +# Hexadecimal literals in the output text are converted into "xxxxxx" since those
          967  +# literals are pointer values that might very from one run of the test to the
          968  +# next, yet we want the output to be consistent.
          969  +#
          970  +proc query_plan_graph {sql} {
          971  +  db eval "EXPLAIN QUERY PLAN $sql" {
          972  +    set dx($id) $detail
          973  +    lappend cx($parent) $id
          974  +  }
          975  +  set a "\n  QUERY PLAN\n"
          976  +  append a [append_graph "  " dx cx 0]
          977  +  return [regsub -all { 0x[A-F0-9]+\y} $a { xxxxxx}]
          978  +}
          979  +
          980  +# Helper routine for [query_plan_graph SQL]:
          981  +#
          982  +# Output rows of the graph that are children of $level.
          983  +#
          984  +#   prefix:  Prepend to every output line
          985  +#
          986  +#   dxname:  Name of an array variable that stores text describe
          987  +#            The description for $id is $dx($id)
          988  +#
          989  +#   cxname:  Name of an array variable holding children of item.
          990  +#            Children of $id are $cx($id)
          991  +#
          992  +#   level:   Render all lines that are children of $level
          993  +# 
          994  +proc append_graph {prefix dxname cxname level} {
          995  +  upvar $dxname dx $cxname cx
          996  +  set a ""
          997  +  set x $cx($level)
          998  +  set n [llength $x]
          999  +  for {set i 0} {$i<$n} {incr i} {
         1000  +    set id [lindex $x $i]
         1001  +    if {$i==$n-1} {
         1002  +      set p1 "`--"
         1003  +      set p2 "   "
         1004  +    } else {
         1005  +      set p1 "|--"
         1006  +      set p2 "|  "
         1007  +    }
         1008  +    append a $prefix$p1$dx($id)\n
         1009  +    if {[info exists cx($id)]} {
         1010  +      append a [append_graph "$prefix$p2" dx cx $id]
         1011  +    }
         1012  +  }
         1013  +  return $a
         1014  +}
         1015  +
         1016  +# Do an EXPLAIN QUERY PLAN test on input $sql with expected results $res
         1017  +#
         1018  +# If $res begins with a "\s+QUERY PLAN\n" then it is assumed to be the 
         1019  +# complete graph which must match the output of [query_plan_graph $sql]
         1020  +# exactly.
         1021  +#
         1022  +# If $res does not begin with "\s+QUERY PLAN\n" then take it is a string
         1023  +# that must be found somewhere in the query plan output.
         1024  +#
   962   1025   proc do_eqp_test {name sql res} {
   963         -  uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
         1026  +  if {[regexp {^\s+QUERY PLAN\n} $res]} {
         1027  +    uplevel do_test $name [list [list query_plan_graph $sql]] [list $res]
         1028  +  } else {
         1029  +    if {[string index $res 0]!="/"} {
         1030  +      set res "/*$res*/"
         1031  +    }
         1032  +    uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
         1033  +  }
   964   1034   }
         1035  +
   965   1036   
   966   1037   #-------------------------------------------------------------------------
   967   1038   #   Usage: do_select_tests PREFIX ?SWITCHES? TESTLIST
   968   1039   #
   969   1040   # Where switches are:
   970   1041   #
   971   1042   #   -errorformat FMTSTRING

Changes to test/tkt-385a5b56b9.test.

    30     30   
    31     31   do_execsql_test 2.0 {
    32     32     CREATE TABLE t2(x, y NOT NULL);
    33     33     CREATE UNIQUE INDEX t2x ON t2(x);
    34     34     CREATE UNIQUE INDEX t2y ON t2(y);
    35     35   }
    36     36   
    37         -do_eqp_test 2.1 { SELECT DISTINCT x FROM t2 } {
    38         -  0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2x}
    39         -}
           37  +do_eqp_test 2.1 { SELECT DISTINCT x FROM t2 } \
           38  +  {SCAN TABLE t2 USING COVERING INDEX t2x}
           39  +
           40  +do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } \
           41  +  {SCAN TABLE t2 USING COVERING INDEX t2y}
    40     42   
    41         -do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } {
    42         -  0 0 0 {SCAN TABLE t2 USING COVERING INDEX t2y}
    43         -}
           43  +do_eqp_test 2.3 { SELECT DISTINCT x, y FROM t2 WHERE y=10 } \
           44  +  {SEARCH TABLE t2 USING INDEX t2y (y=?)}
    44     45   
    45         -do_eqp_test 2.3 { SELECT DISTINCT x, y FROM t2 WHERE y=10 } {
    46         -  0 0 0 {SEARCH TABLE t2 USING INDEX t2y (y=?)}
    47         -}
           46  +do_eqp_test 2.4 { SELECT DISTINCT x, y FROM t2 WHERE x=10 } \
           47  +  {SEARCH TABLE t2 USING INDEX t2x (x=?)}
    48     48   
    49         -do_eqp_test 2.4 { SELECT DISTINCT x, y FROM t2 WHERE x=10 } {
    50         -  0 0 0 {SEARCH TABLE t2 USING INDEX t2x (x=?)}
    51         -}
    52     49   
    53     50   finish_test

Changes to test/tkt-78e04e52ea.test.

    37     37   } {0 {} {} 0 {} 0 1 x CHAR(100) 0 {} 0}
    38     38   do_test tkt-78e04-1.3 {
    39     39     execsql {
    40     40       CREATE INDEX i1 ON ""("" COLLATE nocase);
    41     41     }
    42     42   } {}
    43     43   do_test tkt-78e04-1.4 {
    44         -  execsql {
    45         -    EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1abc%';
    46         -  }
    47         -} {0 0 0 {SCAN TABLE  USING COVERING INDEX i1}}
           44  + db eval {EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1abc%';}
           45  +} {/*SCAN TABLE  USING COVERING INDEX i1*/}
    48     46   do_test tkt-78e04-1.5 {
    49     47     execsql {
    50     48       DROP TABLE "";
    51     49       SELECT name FROM sqlite_master;
    52     50     }
    53     51   } {t2}
    54     52   
    55     53   do_test tkt-78e04-2.1 {
    56     54     execsql {
    57     55       CREATE INDEX "" ON t2(x);
    58     56       EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE x=5;
    59     57     }
    60         -} {0 0 0 {SEARCH TABLE t2 USING COVERING INDEX  (x=?)}}
           58  +} {/*SEARCH TABLE t2 USING COVERING INDEX  (x=?)*/}
    61     59   do_test tkt-78e04-2.2 {
    62     60     execsql {
    63     61       DROP INDEX "";
    64     62       EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE x=2;
    65     63     }
    66         -} {0 0 0 {SCAN TABLE t2}}
           64  +} {/*SCAN TABLE t2*/}
    67     65   
    68     66   finish_test

Changes to test/tkt-b75a9ca6b0.test.

    28     28     INSERT INTO t1 VALUES (3, 1);
    29     29   }
    30     30   
    31     31   do_execsql_test 1.1 {
    32     32     CREATE INDEX i1 ON t1(x, y);
    33     33   } 
    34     34   
    35         -set idxscan {0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}}
    36         -set tblscan {0 0 0 {SCAN TABLE t1}}
    37         -set grpsort {0 0 0 {USE TEMP B-TREE FOR GROUP BY}}
    38         -set sort    {0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
           35  +set idxscan {SCAN TABLE t1 USING COVERING INDEX i1}
           36  +set tblscan {SCAN TABLE t1}
           37  +set grpsort {USE TEMP B-TREE FOR GROUP BY}
           38  +set sort    {USE TEMP B-TREE FOR ORDER BY}
    39     39   
    40     40   foreach {tn q res eqp} [subst -nocommands {
    41     41     1 "SELECT * FROM t1 GROUP BY x, y ORDER BY x,y"
    42     42     {1 3  2 2  3 1} {$idxscan}
    43     43   
    44     44     2 "SELECT * FROM t1 GROUP BY x, y ORDER BY x"
    45         -  {1 3  2 2  3 1} {$idxscan $sort}
           45  +  {1 3  2 2  3 1} {$idxscan*$sort}
    46     46   
    47     47     3 "SELECT * FROM t1 GROUP BY y, x ORDER BY y, x"
    48         -  {3 1  2 2  1 3} {$idxscan $sort}
           48  +  {3 1  2 2  1 3} {$idxscan*$sort}
    49     49     
    50     50     4 "SELECT * FROM t1 GROUP BY x ORDER BY x"
    51     51     {1 3  2 2  3 1} {$idxscan}
    52     52   
    53     53     5 "SELECT * FROM t1 GROUP BY y ORDER BY y"
    54         -  {3 1  2 2  1 3} {$tblscan $grpsort}
           54  +  {3 1  2 2  1 3} {$tblscan*$grpsort}
    55     55   
    56     56     6 "SELECT * FROM t1 GROUP BY y ORDER BY x"
    57         -  {1 3  2 2  3 1} {$tblscan $grpsort $sort}
           57  +  {1 3  2 2  3 1} {$tblscan*$grpsort*$sort}
    58     58   
    59     59     7 "SELECT * FROM t1 GROUP BY x, y ORDER BY x, y DESC"
    60         -  {1 3  2 2  3 1} {$idxscan $sort}
           60  +  {1 3  2 2  3 1} {$idxscan*$sort}
    61     61   
    62     62     8 "SELECT * FROM t1 GROUP BY x, y ORDER BY x DESC, y DESC"
    63         -  {3 1  2 2  1 3} {$idxscan $sort}
           63  +  {3 1  2 2  1 3} {$idxscan*$sort}
    64     64   
    65     65     9 "SELECT * FROM t1 GROUP BY x, y ORDER BY x ASC, y ASC"
    66     66     {1 3  2 2  3 1} {$idxscan}
    67     67   
    68     68     10 "SELECT * FROM t1 GROUP BY x, y ORDER BY x COLLATE nocase, y"
    69         -  {1 3  2 2  3 1} {$idxscan $sort}
           69  +  {1 3  2 2  3 1} {$idxscan*$sort}
    70     70   
    71     71   }] {
    72     72     do_execsql_test 1.$tn.1 $q $res
    73     73     do_eqp_test     1.$tn.2 $q $eqp
    74     74   }
    75     75   
    76     76   
    77     77   finish_test

Changes to test/tkt3442.test.

    30     30          id TEXT,
    31     31          node INTEGER
    32     32        );
    33     33        CREATE UNIQUE INDEX ididx ON listhash(id);
    34     34     }
    35     35   } {}
    36     36   
    37         -
    38         -# Explain Query Plan
    39         -#
    40         -proc EQP {sql} {
    41         -  uplevel "execsql {EXPLAIN QUERY PLAN $sql}"
    42         -}
    43         -
    44         -
    45     37   # These tests perform an EXPLAIN QUERY PLAN on both versions of the 
    46     38   # SELECT referenced in ticket #3442 (both '5000' and "5000") 
    47     39   # and verify that the query plan is the same.
    48     40   #
    49         -ifcapable explain {
    50         -  do_test tkt3442-1.2 {
    51         -    EQP { SELECT node FROM listhash WHERE id='5000' LIMIT 1; }
    52         -  } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}}
    53         -  do_test tkt3442-1.3 {
    54         -    EQP { SELECT node FROM listhash WHERE id="5000" LIMIT 1; }
    55         -  } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}}
    56         -}
           41  +do_eqp_test tkt3442-1.2 {
           42  +  SELECT node FROM listhash WHERE id='5000' LIMIT 1;
           43  +} {SEARCH TABLE listhash USING INDEX ididx (id=?)}
           44  +do_eqp_test tkt3442-1.3 {
           45  +  SELECT node FROM listhash WHERE id="5000" LIMIT 1;
           46  +} {SEARCH TABLE listhash USING INDEX ididx (id=?)}
    57     47   
    58     48   
    59     49   # Some extra tests testing other permutations of 5000.
    60     50   #
    61         -ifcapable explain {
    62         -  do_test tkt3442-1.4 {
    63         -    EQP { SELECT node FROM listhash WHERE id=5000 LIMIT 1; }
    64         -  } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}}
    65         -}
           51  +do_eqp_test tkt3442-1.4 {
           52  +  SELECT node FROM listhash WHERE id=5000 LIMIT 1;
           53  +} {SEARCH TABLE listhash USING INDEX ididx (id=?)}
           54  +
    66     55   do_test tkt3442-1.5 {
    67     56     catchsql {
    68     57       SELECT node FROM listhash WHERE id=[5000] LIMIT 1;
    69     58     }
    70     59   } {1 {no such column: 5000}}
    71     60   
    72     61   finish_test

Changes to test/tpch01.test.

   161    161                                  and p_type = 'LARGE PLATED STEEL'
   162    162                  ) as all_nations
   163    163          group by
   164    164                  o_year
   165    165          order by
   166    166                  o_year;}]
   167    167     set ::eqpres
   168         -} {/0 0 0 {SEARCH TABLE part USING INDEX bootleg_pti .P_TYPE=..} 0 1 2 {SEARCH TABLE lineitem USING INDEX lpki2 .L_PARTKEY=..}.*/}
          168  +} {/*SEARCH TABLE part USING INDEX bootleg_pti *SEARCH TABLE lineitem USING INDEX lpki2*/}
   169    169   do_test tpch01-1.1b {
   170    170     set ::eqpres
   171    171   } {/.* customer .* nation AS n1 .*/}
   172    172   do_test tpch01-1.1c {
   173    173     set ::eqpres
   174    174   } {/.* supplier .* nation AS n2 .*/}
   175    175   
................................................................................
   183    183       c_custkey = o_custkey    and l_orderkey = o_orderkey
   184    184       and o_orderdate >=  '1994-08-01'    and o_orderdate < date('1994-08-01', '+3 month')
   185    185       and l_returnflag = 'R'    and c_nationkey = n_nationkey
   186    186   group by
   187    187       c_custkey,    c_name,    c_acctbal,    c_phone,    n_name, c_address,    c_comment
   188    188   order by
   189    189       revenue desc;
   190         -} {0 0 1 {SEARCH TABLE orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE<?)} 0 1 0 {SEARCH TABLE customer USING INDEX cpki (C_CUSTKEY=?)} 0 2 3 {SEARCH TABLE nation USING INDEX npki (N_NATIONKEY=?)} 0 3 2 {SEARCH TABLE lineitem USING INDEX lpki (L_ORDERKEY=?)} 0 0 0 {USE TEMP B-TREE FOR GROUP BY} 0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
          190  +} {
          191  +  QUERY PLAN
          192  +  |--SEARCH TABLE orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE<?)
          193  +  |--SEARCH TABLE customer USING INDEX cpki (C_CUSTKEY=?)
          194  +  |--SEARCH TABLE nation USING INDEX npki (N_NATIONKEY=?)
          195  +  |--SEARCH TABLE lineitem USING INDEX lpki (L_ORDERKEY=?)
          196  +  |--USE TEMP B-TREE FOR GROUP BY
          197  +  `--USE TEMP B-TREE FOR ORDER BY
          198  +}
   191    199   
   192    200   finish_test

Changes to test/unordered.test.

    36     36     if {$idxmode == "unordered"} {
    37     37       execsql { UPDATE sqlite_stat1 SET stat = stat || ' unordered' }
    38     38     }
    39     39     db close
    40     40     sqlite3 db test.db
    41     41     foreach {tn sql r(ordered) r(unordered)} {
    42     42       1   "SELECT * FROM t1 ORDER BY a"
    43         -        {0 0 0 {SCAN TABLE t1 USING INDEX i1}}
    44         -        {0 0 0 {SCAN TABLE t1} 0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
           43  +        {SCAN TABLE t1 USING INDEX i1}
           44  +        {SCAN TABLE t1*USE TEMP B-TREE FOR ORDER BY}
    45     45       2   "SELECT * FROM t1 WHERE a > 100"
    46         -        {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}}
    47         -        {0 0 0 {SCAN TABLE t1}}
           46  +        {SEARCH TABLE t1 USING INDEX i1 (a>?)}
           47  +        {SCAN TABLE t1}
    48     48       3   "SELECT * FROM t1 WHERE a = ? ORDER BY rowid"
    49         -        {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
    50         -        {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)} 
    51         -         0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
           49  +        {SEARCH TABLE t1 USING INDEX i1 (a=?)}
           50  +        {SEARCH TABLE t1 USING INDEX i1 (a=?)*USE TEMP B-TREE FOR ORDER BY}
    52     51       4   "SELECT max(a) FROM t1"
    53         -        {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1}}
    54         -        {0 0 0 {SEARCH TABLE t1}}
           52  +        {SEARCH TABLE t1 USING COVERING INDEX i1}
           53  +        {SEARCH TABLE t1}
    55     54       5   "SELECT group_concat(b) FROM t1 GROUP BY a"
    56         -        {0 0 0 {SCAN TABLE t1 USING INDEX i1}}
    57         -        {0 0 0 {SCAN TABLE t1} 0 0 0 {USE TEMP B-TREE FOR GROUP BY}}
           55  +        {SCAN TABLE t1 USING INDEX i1}
           56  +        {SCAN TABLE t1*USE TEMP B-TREE FOR GROUP BY}
    58     57   
    59     58       6   "SELECT * FROM t1 WHERE a = ?"
    60         -        {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
    61         -        {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
           59  +        {SEARCH TABLE t1 USING INDEX i1 (a=?)}
           60  +        {SEARCH TABLE t1 USING INDEX i1 (a=?)}
    62     61       7   "SELECT count(*) FROM t1"
    63         -        {0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}}
    64         -        {0 0 0 {SCAN TABLE t1}}
           62  +        {SCAN TABLE t1 USING COVERING INDEX i1}
           63  +        {SCAN TABLE t1}
    65     64     } {
    66     65       do_eqp_test 1.$idxmode.$tn $sql $r($idxmode)
    67     66     }
    68     67   }
    69     68   
    70     69   finish_test

Changes to test/where3.test.

   231    231     CREATE TABLE t301(a INTEGER PRIMARY KEY,b,c);
   232    232     CREATE INDEX t301c ON t301(c);
   233    233     INSERT INTO t301 VALUES(1,2,3);
   234    234     INSERT INTO t301 VALUES(2,2,3);
   235    235     CREATE TABLE t302(x, y);
   236    236     INSERT INTO t302 VALUES(4,5);
   237    237     ANALYZE;
   238         -  explain query plan SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y;
          238  +}
          239  +do_eqp_test where3-3.0a {
          240  +  SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y;
   239    241   } {
   240         -  0 0 0 {SCAN TABLE t302} 
   241         -  0 1 1 {SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)}
          242  +  QUERY PLAN
          243  +  |--SCAN TABLE t302
          244  +  `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
   242    245   }
   243         -do_execsql_test where3-3.1 {
   244         -  explain query plan
          246  +do_eqp_test where3-3.1 {
   245    247     SELECT * FROM t301, t302 WHERE t302.x=5 AND t301.a=t302.y;
   246    248   } {
   247         -  0 0 1 {SCAN TABLE t302} 
   248         -  0 1 0 {SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)}
          249  +  QUERY PLAN
          250  +  |--SCAN TABLE t302
          251  +  `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
   249    252   }
   250    253   do_execsql_test where3-3.2 {
   251    254     SELECT * FROM t301 WHERE c=3 AND a IS NULL;
   252    255   } {}
   253    256   do_execsql_test where3-3.3 {
   254    257     SELECT * FROM t301 WHERE c=3 AND a IS NOT NULL;
   255    258   } {1 2 3 2 2 3}
................................................................................
   304    307                       fk INTEGER DEFAULT NULL, parent INTEGER,
   305    308                       position INTEGER, title LONGVARCHAR,
   306    309                       keyword_id INTEGER, folder_type TEXT,
   307    310                       dateAdded INTEGER, lastModified INTEGER);
   308    311     CREATE INDEX bbb_111 ON bbb (fk, type);
   309    312     CREATE INDEX bbb_222 ON bbb (parent, position);
   310    313     CREATE INDEX bbb_333 ON bbb (fk, lastModified);
   311         -
   312         -  EXPLAIN QUERY PLAN
          314  +}
          315  +do_eqp_test where3-5.0a {
   313    316      SELECT bbb.title AS tag_title 
   314    317        FROM aaa JOIN bbb ON bbb.id = aaa.parent  
   315    318       WHERE aaa.fk = 'constant'
   316    319         AND LENGTH(bbb.title) > 0
   317    320         AND bbb.parent = 4
   318    321       ORDER BY bbb.title COLLATE NOCASE ASC;
   319    322   } {
   320         -  0 0 0 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)} 
   321         -  0 1 1 {SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)} 
   322         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          323  +  QUERY PLAN
          324  +  |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
          325  +  |--SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)
          326  +  `--USE TEMP B-TREE FOR ORDER BY
   323    327   }
   324         -do_execsql_test where3-5.1 {
   325         -  EXPLAIN QUERY PLAN
          328  +do_eqp_test where3-5.1 {
   326    329      SELECT bbb.title AS tag_title 
   327    330        FROM aaa JOIN aaa AS bbb ON bbb.id = aaa.parent  
   328    331       WHERE aaa.fk = 'constant'
   329    332         AND LENGTH(bbb.title) > 0
   330    333         AND bbb.parent = 4
   331    334       ORDER BY bbb.title COLLATE NOCASE ASC;
   332    335   } {
   333         -  0 0 0 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)} 
   334         -  0 1 1 {SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)} 
   335         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          336  +  QUERY PLAN
          337  +  |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
          338  +  |--SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)
          339  +  `--USE TEMP B-TREE FOR ORDER BY
   336    340   }
   337         -do_execsql_test where3-5.2 {
   338         -  EXPLAIN QUERY PLAN
          341  +do_eqp_test where3-5.2 {
   339    342      SELECT bbb.title AS tag_title 
   340    343        FROM bbb JOIN aaa ON bbb.id = aaa.parent  
   341    344       WHERE aaa.fk = 'constant'
   342    345         AND LENGTH(bbb.title) > 0
   343    346         AND bbb.parent = 4
   344    347       ORDER BY bbb.title COLLATE NOCASE ASC;
   345    348   } {
   346         -  0 0 1 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)} 
   347         -  0 1 0 {SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)} 
   348         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          349  +  QUERY PLAN
          350  +  |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
          351  +  |--SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)
          352  +  `--USE TEMP B-TREE FOR ORDER BY
   349    353   }
   350         -do_execsql_test where3-5.3 {
   351         -  EXPLAIN QUERY PLAN
          354  +do_eqp_test where3-5.3 {
   352    355      SELECT bbb.title AS tag_title 
   353    356        FROM aaa AS bbb JOIN aaa ON bbb.id = aaa.parent  
   354    357       WHERE aaa.fk = 'constant'
   355    358         AND LENGTH(bbb.title) > 0
   356    359         AND bbb.parent = 4
   357    360       ORDER BY bbb.title COLLATE NOCASE ASC;
   358    361   } {
   359         -  0 0 1 {SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)} 
   360         -  0 1 0 {SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)} 
   361         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
          362  +  QUERY PLAN
          363  +  |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
          364  +  |--SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)
          365  +  `--USE TEMP B-TREE FOR ORDER BY
   362    366   }
   363    367   
   364    368   # Name resolution with NATURAL JOIN and USING
   365    369   #
   366    370   do_test where3-6.setup {
   367    371     db eval {
   368    372       CREATE TABLE t6w(a, w);

Changes to test/where7.test.

 23337  23337         c2 INTEGER,
 23338  23338         c4 INTEGER,
 23339  23339         FOREIGN KEY (c8) REFERENCES t301(c8)
 23340  23340     );
 23341  23341     CREATE INDEX t302_c3 on t302(c3);
 23342  23342     CREATE INDEX t302_c8_c3 on t302(c8, c3);
 23343  23343     CREATE INDEX t302_c5 on t302(c5);
 23344         -  
 23345         -  EXPLAIN QUERY PLAN
        23344  +}
        23345  +do_eqp_test where7-3.2 {
 23346  23346     SELECT t302.c1 
 23347  23347       FROM t302 JOIN t301 ON t302.c8 = +t301.c8
 23348  23348       WHERE t302.c2 = 19571
 23349  23349         AND t302.c3 > 1287603136
 23350  23350         AND (t301.c4 = 1407449685622784
 23351  23351              OR t301.c8 = 1407424651264000)
 23352  23352      ORDER BY t302.c5 LIMIT 200;
 23353  23353   } {
 23354         -  0 0 1 {SEARCH TABLE t301 USING COVERING INDEX t301_c4 (c4=?)} 
 23355         -  0 0 1 {SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)} 
 23356         -  0 1 0 {SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)} 
 23357         -  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
        23354  +  QUERY PLAN
        23355  +  |--MULTI-INDEX OR
        23356  +  |  |--SEARCH TABLE t301 USING COVERING INDEX t301_c4 (c4=?)
        23357  +  |  `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
        23358  +  |--SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)
        23359  +  `--USE TEMP B-TREE FOR ORDER BY
 23358  23360   }
 23359  23361   
 23360  23362   finish_test

Changes to test/where9.test.

   353    353        WHERE t1.a=t3.y OR t1.b=t3.y*11 OR (t1.c=27027 AND round(t1.d)==80)
   354    354       ORDER BY 1, 2, 3
   355    355     }
   356    356   } {1 80 2 1 80 28 1 80 54 1 80 80 2 80 2 2 80 28 2 80 54 2 80 80 scan 1 sort 1}
   357    357   
   358    358   
   359    359   ifcapable explain {
   360         -  do_execsql_test where9-3.1 {
   361         -    EXPLAIN QUERY PLAN
          360  +  do_eqp_test where9-3.1 {
   362    361       SELECT t2.a FROM t1, t2
   363    362       WHERE t1.a=80 AND ((t1.c=t2.c AND t1.d=t2.d) OR t1.f=t2.f)
   364         -  } {
   365         -    0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)} 
   366         -    0 1 1 {SEARCH TABLE t2 USING INDEX t2d (d=?)} 
   367         -    0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)}
   368         -  }
   369         -  do_execsql_test where9-3.2 {
   370         -    EXPLAIN QUERY PLAN
          363  +  } [string map {"\n  " \n} {
          364  +    QUERY PLAN
          365  +    |--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
          366  +    `--MULTI-INDEX OR
          367  +       |--SEARCH TABLE t2 USING INDEX t2d (d=?)
          368  +       `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)
          369  +  }]
          370  +  do_eqp_test where9-3.2 {
   371    371       SELECT coalesce(t2.a,9999)
   372    372       FROM t1 LEFT JOIN t2 ON (t1.c+1=t2.c AND t1.d=t2.d) OR (t1.f||'x')=t2.f
   373    373       WHERE t1.a=80
   374         -  } {
   375         -    0 0 0 {SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)} 
   376         -    0 1 1 {SEARCH TABLE t2 USING INDEX t2d (d=?)} 
   377         -    0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)}
   378         -  }
          374  +  } [string map {"\n  " \n} {
          375  +    QUERY PLAN
          376  +    |--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
          377  +    `--MULTI-INDEX OR
          378  +       |--SEARCH TABLE t2 USING INDEX t2d (d=?)
          379  +       `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)
          380  +  }]
   379    381   } 
   380    382   
   381    383   # Make sure that INDEXED BY and multi-index OR clauses play well with
   382    384   # one another.
   383    385   #
   384    386   do_test where9-4.1 {
   385    387     count_steps {
................................................................................
   442    444       SELECT a FROM t1 INDEXED BY t1d
   443    445        WHERE b>1000
   444    446          AND (c=31031 OR d IS NULL)
   445    447        ORDER BY +a
   446    448     }
   447    449   } {1 {no query solution}}
   448    450   
   449         -ifcapable explain {
   450         -  # The (c=31031 OR d IS NULL) clause is preferred over b>1000 because
   451         -  # the former is an equality test which is expected to return fewer rows.
   452         -  #
   453         -  do_execsql_test where9-5.1 {
   454         -    EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b>1000 AND (c=31031 OR d IS NULL)
   455         -  } {
   456         -    0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c=?)} 
   457         -    0 0 0 {SEARCH TABLE t1 USING INDEX t1d (d=?)}
   458         -  }
   459         -
   460         -  # In contrast, b=1000 is preferred over any OR-clause.
   461         -  #
   462         -  do_execsql_test where9-5.2 {
   463         -    EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b=1000 AND (c=31031 OR d IS NULL)
   464         -  } {
   465         -    0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}
   466         -  }
   467         -
   468         -  # Likewise, inequalities in an AND are preferred over inequalities in
   469         -  # an OR.
   470         -  #
   471         -  do_execsql_test where9-5.3 {
   472         -    EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b>1000 AND (c>=31031 OR d IS NULL)
   473         -  } {
   474         -    0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>?)}
   475         -  }
          451  +# The (c=31031 OR d IS NULL) clause is preferred over b>1000 because
          452  +# the former is an equality test which is expected to return fewer rows.
          453  +#
          454  +do_eqp_test where9-5.1 {
          455  +  SELECT a FROM t1 WHERE b>1000 AND (c=31031 OR d IS NULL)
          456  +} {
          457  +  QUERY PLAN
          458  +  `--MULTI-INDEX OR
          459  +     |--SEARCH TABLE t1 USING INDEX t1c (c=?)
          460  +     `--SEARCH TABLE t1 USING INDEX t1d (d=?)
   476    461   }
          462  +
          463  +# In contrast, b=1000 is preferred over any OR-clause.
          464  +#
          465  +do_eqp_test where9-5.2 {
          466  +  SELECT a FROM t1 WHERE b=1000 AND (c=31031 OR d IS NULL)
          467  +} {SEARCH TABLE t1 USING INDEX t1b (b=?)}
          468  +
          469  +# Likewise, inequalities in an AND are preferred over inequalities in
          470  +# an OR.
          471  +#
          472  +do_eqp_test where9-5.3 {
          473  +  SELECT a FROM t1 WHERE b>1000 AND (c>=31031 OR d IS NULL)
          474  +} {SEARCH TABLE t1 USING INDEX t1b (b>?)}
   477    475   
   478    476   ############################################################################
   479    477   # Make sure OR-clauses work correctly on UPDATE and DELETE statements.
   480    478   
   481    479   do_test where9-6.2.1 {
   482    480     db eval {SELECT count(*) FROM t1 UNION ALL SELECT a FROM t1 WHERE a>=85}
   483    481   } {99 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99}

Changes to test/whereG.test.

    62     62   } {}
    63     63   do_eqp_test whereG-1.1 {
    64     64     SELECT DISTINCT aname
    65     65       FROM album, composer, track
    66     66      WHERE unlikely(cname LIKE '%bach%')
    67     67        AND composer.cid=track.cid
    68     68        AND album.aid=track.aid;
    69         -} {/.*composer.*track.*album.*/}
           69  +} {composer*track*album}
    70     70   do_execsql_test whereG-1.2 {
    71     71     SELECT DISTINCT aname
    72     72       FROM album, composer, track
    73     73      WHERE unlikely(cname LIKE '%bach%')
    74     74        AND composer.cid=track.cid
    75     75        AND album.aid=track.aid;
    76     76   } {{Mass in B Minor, BWV 232}}
................................................................................
   191    191   
   192    192   do_execsql_test 5.1 {
   193    193     CREATE TABLE t1(a, b, c);
   194    194     CREATE INDEX i1 ON t1(a, b);
   195    195   }
   196    196   do_eqp_test 5.1.2 {
   197    197     SELECT * FROM t1 WHERE a>?
   198         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?)}}
          198  +} {SEARCH TABLE t1 USING INDEX i1 (a>?)}
   199    199   do_eqp_test 5.1.3 {
   200    200     SELECT * FROM t1 WHERE likelihood(a>?, 0.9)
   201         -} {0 0 0 {SCAN TABLE t1}}
          201  +} {SCAN TABLE t1}
   202    202   do_eqp_test 5.1.4 {
   203    203     SELECT * FROM t1 WHERE likely(a>?)
   204         -} {0 0 0 {SCAN TABLE t1}}
          204  +} {SCAN TABLE t1}
   205    205   
   206    206   do_test 5.2 {
   207    207     for {set i 0} {$i < 100} {incr i} {
   208    208       execsql { INSERT INTO t1 VALUES('abc', $i, $i); }
   209    209     }
   210    210     execsql { INSERT INTO t1 SELECT 'def', b, c FROM t1; }
   211    211     execsql { ANALYZE }
   212    212   } {}
   213    213   do_eqp_test 5.2.2 {
   214    214     SELECT * FROM t1 WHERE likelihood(b>?, 0.01)
   215         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (ANY(a) AND b>?)}}
          215  +} {SEARCH TABLE t1 USING INDEX i1 (ANY(a) AND b>?)}
   216    216   do_eqp_test 5.2.3 {
   217    217     SELECT * FROM t1 WHERE likelihood(b>?, 0.9)
   218         -} {0 0 0 {SCAN TABLE t1}}
          218  +} {SCAN TABLE t1}
   219    219   do_eqp_test 5.2.4 {
   220    220     SELECT * FROM t1 WHERE likely(b>?)
   221         -} {0 0 0 {SCAN TABLE t1}}
          221  +} {SCAN TABLE t1}
   222    222   
   223    223   do_eqp_test 5.3.1 {
   224    224     SELECT * FROM t1 WHERE a=?
   225         -} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}}
          225  +} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
   226    226   do_eqp_test 5.3.2 {
   227    227     SELECT * FROM t1 WHERE likelihood(a=?, 0.9)
   228         -} {0 0 0 {SCAN TABLE t1}}
          228  +} {SCAN TABLE t1}
   229    229   do_eqp_test 5.3.3 {
   230    230     SELECT * FROM t1 WHERE likely(a=?)
   231         -} {0 0 0 {SCAN TABLE t1}}
          231  +} {SCAN TABLE t1}
   232    232   
   233    233   # 2015-06-18
   234    234   # Ticket [https://www.sqlite.org/see/tktview/472f0742a1868fb58862bc588ed70]
   235    235   #
   236    236   do_execsql_test 6.0 {
   237    237     DROP TABLE IF EXISTS t1;
   238    238     CREATE TABLE t1(i int, x, y, z);

Changes to test/whereI.test.

    25     25     CREATE INDEX i1 ON t1(b);
    26     26     CREATE INDEX i2 ON t1(c);
    27     27   }
    28     28   
    29     29   do_eqp_test 1.1 {
    30     30     SELECT a FROM t1 WHERE b='b' OR c='x'
    31     31   } {
    32         -  0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b=?)} 
    33         -  0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}
           32  +  QUERY PLAN
           33  +  `--MULTI-INDEX OR
           34  +     |--SEARCH TABLE t1 USING INDEX i1 (b=?)
           35  +     `--SEARCH TABLE t1 USING INDEX i2 (c=?)
    34     36   }
    35     37   
    36     38   do_execsql_test 1.2 {
    37     39     SELECT a FROM t1 WHERE b='b' OR c='x'
    38     40   } {2 3}
    39     41   
    40     42   do_execsql_test 1.3 {
................................................................................
    53     55     CREATE INDEX i3 ON t2(b);
    54     56     CREATE INDEX i4 ON t2(c);
    55     57   }
    56     58   
    57     59   do_eqp_test 2.1 {
    58     60     SELECT a FROM t2 WHERE b='b' OR c='x'
    59     61   } {
    60         -  0 0 0 {SEARCH TABLE t2 USING INDEX i3 (b=?)} 
    61         -  0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
           62  +  QUERY PLAN
           63  +  `--MULTI-INDEX OR
           64  +     |--SEARCH TABLE t2 USING INDEX i3 (b=?)
           65  +     `--SEARCH TABLE t2 USING INDEX i4 (c=?)
    62     66   }
    63     67   
    64     68   do_execsql_test 2.2 {
    65     69     SELECT a FROM t2 WHERE b='b' OR c='x'
    66     70   } {ii iii}
    67     71   
    68     72   do_execsql_test 2.3 {

Changes to test/whereJ.test.

   398    398   
   399    399   # This one should use index "idx_c".
   400    400   do_eqp_test 3.4 {
   401    401     SELECT * FROM t1 WHERE 
   402    402       a = 4 AND b BETWEEN 20 AND 80           -- Matches 80 rows
   403    403         AND
   404    404       c BETWEEN 150 AND 160                   -- Matches 10 rows
   405         -} {
   406         -  0 0 0 {SEARCH TABLE t1 USING INDEX idx_c (c>? AND c<?)}
   407         -}
          405  +} {SEARCH TABLE t1 USING INDEX idx_c (c>? AND c<?)}
   408    406   
   409    407   # This one should use index "idx_ab".
   410    408   do_eqp_test 3.5 {
   411    409     SELECT * FROM t1 WHERE 
   412    410       a = 5 AND b BETWEEN 20 AND 80           -- Matches 1 row
   413    411         AND
   414    412       c BETWEEN 150 AND 160                   -- Matches 10 rows
   415         -} {
   416         -  0 0 0 {SEARCH TABLE t1 USING INDEX idx_ab (a=? AND b>? AND b<?)}
   417         -}
          413  +} {SEARCH TABLE t1 USING INDEX idx_ab (a=? AND b>? AND b<?)}
   418    414   
   419    415   ###########################################################################################
   420    416   
   421    417   # Reset the database and setup for a test case derived from actual SQLite users
   422    418   #
   423    419   db close
   424    420   sqlite3 db test.db

Changes to test/with1.test.

   988    988       FROM xyz ORDER BY 1
   989    989     )
   990    990     SELECT 1 FROM xyz;
   991    991   } 1
   992    992   
   993    993   # EXPLAIN QUERY PLAN on a self-join of a CTE
   994    994   #
   995         -do_execsql_test 19.1 {
          995  +do_execsql_test 19.1a {
   996    996     DROP TABLE IF EXISTS t1;
   997    997     CREATE TABLE t1(x);
   998         -  EXPLAIN QUERY PLAN
          998  +}
          999  +do_eqp_test 19.1b {
   999   1000     WITH
  1000   1001       x1(a) AS (values(100))
  1001   1002     INSERT INTO t1(x)
  1002   1003       SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
  1003   1004     SELECT * FROM t1;
  1004         -} {0 0 0 {SCAN SUBQUERY 1} 0 1 1 {SCAN SUBQUERY 1}}
         1005  +} {
         1006  +  QUERY PLAN
         1007  +  |--MATERIALIZE xxxxxx
         1008  +  |  `--SCAN CONSTANT ROW
         1009  +  |--SCAN SUBQUERY xxxxxx
         1010  +  `--SCAN SUBQUERY xxxxxx
         1011  +}
  1005   1012   
  1006   1013   # 2017-10-28.
  1007   1014   # See check-in https://sqlite.org/src/info/0926df095faf72c2
  1008   1015   # Tried to optimize co-routine processing by changing a Copy opcode
  1009   1016   # into SCopy.  But OSSFuzz found two (similar) cases where that optimization
  1010   1017   # does not work.
  1011   1018   #

Changes to test/with3.test.

    75     75       ANALYZE;
    76     76   
    77     77     }
    78     78   
    79     79     do_eqp_test 3.1.2 {
    80     80       WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1)
    81     81       SELECT * FROM cnt, y1 WHERE i=a
    82         -  } {
    83         -    3 0 0 {SCAN TABLE cnt} 
    84         -    1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)}
    85         -    0 0 0 {SCAN SUBQUERY 1} 
    86         -    0 1 1 {SEARCH TABLE y1 USING INDEX y1a (a=?)}
    87         -  }
           82  +  } [string map {"\n  " \n} {
           83  +    QUERY PLAN
           84  +    |--MATERIALIZE xxxxxx
           85  +    |  |--SETUP
           86  +    |  |  `--SCAN CONSTANT ROW
           87  +    |  `--RECURSIVE STEP
           88  +    |     `--SCAN TABLE cnt
           89  +    |--SCAN SUBQUERY xxxxxx
           90  +    `--SEARCH TABLE y1 USING INDEX y1a (a=?)
           91  +  }]
    88     92   
    89     93     do_eqp_test 3.1.3 {
    90     94       WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000000)
    91     95       SELECT * FROM cnt, y1 WHERE i=a
    92         -  } {
    93         -    3 0 0 {SCAN TABLE cnt} 
    94         -    1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)}
    95         -    0 0 1 {SCAN TABLE y1} 
    96         -    0 1 0 {SEARCH SUBQUERY 1 USING AUTOMATIC COVERING INDEX (i=?)}
    97         -  }
           96  +  } [string map {"\n  " \n} {
           97  +    QUERY PLAN
           98  +    |--MATERIALIZE xxxxxx
           99  +    |  |--SETUP
          100  +    |  |  `--SCAN CONSTANT ROW
          101  +    |  `--RECURSIVE STEP
          102  +    |     `--SCAN TABLE cnt
          103  +    |--SCAN TABLE y1
          104  +    `--SEARCH SUBQUERY xxxxxx USING AUTOMATIC COVERING INDEX (i=?)
          105  +  }]
    98    106   }
    99    107   
   100    108   do_execsql_test 3.2.1 {
   101    109     CREATE TABLE w1(pk INTEGER PRIMARY KEY, x INTEGER);
   102    110     CREATE TABLE w2(pk INTEGER PRIMARY KEY);
   103    111   }
   104    112   
   105    113   do_eqp_test 3.2.2 {
   106    114     WITH RECURSIVE c(w,id) AS (SELECT 0, (SELECT pk FROM w2 LIMIT 1)
   107    115        UNION ALL SELECT c.w + 1, x FROM w1, c LIMIT 1)
   108    116        SELECT * FROM c, w2, w1
   109    117        WHERE c.id=w2.pk AND c.id=w1.pk;
   110    118   } {
   111         -  2 0 0 {EXECUTE SCALAR SUBQUERY 3} 
   112         -  3 0 0 {SCAN TABLE w2} 
   113         -  4 0 0 {SCAN TABLE w1}
   114         -  4 1 1 {SCAN TABLE c} 
   115         -  1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)} 0 0 0 {SCAN SUBQUERY 1}
   116         -  0 1 1 {SEARCH TABLE w2 USING INTEGER PRIMARY KEY (rowid=?)} 
   117         -  0 2 2 {SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?)}
          119  +  QUERY PLAN
          120  +  |--MATERIALIZE xxxxxx
          121  +  |  |--SETUP
          122  +  |  |  |--SCAN CONSTANT ROW
          123  +  |  |  `--SCALAR SUBQUERY
          124  +  |  |     `--SCAN TABLE w2
          125  +  |  `--RECURSIVE STEP
          126  +  |     |--SCAN TABLE w1
          127  +  |     `--SCAN TABLE c
          128  +  |--SCAN SUBQUERY xxxxxx
          129  +  |--SEARCH TABLE w2 USING INTEGER PRIMARY KEY (rowid=?)
          130  +  `--SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?)
   118    131   }
   119    132   
   120    133   finish_test

Changes to test/without_rowid1.test.

   234    234     INSERT INTO t45 VALUES(5, 'two', 'x');
   235    235     INSERT INTO t45 VALUES(7, 'two', 'x');
   236    236     INSERT INTO t45 VALUES(9, 'two', 'x');
   237    237   }
   238    238   
   239    239   do_eqp_test 5.1 {
   240    240     SELECT * FROM t45 WHERE b=? AND a>?
   241         -} {/*USING INDEX i45 (b=? AND a>?)*/}
          241  +} {USING INDEX i45 (b=? AND a>?)}
   242    242   
   243    243   do_execsql_test 5.2 {
   244    244     SELECT * FROM t45 WHERE b='two' AND a>4
   245    245   } {5 two x 7 two x 9 two x}
   246    246   
   247    247   do_execsql_test 5.3 {
   248    248     SELECT * FROM t45 WHERE b='one' AND a<8
................................................................................
   253    253     WITH r(x) AS (
   254    254       SELECT 1 UNION ALL SELECT x+1 FROM r WHERE x<100
   255    255     )
   256    256     INSERT INTO t46 SELECT x / 20, x % 20, x % 10, x FROM r;
   257    257   }
   258    258   
   259    259   set queries {
   260         -  1    2    "c = 5 AND a = 1"          {/*i46 (c=? AND a=?)*/}
   261         -  2    6    "c = 4 AND a < 3"          {/*i46 (c=? AND a<?)*/}
   262         -  3    4    "c = 2 AND a >= 3"         {/*i46 (c=? AND a>?)*/}
   263         -  4    1    "c = 2 AND a = 1 AND b<10" {/*i46 (c=? AND a=? AND b<?)*/}
   264         -  5    1    "c = 0 AND a = 0 AND b>5"  {/*i46 (c=? AND a=? AND b>?)*/}
          260  +  1    2    "c = 5 AND a = 1"          {i46 (c=? AND a=?)}
          261  +  2    6    "c = 4 AND a < 3"          {i46 (c=? AND a<?)}
          262  +  3    4    "c = 2 AND a >= 3"         {i46 (c=? AND a>?)}
          263  +  4    1    "c = 2 AND a = 1 AND b<10" {i46 (c=? AND a=? AND b<?)}
          264  +  5    1    "c = 0 AND a = 0 AND b>5"  {i46 (c=? AND a=? AND b>?)}
   265    265   }
   266    266   
   267    267   foreach {tn cnt where eqp} $queries {
   268    268     do_execsql_test 5.5.$tn.1 "SELECT count(*) FROM t46 WHERE $where" $cnt
   269    269   }
   270    270   
   271    271   do_execsql_test 5.6 {