mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Improve comments and code legibility in new file window.c.
FossilOrigin-Name: bb915854d435bdd78f141d70e23527e97922ec176acd3ed8060c78dffc96bab8
This commit is contained in:
146
src/window.c
146
src/window.c
@@ -1236,6 +1236,12 @@ static void windowReturnRows(
|
||||
sqlite3VdbeJumpHere(v, addr+1); /* The OP_Goto */
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code to set the accumulator register for each window function
|
||||
** in the linked list passed as the second argument to NULL. And perform
|
||||
** any equivalent initialization required by any built-in window functions
|
||||
** in the list.
|
||||
*/
|
||||
static int windowInitAccum(Parse *pParse, Window *pMWin){
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
int regArg;
|
||||
@@ -1258,15 +1264,11 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){
|
||||
|
||||
|
||||
/*
|
||||
** This function does the work of sqlite3WindowCodeStep() for all "ROWS"
|
||||
** window frame types except for "BETWEEN UNBOUNDED PRECEDING AND CURRENT
|
||||
** ROW". Pseudo-code for each follows.
|
||||
**
|
||||
** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
|
||||
** ----------------------------------------------------
|
||||
**
|
||||
** Pseudo-code for the implementation of this window frame type is as
|
||||
** follows. sqlite3WhereBegin() has already been called to generate the
|
||||
** top of the main loop when this function is called.
|
||||
**
|
||||
** Each time the sub-routine at addrGosub is invoked, a single output
|
||||
** row is generated based on the current row indicated by Window.iEphCsr.
|
||||
**
|
||||
** ...
|
||||
** if( new partition ){
|
||||
@@ -1551,6 +1553,16 @@ static void windowCodeRowExprStep(
|
||||
}
|
||||
|
||||
/*
|
||||
** This function does the work of sqlite3WindowCodeStep() for cases that
|
||||
** would normally be handled by windowCodeDefaultStep() when there are
|
||||
** one or more built-in window-functions that require the entire partition
|
||||
** to be cached in a temp table before any rows can be returned. Additionally.
|
||||
** "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" is always handled by
|
||||
** this function.
|
||||
**
|
||||
** Pseudo-code corresponding to the VM code generated by this function
|
||||
** for each type of window follows.
|
||||
**
|
||||
** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
|
||||
**
|
||||
** flush_partition:
|
||||
@@ -1581,8 +1593,64 @@ static void windowCodeRowExprStep(
|
||||
** Return
|
||||
**
|
||||
** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
|
||||
** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||
**
|
||||
** As above, except that the "if( new peer )" branch is always taken.
|
||||
**
|
||||
** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
|
||||
**
|
||||
** As above, except that each of the for() loops becomes:
|
||||
**
|
||||
** for(i=0; i<ctr; i++){
|
||||
** Gosub addrGosub
|
||||
** AggStep (xInverse, iEphCsr)
|
||||
** Next iEphCsr
|
||||
** }
|
||||
**
|
||||
** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||
**
|
||||
** flush_partition:
|
||||
** Once {
|
||||
** OpenDup (iEphCsr -> csrLead)
|
||||
** }
|
||||
** foreach row (csrLead) {
|
||||
** AggStep (csrLead)
|
||||
** }
|
||||
** foreach row (iEphCsr) {
|
||||
** Gosub addrGosub
|
||||
** }
|
||||
**
|
||||
** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||
**
|
||||
** flush_partition:
|
||||
** Once {
|
||||
** OpenDup (iEphCsr -> csrLead)
|
||||
** }
|
||||
** foreach row (csrLead){
|
||||
** AggStep (csrLead)
|
||||
** }
|
||||
** Rewind (csrLead)
|
||||
** Integer ctr 0
|
||||
** foreach row (csrLead){
|
||||
** if( new peer ){
|
||||
** AggFinal (xValue)
|
||||
** for(i=0; i<ctr; i++){
|
||||
** Gosub addrGosub
|
||||
** AggStep (xInverse, iEphCsr)
|
||||
** Next iEphCsr
|
||||
** }
|
||||
** Integer ctr 0
|
||||
** }
|
||||
** Incr ctr
|
||||
** }
|
||||
**
|
||||
** AggFinal (xFinalize)
|
||||
** for(i=0; i<ctr; i++){
|
||||
** Gosub addrGosub
|
||||
** Next iEphCsr
|
||||
** }
|
||||
**
|
||||
** ResetSorter (csr)
|
||||
** Return
|
||||
*/
|
||||
static void windowCodeCacheStep(
|
||||
Parse *pParse,
|
||||
@@ -1598,7 +1666,7 @@ static void windowCodeCacheStep(
|
||||
int addr;
|
||||
ExprList *pPart = pMWin->pPartition;
|
||||
ExprList *pOrderBy = pMWin->pOrderBy;
|
||||
int nPeer = pOrderBy->nExpr;
|
||||
int nPeer = pOrderBy ? pOrderBy->nExpr : 0;
|
||||
int regNewPeer;
|
||||
|
||||
int addrGoto; /* Address of Goto used to jump flush_par.. */
|
||||
@@ -1610,8 +1678,9 @@ static void windowCodeCacheStep(
|
||||
int regArg; /* Register array to martial function args */
|
||||
int regSize;
|
||||
int nArg;
|
||||
int bReverse;
|
||||
int lblEmpty;
|
||||
int bReverse = pMWin->pOrderBy && pMWin->eStart==TK_CURRENT
|
||||
&& pMWin->eEnd==TK_UNBOUNDED;
|
||||
|
||||
assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT)
|
||||
|| (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED)
|
||||
@@ -1620,7 +1689,6 @@ static void windowCodeCacheStep(
|
||||
);
|
||||
|
||||
lblEmpty = sqlite3VdbeMakeLabel(v);
|
||||
bReverse = (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED);
|
||||
regNewPeer = pParse->nMem+1;
|
||||
pParse->nMem += nPeer;
|
||||
|
||||
@@ -1878,34 +1946,60 @@ void sqlite3WindowCodeStep(
|
||||
int addrGosub /* OP_Gosub here to return each row */
|
||||
){
|
||||
Window *pMWin = p->pWin;
|
||||
ExprList *pOrderBy = pMWin->pOrderBy;
|
||||
|
||||
/* Call windowCodeRowExprStep() for all "ROWS" window modes except:
|
||||
/* There are three different functions that may be used to do the work
|
||||
** of this one, depending on the window frame and the specific built-in
|
||||
** window functions used (if any).
|
||||
**
|
||||
** windowCodeRowExprStep() handles all "ROWS" window frames, except for:
|
||||
**
|
||||
** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
|
||||
**
|
||||
** The exception is because windowCodeRowExprStep() implements all window
|
||||
** frame types by caching the entire partition in a temp table, and
|
||||
** "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" is easy enough to
|
||||
** implement without such a cache.
|
||||
**
|
||||
** windowCodeCacheStep() is used for:
|
||||
**
|
||||
** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||
**
|
||||
** It is also used for anything not handled by windowCodeRowExprStep()
|
||||
** that invokes a built-in window function that requires the entire
|
||||
** partition to be cached in a temp table before any rows are returned
|
||||
** (e.g. nth_value() or percent_rank()).
|
||||
**
|
||||
** Finally, assuming there is no built-in window function that requires
|
||||
** the partition to be cached, windowCodeDefaultStep() is used for:
|
||||
**
|
||||
** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
|
||||
** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||
** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
|
||||
** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
|
||||
**
|
||||
** windowCodeDefaultStep() is the only one of the three functions that
|
||||
** does not cache each partition in a temp table before beginning to
|
||||
** return rows.
|
||||
*/
|
||||
if( (pMWin->eType==TK_ROWS
|
||||
&& (pMWin->eStart!=TK_UNBOUNDED || pMWin->eEnd!=TK_CURRENT || !pOrderBy))
|
||||
if( pMWin->eType==TK_ROWS
|
||||
&& (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy)
|
||||
){
|
||||
windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub);
|
||||
}else{
|
||||
Window *pWin;
|
||||
int bCache = 0;
|
||||
int bCache = 0; /* True to use CacheStep() */
|
||||
|
||||
if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED && pOrderBy ){
|
||||
if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED ){
|
||||
bCache = 1;
|
||||
}else{
|
||||
/* Call windowCodeCacheStep() if there is a window function that requires
|
||||
** that the entire partition be cached in a temp table before any rows
|
||||
** are returned. */
|
||||
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
||||
FuncDef *pFunc = pWin->pFunc;
|
||||
if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE)
|
||||
|| (pFunc->xSFunc==nth_valueStepFunc)
|
||||
|| (pFunc->xSFunc==first_valueStepFunc)
|
||||
|| (pFunc->xSFunc==leadStepFunc)
|
||||
|| (pFunc->xSFunc==lagStepFunc)
|
||||
){
|
||||
|| (pFunc->xSFunc==nth_valueStepFunc)
|
||||
|| (pFunc->xSFunc==first_valueStepFunc)
|
||||
|| (pFunc->xSFunc==leadStepFunc)
|
||||
|| (pFunc->xSFunc==lagStepFunc)
|
||||
){
|
||||
bCache = 1;
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user