]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix problems in the backport, reducing the number of errors in the TCL tests
authordrh <drh@noemail.net>
Sat, 12 Feb 2011 05:34:43 +0000 (05:34 +0000)
committerdrh <drh@noemail.net>
Sat, 12 Feb 2011 05:34:43 +0000 (05:34 +0000)
to just a few dozen.  Most of the remaining errors seem to be real and
desirable changes of behavior.

FossilOrigin-Name: 9d2b0af266b85f10823e54ca6417e76950c1d531

manifest
manifest.uuid
src/build.c
src/prepare.c
src/select.c
src/sqliteInt.h
src/vdbeaux.c
test/analyze2.test
test/indexedby.test
test/tester.tcl

index 227ecf3f83d5e574f0c218b6a1642a3dc8d0ddd3..fbee74f8e9c9c5a7b69ac6e5d7ec38ff2cf41086 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-C This\sis\sthe\sbeginning\sof\san\sattempt\sto\sbackport\srecent\squery\splanner\nenhancements\sto\sversion\s3.7.2.\s\sThe\scode\sin\sthis\sversion\sbuilds\sand\sruns\sand\nseems\sto\sgive\scorrect\sanswers,\sbut\sit\sgenerates\ssuboptimal\squery\splans\sand\nhence\smany\sof\sthe\stest\scases\sfail.\s\sThe\stest\sscript\sgives\sup\safter\s1000\serrors.
-D 2011-02-12T01:59:22.979
+C Fix\sproblems\sin\sthe\sbackport,\sreducing\sthe\snumber\sof\serrors\sin\sthe\sTCL\stests\nto\sjust\sa\sfew\sdozen.\s\sMost\sof\sthe\sremaining\serrors\sseem\sto\sbe\sreal\sand\ndesirable\schanges\sof\sbehavior.
+D 2011-02-12T05:34:43.018
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 543f91f24cd7fee774ecc0a61c19704c0c3e78fd
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -119,7 +119,7 @@ F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
 F src/btree.c 5047fb303cdf6806a42676a6f513c57e15b7d69b
 F src/btree.h b4ba2fdf6b64c7c376bdfffa826af6b786b151d9
 F src/btreeInt.h 5b034ff54800046cc5870605d683ac1f9134bd99
-F src/build.c 0018d49629fc4807100c988dd191dd95e185bb38
+F src/build.c a3c83d34a7f1e56308175076f65d510ae52dd6dc
 F src/callback.c da3c38d0ef5d7f04fae371e519bda61aa9cb1704
 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 F src/ctime.c 4f3aadad62c6c9f0d4e5a96718516ac4e3c598df
@@ -166,16 +166,16 @@ F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07
 F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
 F src/pcache1.c e921e8a1d52c93abde63cb6dad1fa39770410c52
 F src/pragma.c 8b24ce00a93de345b6c3bd1e1e2cfba9f63d2325
-F src/prepare.c ce4c35a2b1d5fe916e4a46b70d24a6e997d7c4c6
+F src/prepare.c c2b318037d626fed27905c9446730b560637217a
 F src/printf.c 8ae5082dd38a1b5456030c3755ec3a392cd51506
 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
 F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
-F src/select.c 8add6cab889fc02e1492eda8dba462ccf11f51dd
+F src/select.c 7a673c43b49d5f05f76e9c5a8cafa02862cbb901
 F src/shell.c 8517fc1f9c59ae4007e6cc8b9af91ab231ea2056
 F src/sqlite.h.in 2d72a6242df41c517e38eec8791abcf5484a36f1
 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
-F src/sqliteInt.h f419da0d4ca6f723aca055ef67e440723bc7c6ff
+F src/sqliteInt.h 39a0b4d6bd4f5daf75465a1d35c121f06cf85751
 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
 F src/status.c 496913d4e8441195f6f2a75b1c95993a45b9b30b
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -225,7 +225,7 @@ F src/vdbe.c 66c262a923915e596379b1d597178e04c5d719e4
 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2
 F src/vdbeInt.h ffd68c4d4229227a5089bec53a1c635146177abc
 F src/vdbeapi.c d0f4407e465f261780ad725c1caece7d66a6aa35
-F src/vdbeaux.c c73bcefcebfd3d2cf91bf6a41ef0fb0d884814c6
+F src/vdbeaux.c 157d62a6a8ca22c3792f5957e887df8bda2d58eb
 F src/vdbeblob.c 258a6010ba7a82b72b327fb24c55790655689256
 F src/vdbemem.c e5673f81a2381b35c60e73ef0a8502be2ab1041e
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
@@ -243,7 +243,7 @@ F test/alter3.test 25b95a136708f22b87184fa6a4309eea03d65153
 F test/alter4.test 9386ffd1e9c7245f43eca412b2058d747509cc1f
 F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
 F test/analyze.test bf692e7db414f268a136bade16c03a1bdbb9240c
-F test/analyze2.test 59dac6c399c0c5d1a90a11ee7cc606743fb6db93
+F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3
 F test/analyze3.test 6d4f4b0929545a9d1af803a0608a0c51b92a3537
 F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3
 F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
@@ -450,7 +450,7 @@ F test/incrvacuum_ioerr.test 57d2f5777ab13fa03b87b262a4ea1bad5cfc0291
 F test/index.test cbf301cdb2da43e4eac636c3400c2439af1834ad
 F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
 F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7
-F test/indexedby.test 5a1180602f2e72c481467bd4cae05dae5dc36f47
+F test/indexedby.test be501e381b82b2f8ab406309ba7aac46e221f4ad
 F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
 F test/insert.test aef273dd1cee84cc92407469e6bd1b3cdcb76908
 F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
