]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enable optimization of IN operators on constraints to virtual tables.
authordrh <drh@noemail.net>
Tue, 16 Oct 2012 23:17:14 +0000 (23:17 +0000)
committerdrh <drh@noemail.net>
Tue, 16 Oct 2012 23:17:14 +0000 (23:17 +0000)
FossilOrigin-Name: aa650746b19e4a6a373f7e47effff3ab2f48e78c

manifest
manifest.uuid
src/where.c
test/vtab1.test

index be0f0a1ebcbed5b417bff9b681d462f16e447d4e..f9f1a4b2c98ee15f5e8446f7ace2a448db9c3fe2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Correct\scomments\sand\senhance\sreadability\sof\sthe\smkvsix\stool.
-D 2012-10-15T20:28:22.029
+C Enable\soptimization\sof\sIN\soperators\son\sconstraints\sto\svirtual\stables.
+D 2012-10-16T23:17:14.207
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5f4f26109f9d80829122e0e09f9cda008fa065fb
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -249,7 +249,7 @@ F src/vtab.c 9c64ae18af78c740610df841c6f49fc2d240a279
 F src/wal.c f5c7b5027d0ed0e9bc9afeb4a3a8dfea762ec7d2
 F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
 F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b
-F src/where.c 3e6c1f9efe4c6a029b0a750e0f6a63964f43bcce
+F src/where.c 62f667db8cdbb81028bf1c55ba4b0e845b79622c
 F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/aggnested.test 0be144b453e0622a085fae8665c32f5676708e00
@@ -916,7 +916,7 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
 F test/veryquick.test 7701bb609fe8bf6535514e8b849a309e8f00573b
 F test/view.test b182a67ec43f490b156b5a710827a341be83dd17
-F test/vtab1.test 10fb9e656fe4b318cd82ff1616a340acc01aac4b
+F test/vtab1.test 524beb672c42463fe3d37351b74253c0b835498d
 F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
 F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
 F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
@@ -1021,7 +1021,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9
-P 629a42d47a0d8f73de900f469845ce800bdb8959
-R c7830c7c0cb344c8cb6a175c95e5eb7f
-U mistachkin
-Z f2086ddd83e8b281e8d53ba90c91d2db
+P 2c3af657fee6153842d660a6ce29aa7d791ebd38
+R 5cbef12c646a3899761eba454f8c4105
+T *branch * vtab-IN-opt
+T *sym-vtab-IN-opt *
+T -sym-trunk *
+U drh
+Z 07568d163c180c755b6278e856d28eda
index 915ba493680eb7e7ef9000908593c8d328a24e92..1c366b32f048f3e55ad3d548ba695d6cdc717230 100644 (file)
@@ -1 +1 @@
-2c3af657fee6153842d660a6ce29aa7d791ebd38
\ No newline at end of file
+aa650746b19e4a6a373f7e47effff3ab2f48e78c
\ No newline at end of file
index b7663386acbc2a432654d2fb5868f5a298d7ae77..586d069b3f75acd4973fecd2c87a84bec5656f99 100644 (file)
@@ -253,7 +253,7 @@ struct WhereCost {
 #define WHERE_COLUMN_NULL  0x00080000  /* x IS NULL */
 #define WHERE_INDEXED      0x000f0000  /* Anything that uses an index */
 #define WHERE_NOT_FULLSCAN 0x100f3000  /* Does not do a full table scan */
-#define WHERE_IN_ABLE      0x000f1000  /* Able to support an IN operator */
+#define WHERE_IN_ABLE      0x080f1000  /* Able to support an IN operator */
 #define WHERE_TOP_LIMIT    0x00100000  /* x<EXPR or x<=EXPR constraint */
 #define WHERE_BTM_LIMIT    0x00200000  /* x>EXPR or x>=EXPR constraint */
 #define WHERE_BOTH_LIMIT   0x00300000  /* Both x>EXPR and x<EXPR */
@@ -2038,7 +2038,7 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
     assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
     testcase( pTerm->eOperator==WO_IN );
     testcase( pTerm->eOperator==WO_ISNULL );
-    if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+    if( pTerm->eOperator & (WO_ISNULL) ) continue;
     if( pTerm->wtFlags & TERM_VNULL ) continue;
     nTerm++;
   }
@@ -2086,15 +2086,18 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
                                                                    pUsage;
 
   for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+    u8 op;
     if( pTerm->leftCursor != pSrc->iCursor ) continue;
     assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
     testcase( pTerm->eOperator==WO_IN );
     testcase( pTerm->eOperator==WO_ISNULL );
-    if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+    if( pTerm->eOperator & (WO_ISNULL) ) continue;
     if( pTerm->wtFlags & TERM_VNULL ) continue;
     pIdxCons[j].iColumn = pTerm->u.leftColumn;
     pIdxCons[j].iTermOffset = i;
-    pIdxCons[j].op = (u8)pTerm->eOperator;
+    op = (u8)pTerm->eOperator;
+    if( op==WO_IN ) op = WO_EQ;
+    pIdxCons[j].op = op;
     /* The direct assignment in the previous line is possible only because
     ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical.  The
     ** following asserts verify this fact. */
@@ -2104,7 +2107,7 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
     assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
     assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
     assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
