1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Fix another issue to do with window-functions in aggregate queries.

FossilOrigin-Name: 6413e38a174044c28fa9b8b937e6c972d144547a246e6f2882e782538300d042
This commit is contained in:
dan
2018-06-12 20:53:38 +00:00
parent 7392569f5e
commit c0bb4459d3
6 changed files with 100 additions and 32 deletions

View File

@@ -129,6 +129,11 @@
** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
**
** See sqlite3WindowUpdate() for details.
**
** As well as some of the built-in window functions, aggregate window
** functions min() and max() are implemented using VDBE instructions if
** the start of the window frame is declared as anything other than
** UNBOUNDED PRECEDING.
*/
/*
@@ -471,11 +476,28 @@ void sqlite3WindowFunctions(void){
sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs));
}
/*
** This function is called immediately after resolving the function name
** for a window function within a SELECT statement. Argument pList is a
** linked list of WINDOW definitions for the current SELECT statement.
** Argument pFunc is the function definition just resolved and pWin
** is the Window object representing the associated OVER clause. This
** function updates the contents of pWin as follows:
**
** * If the OVER clause refered to a named window (as in "max(x) OVER win"),
** search list pList for a matching WINDOW definition, and update pWin
** accordingly. If no such WINDOW clause can be found, leave an error
** in pParse.
**
** * If the function is a built-in window function that requires the
** window to be coerced (see "BUILT-IN WINDOW FUNCTIONS" at the top
** of this file), pWin is updated here.
*/
void sqlite3WindowUpdate(
Parse *pParse,
Window *pList,
Window *pWin,
FuncDef *pFunc
Window *pList, /* List of named windows for this SELECT */
Window *pWin, /* Window frame to update */
FuncDef *pFunc /* Window function definition */
){
if( pWin->zName ){
Window *p;
@@ -523,16 +545,21 @@ void sqlite3WindowUpdate(
pWin->pFunc = pFunc;
}
/*
** Context object passed through sqlite3WalkExprList() to
** selectWindowRewriteExprCb() by selectWindowRewriteEList().
*/
typedef struct WindowRewrite WindowRewrite;
struct WindowRewrite {
Window *pWin;
ExprList *pSub;
};
static int selectWindowRewriteSelectCb(Walker *pWalker, Select *pSelect){
return WRC_Prune;
}
/*
** Callback function used by selectWindowRewriteEList(). If necessary,
** this function appends to the output expression-list and updates
** expression (*ppExpr) in place.
*/
static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
struct WindowRewrite *p = pWalker->u.pRewrite;
Parse *pParse = pWalker->pParse;
@@ -578,7 +605,24 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
static int selectWindowRewriteSelectCb(Walker *pWalker, Select *pSelect){
return WRC_Prune;
}
/*
** Iterate through each expression in expression-list pEList. For each:
**
** * TK_COLUMN,
** * aggregate function, or
** * window function with a Window object that is not a member of the
** linked list passed as the second argument (pWin)
**
** Append the node to output expression-list (*ppSub). And replace it
** with a TK_COLUMN that reads the (N-1)th element of table
** pWin->iEphCsr, where N is the number of elements in (*ppSub) after
** appending the new one.
*/
static int selectWindowRewriteEList(
Parse *pParse,
Window *pWin,
@@ -606,6 +650,10 @@ static int selectWindowRewriteEList(
return rc;
}
/*
** Append a copy of each expression in expression-list pAppend to
** expression list pList. Return a pointer to the result list.
*/
static ExprList *exprListAppendList(
Parse *pParse, /* Parsing context */
ExprList *pList, /* List to which to append. Might be NULL */
@@ -627,21 +675,8 @@ static ExprList *exprListAppendList(
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it
** rewrites the SELECT statement so that window function xStep functions
** are invoked in the correct order. The simplest version of the
** transformation is:
**
** SELECT win(args...) OVER (<list1>) FROM <src> ORDER BY <list2>
**
** to
**
** SELECT win(args...) FROM (
** SELECT args... FROM <src> ORDER BY <list1>
** ) ORDER BY <list2>
**
** where <src> may contain WHERE, GROUP BY and HAVING clauses, and <list1>
** is the concatenation of the PARTITION BY and ORDER BY clauses in the
** OVER clause.
**
** are invoked in the correct order as described under "SELECT REWRITING"
** at the top of this file.
*/
int sqlite3WindowRewrite(Parse *pParse, Select *p){
int rc = SQLITE_OK;
@@ -726,6 +761,9 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
return rc;
}
/*
** Free the Window object passed as the second argument.
*/
void sqlite3WindowDelete(sqlite3 *db, Window *p){
if( p ){
sqlite3ExprDelete(db, p->pFilter);
@@ -738,6 +776,9 @@ void sqlite3WindowDelete(sqlite3 *db, Window *p){
}
}
/*
** Free the linked list of Window objects starting at the second argument.
*/
void sqlite3WindowListDelete(sqlite3 *db, Window *p){
while( p ){
Window *pNext = p->pNextWin;
@@ -746,6 +787,9 @@ void sqlite3WindowListDelete(sqlite3 *db, Window *p){
}
}
/*
** Allocate and return a new Window object.
*/
Window *sqlite3WindowAlloc(
Parse *pParse,
int eType,
@@ -768,6 +812,9 @@ Window *sqlite3WindowAlloc(
return pWin;
}
/*
** Attach window object pWin to expression p.
*/
void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
if( p ){
p->pWin = pWin;