@@ -625,7 +625,7 @@ F test/tclsqlite.test 8c154101e704170c2be10f137a5499ac2c6da8d3
 F test/tempdb.test 800c36623d67a2ad1f58784b9c5644e0405af6e6
 F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
 F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
-F test/tester.tcl 6135019fcfac363ea0e11aee670cc97080ab578e
+F test/tester.tcl ba665916dfef8c41769cd225ea374a6b05b75a96
 F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
 F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
 F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
@@ -849,18 +849,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 42537b60566f288167f1b5864a5435986838e3a3
-R 911182819e6787775a4c401119b6d58c
-T *bgcolor * #d1d3a8
-T *branch * branch-3.7.2
-T *sym-branch-3.7.2 *
-T -sym-trunk *
+P e72cf118cb25e9fed96f8d5cebbc0f637892479a
+R cd223ce61acd48a0fa6d93a74733dd61
 U drh
-Z 6673081ac69ed84639c088e8d1e7d477
+Z a73dbb9504f9bb87d458dc1f3711231d
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.6 (GNU/Linux)
 
-iD8DBQFNVel/oxKgR168RlERAmLzAJwLpY7ATRL1epv2W0jdVpK7vB8cTwCfT/I1
-KFlk2dAE9J/wYPCdpsrAlmY=
-=eWSL
+iD8DBQFNVhv2oxKgR168RlERApFoAJ4s0p8GLfjU21wkHd9FYZ6AXkPMTACeL9gy
+rUEoRNhVYquXJEH4o1up8iU=
+=3IXK
 -----END PGP SIGNATURE-----
