]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Query planner always honors the aConstraintUsage[].omit flag for the
authordrh <>
Thu, 27 Jan 2022 21:18:14 +0000 (21:18 +0000)
committerdrh <>
Thu, 27 Jan 2022 21:18:14 +0000 (21:18 +0000)
SQLITE_INDEX_CONSTRAINT_OFFSET constraint.

FossilOrigin-Name: 38c5151eb8cc789ad082a1b40d16b2ddb55454219bd685b6e420995af6a15f55

ext/misc/qpvtab.c
manifest
manifest.uuid
src/where.c
src/whereInt.h
src/wherecode.c
src/whereexpr.c

index 67f3cfc519412e7a8864214993e25765815ce42e..fb0c155a27ccc3fe4756444737bd42f282dd60c4 100644 (file)
@@ -40,7 +40,7 @@
 **
 ** Option 1 is the default behavior.  2 is use if there is a usable
 ** constraint on "flags" with an integer right-hand side that where the
-** value of the right-hand side has its 0x01 bit set.
+** value of the right-hand side has its 0x001 bit set.
 **
 ** All constraints on columns "a" through "e" are marked as "omit".
 **
 ** is an integer and that integer has its 0x02 bit set, then the
 ** orderByConsumed flag is set.
 **
+** FLAGS SUMMARY:
+**
+**   0x001               Columns 'a' through 'e' have INT values
+**   0x002               orderByConsumed is set
+**   0x004               OFFSET and LIMIT have omit set
+**
 ** COMPILE:
 **
 **   gcc -Wall -g -shared -fPIC -I. qpvtab.c -o qqvtab.so
