aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/resolve.c38
-rw-r--r--src/select.c3
-rw-r--r--src/whereexpr.c5
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;
}
}