diff options
author | drh <drh@noemail.net> | 2014-08-01 18:00:24 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2014-08-01 18:00:24 +0000 |
commit | e21a6e1dfe2196184bf17e9d9212f3eae0b346e5 (patch) | |
tree | 09284df58df8e79ff60b9568c6f36142fe2c7a67 /src/expr.c | |
parent | 5c3e9cf9de273e236833bf2465f67f26a348c116 (diff) | |
download | sqlite-e21a6e1dfe2196184bf17e9d9212f3eae0b346e5.tar.gz sqlite-e21a6e1dfe2196184bf17e9d9212f3eae0b346e5.zip |
Remove an unnecessary OP_Null in the IN-operator logic. Attempt to clarify
comments explaining the IN-operator code, though it is not clear that the
comments are correct even yet - more work to be done.
FossilOrigin-Name: c11e55fabbc718cb324ecd3540453c25db98f50c
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/src/expr.c b/src/expr.c index d81882710..591ea9845 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1525,29 +1525,34 @@ int sqlite3CodeOnce(Parse *pParse){ ** ** When the b-tree is being used for membership tests, the calling function ** might need to know whether or not the RHS side of the IN operator -** contains a NULL. If prNotFound is not NULL and +** contains a NULL. If prRhsHasNull is not a NULL pointer and ** if there is any chance that the (...) might contain a NULL value at ** runtime, then a register is allocated and the register number written -** to *prNotFound. If there is no chance that the (...) contains a -** NULL value, then *prNotFound is left unchanged. +** to *prRhsHasNull. If there is no chance that the (...) contains a +** NULL value, then *prRhsHasNull is left unchanged. ** -** If a register is allocated and its location stored in *prNotFound, then -** its initial value is NULL. If the (...) does not remain constant -** for the duration of the query (i.e. the SELECT within the (...) -** is a correlated subquery) then the value of the allocated register is -** reset to NULL each time the subquery is rerun. This allows the -** caller to use vdbe code equivalent to the following: +** If a register is allocated and its location stored in *prRhsHasNull, then +** the value in that register will be: ** -** if( register==NULL ){ -** has_null = <test if data structure contains null> -** register = 1 +** 0 if the (...) contains no NULL values +** 1 if the (...) does not contain NULL values +** NULL if we do not yet know if (...) contains NULLs +** +** If the (...) does not remain constant for the duration of the query +** (i.e. the SELECT within the (...) is a correlated subquery) then the +** value of the allocated register is reset to NULL each time the subquery +** is rerun. This allows the caller to use vdbe code equivalent to the +** following: +** +** if( r[*prRhsHasNull] IS NULL ){ +** r[*prRhsHasNull] = <test if data structure contains null> ** } ** ** in order to avoid running the <test if data structure contains null> ** test more often than is necessary. */ #ifndef SQLITE_OMIT_SUBQUERY -int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prNotFound){ +int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ Select *p; /* SELECT to the right of IN operator */ int eType = 0; /* Type of RHS table. IN_INDEX_* */ int iTab = pParse->nTab++; /* Cursor of the RHS table */ @@ -1621,9 +1626,9 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prNotFound){ assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - if( prNotFound && !pTab->aCol[iCol].notNull ){ - *prNotFound = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); + if( prRhsHasNull && !pTab->aCol[iCol].notNull ){ + *prRhsHasNull = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Null, 0, *prRhsHasNull); } sqlite3VdbeJumpHere(v, iAddr); } @@ -1643,9 +1648,8 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prNotFound){ if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){ eType = IN_INDEX_ROWID; } - }else if( prNotFound ){ - *prNotFound = rMayHaveNull = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull); + }else if( prRhsHasNull ){ + *prRhsHasNull = rMayHaveNull = ++pParse->nMem; } sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID); pParse->nQueryLoop = savedNQueryLoop; |