diff options
author | drh <drh@noemail.net> | 2013-04-25 00:57:10 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2013-04-25 00:57:10 +0000 |
commit | aa87f9a68b5ac0305699507574cb2ed074e722b8 (patch) | |
tree | 02f0a9ef2946b21e63b3173c9e4fbddc86a47e16 /src | |
parent | ed17167e1dc966bfb871aea8297206991eac2794 (diff) | |
download | sqlite-aa87f9a68b5ac0305699507574cb2ed074e722b8.tar.gz sqlite-aa87f9a68b5ac0305699507574cb2ed074e722b8.zip |
Make sure the affinity and datatype of sub-subqueries are initialized
prior to subqueries as the latter relies on the former.
FossilOrigin-Name: 39b4e6ff9316cc78ea88349091e195b8104d1e9e
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 3 | ||||
-rw-r--r-- | src/resolve.c | 2 | ||||
-rw-r--r-- | src/select.c | 3 | ||||
-rw-r--r-- | src/sqliteInt.h | 1 | ||||
-rw-r--r-- | src/walker.c | 17 |
5 files changed, 22 insertions, 4 deletions
diff --git a/src/expr.c b/src/expr.c index ae6a1dec1..a974c5a61 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1214,6 +1214,7 @@ static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ } static int exprIsConst(Expr *p, int initFlag){ Walker w; + memset(&w, 0, sizeof(w)); w.u.i = initFlag; w.xExprCallback = exprNodeIsConstant; w.xSelectCallback = selectNodeIsConstant; @@ -3428,8 +3429,8 @@ void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){ Walker w; if( pParse->cookieGoto ) return; if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return; + memset(&w, 0, sizeof(w)); w.xExprCallback = evalConstExpr; - w.xSelectCallback = 0; w.pParse = pParse; sqlite3WalkExpr(&w, pExpr); } diff --git a/src/resolve.c b/src/resolve.c index 9b350caf8..a8e196926 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -1283,6 +1283,7 @@ int sqlite3ResolveExprNames( #endif savedHasAgg = pNC->ncFlags & NC_HasAgg; pNC->ncFlags &= ~NC_HasAgg; + memset(&w, 0, sizeof(w)); w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.pParse = pNC->pParse; @@ -1323,6 +1324,7 @@ void sqlite3ResolveSelectNames( Walker w; assert( p!=0 ); + memset(&w, 0, sizeof(w)); w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.pParse = pParse; diff --git a/src/select.c b/src/select.c index 1daa5bed3..a745dc370 100644 --- a/src/select.c +++ b/src/select.c @@ -3576,6 +3576,7 @@ static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ */ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ Walker w; + memset(&w, 0, sizeof(w)); w.xSelectCallback = selectExpander; w.xExprCallback = exprWalkNoop; w.pParse = pParse; @@ -3634,9 +3635,11 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ #ifndef SQLITE_OMIT_SUBQUERY Walker w; + memset(&w, 0, sizeof(w)); w.xSelectCallback = selectAddSubqueryTypeInfo; w.xExprCallback = exprWalkNoop; w.pParse = pParse; + w.bSelectDepthFirst = 1; sqlite3WalkSelect(&w, pSelect); #endif } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3722041b0..876629a8c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2588,6 +2588,7 @@ struct Walker { int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */ Parse *pParse; /* Parser context. */ int walkerDepth; /* Number of subqueries */ + u8 bSelectDepthFirst; /* Do subqueries first */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int i; /* Integer value */ diff --git a/src/walker.c b/src/walker.c index eab96ea24..e71ed2ac4 100644 --- a/src/walker.c +++ b/src/walker.c @@ -113,7 +113,9 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ /* ** Call sqlite3WalkExpr() for every expression in Select statement p. ** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and -** on the compound select chain, p->pPrior. +** on the compound select chain, p->pPrior. Invoke the xSelectCallback() +** either before or after the walk of expressions and FROM clause, depending +** on whether pWalker->bSelectDepthFirst is false or true, respectively. ** ** Return WRC_Continue under normal conditions. Return WRC_Abort if ** there is an abort request. @@ -127,14 +129,23 @@ int sqlite3WalkSelect(Walker *pWalker, Select *p){ rc = WRC_Continue; pWalker->walkerDepth++; while( p ){ - rc = pWalker->xSelectCallback(pWalker, p); - if( rc ) break; + if( !pWalker->bSelectDepthFirst ){ + rc = pWalker->xSelectCallback(pWalker, p); + if( rc ) break; + } if( sqlite3WalkSelectExpr(pWalker, p) || sqlite3WalkSelectFrom(pWalker, p) ){ pWalker->walkerDepth--; return WRC_Abort; } + if( pWalker->bSelectDepthFirst ){ + rc = pWalker->xSelectCallback(pWalker, p); + /* Depth-first search is currently only used for + ** selectAddSubqueryTypeInfo() and that routine always returns + ** WRC_Continue (0). So the following branch is never taken. */ + if( NEVER(rc) ) break; + } p = p->pPrior; } pWalker->walkerDepth--; |