index aa7409700f2d63f799ca0ca3771bd1235c1e079a..b7ab61dc19ba5382d31c5f176559c29193b31126 100644 (file)
@@ -1 +1 @@
-e72cf118cb25e9fed96f8d5cebbc0f637892479a
\ No newline at end of file
+9d2b0af266b85f10823e54ca6417e76950c1d531
\ No newline at end of file
index 636b8a6942e36256bc4330d748d3969e4ac84fef..b6316204b5e116fc868f94afaa22dbfa29318728 100644 (file)
@@ -802,6 +802,7 @@ void sqlite3StartTable(
   pTable->iPKey = -1;
   pTable->pSchema = db->aDb[iDb].pSchema;
   pTable->nRef = 1;
+  pTable->nRowEst = 1000000;
   assert( pParse->pNewTable==0 );
   pParse->pNewTable = pTable;
 
@@ -2832,14 +2833,14 @@ exit_create_index:
 void sqlite3DefaultRowEst(Index *pIdx){
   unsigned *a = pIdx->aiRowEst;
   int i;
+  unsigned n;
   assert( a!=0 );
-  a[0] = 1000000;
-  for(i=pIdx->nColumn; i>=5; i--){
-    a[i] = 5;
-  }
-  while( i>=1 ){
-    a[i] = 11 - i;
-    i--;
+  a[0] = pIdx->pTable->nRowEst;
+  if( a[0]<10 ) a[0] = 10;
+  n = 10;
+  for(i=1; i<=pIdx->nColumn; i++){
+    a[i] = n;
+    if( n>5 ) n--;
   }
   if( pIdx->onError!=OE_None ){
     a[pIdx->nColumn] = 1;
index 74accd761f00e0fab8a75b26b0829c2b609e4638..fa64a00dfd51d694c23be23241fce30aa0dbf642 100644 (file)
@@ -628,13 +628,13 @@ static int sqlite3Prepare(
   if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){
     static const char * const azColName[] = {
        "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
-       "order", "from", "detail"
+       "selectid", "order", "from", "detail"
     };
     int iFirst, mx;
     if( pParse->explain==2 ){
-      sqlite3VdbeSetNumCols(pParse->pVdbe, 3);
+      sqlite3VdbeSetNumCols(pParse->pVdbe, 4);
       iFirst = 8;
-      mx = 11;
+      mx = 12;
     }else{
       sqlite3VdbeSetNumCols(pParse->pVdbe, 8);
       iFirst = 0;
index 17184b675a544edb0d4075851136518aa48f93ce..e059ea135dfef30b781eb4ba4a9cd4e5f061516d 100644 (file)
@@ -1302,6 +1302,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
   assert( db->lookaside.bEnabled==0 );
   pTab->nRef = 1;
   pTab->zName = 0;
+  pTab->nRowEst = 1000000;
   selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
   selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
   pTab->iPKey = -1;
@@ -1372,6 +1373,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
       VdbeComment((v, "LIMIT counter"));
       if( n==0 ){
         sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
+      }else{
+        if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n;
       }
     }else{
       sqlite3ExprCode(pParse, p->pLimit, iLimit);
@@ -1528,6 +1531,7 @@ static int multiSelect(
   switch( p->op ){
     case TK_ALL: {
       int addr = 0;
+      int nLimit;
       assert( !pPrior->pLimit );
       pPrior->pLimit = p->pLimit;
       pPrior->pOffset = p->pOffset;
@@ -1548,6 +1552,13 @@ static int multiSelect(
       testcase( rc!=SQLITE_OK );
       pDelete = p->pPrior;
       p->pPrior = pPrior;
+      p->nSelectRow += pPrior->nSelectRow;
+      if( pPrior->pLimit
+       && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
+       && p->nSelectRow > (double)nLimit 
+      ){
+        p->nSelectRow = (double)nLimit;
+      }
       if( addr ){
         sqlite3VdbeJumpHere(v, addr);
       }
@@ -1618,6 +1629,7 @@ static int multiSelect(
       pDelete = p->pPrior;
       p->pPrior = pPrior;
       p->pOrderBy = 0;
+      if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow;
       sqlite3ExprDelete(db, p->pLimit);
       p->pLimit = pLimit;
       p->pOffset = pOffset;
@@ -1695,6 +1707,7 @@ static int multiSelect(
       testcase( rc!=SQLITE_OK );
       pDelete = p->pPrior;
       p->pPrior = pPrior;
+      if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
       sqlite3ExprDelete(db, p->pLimit);
       p->pLimit = pLimit;
       p->pOffset = pOffset;
@@ -2274,6 +2287,7 @@ static int multiSelectOrderBy(
     sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
     sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
     sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
+    p->nSelectRow += pPrior->nSelectRow;
   }
 
   /* Generate a subroutine to run when the results from select B
@@ -2281,6 +2295,7 @@ static int multiSelectOrderBy(
   */
   if( op==TK_INTERSECT ){
     addrEofB = addrEofA;
+    if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
   }else{  
     VdbeNoopComment((v, "eof-B subroutine"));
     addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
@@ -3101,6 +3116,7 @@ static int selectExpander(Walker *pWalker, Select *p){
       while( pSel->pPrior ){ pSel = pSel->pPrior; }
       selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
       pTab->iPKey = -1;
+      pTab->nRowEst = 1000000;
       pTab->tabFlags |= TF_Ephemeral;
 #endif
     }else{
@@ -3658,6 +3674,7 @@ int sqlite3Select(
       assert( pItem->isPopulated==0 );
       sqlite3Select(pParse, pSub, &dest);
       pItem->isPopulated = 1;
+      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
     }
     if( /*pParse->nErr ||*/ db->mallocFailed ){
       goto select_end;
@@ -3758,6 +3775,7 @@ int sqlite3Select(
   /* Set the limiter.
   */
   iEnd = sqlite3VdbeMakeLabel(v);
+  p->nSelectRow = (double)LARGEST_INT64;
   computeLimitRegisters(pParse, p, iEnd);
 
   /* Open a virtual index to use for the distinct set.
@@ -3780,6 +3798,7 @@ int sqlite3Select(
     */
     pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
     if( pWInfo==0 ) goto select_end;
+    if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
 
     /* If sorting index that was created by a prior OP_OpenEphemeral 
     ** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -3824,6 +3843,9 @@ int sqlite3Select(
       for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
         pItem->iAlias = 0;
       }
+      if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100;
+    }else{
+      p->nSelectRow = (double)1;
     }
 
  
index 123868444df8846b6238297df615faf5a88d1452..e2880d230b1969671e9000faaa18d0e1fdad0c02 100644 (file)
@@ -1995,6 +1995,7 @@ struct Select {
   Expr *pOffset;         /* OFFSET expression. NULL means not used. */
   int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
   int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this select */
+  double nSelectRow;     /* Estimated number of result rows */
 };
 
 /*
index 5a4ad84975cab5afd007070b5b3649e60e93e8b6..2ef841e23be4d84f4e690898d766c4aaa32ac041 100644 (file)
@@ -1182,12 +1182,10 @@ int sqlite3VdbeList(
     pMem->type = SQLITE_INTEGER;
     pMem++;
 
-    if( p->explain==1 ){
-      pMem->flags = MEM_Int;
-      pMem->u.i = pOp->p3;                          /* P3 */
-      pMem->type = SQLITE_INTEGER;
-      pMem++;
-    }
+    pMem->flags = MEM_Int;
+    pMem->u.i = pOp->p3;                          /* P3 */
+    pMem->type = SQLITE_INTEGER;
+    pMem++;
 
     if( sqlite3VdbeMemGrow(pMem, 32, 0) ){            /* P4 */
       assert( p->db->mallocFailed );
@@ -1232,7 +1230,7 @@ int sqlite3VdbeList(
       }
     }
 
-    p->nResColumn = 8 - 5*(p->explain-1);
+    p->nResColumn = 8 - 4*(p->explain-1);
     p->rc = SQLITE_OK;
     rc = SQLITE_ROW;
   }
index 7a606bb7f6d5d6e136283c270e9fef1bea616419..de2567bb6f704094f7c6920e033252a73755c531 100644 (file)
@@ -22,6 +22,8 @@ ifcapable !stat2 {
   return
 }
 
+set testprefix analyze2
+
 # Do not use a codec for tests in this file, as the database file is
 # manipulated directly using tcl scripts (using the [hexio_write] command).
 #
@@ -119,36 +121,56 @@ do_test analyze2-2.1 {
   execsql COMMIT
   execsql ANALYZE
 } {}
-do_test analyze2-2.2 {
-  eqp "SELECT * FROM t1 WHERE x>500 AND y>700"
-} {0 0 {TABLE t1 WITH INDEX t1_y}}
-do_test analyze2-2.3 {
-  eqp "SELECT * FROM t1 WHERE x>700 AND y>500"
-} {0 0 {TABLE t1 WITH INDEX t1_x}}
-do_test analyze2-2.3 {
-  eqp "SELECT * FROM t1 WHERE y>700 AND x>500"
-} {0 0 {TABLE t1 WITH INDEX t1_y}}
-do_test analyze2-2.4 {
-  eqp "SELECT * FROM t1 WHERE y>500 AND x>700"
-} {0 0 {TABLE t1 WITH INDEX t1_x}}
-do_test analyze2-2.5 {
-  eqp "SELECT * FROM t1 WHERE x BETWEEN 100 AND 200 AND y BETWEEN 400 AND 700"
-} {0 0 {TABLE t1 WITH INDEX t1_x}}
-do_test analyze2-2.6 {
-  eqp "SELECT * FROM t1 WHERE x BETWEEN 100 AND 500 AND y BETWEEN 400 AND 700"
-} {0 0 {TABLE t1 WITH INDEX t1_y}}
-do_test analyze2-2.7 {
-  eqp "SELECT * FROM t1 WHERE x BETWEEN -400 AND -300 AND y BETWEEN 100 AND 300"
-} {0 0 {TABLE t1 WITH INDEX t1_x}}
-do_test analyze2-2.8 {
-  eqp "SELECT * FROM t1 WHERE x BETWEEN 100 AND 300 AND y BETWEEN -400 AND -300"
-} {0 0 {TABLE t1 WITH INDEX t1_y}}
-do_test analyze2-2.9 {
-  eqp "SELECT * FROM t1 WHERE x BETWEEN 500 AND 100 AND y BETWEEN 100 AND 300"
-} {0 0 {TABLE t1 WITH INDEX t1_x}}
-do_test analyze2-2.10 {
-  eqp "SELECT * FROM t1 WHERE x BETWEEN 100 AND 300 AND y BETWEEN 500 AND 100"
-} {0 0 {TABLE t1 WITH INDEX t1_y}}
+do_eqp_test 2.2 {
+  SELECT * FROM t1 WHERE x>500 AND y>700
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~100 rows)}
+}
+do_eqp_test 2.3 {
+  SELECT * FROM t1 WHERE x>700 AND y>500
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>?) (~100 rows)}
+}
+do_eqp_test 2.3 {
+  SELECT * FROM t1 WHERE y>700 AND x>500
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~100 rows)}
+}
+do_eqp_test 2.4 {
+  SELECT * FROM t1 WHERE y>500 AND x>700
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>?) (~100 rows)}
+}
+do_eqp_test 2.5 {
+  SELECT * FROM t1 WHERE x BETWEEN 100 AND 200 AND y BETWEEN 400 AND 700
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x<?) (~25 rows)}
+}
+do_eqp_test 2.6 {
+  SELECT * FROM t1 WHERE x BETWEEN 100 AND 500 AND y BETWEEN 400 AND 700
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y<?) (~75 rows)}
+}
+do_eqp_test 2.7 {
+  SELECT * FROM t1 WHERE x BETWEEN -400 AND -300 AND y BETWEEN 100 AND 300
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x<?) (~12 rows)}
+}
+do_eqp_test 2.8 {
+  SELECT * FROM t1 WHERE x BETWEEN 100 AND 300 AND y BETWEEN -400 AND -300
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y<?) (~12 rows)}
+}
+do_eqp_test 2.9 {
+  SELECT * FROM t1 WHERE x BETWEEN 500 AND 100 AND y BETWEEN 100 AND 300
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x<?) (~12 rows)}
+}
+do_eqp_test 2.10 {
+  SELECT * FROM t1 WHERE x BETWEEN 100 AND 300 AND y BETWEEN 500 AND 100
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y<?) (~12 rows)}
+}
 
 do_test analyze2-3.1 {
   set alphabet [list a b c d e f g h i j]
@@ -177,21 +199,31 @@ do_test analyze2-3.2 {
   }
 } {t1 t1_y {100 299 499 699 899 ajj cjj ejj gjj ijj}}
 
