From: drh Date: Fri, 14 Feb 2014 23:49:13 +0000 (+0000) Subject: Seek past NULLs in a top-constrained search. Avoid checking for NULLs in X-Git-Tag: version-3.8.4~66 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cfc6ca41797342ea1d572c982a416024528b7ccd;p=thirdparty%2Fsqlite.git Seek past NULLs in a top-constrained search. Avoid checking for NULLs in the body of the search. FossilOrigin-Name: e07a32f30862acf3b322d4d8deb015846d6f8f5f --- diff --git a/manifest b/manifest index d8dd849567..8aef1ebcfc 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 3ff1fc2f3d..ed5e06552e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3c1ae447dec8fc2af1c5105134061717594ac0e0 \ No newline at end of file +e07a32f30862acf3b322d4d8deb015846d6f8f5f \ No newline at end of file diff --git a/src/where.c b/src/where.c index 96ee0e931e..c5bbeea0e1 100644 --- a/src/where.c +++ b/src/where.c @@ -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); diff --git a/test/where.test b/test/where.test index a50fe7ebcf..f560708cca 100644 --- a/test/where.test +++ b/test/where.test @@ -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} diff --git a/test/where4.test b/test/where4.test index 280eb5ff7f..a26e9ad355 100644 --- a/test/where4.test +++ b/test/where4.test @@ -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} diff --git a/test/where8.test b/test/where8.test index 287e4004c8..139251aa07 100644 --- a/test/where8.test +++ b/test/where8.test @@ -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 {