diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/resolve.c | 38 | ||||
-rw-r--r-- | src/select.c | 3 | ||||
-rw-r--r-- | src/whereexpr.c | 5 |
3 files changed, 46 insertions, 0 deletions
diff --git a/src/resolve.c b/src/resolve.c index 689f19703..203253c6e 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -785,6 +785,44 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ break; } + /* An "<expr> IS NOT NULL" or "<expr> IS NULL". After resolving the + ** LHS, check if there is a NOT NULL constraint in the schema that + ** means the value of the expression can be determined immediately. + ** If that is the case, replace the current expression node with + ** a TK_TRUEFALSE node. + ** + ** If the node is replaced with a TK_TRUEFALSE node, then also restore + ** the NameContext ref-counts to the state they where in before the + ** LHS expression was resolved. This prevents the current select + ** from being erroneously marked as correlated in some cases. + */ + case TK_NOTNULL: + case TK_ISNULL: { + int anRef[8]; + NameContext *p; + int i; + for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){ + anRef[i] = p->nRef; + } + sqlite3WalkExpr(pWalker, pExpr->pLeft); + if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) ){ + if( pExpr->op==TK_NOTNULL ){ + pExpr->u.zToken = "true"; + ExprSetProperty(pExpr, EP_IsTrue); + }else{ + pExpr->u.zToken = "false"; + ExprSetProperty(pExpr, EP_IsFalse); + } + pExpr->op = TK_TRUEFALSE; + for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){ + p->nRef = anRef[i]; + } + sqlite3ExprDelete(pParse->db, pExpr->pLeft); + pExpr->pLeft = 0; + } + return WRC_Prune; + } + /* A column name: ID ** Or table name and column name: ID.ID ** Or a database, table and column: ID.ID.ID diff --git a/src/select.c b/src/select.c index b1a1ea507..798df06e1 100644 --- a/src/select.c +++ b/src/select.c @@ -407,6 +407,9 @@ static void unsetJoinExpr(Expr *p, int iTable){ && (iTable<0 || p->iRightJoinTable==iTable) ){ ExprClearProperty(p, EP_FromJoin); } + if( p->op==TK_COLUMN && p->iTable==iTable ){ + ExprClearProperty(p, EP_CanBeNull); + } if( p->op==TK_FUNCTION && p->x.pList ){ int i; for(i=0; i<p->x.pList->nExpr; i++){ diff --git a/src/whereexpr.c b/src/whereexpr.c index 09ed7f6c3..f547db4f0 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -1407,6 +1407,11 @@ static void exprAnalyze( pNew->prereqRight = prereqLeft | extraRight; pNew->prereqAll = prereqAll; pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; + }else if( op==TK_ISNULL && 0==sqlite3ExprCanBeNull(pLeft) ){ + pExpr->op = TK_TRUEFALSE; + ExprSetProperty(pExpr, EP_IsFalse); + pTerm->prereqAll = 0; + pTerm->eOperator = 0; } } |