Prevent aliases of window functions expressions from being used as arguments to aggregate or other window functions.
FossilOrigin-Name: 1e16d3e8fc60d39ca3899759ff15d355fdd7d3e23b325d8d2b0f954e11ce8dce
diff --git a/src/resolve.c b/src/resolve.c
index 2644e06..eb9e137 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -435,6 +435,10 @@
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
return WRC_Abort;
}
+ if( (pNC->ncFlags&NC_AllowWin)==0 && ExprHasProperty(pOrig, EP_Win) ){
+ sqlite3ErrorMsg(pParse, "misuse of aliased window function %s",zAs);
+ return WRC_Abort;
+ }
if( sqlite3ExprVectorSize(pOrig)!=1 ){
sqlite3ErrorMsg(pParse, "row value misused");
return WRC_Abort;
@@ -725,6 +729,7 @@
const char *zId; /* The function name. */
FuncDef *pDef; /* Information about the function */
u8 enc = ENC(pParse->db); /* The database encoding */
+ int savedAllowFlags = (pNC->ncFlags & (NC_AllowAgg | NC_AllowWin));
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
zId = pExpr->u.zToken;
@@ -846,8 +851,11 @@
pNC->nErr++;
}
if( is_agg ){
+ /* Window functions may not be arguments of aggregate functions.
+ ** Or arguments of other window functions. But aggregate functions
+ ** may be arguments for window functions. */
#ifndef SQLITE_OMIT_WINDOWFUNC
- pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg);
+ pNC->ncFlags &= ~(NC_AllowWin | (!pExpr->y.pWin ? NC_AllowAgg : 0));
#else
pNC->ncFlags &= ~NC_AllowAgg;
#endif
@@ -868,7 +876,7 @@
pExpr->y.pWin->pNextWin = pSel->pWin;
pSel->pWin = pExpr->y.pWin;
}
- pNC->ncFlags |= NC_AllowWin;
+ pNC->ncFlags |= NC_HasWin;
}else
#endif /* SQLITE_OMIT_WINDOWFUNC */
{
@@ -886,8 +894,8 @@
pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
}
- pNC->ncFlags |= NC_AllowAgg;
}
+ pNC->ncFlags |= savedAllowFlags;
}
/* FIX ME: Compute pExpr->affinity based on the expected return
** type of the function
@@ -1648,8 +1656,8 @@
Walker w;
if( pExpr==0 ) return SQLITE_OK;
- savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg);
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg);
+ savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
w.xSelectCallback = resolveSelectStep;
@@ -1668,6 +1676,9 @@
if( pNC->ncFlags & NC_HasAgg ){
ExprSetProperty(pExpr, EP_Agg);
}
+ if( pNC->ncFlags & NC_HasWin ){
+ ExprSetProperty(pExpr, EP_Win);
+ }
pNC->ncFlags |= savedHasAgg;
return pNC->nErr>0 || w.pParse->nErr>0;
}