-do_test analyze2-3.3 {
-  eqp "SELECT * FROM t1 WHERE x BETWEEN 100 AND 500 AND y BETWEEN 'a' AND 'b'"
-} {0 0 {TABLE t1 WITH INDEX t1_y}}
-do_test analyze2-3.4 {
-  eqp "SELECT * FROM t1 WHERE x BETWEEN 100 AND 400 AND y BETWEEN 'a' AND 'h'"
-} {0 0 {TABLE t1 WITH INDEX t1_x}}
-do_test analyze2-3.5 {
-  eqp "SELECT * FROM t1 WHERE x<'a' AND y>'h'"
-} {0 0 {TABLE t1 WITH INDEX t1_y}}
-do_test analyze2-3.6 {
-  eqp "SELECT * FROM t1 WHERE x<444 AND y>'h'"
-} {0 0 {TABLE t1 WITH INDEX t1_y}}
-do_test analyze2-3.7 {
-  eqp "SELECT * FROM t1 WHERE x<221 AND y>'g'"
-} {0 0 {TABLE t1 WITH INDEX t1_x}}
+do_eqp_test 3.3 {
+  SELECT * FROM t1 WHERE x BETWEEN 100 AND 500 AND y BETWEEN 'a' AND 'b'
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y<?) (~50 rows)}
+}
+do_eqp_test 3.4 {
+  SELECT * FROM t1 WHERE x BETWEEN 100 AND 400 AND y BETWEEN 'a' AND 'h'
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x<?) (~100 rows)}
+}
+do_eqp_test 3.5 {
+  SELECT * FROM t1 WHERE x<'a' AND y>'h'
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~66 rows)}
+}
+do_eqp_test 3.6 {
+  SELECT * FROM t1 WHERE x<444 AND y>'h'
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~66 rows)}
+}
+do_eqp_test 3.7 {
+  SELECT * FROM t1 WHERE x<221 AND y>'g'
+} {
+  0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x<?) (~66 rows)}
+}
 
 do_test analyze2-4.1 {
   execsql { CREATE TABLE t3(a COLLATE nocase, b) }
@@ -210,10 +242,12 @@ do_test analyze2-4.1 {
 } {}
 do_test analyze2-4.2 {
   execsql { 
+    PRAGMA automatic_index=OFF;
     SELECT tbl,idx,group_concat(sample,' ') 
     FROM sqlite_stat2 
     WHERE idx = 't3a' 
-    GROUP BY tbl,idx
+    GROUP BY tbl,idx;
+    PRAGMA automatic_index=ON;
   }
 } {t3 t3a {AfA bEj CEj dEj EEj fEj GEj hEj IEj jEj}}
 do_test analyze2-4.3 {
@@ -225,12 +259,16 @@ do_test analyze2-4.3 {
   }
 } {t3 t3b {AbA CIj EIj GIj IIj bIj dIj fIj hIj jIj}}
 
-do_test analyze2-4.4 {
-  eqp "SELECT * FROM t3 WHERE a > 'A' AND a < 'C' AND b > 'A' AND b < 'C'"
-} {0 0 {TABLE t3 WITH INDEX t3b}}
-do_test analyze2-4.5 {
-  eqp "SELECT * FROM t3 WHERE a > 'A' AND a < 'c' AND b > 'A' AND b < 'c'"
-} {0 0 {TABLE t3 WITH INDEX t3a}}
+do_eqp_test 4.4 {
+  SELECT * FROM t3 WHERE a > 'A' AND a < 'C' AND b > 'A' AND b < 'C'
+} {
+  0 0 0 {SEARCH TABLE t3 USING INDEX t3b (b>? AND b<?) (~11 rows)}
+}
+do_eqp_test 4.5 {
+  SELECT * FROM t3 WHERE a > 'A' AND a < 'c' AND b > 'A' AND b < 'c'
+} {
+  0 0 0 {SEARCH TABLE t3 USING INDEX t3a (a>? AND a<?) (~22 rows)}
+}
 
 ifcapable utf16 {
   proc test_collate {enc lhs rhs} {
@@ -260,15 +298,21 @@ ifcapable utf16 {
       GROUP BY tbl,idx
     }
   } {t4 t4x {afa bej cej dej eej fej gej hej iej jej}}
-  do_test analyze2-5.3 {
-    eqp "SELECT * FROM t4 WHERE x>'ccc'"
-  } {0 0 {TABLE t4 WITH INDEX t4x}}
-  do_test analyze2-5.4 {
-    eqp "SELECT * FROM t4 AS t41, t4 AS t42 WHERE t41.x>'ccc' AND t42.x>'ggg'"
-  } {0 1 {TABLE t4 AS t42 WITH INDEX t4x} 1 0 {TABLE t4 AS t41 WITH INDEX t4x}}
-  do_test analyze2-5.5 {
-    eqp "SELECT * FROM t4 AS t41, t4 AS t42 WHERE t41.x>'ddd' AND t42.x>'ccc'"
-  } {0 0 {TABLE t4 AS t41 WITH INDEX t4x} 1 1 {TABLE t4 AS t42 WITH INDEX t4x}}
+  do_eqp_test 5.3 {
+    SELECT * FROM t4 WHERE x>'ccc'
+  } {0 0 0 {SEARCH TABLE t4 USING COVERING INDEX t4x (x>?) (~800 rows)}}
+  do_eqp_test 5.4 {
+    SELECT * FROM t4 AS t41, t4 AS t42 WHERE t41.x>'ccc' AND t42.x>'ggg'
+  } {
+    0 0 1 {SEARCH TABLE t4 AS t42 USING COVERING INDEX t4x (x>?) (~300 rows)} 
+    0 1 0 {SEARCH TABLE t4 AS t41 USING COVERING INDEX t4x (x>?) (~800 rows)}
+  }
+  do_eqp_test 5.5 {
+    SELECT * FROM t4 AS t41, t4 AS t42 WHERE t41.x>'ddd' AND t42.x>'ccc'
+  } {
+    0 0 0 {SEARCH TABLE t4 AS t41 USING COVERING INDEX t4x (x>?) (~700 rows)} 
+    0 1 1 {SEARCH TABLE t4 AS t42 USING COVERING INDEX t4x (x>?) (~800 rows)}
+  }
 }
 
 #--------------------------------------------------------------------
@@ -306,7 +350,7 @@ do_test analyze2-6.1.1 {
        t5.a = 1 AND
        t6.a = 1 AND t6.b = 1
   }
-} {0 1 {TABLE t6 WITH INDEX t6i} 1 0 {TABLE t5 USING PRIMARY KEY}}
+} {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a=? AND b=?) (~9 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 do_test analyze2-6.1.2 {
   db cache flush
   execsql ANALYZE
@@ -314,14 +358,14 @@ do_test analyze2-6.1.2 {
        t5.a = 1 AND
        t6.a = 1 AND t6.b = 1
   }
-} {0 0 {TABLE t5 WITH INDEX t5i} 1 1 {TABLE t6 USING PRIMARY KEY}}
+} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 do_test analyze2-6.1.3 {
   sqlite3 db test.db
   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
        t5.a = 1 AND
        t6.a = 1 AND t6.b = 1
   }
