]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Seek past NULLs in a top-constrained search. Avoid checking for NULLs in
authordrh <drh@noemail.net>
Fri, 14 Feb 2014 23:49:13 +0000 (23:49 +0000)
committerdrh <drh@noemail.net>
Fri, 14 Feb 2014 23:49:13 +0000 (23:49 +0000)
the body of the search.

FossilOrigin-Name: e07a32f30862acf3b322d4d8deb015846d6f8f5f

manifest
manifest.uuid
src/where.c
test/where.test
test/where4.test
test/where8.test

index d8dd8495677f2333e0836e5146e9ea6acae21464..8aef1ebcfcd4048e61490963e028aa75710a97e9 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Reduce\sthe\snumber\sof\scases\swhere\sit\sis\snecessary\sto\scheck\sfor\sNULL\safter\nthe\sloop\sterminating\scondition.
-D 2014-02-14T20:59:53.587
+C Seek\spast\sNULLs\sin\sa\stop-constrained\ssearch.\s\sAvoid\schecking\sfor\sNULLs\sin\nthe\sbody\sof\sthe\ssearch.
+D 2014-02-14T23:49:13.552
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
 F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
-F src/where.c bf849f08ee09f15e507b5d5f4bc5b608761d5fe2
+F src/where.c 7d9c988741c7d0e4a57774ae4b56e59675c4014a
 F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -1068,14 +1068,14 @@ F test/walro.test 6cc247a0cc9b36aeea2057dd28a922a1cdfbd630
 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
 F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
 F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
-F test/where.test 701a633ed16c661cd597b9d504b485197a0f49d7
+F test/where.test 28b64e93428961b07b0d486778d63fd672948f6b
 F test/where2.test ed6baa9420a109d8be683dbef5d153d186f3690b
 F test/where3.test d28c51f257e60be30f74308fa385ceeddfb54a6e
-F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
+F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf
 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
 F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
-F test/where8.test 84033c4da466d90fe7ef0152661ff67fd218105f
+F test/where8.test 806f1dcec4088be2b826b33f757fe6e17c3236a1
 F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
 F test/where9.test 4f3eab951353a3ae164befc521c777dfa903e46c
 F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
@@ -1150,7 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P b6bea903ac8e1717ed50b221d73bd0be061c7663
-R f976ccc3e6f99e20be380cc680402b19
+P 3c1ae447dec8fc2af1c5105134061717594ac0e0
+R 20e62eafcdc3ac9a7a16fa36432e6177
 U drh
-Z d8a7427791a9ddd9c5e417477ea3c5a6
+Z f35a13e794e2689c6821aa3d892fcd6f
index 3ff1fc2f3d976ac9960d001e6701666657e59e57..ed5e06552e9f85cc91a2dc4bf71debd96288b6d5 100644 (file)
@@ -1 +1 @@
-3c1ae447dec8fc2af1c5105134061717594ac0e0
\ No newline at end of file
+e07a32f30862acf3b322d4d8deb015846d6f8f5f
\ No newline at end of file
index 96ee0e931eee32dba3a50ee051088f65d90eed5e..c5bbeea0e1fd5b06883ada52a70e02a77d951e03 100644 (file)
@@ -2985,9 +2985,7 @@ static Bitmask codeOneLoopStart(
       OP_IdxLT,            /* 3: (end_constraints &&  bRev &&  endEq) */
     };
     u16 nEq = pLoop->u.btree.nEq;     /* Number of == or IN terms */
-    int isMinQuery = 0;          /* If this is an optimized SELECT min(x).. */
     int regBase;                 /* Base register holding constraint values */
-    int r1;                      /* Temp register */
     WhereTerm *pRangeStart = 0;  /* Inequality constraint at range start */
     WhereTerm *pRangeEnd = 0;    /* Inequality constraint at range end */
     int startEq;                 /* True if range start uses ==, >= or <= */