@@ -228,7 +234,7 @@ static int qpvtabColumn(
       sqlite3_result_text64(ctx, z, zEnd-z, SQLITE_TRANSIENT, SQLITE_UTF8);
     }
   }else if( i>=QPVTAB_A && i<=QPVTAB_E ){
-    if( pCur->flags & 1 ){
+    if( pCur->flags & 0x001 ){
       sqlite3_result_int(ctx, i-QPVTAB_A+1);
     }else{
       char x = 'a'+i-QPVTAB_A;
@@ -347,7 +353,7 @@ static int qpvtabBestIndex(
       assert( rc==SQLITE_OK || pVal==0 );
       if( pVal ){
         pIdxInfo->idxNum = sqlite3_value_int(pVal);
-        if( pIdxInfo->idxNum & 2 ) pIdxInfo->orderByConsumed = 1;
+        if( pIdxInfo->idxNum & 0x002 ) pIdxInfo->orderByConsumed = 1;
       }
     }
     if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
@@ -367,9 +373,20 @@ static int qpvtabBestIndex(
       qpvtabStrAppendValue(pStr, pVal);
     }
     sqlite3_str_append(pStr, "\n", 1);
+  }
+  for(i=0; i<pIdxInfo->nConstraint; i++){
+    int iCol = pIdxInfo->aConstraint[i].iColumn;
+    int op = pIdxInfo->aConstraint[i].op;
+    if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
+     || op==SQLITE_INDEX_CONSTRAINT_OFFSET
+    ){
+      iCol = QPVTAB_NONE;
+    }
     if( iCol>=QPVTAB_A && pIdxInfo->aConstraint[i].usable ){
-      pIdxInfo->aConstraintUsage[i].argvIndex = ++k;   
-      pIdxInfo->aConstraintUsage[i].omit = 1;
+      pIdxInfo->aConstraintUsage[i].argvIndex = ++k;
+      if( iCol<=QPVTAB_FLAGS || (pIdxInfo->idxNum & 0x004)!=0 ){
+        pIdxInfo->aConstraintUsage[i].omit = 1;
+      }
     }
   }
   sqlite3_str_appendf(pStr, "nOrderBy,%d,,,,\n", pIdxInfo->nOrderBy);
index 55c1838999fefc93508765130e84f2d2416c4c36..f1f49fa5021ed56633b04fe126e92b407fb2c624 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Make\sLIMIT\sand\sOFFSET\svalues\savailable\sto\ssqlite3_vtab_rhs_value().
-D 2022-01-27T18:45:26.825
+C Query\splanner\salways\shonors\sthe\saConstraintUsage[].omit\sflag\sfor\sthe\nSQLITE_INDEX_CONSTRAINT_OFFSET\sconstraint.
+D 2022-01-27T21:18:14.656
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -316,7 +316,7 @@ F ext/misc/noop.c 81efe4cad9ec740e64388b14281cb983e6e2c223fed43eb77ab3e34946e0c1
 F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
 F ext/misc/percentile.c b9086e223d583bdaf8cb73c98a6539d501a2fc4282654adbfea576453d82e691
 F ext/misc/prefixes.c 0f4f8cff5aebc00a7e3ac4021fd59cfe1a8e17c800ceaf592859ecb9cbc38196
-F ext/misc/qpvtab.c 03986dca441274933dd924170ceee50ad248d24a4cd6a686ff45d5e65e5deac4
+F ext/misc/qpvtab.c 09738419e25f603a35c0ac8bd0a04daab794f48d08a9bc07a6085b9057b99009
 F ext/misc/regexp.c b267fd05ff8d38b22f4c2809d7b7a2c61d522e9faf2feb928dbb9662e4a3a386
 F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
 F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
@@ -639,10 +639,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
 F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
-F src/where.c f89c21296cdf23bbc73333c77a01e0bfdccc9d1a767d38a145e3a8658456b66c
-F src/whereInt.h e23780eb06810dc8bd7d855c97a667bf116cb929d8aa107ce1db91df8e47aaa8
-F src/wherecode.c 37878a0a6f790b77f41e7b3d77c42f14bded09aef3d363eaf19b3ee02e765666
-F src/whereexpr.c 455b5eeef49693ac6f7303e4529bb997fd4e0f0bd594a6f8e49c0ea7e399368f
+F src/where.c f61ca6dbb4bbb7171aa5f5459982d8d98aac24852572bcee250f9c469a1963ba
+F src/whereInt.h 0748a6fce98b41862445906922a809146ff7ef4de16ed9022b0bc4e5c43aa60a
+F src/wherecode.c c313ccf5ed13dc7e88c64f93733f414dee369a212508a866878696d83c64fc36
+F src/whereexpr.c 391d04108e4a5a701d2fad374ff54db8629bce12b55a7ee30a478d440ea4bfe0
 F src/window.c dfaec4abc6012cbc18e4a202ca3a5d5a0efcc4011d86a06d882ddaab8aedee4d
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
@@ -1942,8 +1942,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 74fa5757ee0a8499bcd6546dac1a3ecc6048ba9cff9e3e574e28e6e82e894a3d
-R 4f1dec533377c1a483f6b7fee31b9110
+P b2d37c086c87fe4aee013bba4eab26f642207cd2a797fe4888a6ef868884c191
+R 87c4173ca514b2a053765a7d35c4d8eb
 U drh
-Z 8464b51a4c3f5e11d93482ca57b3dd6d
+Z 05d67635fa5a91d132911c78dd294cd6
 # Remove this line to create a well-formed Fossil manifest.
index 93e902aff73083ae902534d070b050f0347a89ed..5e209241f674d0239e0bbe92b743267cef01b4f3 100644 (file)
@@ -1 +1 @@
-b2d37c086c87fe4aee013bba4eab26f642207cd2a797fe4888a6ef868884c191
\ No newline at end of file
+38c5151eb8cc789ad082a1b40d16b2ddb55454219bd685b6e420995af6a15f55
\ No newline at end of file
index 2afc012f600719d2e15c96e0d5b0e1eebaf994cf..ce6ae30709b1d9b2e4772062c3660277366eed95 100644 (file)
@@ -3463,10 +3463,9 @@ static int whereLoopAddBtree(
 ** Return true if pTerm is a virtual table LIMIT or OFFSET term.
 */
 static int isLimitTerm(WhereTerm *pTerm){
-  return pTerm->eOperator==WO_AUX && (
-       pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_LIMIT 
-    || pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET
-  );
+  assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 );
+  return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT 
+      && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
 }
 
 /*
@@ -3555,8 +3554,8 @@ static int whereLoopAddVirtualOne(
 
   mxTerm = -1;
   assert( pNew->nLSlot>=nConstraint );
-  for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
-  pNew->u.vtab.omitMask = 0;
+  memset(pNew->aLTerm, 0, sizeof(pNew->aLTerm[0])*nConstraint );
+  memset(&pNew->u.vtab, 0, sizeof(pNew->u.vtab));
   pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
   for(i=0; i<nConstraint; i++, pIdxCons++){
     int iTerm;
@@ -3590,6 +3589,9 @@ static int whereLoopAddVirtualOne(
         }else{
           testcase( i!=iTerm );
         }
+        if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET ){
+          pNew->u.vtab.bOmitOffset = 1;
+        }
       }
       if( (pTerm->eOperator & WO_IN)!=0 ){
         /* A virtual table that is constrained by an IN clause may not
index cdddc10524eabcc1893d2c31ce786db7f643579b..14c40fcb43b5f708f8ba41fb63924f68980a609a 100644 (file)
@@ -123,7 +123,8 @@ struct WhereLoop {
     } btree;
     struct {               /* Information for virtual tables */
       int idxNum;            /* Index number */
-      u8 needFree;           /* True if sqlite3_free(idxStr) is needed */
+      u8 needFree : 1;       /* True if sqlite3_free(idxStr) is needed */
+      u8 bOmitOffset : 1;    /* True to let virtual table handle offset */
       i8 isOrdered;          /* True if satisfies ORDER BY */
       u16 omitMask;          /* Terms that may be omitted */
       char *idxStr;          /* Index identifier string */
@@ -612,5 +613,6 @@ void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
 #define WHERE_TRANSCONS    0x00200000  /* Uses a transitive constraint */
 #define WHERE_BLOOMFILTER  0x00400000  /* Consider using a Bloom-filter */
 #define WHERE_SELFCULL     0x00800000  /* nOut reduced by extra WHERE terms */
+#define WHERE_OMIT_OFFSET  0x01000000  /* Set offset counter to zero */
 
 #endif /* !defined(SQLITE_WHEREINT_H) */
index 4990cda0cef5920fb0fd406b3f87758033a14fb2..2beb596e69891d18e97c672a5bd87ab317905f38 100644 (file)
@@ -1537,6 +1537,15 @@ Bitmask sqlite3WhereCodeOneLoopStart(
       }else{
         Expr *pRight = pTerm->pExpr->pRight;
         codeExprOrVector(pParse, pRight, iTarget, 1);
+        if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET
+         && pLoop->u.vtab.bOmitOffset
+        ){
+          assert( pTerm->eOperator==WO_AUX );
+          assert( pWInfo->pLimit!=0 );
+          assert( pWInfo->pLimit->iOffset>0 );
+          sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pLimit->iOffset);
+          VdbeComment((v,"Zero OFFSET counter"));
+        }
       }
     }
     sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
index 183f22f599bfa4e8246cb16ca985f40eb4627f82..8381994e2b630d0a76197efa077b9613268463bf 100644 (file)
@@ -1656,6 +1656,7 @@ void sqlite3WhereClauseClear(WhereClause *pWC){
     }
 #endif
     while(1){
+      assert( a->eMatchOp==0 || a->eOperator==WO_AUX );
       if( a->wtFlags & TERM_DYNAMIC ){
         sqlite3ExprDelete(db, a->pExpr);
       }