diff options
author | drh <> | 2024-04-05 20:01:28 +0000 |
---|---|---|
committer | drh <> | 2024-04-05 20:01:28 +0000 |
commit | 743ae4c68b51fe56e6a269a79532224d2e45ce12 (patch) | |
tree | ace9b5342b3fbc46b7aebf97f9d61ce25ffe2bbd /src/expr.c | |
parent | b411c4d69e1d7df018e9c313e104e973fc79d583 (diff) | |
download | sqlite-743ae4c68b51fe56e6a269a79532224d2e45ce12.tar.gz sqlite-743ae4c68b51fe56e6a269a79532224d2e45ce12.zip |
Experimental enhancement in which expressions of the form "expr IN table"
can be pushed down into subexpressions.
FossilOrigin-Name: 2cbd7838fd6ffdf210f34671cd2e3e749a076a3a6f155bbe5f910a67db31c5b1
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/src/expr.c b/src/expr.c index edfea3fc9..f2b252792 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2500,7 +2500,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } } -static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){ +static int exprIsConst(Parse *pParse, Expr *p, int initFlag){ Walker w; w.eCode = initFlag; w.pParse = pParse; @@ -2509,7 +2509,6 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){ #ifdef SQLITE_DEBUG w.xSelectCallback2 = sqlite3SelectWalkAssert2; #endif - w.u.iCur = iCur; sqlite3WalkExpr(&w, p); return w.eCode; } @@ -2529,7 +2528,7 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){ ** function and on its parameters. */ int sqlite3ExprIsConstant(Parse *pParse, Expr *p){ - return exprIsConst(pParse, p, 1, 0); + return exprIsConst(pParse, p, 1); } /* @@ -2546,7 +2545,44 @@ int sqlite3ExprIsConstant(Parse *pParse, Expr *p){ ** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce(). */ static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){ - return exprIsConst(pParse, p, 2, 0); + return exprIsConst(pParse, p, 2); +} + +/* +** This routine examines sub-SELECT statements as an expression is being +** walked as part of sqlite3ExprIsTableConstant() (hereafter IsTabConst()). +** Most SELECT statements will cause IsTabConst() to return false. However, +** if: +** +** (1) The SELECT is the right-hand side of an IN operator, and +** (2) Nothing in the SELECT refers to anything other than itself +** +** Then this routine causes the sub-SELECT to be bypassed, so that if +** nothing else is amiss the IsTabConst() routine can return true. +*/ +static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){ + int savedCursor; + assert( pSelect!=0 ); + assert( pWalker->eCode==3 || pWalker->eCode==0 ); + if( (pSelect->selFlags & SF_RhsOfIN)==0 ){ + pWalker->eCode = 0; + return WRC_Abort; + } + assert( pSelect->pSrc!=0 ); + assert( pSelect->pSrc->nSrc==1 ); + assert( pSelect->pWhere==0 ); + assert( pSelect->pGroupBy==0 ); + assert( pSelect->pHaving==0 ); + assert( pSelect->pOrderBy==0 ); + assert( pSelect->pPrior==0 ); + assert( pSelect->pNext==0 ); + assert( pSelect->pLimit==0 ); + assert( pSelect->pWith==0 ); + savedCursor = pWalker->u.iCur; + pWalker->u.iCur = pSelect->pSrc->a[0].iCursor; + sqlite3WalkExprList(pWalker, pSelect->pEList); + pWalker->u.iCur = savedCursor; + return WRC_Prune; } /* @@ -2554,9 +2590,19 @@ static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){ ** for any single row of the table with cursor iCur. In other words, the ** expression must not refer to any non-deterministic function nor any ** table other than iCur. +** +** 2024-04-05: Operators of the form "expr IN table" are now allowed, where +** "table" is the name of a table. */ -int sqlite3ExprIsTableConstant(Expr *p, int iCur){ - return exprIsConst(0, p, 3, iCur); +static int sqlite3ExprIsTableConstant(Expr *p, int iCur){ + Walker w; + w.eCode = 3; + w.pParse = 0; + w.xExprCallback = exprNodeIsConstant; + w.xSelectCallback = exprSelectWalkTableConstant; + w.u.iCur = iCur; + sqlite3WalkExpr(&w, p); + return w.eCode; } /* @@ -2713,7 +2759,7 @@ int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){ */ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ assert( isInit==0 || isInit==1 ); - return exprIsConst(0, p, 4+isInit, 0); + return exprIsConst(0, p, 4+isInit); } #ifdef SQLITE_ENABLE_CURSOR_HINTS |