-} {0 0 {TABLE t5 WITH INDEX t5i} 1 1 {TABLE t6 USING PRIMARY KEY}}
+} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 do_test analyze2-6.1.4 {
   execsql { 
     PRAGMA writable_schema = 1;
@@ -332,7 +376,7 @@ do_test analyze2-6.1.4 {
        t5.a = 1 AND
        t6.a = 1 AND t6.b = 1
   }
-} {0 0 {TABLE t5 WITH INDEX t5i} 1 1 {TABLE t6 USING PRIMARY KEY}}
+} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 do_test analyze2-6.1.5 {
   execsql { 
     PRAGMA writable_schema = 1;
@@ -343,7 +387,7 @@ do_test analyze2-6.1.5 {
        t5.a = 1 AND
        t6.a = 1 AND t6.b = 1
   }
-} {0 1 {TABLE t6 WITH INDEX t6i} 1 0 {TABLE t5 USING PRIMARY KEY}}
+} {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a=? AND b=?) (~9 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 do_test analyze2-6.1.6 {
   execsql { 
     PRAGMA writable_schema = 1;
@@ -354,7 +398,7 @@ do_test analyze2-6.1.6 {
        t5.a = 1 AND
        t6.a = 1 AND t6.b = 1
   }
-} {0 0 {TABLE t5 WITH INDEX t5i} 1 1 {TABLE t6 USING PRIMARY KEY}}
+} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 
 do_test analyze2-6.2.1 {
   execsql { 
@@ -366,7 +410,7 @@ do_test analyze2-6.2.1 {
         t5.a>1 AND t5.a<15 AND
         t6.a>1
   }
-} {0 0 {TABLE t5 WITH INDEX t5i} 1 1 {TABLE t6 USING PRIMARY KEY}}
+} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a<?) (~60000 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 do_test analyze2-6.2.2 {
   db cache flush
   execsql ANALYZE
@@ -374,14 +418,14 @@ do_test analyze2-6.2.2 {
         t5.a>1 AND t5.a<15 AND
         t6.a>1
   }
-} {0 1 {TABLE t6 WITH INDEX t6i} 1 0 {TABLE t5 USING PRIMARY KEY}}
+} {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 do_test analyze2-6.2.3 {
   sqlite3 db test.db
   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
         t5.a>1 AND t5.a<15 AND
         t6.a>1
   }
-} {0 1 {TABLE t6 WITH INDEX t6i} 1 0 {TABLE t5 USING PRIMARY KEY}}
+} {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 do_test analyze2-6.2.4 {
   execsql { 
     PRAGMA writable_schema = 1;
@@ -392,7 +436,7 @@ do_test analyze2-6.2.4 {
         t5.a>1 AND t5.a<15 AND
         t6.a>1
   }
-} {0 0 {TABLE t5 WITH INDEX t5i} 1 1 {TABLE t6 USING PRIMARY KEY}}
+} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a<?) (~60000 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 do_test analyze2-6.2.5 {
   execsql { 
     PRAGMA writable_schema = 1;
@@ -403,7 +447,7 @@ do_test analyze2-6.2.5 {
         t5.a>1 AND t5.a<15 AND
         t6.a>1
   }
-} {0 0 {TABLE t5 WITH INDEX t5i} 1 1 {TABLE t6 USING PRIMARY KEY}}
+} {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a<?) (~60000 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 do_test analyze2-6.2.6 {
   execsql { 
     PRAGMA writable_schema = 1;
@@ -415,7 +459,7 @@ do_test analyze2-6.2.6 {
         t5.a>1 AND t5.a<15 AND
         t6.a>1
   }
-} {0 1 {TABLE t6 WITH INDEX t6i} 1 0 {TABLE t5 USING PRIMARY KEY}}
+} {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 
 #--------------------------------------------------------------------
 # These tests, analyze2-7.*, test that the sqlite_stat2 functionality
@@ -459,7 +503,7 @@ ifcapable shared_cache {
           t5.a>1 AND t5.a<15 AND
           t6.a>1
     } db1
-  } {0 1 {TABLE t6 WITH INDEX t6i} 1 0 {TABLE t5 USING PRIMARY KEY}}
+  } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
   do_test analyze2-7.6 {
     incr_schema_cookie test.db
     execsql { SELECT * FROM sqlite_master } db2
@@ -467,7 +511,7 @@ ifcapable shared_cache {
           t5.a>1 AND t5.a<15 AND
           t6.a>1
     } db2
-  } {0 1 {TABLE t6 WITH INDEX t6i} 1 0 {TABLE t5 USING PRIMARY KEY}}
+  } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
   do_test analyze2-7.7 {
     incr_schema_cookie test.db
     execsql { SELECT * FROM sqlite_master } db1
@@ -475,7 +519,7 @@ ifcapable shared_cache {
           t5.a>1 AND t5.a<15 AND
           t6.a>1
     } db1
-  } {0 1 {TABLE t6 WITH INDEX t6i} 1 0 {TABLE t5 USING PRIMARY KEY}}
+  } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 
   do_test analyze2-7.8 {
     execsql { DELETE FROM sqlite_stat2 } db2
@@ -484,14 +528,14 @@ ifcapable shared_cache {
           t5.a>1 AND t5.a<15 AND
           t6.a>1
     } db1
-  } {0 1 {TABLE t6 WITH INDEX t6i} 1 0 {TABLE t5 USING PRIMARY KEY}}
+  } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
   do_test analyze2-7.9 {
     execsql { SELECT * FROM sqlite_master } db2
     eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
           t5.a>1 AND t5.a<15 AND
           t6.a>1
     } db2
