diff options
author | drh <drh@noemail.net> | 2014-02-18 01:07:38 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2014-02-18 01:07:38 +0000 |
commit | 552fd4544162c4ae28dda3ef29a62175c7bf630f (patch) | |
tree | f0f3e1a6475005a5fd2724e38ced38e6bd3768c0 /src/expr.c | |
parent | bb13813ed1c68aaa3120c648db444922b9ec18c9 (diff) | |
download | sqlite-552fd4544162c4ae28dda3ef29a62175c7bf630f.tar.gz sqlite-552fd4544162c4ae28dda3ef29a62175c7bf630f.zip |
Improvements to "NOT IN (SELECT ...)" processing. Only test for NULL values
on the RHS on the first iteration, then remember the result. There has been
logic to do this for year, but it didn't work right and ended up repeating
the NULL test on every iteration. This inefficiency was found using the
VDBE coverage testing tools.
FossilOrigin-Name: 915f6f1c7aab54583729e60bdc1565f25ecc6f74
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 22 |
1 files changed, 9 insertions, 13 deletions
diff --git a/src/expr.c b/src/expr.c index 85354e586..06fc1a54a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1630,11 +1630,11 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - sqlite3VdbeJumpHere(v, iAddr); if( prNotFound && !pTab->aCol[iCol].notNull ){ *prNotFound = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); } + sqlite3VdbeJumpHere(v, iAddr); } } } @@ -2004,7 +2004,7 @@ static void sqlite3ExprCodeIN( ** the presence of a NULL on the RHS makes a difference in the ** outcome. */ - int j1, j2, j3; + int j1, j2; /* First check to see if the LHS is contained in the RHS. If so, ** then the presence of NULLs in the RHS does not matter, so jump @@ -2019,19 +2019,15 @@ static void sqlite3ExprCodeIN( ** jump to destIfNull. If there are no NULLs in the RHS then ** jump to destIfFalse. */ - j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull); VdbeCoverage(v); - j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull); - sqlite3VdbeJumpHere(v, j3); - sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1); - sqlite3VdbeJumpHere(v, j2); - - /* Jump to the appropriate target depending on whether or not - ** the RHS contains a NULL - */ sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IfNot, rRhsHasNull, destIfFalse); VdbeCoverage(v); + j2 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Integer, 0, rRhsHasNull); sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeAddOp2(v, OP_Integer, 1, rRhsHasNull); + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); /* The OP_Found at the top of this branch jumps here when true, ** causing the overall IN expression evaluation to fall through. |