More aggressive optimization of IS NULL and IS NOT NULL operators.

FossilOrigin-Name: c69eec9909af40e1e22d44a6859ef52378ebe06a587373f332f9d379cb39a84d
This commit is contained in:
drh
2025-12-03 18:18:29 +00:00
parent 1e235b9b02
commit 5be3ac87db
3 changed files with 55 additions and 34 deletions
+6 -9
View File
@@ -1,5 +1,5 @@
C Create\sa\snew\sinternal\ssubroutine\sspecifically\sdesigned\sto\sallocate\nExpr\snodes\sthat\shold\sa\s32-bit\sinteger.
D 2025-12-03T16:54:48.746
C More\saggressive\soptimization\sof\sIS\sNULL\sand\sIS\sNOT\sNULL\soperators.
D 2025-12-03T18:18:29.761
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -726,7 +726,7 @@ F src/os_win.c a89b501fc195085c7d6c9eec7f5bd782625e94bb2a96b000f4d009703df1083f
F src/os_win.h 4c247cdb6d407c75186c94a1e84d5a22cbae4adcec93fcae8d2bc1f956fd1f19
F src/pager.c a81461de271ac4886ad75b7ca2cca8157a48635820c4646cd2714acdc2c17e5f
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
F src/parse.y 1af718c29a259a80cba96ab7e62ddc2d3f14b1242a1d176868f80c5d4f412e16
F src/parse.y 6afdb006a4a8aac04a4dd37efd8b5e2d5cc39f9751b63e02cf11d9486ba3562a
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
@@ -2183,11 +2183,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P afe5ee64f1cde4945c878220b029f2a22578c2bccda4fddc005c4e6a4718c6cd
R c225aed59957640feafaa5b7a326af34
T *branch * expr-opt
T *sym-expr-opt *
T -sym-trunk *
P 38d06f69e516dd13becbfb735a2a0035c2f3c50ea5d661a668b109a996656523
R e345b725a39db244a730c4ef212bf292
U drh
Z 7b5c81060b54c05ccfb8538b780dea3f
Z 8f73060af5100688a4299f0ba560aae8
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
38d06f69e516dd13becbfb735a2a0035c2f3c50ea5d661a668b109a996656523
c69eec9909af40e1e22d44a6859ef52378ebe06a587373f332f9d379cb39a84d
+48 -24
View File
@@ -1363,43 +1363,67 @@ expr(A) ::= expr(A) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] {
if( A ) A->flags |= EP_InfixFunc;
}
expr(A) ::= expr(A) ISNULL|NOTNULL(E). {A = sqlite3PExpr(pParse,@E,A,0);}
expr(A) ::= expr(A) NOT NULL. {A = sqlite3PExpr(pParse,TK_NOTNULL,A,0);}
%include {
/* A routine to convert a binary TK_IS or TK_ISNOT expression into a
** unary TK_ISNULL or TK_NOTNULL expression. */
static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
sqlite3 *db = pParse->db;
if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){
pA->op = (u8)op;
sqlite3ExprDelete(db, pA->pRight);
pA->pRight = 0;
/* Create a TK_ISNULL or TK_NOTNULL expression, perhaps optimized to
** to TK_TRUEFALSE, if possible */
static Expr *sqlite3PExprIsNull(
Parse *pParse, /* Parsing context */
int op, /* TK_ISNULL or TK_NOTNULL */
Expr *pLeft /* Operand */
){
Expr *p = pLeft;
assert( op==TK_ISNULL || op==TK_NOTNULL );
assert( pLeft!=0 );
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
p = p->pLeft;
assert( p!=0 );
}
switch( p->op ){
case TK_INTEGER:
case TK_STRING:
case TK_FLOAT:
case TK_BLOB:
sqlite3ExprDeferredDelete(pParse, pLeft);
return sqlite3ExprInt32(pParse->db, op==TK_NOTNULL);
default:
break;
}
return sqlite3PExpr(pParse, op, pLeft, 0);
}
/* Create a TK_IS or TK_ISNOT operator, perhaps optimized to
** TK_ISNULL or TK_NOTNULL or TK_TRUEFALSE. */
static Expr *sqlite3PExprIs(
Parse *pParse, /* Parsing context */
int op, /* TK_IS or TK_ISNOT */
Expr *pLeft, /* Left operand */
Expr *pRight /* Right operand */
){
if( pRight && pRight->op==TK_NULL ){
sqlite3ExprDeferredDelete(pParse, pRight);
return sqlite3PExprIsNull(pParse, op==TK_IS ? TK_ISNULL : TK_NOTNULL, pLeft);
}
return sqlite3PExpr(pParse, op, pLeft, pRight);
}
}
// expr1 IS expr2
// expr1 IS NOT expr2
expr(A) ::= expr(A) ISNULL|NOTNULL(E). {A = sqlite3PExprIsNull(pParse,@E,A);}
expr(A) ::= expr(A) NOT NULL. {A = sqlite3PExprIsNull(pParse,TK_NOTNULL,A);}
// expr1 IS expr2 same as expr1 IS NOT DISTICT FROM expr2
// expr1 IS NOT expr2 same as expr1 IS DISTINCT FROM expr2
//
// If expr2 is NULL then code as TK_ISNULL or TK_NOTNULL. If expr2
// is any other expression, code as TK_IS or TK_ISNOT.
//
expr(A) ::= expr(A) IS expr(Y). {
A = sqlite3PExpr(pParse,TK_IS,A,Y);
binaryToUnaryIfNull(pParse, Y, A, TK_ISNULL);
A = sqlite3PExprIs(pParse, TK_IS, A, Y);
}
expr(A) ::= expr(A) IS NOT expr(Y). {
A = sqlite3PExpr(pParse,TK_ISNOT,A,Y);
binaryToUnaryIfNull(pParse, Y, A, TK_NOTNULL);
A = sqlite3PExprIs(pParse, TK_ISNOT, A, Y);
}
expr(A) ::= expr(A) IS NOT DISTINCT FROM expr(Y). {
A = sqlite3PExpr(pParse,TK_IS,A,Y);
binaryToUnaryIfNull(pParse, Y, A, TK_ISNULL);
A = sqlite3PExprIs(pParse, TK_IS, A, Y);
}
expr(A) ::= expr(A) IS DISTINCT FROM expr(Y). {
A = sqlite3PExpr(pParse,TK_ISNOT,A,Y);
binaryToUnaryIfNull(pParse, Y, A, TK_NOTNULL);
A = sqlite3PExprIs(pParse, TK_ISNOT, A, Y);
}
expr(A) ::= NOT(B) expr(X).