-  } {0 1 {TABLE t6 WITH INDEX t6i} 1 0 {TABLE t5 USING PRIMARY KEY}}
+  } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 
   do_test analyze2-7.10 {
     incr_schema_cookie test.db
@@ -500,7 +544,7 @@ ifcapable shared_cache {
           t5.a>1 AND t5.a<15 AND
           t6.a>1
     } db1
-  } {0 0 {TABLE t5 WITH INDEX t5i} 1 1 {TABLE t6 USING PRIMARY KEY}}
+  } {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a<?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
 
   db1 close
   db2 close
index 70ab9f9b21eb0b80b20541e7ceacd26cd9ee1182..7ccc4de24a8dcd870503b57c5ad1d7d752c3e36d 100644 (file)
@@ -40,15 +40,18 @@ proc EQP {sql} {
 
 # These tests are to check that "EXPLAIN QUERY PLAN" is working as expected.
 #
-do_test indexedby-1.2 {
-  EQP { select * from t1 WHERE a = 10; }
-} {0 0 {TABLE t1 WITH INDEX i1}}
-do_test indexedby-1.3 {
-  EQP { select * from t1 ; }
-} {0 0 {TABLE t1}}
-do_test indexedby-1.4 {
-  EQP { select * from t1, t2 WHERE c = 10; }
-} {0 1 {TABLE t2 WITH INDEX i3} 1 0 {TABLE t1}}
+do_execsql_test indexedby-1.2 {
+  EXPLAIN QUERY PLAN select * from t1 WHERE a = 10; 
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~10 rows)}}
+do_execsql_test indexedby-1.3 {
+  EXPLAIN QUERY PLAN select * from t1 ; 
+} {0 0 0 {SCAN TABLE t1 (~1000000 rows)}}
+do_execsql_test indexedby-1.4 {
+  EXPLAIN QUERY PLAN select * from t1, t2 WHERE c = 10; 
+} {
+  0 0 1 {SEARCH TABLE t2 USING INDEX i3 (c=?) (~10 rows)} 
+  0 1 0 {SCAN TABLE t1 (~1000000 rows)}
+}
 
 # Parser tests. Test that an INDEXED BY or NOT INDEX clause can be 
 # attached to a table in the FROM clause, but not to a sub-select or
