Suppress more instances of unnecessary OP_IsNull and OP_Affinity opcodes.
FossilOrigin-Name: bf6c0bd1c5568c6292ea0a64c8a5071e1bd3079a
diff --git a/src/expr.c b/src/expr.c
index db74e87..99d88f9 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1289,6 +1289,24 @@
}
/*
+** 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);
+ }
+}
+
+/*
** Return TRUE if the given expression is a constant which would be
** unchanged by OP_Affinity with the affinity given in the second
** argument.
@@ -1317,6 +1335,10 @@
case TK_BLOB: {
return 1;
}
+ case TK_COLUMN: {
+ return p->iTable>=0 && p->iColumn<0
+ && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC);
+ }
default: {
return 0;
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 64c7c35..293c244 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2675,6 +2675,7 @@
int sqlite3ExprIsConstantOrFunction(Expr*);
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3ExprCanBeNull(const Expr*);
+void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, int);
diff --git a/src/where.c b/src/where.c
index 7abf7d5..c395040 100644
--- a/src/where.c
+++ b/src/where.c
@@ -2789,9 +2789,7 @@
testcase( pTerm->eOperator & WO_IN );
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
Expr *pRight = pTerm->pExpr->pRight;
- if( sqlite3ExprCanBeNull(pRight) ){
- sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
- }
+ sqlite3ExprCodeIsNullJump(v, pRight, regBase+j, pLevel->addrBrk);
if( zAff ){
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){
zAff[j] = SQLITE_AFF_NONE;
@@ -3124,7 +3122,7 @@
if( pRangeStart ){
Expr *pRight = pRangeStart->pExpr->pRight;
sqlite3ExprCode(pParse, pRight, regBase+nEq);
- sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
+ sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
if( zAff ){
if( sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE){
/* Since the comparison is to be performed with no conversions
@@ -3162,7 +3160,7 @@
Expr *pRight = pRangeEnd->pExpr->pRight;
sqlite3ExprCacheRemove(pParse, regBase+nEq);
sqlite3ExprCode(pParse, pRight, regBase+nEq);
- sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
+ sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
if( zAff ){
if( sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE){
/* Since the comparison is to be performed with no conversions