diff options
author | dan <dan@noemail.net> | 2019-07-22 16:33:02 +0000 |
---|---|---|
committer | dan <dan@noemail.net> | 2019-07-22 16:33:02 +0000 |
commit | 7f6f12bdd35c55d9f98b6eefbe2d40c4a85aab87 (patch) | |
tree | c90be8f5173dfe1513abdfe7ae4a356f4f82bd9c /src | |
parent | 1e60261cfbc34cdad2625241ba6e5bedfb2e6716 (diff) | |
parent | 75b0821e999cb14d4081a6ff8090e28e49e5bc7e (diff) | |
download | sqlite-7f6f12bdd35c55d9f98b6eefbe2d40c4a85aab87.tar.gz sqlite-7f6f12bdd35c55d9f98b6eefbe2d40c4a85aab87.zip |
Remove Window objects from the corresponding Select.pWin list when they are deleted, as they are, for example, when the ORDER BY clause is optimized out.
FossilOrigin-Name: fd7316cda0fdfe86985f41a97dff3beba188606ec9bc6fef38a686a6976a6e01
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 13 | ||||
-rw-r--r-- | src/resolve.c | 42 | ||||
-rw-r--r-- | src/select.c | 1 | ||||
-rw-r--r-- | src/sqliteInt.h | 1 | ||||
-rw-r--r-- | src/window.c | 4 |
5 files changed, 40 insertions, 21 deletions
diff --git a/src/expr.c b/src/expr.c index 56b3148ed..571e9e494 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1326,10 +1326,17 @@ static With *withDup(sqlite3 *db, With *p){ */ static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){ if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_WinFunc) ){ - assert( pExpr->y.pWin ); + Select *pSelect = pWalker->u.pSelect; + Window *pWin = pExpr->y.pWin; + assert( pWin ); assert( IsWindowFunc(pExpr) ); - pExpr->y.pWin->pNextWin = pWalker->u.pSelect->pWin; - pWalker->u.pSelect->pWin = pExpr->y.pWin; + if( pSelect->pWin ){ + *pSelect->pWin->ppThis = pSelect->pWin->pNextWin; + pSelect->pWin->ppThis = &pWin->pNextWin; + } + pWin->pNextWin = pSelect->pWin; + pWin->ppThis = &pSelect->pWin; + pSelect->pWin = pWin; } return WRC_Continue; } diff --git a/src/resolve.c b/src/resolve.c index be6430deb..48d8fcb9b 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -901,6 +901,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ #ifndef SQLITE_OMIT_WINDOWFUNC if( pWin ){ Select *pSel = pNC->pWinSelect; + assert( pWin==pExpr->y.pWin ); if( IN_RENAME_OBJECT==0 ){ sqlite3WindowUpdate(pParse, pSel->pWinDefn, pWin, pDef); } @@ -910,8 +911,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ if( 0==pSel->pWin || 0==sqlite3WindowCompare(pParse, pSel->pWin, pWin, 0) ){ - pExpr->y.pWin->pNextWin = pSel->pWin; - pSel->pWin = pExpr->y.pWin; + pWin->pNextWin = pSel->pWin; + if( pSel->pWin ){ + pSel->pWin->ppThis = &pWin->pNextWin; + } + pSel->pWin = pWin; + pWin->ppThis = &pSel->pWin; } pNC->ncFlags |= NC_HasWin; }else @@ -1295,16 +1300,15 @@ int sqlite3ResolveOrderGroupBy( #ifndef SQLITE_OMIT_WINDOWFUNC /* -** Walker callback for resolveRemoveWindows(). +** Walker callback for windowRemoveExprFromSelect(). */ static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){ if( ExprHasProperty(pExpr, EP_WinFunc) ){ - Window **pp; - for(pp=&pWalker->u.pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ - if( *pp==pExpr->y.pWin ){ - *pp = (*pp)->pNextWin; - break; - } + Window *pWin = pExpr->y.pWin; + if( pWin->ppThis ){ + *pWin->ppThis = pWin->pNextWin; + if( pWin->pNextWin ) pWin->pNextWin->ppThis = pWin->ppThis; + pWin->ppThis = 0; } } return WRC_Continue; @@ -1314,16 +1318,18 @@ static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){ ** Remove any Window objects owned by the expression pExpr from the ** Select.pWin list of Select object pSelect. */ -static void resolveRemoveWindows(Select *pSelect, Expr *pExpr){ - Walker sWalker; - memset(&sWalker, 0, sizeof(Walker)); - sWalker.xExprCallback = resolveRemoveWindowsCb; - sWalker.u.pSelect = pSelect; - sqlite3WalkExpr(&sWalker, pExpr); +static void windowRemoveExprFromSelect(Select *pSelect, Expr *pExpr){ + if( pSelect->pWin ){ + Walker sWalker; + memset(&sWalker, 0, sizeof(Walker)); + sWalker.xExprCallback = resolveRemoveWindowsCb; + sWalker.u.pSelect = pSelect; + sqlite3WalkExpr(&sWalker, pExpr); + } } #else -# define resolveRemoveWindows(x,y) -#endif +# define windowRemoveExprFromSelect(a, b) +#endif /* SQLITE_OMIT_WINDOWFUNC */ /* ** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect. @@ -1394,7 +1400,7 @@ static int resolveOrderGroupBy( /* Since this expresion is being changed into a reference ** to an identical expression in the result set, remove all Window ** objects belonging to the expression from the Select.pWin list. */ - resolveRemoveWindows(pSelect, pE); + windowRemoveExprFromSelect(pSelect, pE); pItem->u.x.iOrderByCol = j+1; } } diff --git a/src/select.c b/src/select.c index 397037b17..6e0eeb2f4 100644 --- a/src/select.c +++ b/src/select.c @@ -102,6 +102,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){ } #endif if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); + assert( p->pWin==0 ); if( bFree ) sqlite3DbFreeNN(db, p); p = pPrior; bFree = 1; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 837e056cf..e55eadea6 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3594,6 +3594,7 @@ struct Window { u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */ Expr *pStart; /* Expression for "<expr> PRECEDING" */ Expr *pEnd; /* Expression for "<expr> FOLLOWING" */ + Window **ppThis; /* Pointer to this object in Select.pWin list */ Window *pNextWin; /* Next window function belonging to this SELECT */ Expr *pFilter; /* The FILTER expression */ FuncDef *pFunc; /* The function */ diff --git a/src/window.c b/src/window.c index d769b0bb7..f94370a49 100644 --- a/src/window.c +++ b/src/window.c @@ -1022,6 +1022,10 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ */ void sqlite3WindowDelete(sqlite3 *db, Window *p){ if( p ){ + if( p->ppThis ){ + *p->ppThis = p->pNextWin; + if( p->pNextWin ) p->pNextWin->ppThis = p->ppThis; + } sqlite3ExprDelete(db, p->pFilter); sqlite3ExprListDelete(db, p->pPartition); sqlite3ExprListDelete(db, p->pOrderBy); |