mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Add VdbeCoverage() and VdbeCoverageIf() macros for improved VDBE coverage
testing. FossilOrigin-Name: b92d31a97d5fe4606d9ae1393c7f3e052f46bf5a
This commit is contained in:
18
manifest
18
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Improvements\sto\s"NOT\sIN\s(SELECT\s...)"\sprocessing.\s\sOnly\stest\sfor\sNULL\svalues\non\sthe\sRHS\son\sthe\sfirst\siteration,\sthen\sremember\sthe\sresult.\s\sThere\shas\sbeen\nlogic\sto\sdo\sthis\sfor\syear,\sbut\sit\sdidn't\swork\sright\sand\sended\sup\srepeating\nthe\sNULL\stest\son\severy\siteration.\s\sThis\sinefficiency\swas\sfound\susing\sthe\nVDBE\scoverage\stesting\stools.
|
C Add\sVdbeCoverage()\sand\sVdbeCoverageIf()\smacros\sfor\simproved\sVDBE\scoverage\ntesting.
|
||||||
D 2014-02-18T01:07:38.047
|
D 2014-02-18T03:07:12.342
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -172,7 +172,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
|||||||
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
|
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
|
||||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||||
F src/delete.c a00bf893bd39868c51020eba1fc5182eb36bfeb7
|
F src/delete.c a00bf893bd39868c51020eba1fc5182eb36bfeb7
|
||||||
F src/expr.c e908787e4728beefdf742db90666248f89b1da01
|
F src/expr.c 014b8087a15c4c314bdd798cb1cb0b32693f8b40
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c 3cd6ce998404fb1b7203d886d6fdff71cf3c8846
|
F src/fkey.c 3cd6ce998404fb1b7203d886d6fdff71cf3c8846
|
||||||
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
|
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
|
||||||
@@ -216,12 +216,12 @@ F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
|
|||||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||||
F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e
|
F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e
|
||||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||||
F src/select.c 618b53bd4553bd7a9ef95069396f12a8f28489e7
|
F src/select.c 28bff39f9bc5ec618b0719fe3f7b4be9f88b6f02
|
||||||
F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239
|
F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239
|
||||||
F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80
|
F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80
|
||||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||||
F src/sqliteInt.h 004bd50575a05eefba7228c2d0fee432a53200de
|
F src/sqliteInt.h 22111056d7d5c404fef783b13088ef87d98074d0
|
||||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
@@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
|||||||
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
|
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||||
F src/where.c 7825dce3f92d7c7de9329505deefe176cbd5ba43
|
F src/where.c d622974f30d3347c7b71bfe49ce1f1e9b6570980
|
||||||
F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
|
F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
@@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P a72687699ba2af2e7383be7371d4121750c7e34f
|
P 915f6f1c7aab54583729e60bdc1565f25ecc6f74
|
||||||
R babb7ab4a8213aedecd107bc9c2410b3
|
R d0043e1267f21a1ea521214d42169c3d
|
||||||
U drh
|
U drh
|
||||||
Z 3cb428699d451ff8a4012effde517352
|
Z f5a439caf79133298419241dae122f4e
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
915f6f1c7aab54583729e60bdc1565f25ecc6f74
|
b92d31a97d5fe4606d9ae1393c7f3e052f46bf5a
|
||||||
164
src/expr.c
164
src/expr.c
@@ -1369,24 +1369,6 @@ int sqlite3ExprCanBeNull(const Expr *p){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Generate an OP_IsNull instruction that tests register iReg and jumps
|
|
||||||
** to location iDest if the value in iReg is NULL. The value in iReg
|
|
||||||
** was computed by pExpr. If we can look at pExpr at compile-time and
|
|
||||||
** determine that it can never generate a NULL, then the OP_IsNull operation
|
|
||||||
** can be omitted.
|
|
||||||
*/
|
|
||||||
void sqlite3ExprCodeIsNullJump(
|
|
||||||
Vdbe *v, /* The VDBE under construction */
|
|
||||||
const Expr *pExpr, /* Only generate OP_IsNull if this expr can be NULL */
|
|
||||||
int iReg, /* Test the value in this register for NULL */
|
|
||||||
int iDest /* Jump here if the value is null */
|
|
||||||
){
|
|
||||||
if( sqlite3ExprCanBeNull(pExpr) ){
|
|
||||||
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iDest); VdbeCoverage(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Return TRUE if the given expression is a constant which would be
|
** Return TRUE if the given expression is a constant which would be
|
||||||
** unchanged by OP_Affinity with the affinity given in the second
|
** unchanged by OP_Affinity with the affinity given in the second
|
||||||
@@ -1486,9 +1468,7 @@ static int isCandidateForInOpt(Select *p){
|
|||||||
*/
|
*/
|
||||||
int sqlite3CodeOnce(Parse *pParse){
|
int sqlite3CodeOnce(Parse *pParse){
|
||||||
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
|
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
|
||||||
int addr = sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
|
return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
|
||||||
VdbeCoverage(v);
|
|
||||||
return addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1596,9 +1576,8 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
|
|||||||
*/
|
*/
|
||||||
assert(v);
|
assert(v);
|
||||||
if( iCol<0 ){
|
if( iCol<0 ){
|
||||||
int iAddr;
|
int iAddr = sqlite3CodeOnce(pParse);
|
||||||
|
VdbeCoverage(v);
|
||||||
iAddr = sqlite3CodeOnce(pParse);
|
|
||||||
|
|
||||||
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
||||||
eType = IN_INDEX_ROWID;
|
eType = IN_INDEX_ROWID;
|
||||||
@@ -1623,7 +1602,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
|
|||||||
&& sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
|
&& sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
|
||||||
&& (!mustBeUnique || (pIdx->nKeyCol==1 && pIdx->onError!=OE_None))
|
&& (!mustBeUnique || (pIdx->nKeyCol==1 && pIdx->onError!=OE_None))
|
||||||
){
|
){
|
||||||
int iAddr = sqlite3CodeOnce(pParse);
|
int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||||
sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
|
sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
|
||||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||||
VdbeComment((v, "%s", pIdx->zName));
|
VdbeComment((v, "%s", pIdx->zName));
|
||||||
@@ -1723,7 +1702,7 @@ int sqlite3CodeSubselect(
|
|||||||
** save the results, and reuse the same result on subsequent invocations.
|
** save the results, and reuse the same result on subsequent invocations.
|
||||||
*/
|
*/
|
||||||
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
|
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
|
||||||
testAddr = sqlite3CodeOnce(pParse);
|
testAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_EXPLAIN
|
#ifndef SQLITE_OMIT_EXPLAIN
|
||||||
@@ -2548,22 +2527,16 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
case TK_GE:
|
case TK_GE:
|
||||||
case TK_NE:
|
case TK_NE:
|
||||||
case TK_EQ: {
|
case TK_EQ: {
|
||||||
assert( TK_LT==OP_Lt );
|
|
||||||
assert( TK_LE==OP_Le );
|
|
||||||
assert( TK_GT==OP_Gt );
|
|
||||||
assert( TK_GE==OP_Ge );
|
|
||||||
assert( TK_EQ==OP_Eq );
|
|
||||||
assert( TK_NE==OP_Ne );
|
|
||||||
testcase( op==TK_LT );
|
|
||||||
testcase( op==TK_LE );
|
|
||||||
testcase( op==TK_GT );
|
|
||||||
testcase( op==TK_GE );
|
|
||||||
testcase( op==TK_EQ );
|
|
||||||
testcase( op==TK_NE );
|
|
||||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||||
r1, r2, inReg, SQLITE_STOREP2); VdbeCoverage(v);
|
r1, r2, inReg, SQLITE_STOREP2);
|
||||||
|
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||||
|
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||||
|
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
||||||
|
assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
|
||||||
|
assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
|
||||||
|
assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
|
||||||
testcase( regFree1==0 );
|
testcase( regFree1==0 );
|
||||||
testcase( regFree2==0 );
|
testcase( regFree2==0 );
|
||||||
break;
|
break;
|
||||||
@@ -2577,7 +2550,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
op = (op==TK_IS) ? TK_EQ : TK_NE;
|
op = (op==TK_IS) ? TK_EQ : TK_NE;
|
||||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||||
r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
|
r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
|
||||||
VdbeCoverage(v);
|
VdbeCoverageIf(v, op==TK_EQ);
|
||||||
|
VdbeCoverageIf(v, op==TK_NE);
|
||||||
testcase( regFree1==0 );
|
testcase( regFree1==0 );
|
||||||
testcase( regFree2==0 );
|
testcase( regFree2==0 );
|
||||||
break;
|
break;
|
||||||
@@ -2594,28 +2568,17 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
case TK_LSHIFT:
|
case TK_LSHIFT:
|
||||||
case TK_RSHIFT:
|
case TK_RSHIFT:
|
||||||
case TK_CONCAT: {
|
case TK_CONCAT: {
|
||||||
assert( TK_AND==OP_And );
|
assert( TK_AND==OP_And ); testcase( op==TK_AND );
|
||||||
assert( TK_OR==OP_Or );
|
assert( TK_OR==OP_Or ); testcase( op==TK_OR );
|
||||||
assert( TK_PLUS==OP_Add );
|
assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS );
|
||||||
assert( TK_MINUS==OP_Subtract );
|
assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS );
|
||||||
assert( TK_REM==OP_Remainder );
|
assert( TK_REM==OP_Remainder ); testcase( op==TK_REM );
|
||||||
assert( TK_BITAND==OP_BitAnd );
|
assert( TK_BITAND==OP_BitAnd ); testcase( op==TK_BITAND );
|
||||||
assert( TK_BITOR==OP_BitOr );
|
assert( TK_BITOR==OP_BitOr ); testcase( op==TK_BITOR );
|
||||||
assert( TK_SLASH==OP_Divide );
|
assert( TK_SLASH==OP_Divide ); testcase( op==TK_SLASH );
|
||||||
assert( TK_LSHIFT==OP_ShiftLeft );
|
assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT );
|
||||||
assert( TK_RSHIFT==OP_ShiftRight );
|
assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT );
|
||||||
assert( TK_CONCAT==OP_Concat );
|
assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT );
|
||||||
testcase( op==TK_AND );
|
|
||||||
testcase( op==TK_OR );
|
|
||||||
testcase( op==TK_PLUS );
|
|
||||||
testcase( op==TK_MINUS );
|
|
||||||
testcase( op==TK_REM );
|
|
||||||
testcase( op==TK_BITAND );
|
|
||||||
testcase( op==TK_BITOR );
|
|
||||||
testcase( op==TK_SLASH );
|
|
||||||
testcase( op==TK_LSHIFT );
|
|
||||||
testcase( op==TK_RSHIFT );
|
|
||||||
testcase( op==TK_CONCAT );
|
|
||||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||||
sqlite3VdbeAddOp3(v, op, r2, r1, target);
|
sqlite3VdbeAddOp3(v, op, r2, r1, target);
|
||||||
@@ -2647,10 +2610,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
}
|
}
|
||||||
case TK_BITNOT:
|
case TK_BITNOT:
|
||||||
case TK_NOT: {
|
case TK_NOT: {
|
||||||
assert( TK_BITNOT==OP_BitNot );
|
assert( TK_BITNOT==OP_BitNot ); testcase( op==TK_BITNOT );
|
||||||
assert( TK_NOT==OP_Not );
|
assert( TK_NOT==OP_Not ); testcase( op==TK_NOT );
|
||||||
testcase( op==TK_BITNOT );
|
|
||||||
testcase( op==TK_NOT );
|
|
||||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||||
testcase( regFree1==0 );
|
testcase( regFree1==0 );
|
||||||
inReg = target;
|
inReg = target;
|
||||||
@@ -2660,14 +2621,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
case TK_ISNULL:
|
case TK_ISNULL:
|
||||||
case TK_NOTNULL: {
|
case TK_NOTNULL: {
|
||||||
int addr;
|
int addr;
|
||||||
assert( TK_ISNULL==OP_IsNull );
|
assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
|
||||||
assert( TK_NOTNULL==OP_NotNull );
|
assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
|
||||||
testcase( op==TK_ISNULL );
|
|
||||||
testcase( op==TK_NOTNULL );
|
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
|
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
|
||||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||||
testcase( regFree1==0 );
|
testcase( regFree1==0 );
|
||||||
addr = sqlite3VdbeAddOp1(v, op, r1); VdbeCoverage(v);
|
addr = sqlite3VdbeAddOp1(v, op, r1);
|
||||||
|
VdbeCoverageIf(v, op==TK_ISNULL);
|
||||||
|
VdbeCoverageIf(v, op==TK_NOTNULL);
|
||||||
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
|
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
sqlite3VdbeJumpHere(v, addr);
|
||||||
break;
|
break;
|
||||||
@@ -2857,8 +2818,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
r3 = sqlite3GetTempReg(pParse);
|
r3 = sqlite3GetTempReg(pParse);
|
||||||
r4 = sqlite3GetTempReg(pParse);
|
r4 = sqlite3GetTempReg(pParse);
|
||||||
codeCompare(pParse, pLeft, pRight, OP_Ge,
|
codeCompare(pParse, pLeft, pRight, OP_Ge,
|
||||||
r1, r2, r3, SQLITE_STOREP2);
|
r1, r2, r3, SQLITE_STOREP2); VdbeCoverage(v);
|
||||||
VdbeCoverage(v);
|
|
||||||
pLItem++;
|
pLItem++;
|
||||||
pRight = pLItem->pExpr;
|
pRight = pLItem->pExpr;
|
||||||
sqlite3ReleaseTempReg(pParse, regFree2);
|
sqlite3ReleaseTempReg(pParse, regFree2);
|
||||||
@@ -3605,23 +3565,17 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||||||
case TK_GE:
|
case TK_GE:
|
||||||
case TK_NE:
|
case TK_NE:
|
||||||
case TK_EQ: {
|
case TK_EQ: {
|
||||||
assert( TK_LT==OP_Lt );
|
|
||||||
assert( TK_LE==OP_Le );
|
|
||||||
assert( TK_GT==OP_Gt );
|
|
||||||
assert( TK_GE==OP_Ge );
|
|
||||||
assert( TK_EQ==OP_Eq );
|
|
||||||
assert( TK_NE==OP_Ne );
|
|
||||||
testcase( op==TK_LT );
|
|
||||||
testcase( op==TK_LE );
|
|
||||||
testcase( op==TK_GT );
|
|
||||||
testcase( op==TK_GE );
|
|
||||||
testcase( op==TK_EQ );
|
|
||||||
testcase( op==TK_NE );
|
|
||||||
testcase( jumpIfNull==0 );
|
testcase( jumpIfNull==0 );
|
||||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||||
r1, r2, dest, jumpIfNull); VdbeCoverage(v);
|
r1, r2, dest, jumpIfNull);
|
||||||
|
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||||
|
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||||
|
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
||||||
|
assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
|
||||||
|
assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
|
||||||
|
assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
|
||||||
testcase( regFree1==0 );
|
testcase( regFree1==0 );
|
||||||
testcase( regFree2==0 );
|
testcase( regFree2==0 );
|
||||||
break;
|
break;
|
||||||
@@ -3634,19 +3588,21 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||||
op = (op==TK_IS) ? TK_EQ : TK_NE;
|
op = (op==TK_IS) ? TK_EQ : TK_NE;
|
||||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||||
r1, r2, dest, SQLITE_NULLEQ); VdbeCoverage(v);
|
r1, r2, dest, SQLITE_NULLEQ);
|
||||||
|
VdbeCoverageIf(v, op==TK_EQ);
|
||||||
|
VdbeCoverageIf(v, op==TK_NE);
|
||||||
testcase( regFree1==0 );
|
testcase( regFree1==0 );
|
||||||
testcase( regFree2==0 );
|
testcase( regFree2==0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_ISNULL:
|
case TK_ISNULL:
|
||||||
case TK_NOTNULL: {
|
case TK_NOTNULL: {
|
||||||
assert( TK_ISNULL==OP_IsNull );
|
assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
|
||||||
assert( TK_NOTNULL==OP_NotNull );
|
assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
|
||||||
testcase( op==TK_ISNULL );
|
|
||||||
testcase( op==TK_NOTNULL );
|
|
||||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||||
sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverage(v);
|
sqlite3VdbeAddOp2(v, op, r1, dest);
|
||||||
|
VdbeCoverageIf(v, op==TK_ISNULL);
|
||||||
|
VdbeCoverageIf(v, op==TK_NOTNULL);
|
||||||
testcase( regFree1==0 );
|
testcase( regFree1==0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3765,17 +3721,17 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||||||
case TK_GE:
|
case TK_GE:
|
||||||
case TK_NE:
|
case TK_NE:
|
||||||
case TK_EQ: {
|
case TK_EQ: {
|
||||||
testcase( op==TK_LT );
|
|
||||||
testcase( op==TK_LE );
|
|
||||||
testcase( op==TK_GT );
|
|
||||||
testcase( op==TK_GE );
|
|
||||||
testcase( op==TK_EQ );
|
|
||||||
testcase( op==TK_NE );
|
|
||||||
testcase( jumpIfNull==0 );
|
testcase( jumpIfNull==0 );
|
||||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||||
r1, r2, dest, jumpIfNull); VdbeCoverage(v);
|
r1, r2, dest, jumpIfNull);
|
||||||
|
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||||
|
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||||
|
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
||||||
|
assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
|
||||||
|
assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
|
||||||
|
assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
|
||||||
testcase( regFree1==0 );
|
testcase( regFree1==0 );
|
||||||
testcase( regFree2==0 );
|
testcase( regFree2==0 );
|
||||||
break;
|
break;
|
||||||
@@ -3788,17 +3744,19 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||||
op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
|
op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
|
||||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||||
r1, r2, dest, SQLITE_NULLEQ); VdbeCoverage(v);
|
r1, r2, dest, SQLITE_NULLEQ);
|
||||||
|
VdbeCoverageIf(v, op==TK_EQ);
|
||||||
|
VdbeCoverageIf(v, op==TK_NE);
|
||||||
testcase( regFree1==0 );
|
testcase( regFree1==0 );
|
||||||
testcase( regFree2==0 );
|
testcase( regFree2==0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_ISNULL:
|
case TK_ISNULL:
|
||||||
case TK_NOTNULL: {
|
case TK_NOTNULL: {
|
||||||
testcase( op==TK_ISNULL );
|
|
||||||
testcase( op==TK_NOTNULL );
|
|
||||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||||
sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverage(v);
|
sqlite3VdbeAddOp2(v, op, r1, dest);
|
||||||
|
testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL);
|
||||||
|
testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL);
|
||||||
testcase( regFree1==0 );
|
testcase( regFree1==0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4595,7 +4595,7 @@ int sqlite3Select(
|
|||||||
/* If the subquery is not correlated and if we are not inside of
|
/* If the subquery is not correlated and if we are not inside of
|
||||||
** a trigger, then we only need to compute the value of the subquery
|
** a trigger, then we only need to compute the value of the subquery
|
||||||
** once. */
|
** once. */
|
||||||
onceAddr = sqlite3CodeOnce(pParse);
|
onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||||
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||||
}else{
|
}else{
|
||||||
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||||
|
|||||||
@@ -3087,7 +3087,6 @@ int sqlite3ExprIsConstantNotJoin(Expr*);
|
|||||||
int sqlite3ExprIsConstantOrFunction(Expr*);
|
int sqlite3ExprIsConstantOrFunction(Expr*);
|
||||||
int sqlite3ExprIsInteger(Expr*, int*);
|
int sqlite3ExprIsInteger(Expr*, int*);
|
||||||
int sqlite3ExprCanBeNull(const Expr*);
|
int sqlite3ExprCanBeNull(const Expr*);
|
||||||
void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
|
|
||||||
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
||||||
int sqlite3IsRowid(const char*);
|
int sqlite3IsRowid(const char*);
|
||||||
void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
|
void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
|
||||||
|
|||||||
83
src/where.c
83
src/where.c
@@ -1601,7 +1601,7 @@ static void constructAutomaticIndex(
|
|||||||
** transient index on 2nd and subsequent iterations of the loop. */
|
** transient index on 2nd and subsequent iterations of the loop. */
|
||||||
v = pParse->pVdbe;
|
v = pParse->pVdbe;
|
||||||
assert( v!=0 );
|
assert( v!=0 );
|
||||||
addrInit = sqlite3CodeOnce(pParse);
|
addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||||
|
|
||||||
/* Count the number of columns that will be added to the index
|
/* Count the number of columns that will be added to the index
|
||||||
** and used to match WHERE clause constraints */
|
** and used to match WHERE clause constraints */
|
||||||
@@ -2388,7 +2388,9 @@ static int codeEqualityTerm(
|
|||||||
bRev = !bRev;
|
bRev = !bRev;
|
||||||
}
|
}
|
||||||
iTab = pX->iTable;
|
iTab = pX->iTable;
|
||||||
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); VdbeCoverage(v);
|
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
|
||||||
|
VdbeCoverageIf(v, bRev);
|
||||||
|
VdbeCoverageIf(v, !bRev);
|
||||||
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
|
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
|
||||||
pLoop->wsFlags |= WHERE_IN_ABLE;
|
pLoop->wsFlags |= WHERE_IN_ABLE;
|
||||||
if( pLevel->u.in.nIn==0 ){
|
if( pLevel->u.in.nIn==0 ){
|
||||||
@@ -2502,11 +2504,15 @@ static int codeAllEqualityTerms(
|
|||||||
|
|
||||||
if( nSkip ){
|
if( nSkip ){
|
||||||
int iIdxCur = pLevel->iIdxCur;
|
int iIdxCur = pLevel->iIdxCur;
|
||||||
sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); VdbeCoverage(v);
|
sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
|
||||||
|
VdbeCoverageIf(v, bRev==0);
|
||||||
|
VdbeCoverageIf(v, bRev!=0);
|
||||||
VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
|
VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
|
||||||
j = sqlite3VdbeAddOp0(v, OP_Goto);
|
j = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||||
pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
|
pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
|
||||||
iIdxCur, 0, regBase, nSkip); VdbeCoverage(v);
|
iIdxCur, 0, regBase, nSkip);
|
||||||
|
VdbeCoverageIf(v, bRev==0);
|
||||||
|
VdbeCoverageIf(v, bRev!=0);
|
||||||
sqlite3VdbeJumpHere(v, j);
|
sqlite3VdbeJumpHere(v, j);
|
||||||
for(j=0; j<nSkip; j++){
|
for(j=0; j<nSkip; j++){
|
||||||
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
|
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
|
||||||
@@ -2539,7 +2545,10 @@ static int codeAllEqualityTerms(
|
|||||||
testcase( pTerm->eOperator & WO_IN );
|
testcase( pTerm->eOperator & WO_IN );
|
||||||
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
|
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
|
||||||
Expr *pRight = pTerm->pExpr->pRight;
|
Expr *pRight = pTerm->pExpr->pRight;
|
||||||
sqlite3ExprCodeIsNullJump(v, pRight, regBase+j, pLevel->addrBrk);
|
if( sqlite3ExprCanBeNull(pRight) ){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
|
||||||
|
VdbeCoverage(v);
|
||||||
|
}
|
||||||
if( zAff ){
|
if( zAff ){
|
||||||
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){
|
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){
|
||||||
zAff[j] = SQLITE_AFF_NONE;
|
zAff[j] = SQLITE_AFF_NONE;
|
||||||
@@ -2904,13 +2913,18 @@ static Bitmask codeOneLoopStart(
|
|||||||
testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
|
testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
|
||||||
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
|
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
|
||||||
sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1);
|
sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1);
|
||||||
VdbeComment((v, "pk")); VdbeCoverage(v);
|
VdbeComment((v, "pk"));
|
||||||
|
VdbeCoverageIf(v, pX->op==TK_GT);
|
||||||
|
VdbeCoverageIf(v, pX->op==TK_LE);
|
||||||
|
VdbeCoverageIf(v, pX->op==TK_LT);
|
||||||
|
VdbeCoverageIf(v, pX->op==TK_GE);
|
||||||
sqlite3ExprCacheAffinityChange(pParse, r1, 1);
|
sqlite3ExprCacheAffinityChange(pParse, r1, 1);
|
||||||
sqlite3ReleaseTempReg(pParse, rTemp);
|
sqlite3ReleaseTempReg(pParse, rTemp);
|
||||||
disableTerm(pLevel, pStart);
|
disableTerm(pLevel, pStart);
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk);
|
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk);
|
||||||
VdbeCoverage(v);
|
VdbeCoverageIf(v, bRev==0);
|
||||||
|
VdbeCoverageIf(v, bRev!=0);
|
||||||
}
|
}
|
||||||
if( pEnd ){
|
if( pEnd ){
|
||||||
Expr *pX;
|
Expr *pX;
|
||||||
@@ -2938,7 +2952,10 @@ static Bitmask codeOneLoopStart(
|
|||||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
|
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
|
||||||
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
|
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
|
||||||
sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
|
sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
|
||||||
VdbeCoverage(v);
|
VdbeCoverageIf(v, testOp==OP_Le);
|
||||||
|
VdbeCoverageIf(v, testOp==OP_Lt);
|
||||||
|
VdbeCoverageIf(v, testOp==OP_Ge);
|
||||||
|
VdbeCoverageIf(v, testOp==OP_Gt);
|
||||||
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
|
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
|
||||||
}
|
}
|
||||||
}else if( pLoop->wsFlags & WHERE_INDEXED ){
|
}else if( pLoop->wsFlags & WHERE_INDEXED ){
|
||||||
@@ -3080,8 +3097,11 @@ static Bitmask codeOneLoopStart(
|
|||||||
if( pRangeStart ){
|
if( pRangeStart ){
|
||||||
Expr *pRight = pRangeStart->pExpr->pRight;
|
Expr *pRight = pRangeStart->pExpr->pRight;
|
||||||
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||||
if( (pRangeStart->wtFlags & TERM_VNULL)==0 ){
|
if( (pRangeStart->wtFlags & TERM_VNULL)==0
|
||||||
sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
|
&& sqlite3ExprCanBeNull(pRight)
|
||||||
|
){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
||||||
|
VdbeCoverage(v);
|
||||||
}
|
}
|
||||||
if( zStartAff ){
|
if( zStartAff ){
|
||||||
if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){
|
if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){
|
||||||
@@ -3105,20 +3125,14 @@ static Bitmask codeOneLoopStart(
|
|||||||
codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff);
|
codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff);
|
||||||
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
||||||
assert( op!=0 );
|
assert( op!=0 );
|
||||||
testcase( op==OP_Rewind );
|
|
||||||
testcase( op==OP_Last );
|
|
||||||
testcase( op==OP_SeekGT );
|
|
||||||
testcase( op==OP_SeekGE );
|
|
||||||
testcase( op==OP_SeekLE );
|
|
||||||
testcase( op==OP_SeekLT );
|
|
||||||
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
||||||
VdbeCoverage(v);
|
VdbeCoverage(v);
|
||||||
VdbeCoverageIf(v, op==OP_Rewind);
|
VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
|
||||||
VdbeCoverageIf(v, op==OP_Last);
|
VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last );
|
||||||
VdbeCoverageIf(v, op==OP_SeekGT);
|
VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT );
|
||||||
VdbeCoverageIf(v, op==OP_SeekGE);
|
VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE );
|
||||||
VdbeCoverageIf(v, op==OP_SeekLE);
|
VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE );
|
||||||
VdbeCoverageIf(v, op==OP_SeekLT);
|
VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT );
|
||||||
|
|
||||||
/* Load the value for the inequality constraint at the end of the
|
/* Load the value for the inequality constraint at the end of the
|
||||||
** range (if any).
|
** range (if any).
|
||||||
@@ -3128,8 +3142,11 @@ static Bitmask codeOneLoopStart(
|
|||||||
Expr *pRight = pRangeEnd->pExpr->pRight;
|
Expr *pRight = pRangeEnd->pExpr->pRight;
|
||||||
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
|
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
|
||||||
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||||
if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){
|
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
|
||||||
sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
|
&& sqlite3ExprCanBeNull(pRight)
|
||||||
|
){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
||||||
|
VdbeCoverage(v);
|
||||||
}
|
}
|
||||||
if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE
|
if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE
|
||||||
&& !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff)
|
&& !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff)
|
||||||
@@ -3151,12 +3168,11 @@ static Bitmask codeOneLoopStart(
|
|||||||
/* Check if the index cursor is past the end of the range. */
|
/* Check if the index cursor is past the end of the range. */
|
||||||
if( nConstraint ){
|
if( nConstraint ){
|
||||||
op = aEndOp[bRev*2 + endEq];
|
op = aEndOp[bRev*2 + endEq];
|
||||||
testcase( op==OP_IdxGT );
|
|
||||||
testcase( op==OP_IdxGE );
|
|
||||||
testcase( op==OP_IdxLT );
|
|
||||||
testcase( op==OP_IdxLE );
|
|
||||||
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
||||||
VdbeCoverage(v);
|
testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
|
||||||
|
testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
|
||||||
|
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
|
||||||
|
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Seek the table cursor, if required */
|
/* Seek the table cursor, if required */
|
||||||
@@ -3430,8 +3446,8 @@ static Bitmask codeOneLoopStart(
|
|||||||
pLevel->op = aStep[bRev];
|
pLevel->op = aStep[bRev];
|
||||||
pLevel->p1 = iCur;
|
pLevel->p1 = iCur;
|
||||||
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
|
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
|
||||||
VdbeCoverageIf(v, bRev);
|
VdbeCoverageIf(v, bRev==0);
|
||||||
VdbeCoverageIf(v, !bRev);
|
VdbeCoverageIf(v, bRev!=0);
|
||||||
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
|
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5802,6 +5818,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|||||||
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
|
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
|
||||||
sqlite3VdbeChangeP5(v, pLevel->p5);
|
sqlite3VdbeChangeP5(v, pLevel->p5);
|
||||||
VdbeCoverage(v);
|
VdbeCoverage(v);
|
||||||
|
VdbeCoverageIf(v, pLevel->op==OP_Next);
|
||||||
|
VdbeCoverageIf(v, pLevel->op==OP_Prev);
|
||||||
|
VdbeCoverageIf(v, pLevel->op==OP_VNext);
|
||||||
}
|
}
|
||||||
if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
|
if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
|
||||||
struct InLoop *pIn;
|
struct InLoop *pIn;
|
||||||
@@ -5811,6 +5830,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|||||||
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
|
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
|
||||||
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
|
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
|
||||||
VdbeCoverage(v);
|
VdbeCoverage(v);
|
||||||
|
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen);
|
||||||
|
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
|
||||||
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
|
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
|
||||||
}
|
}
|
||||||
sqlite3DbFree(db, pLevel->u.in.aInLoop);
|
sqlite3DbFree(db, pLevel->u.in.aInLoop);
|
||||||
|
|||||||
Reference in New Issue
Block a user