@@ -3000,6 +2998,8 @@ static Bitmask codeOneLoopStart(
     int op;                      /* Instruction opcode */
     char *zStartAff;             /* Affinity for start of range constraint */
     char cEndAff = 0;            /* Affinity for end of range constraint */
+    u8 bSeekPastNull = 0;        /* True to seek past initial nulls */
+    u8 bStopAtNull = 0;          /* Add condition to terminate at NULLs */
 
     pIdx = pLoop->u.btree.pIndex;
     iIdxCur = pLevel->iIdxCur;
@@ -3018,7 +3018,7 @@ static Bitmask codeOneLoopStart(
      && (pIdx->nKeyCol>nEq)
     ){
       assert( pLoop->u.btree.nSkip==0 );
-      isMinQuery = 1;
+      bSeekPastNull = 1;
       nExtraReg = 1;
     }
 
@@ -3033,6 +3033,13 @@ static Bitmask codeOneLoopStart(
     if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
       pRangeEnd = pLoop->aLTerm[j++];
       nExtraReg = 1;
+      if( pRangeStart==0
+       && (pRangeEnd->wtFlags & TERM_VNULL)==0
+       && (j = pIdx->aiColumn[nEq])>=0 
+       && pIdx->pTable->aCol[j].notNull==0
+      ){
+        bSeekPastNull = 1;
+      }
     }
 
     /* Generate code to evaluate all constraint terms using == or IN
@@ -3052,6 +3059,7 @@ static Bitmask codeOneLoopStart(
      || (bRev && pIdx->nKeyCol==nEq)
     ){
       SWAP(WhereTerm *, pRangeEnd, pRangeStart);
+      SWAP(u8, bSeekPastNull, bStopAtNull);
     }
 
     testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
@@ -3083,13 +3091,13 @@ static Bitmask codeOneLoopStart(
       }  
       nConstraint++;
       testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
-    }else if( isMinQuery ){
+    }else if( bSeekPastNull ){
       sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
       nConstraint++;
       startEq = 0;
       start_constraints = 1;
     }
-    codeApplyAffinity(pParse, regBase, nConstraint, zStartAff);
+    codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff);
     op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
     assert( op!=0 );
     testcase( op==OP_Rewind );
@@ -3118,6 +3126,10 @@ static Bitmask codeOneLoopStart(
       }
       nConstraint++;
       testcase( pRangeEnd->wtFlags & TERM_VIRTUAL );
+    }else if( bStopAtNull ){
+      sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
+      endEq = 0;
+      nConstraint++;
     }
     sqlite3DbFree(db, zStartAff);
 
@@ -3125,7 +3137,7 @@ static Bitmask codeOneLoopStart(
     pLevel->p2 = sqlite3VdbeCurrentAddr(v);
 
     /* Check if the index cursor is past the end of the range. */
-    if( pRangeEnd || nEq ){
+    if( nConstraint ){
       op = aEndOp[bRev*2 + endEq];
       testcase( op==OP_IdxGT );
       testcase( op==OP_IdxGE );
@@ -3134,22 +3146,6 @@ static Bitmask codeOneLoopStart(
       sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
     }
 
-    /* If there are inequality constraint upper bound but not a lower
-    ** bound, then check that the value of the table column that the
-    ** inequality contrains is not NULL since there is alway an implied
-    ** lower bound of "column>NULL".
-    */
-    r1 = sqlite3GetTempReg(pParse);
-    if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==WHERE_TOP_LIMIT 
-     && (j = pIdx->aiColumn[nEq])>=0 
-     && pIdx->pTable->aCol[j].notNull==0 
-    ){
-      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
-      VdbeComment((v, "%s", pIdx->pTable->aCol[j].zName));
-      sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
-    }
-    sqlite3ReleaseTempReg(pParse, r1);
-
     /* Seek the table cursor, if required */
     disableTerm(pLevel, pRangeStart);
     disableTerm(pLevel, pRangeEnd);
index a50fe7ebcf0858e8e34171127e92cd395d4689ad..f560708cca0e92165d245af23e55cfad92811665 100644 (file)
@@ -237,10 +237,10 @@ do_test where-1.34 {
 } {97 99}
 do_test where-1.35 {
   count {SELECT w FROM t1 WHERE w<3}
-} {1 2 2}
+} {1 2 3}
 do_test where-1.36 {
   count {SELECT w FROM t1 WHERE w<=3}
-} {1 2 3 3}
+} {1 2 3 4}
 do_test where-1.37 {
   count {SELECT w FROM t1 WHERE w+1<=4 ORDER BY w}
 } {1 2 3 99}
index 280eb5ff7fb4703fbe5f36c7cfba3e7731ac8c72..a26e9ad35528b9531850e3193b231a23c6ba2ca9 100644 (file)
@@ -71,7 +71,7 @@ do_test where4-1.5 {
 } {1 2}
 do_test where4-1.6 {
   count {SELECT rowid FROM t1 WHERE w=1 AND x<9}
-} {1 3}
+} {1 2}
 do_test where4-1.7 {
   count {SELECT rowid FROM t1 WHERE w=1 AND x IS NULL AND y=3}
 } {2 2}
@@ -98,7 +98,7 @@ do_test where4-1.14 {
 } {7 2}
 do_test where4-1.15 {
   count {SELECT rowid FROM t1 WHERE w IS NULL AND x IS NULL AND y<0}
-} {2}
+} {1}
 do_test where4-1.16 {
   count {SELECT rowid FROM t1 WHERE w IS NULL AND x IS NULL AND y>=0}
 } {1}
index 287e4004c813369dcd97d2d00d75f4a34e314939..139251aa0729fca54adb348248ae451cb2190dd8 100644 (file)
@@ -87,13 +87,13 @@ do_test where8-1.8 {
 
 do_test where8-1.9 {
   execsql_status2 { SELECT c FROM t1 WHERE a >= 9 OR b <= 'eight' }
-} {IX X VIII 0 0 6}
+} {IX X VIII 0 0 7}
 
 do_test where8-1.10 {
   execsql_status2 { 
     SELECT c FROM t1 WHERE (a >= 9 AND c != 'X') OR b <= 'eight' 
   }
-} {IX VIII 0 0 6}
+} {IX VIII 0 0 7}
 
 do_test where8-1.11 {
   execsql_status2 {