@@ -80,15 +83,17 @@ do_test indexedby-2.7 {
 
 # Tests for single table cases.
 #
-do_test indexedby-3.1 {
-  EQP { SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'}
-} {0 0 {TABLE t1}}
-do_test indexedby-3.2 {
-  EQP { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'}
-} {0 0 {TABLE t1 WITH INDEX i1}}
-do_test indexedby-3.3 {
-  EQP { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'}
-} {0 0 {TABLE t1 WITH INDEX i2}}
+do_execsql_test indexedby-3.1 {
+  EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
+} {0 0 0 {SCAN TABLE t1 (~10000 rows)}}
+do_execsql_test indexedby-3.2 {
+  EXPLAIN QUERY PLAN 
+  SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~2 rows)}}
+do_execsql_test indexedby-3.3 {
+  EXPLAIN QUERY PLAN 
+  SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?) (~2 rows)}}
 do_test indexedby-3.4 {
   catchsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' }
 } {1 {cannot use index: i2}}
@@ -102,12 +107,14 @@ do_test indexedby-3.7 {
   catchsql { SELECT * FROM t1 INDEXED BY i1 ORDER BY a }
 } {0 {}}
 
-do_test indexedby-3.8 {
-  EQP { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 ORDER BY e }
-} {0 0 {TABLE t3 WITH INDEX sqlite_autoindex_t3_1 ORDER BY}}
-do_test indexedby-3.9 {
-  EQP { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE e = 10 }
-} {0 0 {TABLE t3 WITH INDEX sqlite_autoindex_t3_1}}
+do_execsql_test indexedby-3.8 {
+  EXPLAIN QUERY PLAN 
+  SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 ORDER BY e 
+} {0 0 0 {SCAN TABLE t3 USING INDEX sqlite_autoindex_t3_1 (~1000000 rows)}}
+do_execsql_test indexedby-3.9 {
+  EXPLAIN QUERY PLAN 
+  SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE e = 10 
+} {0 0 0 {SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (e=?) (~1 rows)}}
 do_test indexedby-3.10 {
   catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE f = 10 }
 } {1 {cannot use index: sqlite_autoindex_t3_1}}
@@ -117,12 +124,18 @@ do_test indexedby-3.11 {
 
 # Tests for multiple table cases.
 #
-do_test indexedby-4.1 {
-  EQP { SELECT * FROM t1, t2 WHERE a = c }
-} {0 0 {TABLE t1} 1 1 {TABLE t2 WITH INDEX i3}}
-do_test indexedby-4.2 {
-  EQP { SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c }
-} {0 1 {TABLE t2} 1 0 {TABLE t1 WITH INDEX i1}}
+do_execsql_test indexedby-4.1 {
+  EXPLAIN QUERY PLAN SELECT * FROM t1, t2 WHERE a = c 
+} {
+  0 0 0 {SCAN TABLE t1 (~1000000 rows)} 
+  0 1 1 {SEARCH TABLE t2 USING INDEX i3 (c=?) (~10 rows)}
+}
+do_execsql_test indexedby-4.2 {
+  EXPLAIN QUERY PLAN SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c 
+} {
+  0 0 1 {SCAN TABLE t2 (~1000000 rows)} 
+  0 1 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~10 rows)}
+}
 do_test indexedby-4.3 {
   catchsql {
     SELECT * FROM t1 INDEXED BY i1, t2 INDEXED BY i3 WHERE a=c
@@ -138,15 +151,13 @@ do_test indexedby-4.4 {
 # also tests that nothing bad happens if an index refered to by
 # a CREATE VIEW statement is dropped and recreated.
 #
-do_test indexedby-5.1 {
-  execsql {
-    CREATE VIEW v2 AS SELECT * FROM t1 INDEXED BY i1 WHERE a > 5;
-  }
-  EQP { SELECT * FROM v2 }
-} {0 0 {TABLE t1 WITH INDEX i1}}
-do_test indexedby-5.2 {
-  EQP { SELECT * FROM v2 WHERE b = 10 }
-} {0 0 {TABLE t1 WITH INDEX i1}}
+do_execsql_test indexedby-5.1 {
+  CREATE VIEW v2 AS SELECT * FROM t1 INDEXED BY i1 WHERE a > 5;
+  EXPLAIN QUERY PLAN SELECT * FROM v2 
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?) (~250000 rows)}}
+do_execsql_test indexedby-5.2 {
+  EXPLAIN QUERY PLAN SELECT * FROM v2 WHERE b = 10 
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a>?) (~25000 rows)}}
 do_test indexedby-5.3 {
   execsql { DROP INDEX i1 }
   catchsql { SELECT * FROM v2 }
@@ -165,51 +176,53 @@ do_test indexedby-5.5 {
 
 # Test that "NOT INDEXED" may use the rowid index, but not others.
 # 
-do_test indexedby-6.1 {
-  EQP { SELECT * FROM t1 WHERE b = 10 ORDER BY rowid }
-} {0 0 {TABLE t1 WITH INDEX i2 ORDER BY}}
-do_test indexedby-6.2 {
-  EQP { SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid }
-} {0 0 {TABLE t1 USING PRIMARY KEY ORDER BY}}
+do_execsql_test indexedby-6.1 {
+  EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 10 ORDER BY rowid 
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?) (~10 rows)}}
+do_execsql_test indexedby-6.2 {
+  EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid 
+} {0 0 0 {SCAN TABLE t1 USING INTEGER PRIMARY KEY (~100000 rows)}}
 
 # Test that "INDEXED BY" can be used in a DELETE statement.
 # 
