aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <dan@noemail.net>2019-07-22 16:33:02 +0000
committerdan <dan@noemail.net>2019-07-22 16:33:02 +0000
commit7f6f12bdd35c55d9f98b6eefbe2d40c4a85aab87 (patch)
treec90be8f5173dfe1513abdfe7ae4a356f4f82bd9c /src
parent1e60261cfbc34cdad2625241ba6e5bedfb2e6716 (diff)
parent75b0821e999cb14d4081a6ff8090e28e49e5bc7e (diff)
downloadsqlite-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.c13
-rw-r--r--src/resolve.c42
-rw-r--r--src/select.c1
-rw-r--r--src/sqliteInt.h1
-rw-r--r--src/window.c4
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);