Ensure that SQLite does not attempt to process incompatible window functions in a single scan. Fix for [256741a1].
FossilOrigin-Name: 4f5b2d938194fab7627486e2ced633def2c90d9d3328e3700612feb9dbfa3d9a
diff --git a/src/expr.c b/src/expr.c
index e00b319..8f02ae5 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1325,12 +1325,7 @@
assert( pWin );
assert( IsWindowFunc(pExpr) );
assert( pWin->ppThis==0 );
- if( pSelect->pWin ){
- pSelect->pWin->ppThis = &pWin->pNextWin;
- }
- pWin->pNextWin = pSelect->pWin;
- pWin->ppThis = &pSelect->pWin;
- pSelect->pWin = pWin;
+ sqlite3WindowLink(pSelect, pWin);
}
return WRC_Continue;
}
diff --git a/src/resolve.c b/src/resolve.c
index d88abc4..3160038 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -908,16 +908,7 @@
sqlite3WalkExprList(pWalker, pWin->pPartition);
sqlite3WalkExprList(pWalker, pWin->pOrderBy);
sqlite3WalkExpr(pWalker, pWin->pFilter);
- if( 0==pSel->pWin
- || 0==sqlite3WindowCompare(pParse, pSel->pWin, pWin, 0)
- ){
- pWin->pNextWin = pSel->pWin;
- if( pSel->pWin ){
- pSel->pWin->ppThis = &pWin->pNextWin;
- }
- pSel->pWin = pWin;
- pWin->ppThis = &pSel->pWin;
- }
+ sqlite3WindowLink(pSel, pWin);
pNC->ncFlags |= NC_HasWin;
}else
#endif /* SQLITE_OMIT_WINDOWFUNC */
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 1104b77..d6746aa 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3609,6 +3609,7 @@
void sqlite3WindowListDelete(sqlite3 *db, Window *p);
Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
void sqlite3WindowAttach(Parse*, Expr*, Window*);
+void sqlite3WindowLink(Select *pSel, Window *pWin);
int sqlite3WindowCompare(Parse*, Window*, Window*, int);
void sqlite3WindowCodeInit(Parse*, Window*);
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
diff --git a/src/window.c b/src/window.c
index ebcb576..e2f0b62 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1230,6 +1230,25 @@
}
/*
+** Possibly link window pWin into the list at pSel->pWin (window functions
+** to be processed as part of SELECT statement pSel). The window is linked
+** in if either (a) there are no other windows already linked to this
+** SELECT, or (b) the windows already linked use a compatible window frame.
+*/
+void sqlite3WindowLink(Select *pSel, Window *pWin){
+ if( 0==pSel->pWin
+ || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0)
+ ){
+ pWin->pNextWin = pSel->pWin;
+ if( pSel->pWin ){
+ pSel->pWin->ppThis = &pWin->pNextWin;
+ }
+ pSel->pWin = pWin;
+ pWin->ppThis = &pSel->pWin;
+ }
+}
+
+/*
** Return 0 if the two window objects are identical, or non-zero otherwise.
** Identical window objects can be processed in a single scan.
*/
@@ -1416,6 +1435,8 @@
int nArg = windowArgCount(pWin);
int i;
+ assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED );
+
for(i=0; i<nArg; i++){
if( i!=1 || pFunc->zName!=nth_valueName ){
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i);