-    assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
+    assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
     j++;
   }
   for(i=0; i<nOrderBy; i++){
@@ -4030,6 +4033,7 @@ static Bitmask codeOneLoopStart(
     **          to access the data.
     */
     int iReg;   /* P3 Value for OP_VFilter */
+    int addrNotFound;
     sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
     int nConstraint = pVtabIdx->nConstraint;
     struct sqlite3_index_constraint_usage *aUsage =
@@ -4039,11 +4043,18 @@ static Bitmask codeOneLoopStart(
 
     sqlite3ExprCachePush(pParse);
     iReg = sqlite3GetTempRange(pParse, nConstraint+2);
+    addrNotFound = pLevel->addrBrk;
     for(j=1; j<=nConstraint; j++){
       for(k=0; k<nConstraint; k++){
         if( aUsage[k].argvIndex==j ){
-          int iTerm = aConstraint[k].iTermOffset;
-          sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1);
+          WhereTerm *pTerm = &pWC->a[aConstraint[k].iTermOffset];
+          int iTarget = iReg+j+1;
+          if( pTerm->eOperator & WO_IN ){
+            codeEqualityTerm(pParse, pTerm, pLevel, iTarget);
+            addrNotFound = pLevel->addrNxt;
+          }else{
+            sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
+          }
           break;
         }
       }
@@ -4051,7 +4062,7 @@ static Bitmask codeOneLoopStart(
     }
     sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
     sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
-    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr,
+    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
                       pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
     pVtabIdx->needToFreeIdxStr = 0;
     for(j=0; j<nConstraint; j++){
index 340994304ccd1f4a69344a9c9be2c0f1109e4912..3db65c58d913fd89b54193beda533e5d71b38ce0 100644 (file)
@@ -1091,12 +1091,54 @@ do_test vtab1.13-3 {
 } {15 {} 16}
 
 
+do_test vtab1-14.001 {
+  execsql {SELECT rowid, * FROM echo_c WHERE +rowid IN (1,2,3)}
+} {1 3 G H 2 {} 15 16 3 15 {} 16}
+do_test vtab1-14.002 {
+  execsql {SELECT rowid, * FROM echo_c WHERE rowid IN (1,2,3)}
+} {1 3 G H 2 {} 15 16 3 15 {} 16}
+do_test vtab1-14.003 {
+  execsql {SELECT rowid, * FROM echo_c WHERE +rowid IN (0,1,5,2,'a',3,NULL)}
+} {1 3 G H 2 {} 15 16 3 15 {} 16}
+do_test vtab1-14.004 {
+  execsql {SELECT rowid, * FROM echo_c WHERE rowid IN (0,1,5,'a',2,3,NULL)}
+} {1 3 G H 2 {} 15 16 3 15 {} 16}
+do_test vtab1-14.005 {
+  execsql {SELECT rowid, * FROM echo_c WHERE rowid NOT IN (0,1,5,'a',2,3)}
+} {}
+do_test vtab1-14.006 {
+  execsql {SELECT rowid, * FROM echo_c WHERE rowid NOT IN (0,5,'a',2,3)}
+} {1 3 G H}
+do_test vtab1-14.007 {
+  execsql {SELECT rowid, * FROM echo_c WHERE +rowid NOT IN (0,5,'a',2,3,NULL)}
+} {}
+do_test vtab1-14.008 {
+  execsql {SELECT rowid, * FROM echo_c WHERE rowid NOT IN (0,5,'a',2,3,NULL)}
+} {}
+do_test vtab1-14.011 {
+  execsql {SELECT * FROM echo_c WHERE +a IN (1,3,8,'x',NULL,15,24)}
+} {3 G H 15 {} 16}
+do_test vtab1-14.012 {
+  execsql {SELECT * FROM echo_c WHERE a IN (1,3,8,'x',NULL,15,24)}
+} {3 G H 15 {} 16}
+do_test vtab1-14.013 {
+  execsql {SELECT * FROM echo_c WHERE a NOT IN (1,8,'x',15,24)}
+} {3 G H}
+do_test vtab1-14.014 {
+  execsql {SELECT * FROM echo_c WHERE a NOT IN (1,8,'x',NULL,15,24)}
+} {}
+do_test vtab1-14.015 {
+  execsql {SELECT * FROM echo_c WHERE +a NOT IN (1,8,'x',NULL,15,24)}
+} {}
+
+
+
 do_test vtab1-14.1 {
   execsql { DELETE FROM c }
   set echo_module ""
   execsql { SELECT * FROM echo_c WHERE rowid IN (1, 2, 3) }
   set echo_module
-} [list xBestIndex {SELECT rowid, * FROM 'c'} xFilter {SELECT rowid, * FROM 'c'}]
+} {/xBestIndex {SELECT rowid, . FROM 'c' WHERE rowid = .} xFilter {SELECT rowid, . FROM 'c' WHERE rowid = .} 1/}
 
 do_test vtab1-14.2 {
   set echo_module ""
@@ -1114,7 +1156,7 @@ do_test vtab1-14.4 {
   set echo_module ""
   execsql { SELECT * FROM echo_c WHERE a IN (1, 2) }
   set echo_module
-} [list xBestIndex {SELECT rowid, * FROM 'c'} xFilter {SELECT rowid, * FROM 'c'}]
+} {/xBestIndex {SELECT rowid, . FROM 'c' WHERE a = .} xFilter {SELECT rowid, . FROM 'c' WHERE a = .} 1/}
 
 do_test vtab1-15.1 {
   execsql {