]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
An early attempt to get indexes to work with the IS operator. This code
authordrh <drh@noemail.net>
Wed, 13 May 2015 15:24:07 +0000 (15:24 +0000)
committerdrh <drh@noemail.net>
Wed, 13 May 2015 15:24:07 +0000 (15:24 +0000)
passes tests, but much more testing is needed to verify that it works on
all corner cases.

FossilOrigin-Name: 6f7f1673d00d216a5aa456acb44793a14f3b3d91

manifest
manifest.uuid
src/where.c
src/whereInt.h

index 0c5a5294e3b04b9bc7259cf3c60a13ee83cb8756..ec12a04f7c4b4fb1afca0159b864942dd5d28574 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhancements\sto\sthe\sMSVC\smakefile.
-D 2015-05-13T04:50:30.732
+C An\searly\sattempt\sto\sget\sindexes\sto\swork\swith\sthe\sIS\soperator.\s\sThis\scode\npasses\stests,\sbut\smuch\smore\stesting\sis\sneeded\sto\sverify\sthat\sit\sworks\son\nall\scorner\scases.
+D 2015-05-13T15:24:07.257
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in edfc69769e613a6359c42c06ea1d42c3bece1736
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -307,8 +307,8 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
 F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
-F src/where.c 85fff9c40569ccb79c3177419b339e7d7df566cb
-F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
+F src/where.c 48e3c1f0a8a7ecbaeb5a57c195254243d49430ba
+F src/whereInt.h 6b5a8ac7b4adc055176c3330d755735ed674335d
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
@@ -1258,7 +1258,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P b33f1bacfdb34fe66b7b073e68bfac38498d6e88
-R 786cf9bafb843a30daaea508385a36b1
-U mistachkin
-Z cf0d8cd171ac487c0fd87c289759c254
+P 59e3e9e764440b7feaafadff74f422535d21bca2
+R 9f6038338a4c8e424f8c4ba92f9afc16
+T *branch * index-is-operator
+T *sym-index-is-operator *
+T -sym-trunk *
+U drh
+Z a0eadd388567e992c46f2fabbded464e
index af09740391caad5f8097efb6a468eab85473077d..877d59c28e6cabeeb524bc8ccc726fcacab37797 100644 (file)
@@ -1 +1 @@
-59e3e9e764440b7feaafadff74f422535d21bca2
\ No newline at end of file
+6f7f1673d00d216a5aa456acb44793a14f3b3d91
\ No newline at end of file
index 85eb00b46be41653f5de00fdaea2739a60e617a1..6bbfaca8798263f8cd0d22307e3369059217bc8a 100644 (file)
@@ -363,7 +363,7 @@ static int allowedOp(int op){
   assert( TK_LT>TK_EQ && TK_LT<TK_GE );
   assert( TK_LE>TK_EQ && TK_LE<TK_GE );
   assert( TK_GE==TK_EQ+4 );
-  return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL;
+  return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
 }
 
 /*
@@ -416,6 +416,8 @@ static u16 operatorMask(int op){
     c = WO_IN;
   }else if( op==TK_ISNULL ){
     c = WO_ISNULL;
+  }else if( op==TK_IS ){
+    c = WO_EQ;
   }else{
     assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
     c = (u16)(WO_EQ<<(op-TK_EQ));
@@ -427,6 +429,7 @@ static u16 operatorMask(int op){
   assert( op!=TK_LE || c==WO_LE );
   assert( op!=TK_GT || c==WO_GT );
   assert( op!=TK_GE || c==WO_GE );
+  assert( op!=TK_IS || c==WO_EQ );
   return c;
 }
 
@@ -1254,6 +1257,7 @@ static void exprAnalyze(
       pTerm->u.leftColumn = pLeft->iColumn;
       pTerm->eOperator = operatorMask(op) & opMask;
     }
+    if( op==TK_IS ) pTerm->wtFlags |= TERM_NULLOK;
     if( pRight && pRight->op==TK_COLUMN ){
       WhereTerm *pNew;
       Expr *pDup;
@@ -1278,6 +1282,7 @@ static void exprAnalyze(
           pTerm->eOperator |= WO_EQUIV;
           eExtraOp = WO_EQUIV;
         }
+        if( op==TK_IS ) pNew->wtFlags |= TERM_NULLOK;
       }else{
         pDup = pExpr;
         pNew = pTerm;
@@ -1468,10 +1473,8 @@ static void exprAnalyze(
   ** as "x>NULL" if x is not an INTEGER PRIMARY KEY.  So construct a
   ** virtual term of that form.
   **
-  ** Note that the virtual term must be tagged with TERM_VNULL.  This
-  ** TERM_VNULL tag will suppress the not-null check at the beginning
-  ** of the loop.  Without the TERM_VNULL flag, the not-null check at
-  ** the start of the loop will prevent any results from being returned.
+  ** Note that the virtual term must be tagged with both TERM_VNULL
+  ** and TERM_NULLOK.
   */
   if( pExpr->op==TK_NOTNULL
    && pExpr->pLeft->op==TK_COLUMN
@@ -1488,7 +1491,7 @@ static void exprAnalyze(
                             sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0);
 
     idxNew = whereClauseInsert(pWC, pNewExpr,
-                              TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
+                              TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL|TERM_NULLOK);
     if( idxNew ){
       pNewTerm = &pWC->a[idxNew];
       pNewTerm->prereqRight = 0;
@@ -2792,7 +2795,7 @@ static int codeEqualityTerm(
   int iReg;                  /* Register holding results */
 
   assert( iTarget>0 );
-  if( pX->op==TK_EQ ){
+  if( pX->op==TK_EQ || pX->op==TK_IS ){
     iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
   }else if( pX->op==TK_ISNULL ){
     iReg = iTarget;
@@ -2977,7 +2980,9 @@ static int codeAllEqualityTerms(
     testcase( pTerm->eOperator & WO_IN );
     if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
       Expr *pRight = pTerm->pExpr->pRight;
-      if( sqlite3ExprCanBeNull(pRight) ){
+      if( (pTerm->wtFlags & TERM_NULLOK)==0
+       && sqlite3ExprCanBeNull(pRight)
+      ){
         sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
         VdbeCoverage(v);
       }
@@ -3626,7 +3631,7 @@ static Bitmask codeOneLoopStart(
       Expr *pRight = pRangeStart->pExpr->pRight;
       sqlite3ExprCode(pParse, pRight, regBase+nEq);
       whereLikeOptimizationStringFixup(v, pLevel, pRangeStart);
-      if( (pRangeStart->wtFlags & TERM_VNULL)==0
+      if( (pRangeStart->wtFlags & TERM_NULLOK)==0
        && sqlite3ExprCanBeNull(pRight)
       ){
         sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
@@ -3672,7 +3677,7 @@ static Bitmask codeOneLoopStart(
       sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
       sqlite3ExprCode(pParse, pRight, regBase+nEq);
       whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
-      if( (pRangeEnd->wtFlags & TERM_VNULL)==0
+      if( (pRangeEnd->wtFlags & TERM_NULLOK)==0
        && sqlite3ExprCanBeNull(pRight)
       ){
         sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
@@ -4158,9 +4163,10 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){
     if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
     if( pTerm->eOperator & WO_EQUIV  ) zType[1] = 'E';
     if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
-    sqlite3DebugPrintf("TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x\n",
-                       iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb,
-                       pTerm->eOperator);
+    sqlite3DebugPrintf(
+       "TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x wtFlags=0x%04x\n",
+       iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb,
+       pTerm->eOperator, pTerm->wtFlags);
     sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
   }
 }
index 04cc2029d8d3160da3f89f34160f1860a4bc3b8b..915d7b8d68318740256686b9afb2faa8c2341354 100644 (file)
@@ -280,6 +280,7 @@ struct WhereTerm {
 #define TERM_LIKEOPT    0x100  /* Virtual terms from the LIKE optimization */
 #define TERM_LIKECOND   0x200  /* Conditionally this LIKE operator term */
 #define TERM_LIKE       0x400  /* The original LIKE operator */
+#define TERM_NULLOK     0x800  /* Comparison operators against NULL work */
 
 /*
 ** An instance of the WhereScan object is used as an iterator for locating