1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-08 03:22:21 +03:00

Make the result of an IN or NOT IN expression with an empty set on the

right-hand side always either false or true, respectively, even if the
left-hand side is NULL.  Ticket [80e031a00f45dc]

FossilOrigin-Name: c288ac644d0bfda2b9bc204dc86df8e74d4f6843
This commit is contained in:
drh
2010-07-14 18:24:06 +00:00
parent e84322e503
commit 094430eb71
7 changed files with 115 additions and 20 deletions

View File

@@ -1705,7 +1705,6 @@ int sqlite3CodeSubselect(
** an integer 0 (not exists) or 1 (exists) into a memory cell
** and record that memory cell in iColumn.
*/
static const Token one = { "1", 1 }; /* Token for literal value 1 */
Select *pSel; /* SELECT statement to encode */
SelectDest dest; /* How to deal with SELECt result */
@@ -1726,7 +1725,8 @@ int sqlite3CodeSubselect(
VdbeComment((v, "Init EXISTS result"));
}
sqlite3ExprDelete(pParse->db, pSel->pLimit);
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one);
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0,
&sqlite3IntTokens[1]);
if( sqlite3Select(pParse, pSel, &dest) ){
return 0;
}
@@ -1794,8 +1794,20 @@ static void sqlite3ExprCodeIN(
sqlite3ExprCachePush(pParse);
r1 = sqlite3GetTempReg(pParse);
sqlite3ExprCode(pParse, pExpr->pLeft, r1);
sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull);
/* If the LHS is NULL, then the result is either false or NULL depending
** on whether the RHS is empty or not, respectively.
*/
if( destIfNull==destIfFalse ){
/* Shortcut for the common case where the false and NULL outcomes are
** the same. */
sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull);
}else{
int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1);
sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
sqlite3VdbeJumpHere(v, addr1);
}
if( eType==IN_INDEX_ROWID ){
/* In this case, the RHS is the ROWID of table b-tree