-do_test indexedby-7.1 {
-  EQP { DELETE FROM t1 WHERE a = 5 }
-} {0 0 {TABLE t1 WITH INDEX i1}}
-do_test indexedby-7.2 {
-  EQP { DELETE FROM t1 NOT INDEXED WHERE a = 5 }
-} {0 0 {TABLE t1}}
-do_test indexedby-7.3 {
-  EQP { DELETE FROM t1 INDEXED BY i1 WHERE a = 5 }
-} {0 0 {TABLE t1 WITH INDEX i1}}
-do_test indexedby-7.4 {
-  EQP { DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10}
-} {0 0 {TABLE t1 WITH INDEX i1}}
-do_test indexedby-7.5 {
-  EQP { DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10}
-} {0 0 {TABLE t1 WITH INDEX i2}}
+do_execsql_test indexedby-7.1 {
+  EXPLAIN QUERY PLAN DELETE FROM t1 WHERE a = 5 
+} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) (~10 rows)}}
+do_execsql_test indexedby-7.2 {
+  EXPLAIN QUERY PLAN DELETE FROM t1 NOT INDEXED WHERE a = 5 
+} {0 0 0 {SCAN TABLE t1 (~100000 rows)}}
+do_execsql_test indexedby-7.3 {
+  EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i1 WHERE a = 5 
+} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) (~10 rows)}}
+do_execsql_test indexedby-7.4 {
+  EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~2 rows)}}
+do_execsql_test indexedby-7.5 {
+  EXPLAIN QUERY PLAN DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?) (~2 rows)}}
 do_test indexedby-7.6 {
   catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5}
 } {1 {cannot use index: i2}}
 
 # Test that "INDEXED BY" can be used in an UPDATE statement.
 # 
-do_test indexedby-8.1 {
-  EQP { UPDATE t1 SET rowid=rowid+1 WHERE a = 5 }
-} {0 0 {TABLE t1 WITH INDEX i1}}
-do_test indexedby-8.2 {
-  EQP { UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 }
-} {0 0 {TABLE t1}}
-do_test indexedby-8.3 {
-  EQP { UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 }
-} {0 0 {TABLE t1 WITH INDEX i1}}
-do_test indexedby-8.4 {
-  EQP { UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 AND b = 10}
-} {0 0 {TABLE t1 WITH INDEX i1}}
-do_test indexedby-8.5 {
-  EQP { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5 AND b = 10}
-} {0 0 {TABLE t1 WITH INDEX i2}}
+do_execsql_test indexedby-8.1 {
+  EXPLAIN QUERY PLAN UPDATE t1 SET rowid=rowid+1 WHERE a = 5 
+} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) (~10 rows)}}
+do_execsql_test indexedby-8.2 {
+  EXPLAIN QUERY PLAN UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 
+} {0 0 0 {SCAN TABLE t1 (~100000 rows)}}
+do_execsql_test indexedby-8.3 {
+  EXPLAIN QUERY PLAN UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 
+} {0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?) (~10 rows)}}
+do_execsql_test indexedby-8.4 {
+  EXPLAIN QUERY PLAN 
+  UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 AND b = 10
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?) (~2 rows)}}
+do_execsql_test indexedby-8.5 {
+  EXPLAIN QUERY PLAN 
+  UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5 AND b = 10
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b=?) (~2 rows)}}
 do_test indexedby-8.6 {
   catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5}
 } {1 {cannot use index: i2}}
index fb26561b231f92eccbef7040b872da7a2b96f40e..736cc945ffbf54ef34ed6887a74caa0984245691 100644 (file)
@@ -338,6 +338,10 @@ proc do_execsql_test {testname sql result} {
 proc do_catchsql_test {testname sql result} {
   uplevel do_test $testname [list "catchsql {$sql}"] [list $result]
 }
+proc do_eqp_test {name sql res} {
+  uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] \
+     [list [string trim $res]]
+}
 
 
 # Run an SQL script.