aboutsummaryrefslogtreecommitdiff
path: root/src/resolve.c
diff options
context:
space:
mode:
authordan <dan@noemail.net>2018-05-16 20:58:07 +0000
committerdan <dan@noemail.net>2018-05-16 20:58:07 +0000
commit86fb6e173885b9ac170b14ce9a9d0ccf7cd34e50 (patch)
treeca728c5c40cf8c1487880b4446d95d75f3cdbe6e /src/resolve.c
parentf80bba9d8d6a1bff6728db40d8d65af06d0723f9 (diff)
downloadsqlite-86fb6e173885b9ac170b14ce9a9d0ccf7cd34e50.tar.gz
sqlite-86fb6e173885b9ac170b14ce9a9d0ccf7cd34e50.zip
Start of experimental implementation of SQL window functions. Does not yet
work. FossilOrigin-Name: 3781e520854808fe02ad3fe77dd11fc917448c58ff1fd79123289dd91937decd
Diffstat (limited to 'src/resolve.c')
-rw-r--r--src/resolve.c48
1 files changed, 33 insertions, 15 deletions
diff --git a/src/resolve.c b/src/resolve.c
index 4ed36a479..073fdf193 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -753,8 +753,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
NC_IdxExpr|NC_PartIdx);
}
}
- if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
- sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
+ if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
+ || (pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0)
+ ){
+ const char *zType = pExpr->pWin ? "window" : "aggregate";
+ sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
pNC->nErr++;
is_agg = 0;
}else if( no_such_func && pParse->db->init.busy==0
@@ -772,19 +775,28 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
sqlite3WalkExprList(pWalker, pList);
if( is_agg ){
- NameContext *pNC2 = pNC;
- pExpr->op = TK_AGG_FUNCTION;
- pExpr->op2 = 0;
- while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
- pExpr->op2++;
- pNC2 = pNC2->pNext;
+ if( pExpr->pWin ){
+ pExpr->pWin->pNextWin = pNC->pWin;
+ pNC->pWin = pExpr->pWin;
+ pExpr->pWin->pFunc = pDef;
+ pExpr->pWin->nArg = pExpr->x.pList->nExpr;
}
- assert( pDef!=0 );
- if( pNC2 ){
- assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
- testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
- pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
+ else
+ {
+ NameContext *pNC2 = pNC;
+ pExpr->op = TK_AGG_FUNCTION;
+ pExpr->op2 = 0;
+ while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
+ pExpr->op2++;
+ pNC2 = pNC2->pNext;
+ }
+ assert( pDef!=0 );
+ if( pNC2 ){
+ assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
+ testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
+ pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
+ }
}
pNC->ncFlags |= NC_AllowAgg;
}
@@ -1234,6 +1246,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
nCompound = 0;
pLeftmost = p;
while( p ){
+ assert( p->pWin==0 );
assert( (p->selFlags & SF_Expanded)!=0 );
assert( (p->selFlags & SF_Resolved)==0 );
p->selFlags |= SF_Resolved;
@@ -1291,12 +1304,13 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
** resolve the result-set expression list.
*/
- sNC.ncFlags = NC_AllowAgg;
+ sNC.ncFlags = NC_AllowAgg|NC_AllowWin;
sNC.pSrcList = p->pSrc;
sNC.pNext = pOuterNC;
/* Resolve names in the result set. */
if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort;
+ sNC.ncFlags &= ~NC_AllowWin;
/* If there are no aggregate functions in the result-set, and no GROUP BY
** expression, do not allow aggregates in any of the other expressions.
@@ -1345,7 +1359,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** outer queries
*/
sNC.pNext = 0;
- sNC.ncFlags |= NC_AllowAgg;
+ sNC.ncFlags |= NC_AllowAgg|NC_AllowWin;
/* If this is a converted compound query, move the ORDER BY clause from
** the sub-query back to the parent query. At this point each term
@@ -1376,6 +1390,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
if( db->mallocFailed ){
return WRC_Abort;
}
+ sNC.ncFlags &= ~NC_AllowWin;
/* Resolve the GROUP BY clause. At the same time, make sure
** the GROUP BY clause does not contain aggregate functions.
@@ -1402,6 +1417,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
return WRC_Abort;
}
+ p->pWin = sNC.pWin;
+ sNC.pWin = 0;
+
/* Advance to the next term of the compound
*/
p = p->pPrior;