3 ** The author disclaims copyright to this source code. In place of
4 ** a legal notice, here is a blessing:
6 ** May you do good and not evil.
7 ** May you find forgiveness for yourself and forgive others.
8 ** May you share freely, never taking more than you give.
10 *************************************************************************
12 #include "sqliteInt.h"
15 ** Implementation of built-in window function row_number(). Assumes that the
16 ** window frame has been coerced to:
18 ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
20 static void row_numberStepFunc(
21 sqlite3_context
*pCtx
,
25 i64
*p
= (i64
*)sqlite3_aggregate_context(pCtx
, sizeof(*p
));
28 static void row_numberInverseFunc(
29 sqlite3_context
*pCtx
,
34 static void row_numberValueFunc(sqlite3_context
*pCtx
){
35 i64
*p
= (i64
*)sqlite3_aggregate_context(pCtx
, sizeof(*p
));
36 sqlite3_result_int64(pCtx
, (p
? *p
: 0));
40 ** Context object type used by rank() and dense_rank().
49 ** Implementation of built-in window function dense_rank().
51 static void dense_rankStepFunc(
52 sqlite3_context
*pCtx
,
57 p
= (struct CallCount
*)sqlite3_aggregate_context(pCtx
, sizeof(*p
));
60 static void dense_rankInverseFunc(
61 sqlite3_context
*pCtx
,
66 static void dense_rankValueFunc(sqlite3_context
*pCtx
){
68 p
= (struct CallCount
*)sqlite3_aggregate_context(pCtx
, sizeof(*p
));
74 sqlite3_result_int64(pCtx
, p
->nValue
);
79 ** Implementation of built-in window function rank().
81 static void rankStepFunc(
82 sqlite3_context
*pCtx
,
87 p
= (struct CallCount
*)sqlite3_aggregate_context(pCtx
, sizeof(*p
));
95 static void rankInverseFunc(
96 sqlite3_context
*pCtx
,
101 static void rankValueFunc(sqlite3_context
*pCtx
){
103 p
= (struct CallCount
*)sqlite3_aggregate_context(pCtx
, sizeof(*p
));
105 sqlite3_result_int64(pCtx
, p
->nValue
);
111 ** Implementation of built-in window function percent_rank().
113 static void percent_rankStepFunc(
114 sqlite3_context
*pCtx
,
116 sqlite3_value
**apArg
121 p
= (struct CallCount
*)sqlite3_aggregate_context(pCtx
, sizeof(*p
));
124 p
->nTotal
= sqlite3_value_int64(apArg
[0]);
128 p
->nValue
= p
->nStep
;
132 static void percent_rankInverseFunc(
133 sqlite3_context
*pCtx
,
135 sqlite3_value
**apArg
138 static void percent_rankValueFunc(sqlite3_context
*pCtx
){
140 p
= (struct CallCount
*)sqlite3_aggregate_context(pCtx
, sizeof(*p
));
143 double r
= (double)(p
->nValue
-1) / (double)(p
->nTotal
-1);
144 sqlite3_result_double(pCtx
, r
);
146 sqlite3_result_double(pCtx
, 100.0);
152 static void nth_valueStepFunc(
153 sqlite3_context
*pCtx
,
155 sqlite3_value
**apArg
158 static void nth_valueInverseFunc(
159 sqlite3_context
*pCtx
,
161 sqlite3_value
**apArg
164 static void nth_valueValueFunc(sqlite3_context
*pCtx
){
167 #define WINDOWFUNC(name,nArg,extra) { \
168 nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
169 name ## StepFunc, name ## ValueFunc, name ## ValueFunc, \
170 name ## InverseFunc, #name \
174 ** Register those built-in window functions that are not also aggregates.
176 void sqlite3WindowFunctions(void){
177 static FuncDef aWindowFuncs
[] = {
178 WINDOWFUNC(row_number
, 0, 0),
179 WINDOWFUNC(dense_rank
, 0, 0),
180 WINDOWFUNC(rank
, 0, 0),
181 WINDOWFUNC(percent_rank
, 0, SQLITE_FUNC_WINDOW_SIZE
),
182 WINDOWFUNC(nth_value
, 2, 0),
184 sqlite3InsertBuiltinFuncs(aWindowFuncs
, ArraySize(aWindowFuncs
));
187 void sqlite3WindowUpdate(Parse
*pParse
, Window
*pWin
, FuncDef
*pFunc
){
188 if( pFunc
->funcFlags
& SQLITE_FUNC_WINDOW
){
189 sqlite3
*db
= pParse
->db
;
190 if( pFunc
->xSFunc
==row_numberStepFunc
){
191 sqlite3ExprDelete(db
, pWin
->pStart
);
192 sqlite3ExprDelete(db
, pWin
->pEnd
);
193 pWin
->pStart
= pWin
->pEnd
= 0;
194 pWin
->eType
= TK_ROWS
;
195 pWin
->eStart
= TK_UNBOUNDED
;
196 pWin
->eEnd
= TK_CURRENT
;
199 if( pFunc
->xSFunc
==dense_rankStepFunc
|| pFunc
->xSFunc
==rankStepFunc
200 || pFunc
->xSFunc
==percent_rankStepFunc
202 sqlite3ExprDelete(db
, pWin
->pStart
);
203 sqlite3ExprDelete(db
, pWin
->pEnd
);
204 pWin
->pStart
= pWin
->pEnd
= 0;
205 pWin
->eType
= TK_RANGE
;
206 pWin
->eStart
= TK_UNBOUNDED
;
207 pWin
->eEnd
= TK_CURRENT
;
212 typedef struct WindowRewrite WindowRewrite
;
213 struct WindowRewrite
{
218 static int selectWindowRewriteSelectCb(Walker
*pWalker
, Select
*pSelect
){
222 static int selectWindowRewriteExprCb(Walker
*pWalker
, Expr
*pExpr
){
223 struct WindowRewrite
*p
= pWalker
->u
.pRewrite
;
224 Parse
*pParse
= pWalker
->pParse
;
229 if( pExpr
->pWin
==0 ){
233 for(pWin
=p
->pWin
; pWin
; pWin
=pWin
->pNextWin
){
234 if( pExpr
->pWin
==pWin
){
235 pExpr
->pWin
->pOwner
= pExpr
;
243 Expr
*pDup
= sqlite3ExprDup(pParse
->db
, pExpr
, 0);
244 p
->pSub
= sqlite3ExprListAppend(pParse
, p
->pSub
, pDup
);
246 assert( ExprHasProperty(pExpr
, EP_Static
)==0 );
247 ExprSetProperty(pExpr
, EP_Static
);
248 sqlite3ExprDelete(pParse
->db
, pExpr
);
249 ExprClearProperty(pExpr
, EP_Static
);
250 memset(pExpr
, 0, sizeof(Expr
));
252 pExpr
->op
= TK_COLUMN
;
253 pExpr
->iColumn
= p
->pSub
->nExpr
-1;
254 pExpr
->iTable
= p
->pWin
->iEphCsr
;
267 static int selectWindowRewriteEList(
270 ExprList
*pEList
, /* Rewrite expressions in this list */
271 ExprList
**ppSub
/* IN/OUT: Sub-select expression-list */
274 WindowRewrite sRewrite
;
277 memset(&sWalker
, 0, sizeof(Walker
));
278 memset(&sRewrite
, 0, sizeof(WindowRewrite
));
280 sRewrite
.pSub
= *ppSub
;
281 sRewrite
.pWin
= pWin
;
283 sWalker
.pParse
= pParse
;
284 sWalker
.xExprCallback
= selectWindowRewriteExprCb
;
285 sWalker
.xSelectCallback
= selectWindowRewriteSelectCb
;
286 sWalker
.u
.pRewrite
= &sRewrite
;
288 rc
= sqlite3WalkExprList(&sWalker
, pEList
);
290 *ppSub
= sRewrite
.pSub
;
294 static ExprList
*exprListAppendList(
295 Parse
*pParse
, /* Parsing context */
296 ExprList
*pList
, /* List to which to append. Might be NULL */
297 ExprList
*pAppend
/* List of values to append. Might be NULL */
301 int nInit
= pList
? pList
->nExpr
: 0;
302 for(i
=0; i
<pAppend
->nExpr
; i
++){
303 Expr
*pDup
= sqlite3ExprDup(pParse
->db
, pAppend
->a
[i
].pExpr
, 0);
304 pList
= sqlite3ExprListAppend(pParse
, pList
, pDup
);
305 if( pList
) pList
->a
[nInit
+i
].sortOrder
= pAppend
->a
[i
].sortOrder
;
312 ** If the SELECT statement passed as the second argument does not invoke
313 ** any SQL window functions, this function is a no-op. Otherwise, it
314 ** rewrites the SELECT statement so that window function xStep functions
315 ** are invoked in the correct order. The simplest version of the
316 ** transformation is:
318 ** SELECT win(args...) OVER (<list1>) FROM <src> ORDER BY <list2>
322 ** SELECT win(args...) FROM (
323 ** SELECT args... FROM <src> ORDER BY <list1>
324 ** ) ORDER BY <list2>
326 ** where <src> may contain WHERE, GROUP BY and HAVING clauses, and <list1>
327 ** is the concatenation of the PARTITION BY and ORDER BY clauses in the
331 int sqlite3WindowRewrite(Parse
*pParse
, Select
*p
){
334 Vdbe
*v
= sqlite3GetVdbe(pParse
);
336 sqlite3
*db
= pParse
->db
;
337 Select
*pSub
= 0; /* The subquery */
338 SrcList
*pSrc
= p
->pSrc
;
339 Expr
*pWhere
= p
->pWhere
;
340 ExprList
*pGroupBy
= p
->pGroupBy
;
341 Expr
*pHaving
= p
->pHaving
;
344 ExprList
*pSublist
= 0; /* Expression list for sub-query */
345 Window
*pMWin
= p
->pWin
; /* Master window object */
346 Window
*pWin
; /* Window object iterator */
353 /* Assign a cursor number for the ephemeral table used to buffer rows.
354 ** The OpenEphemeral instruction is coded later, after it is known how
355 ** many columns the table will have. */
356 pMWin
->iEphCsr
= pParse
->nTab
++;
358 rc
= selectWindowRewriteEList(pParse
, pMWin
, p
->pEList
, &pSublist
);
360 rc
= selectWindowRewriteEList(pParse
, pMWin
, p
->pOrderBy
, &pSublist
);
362 pMWin
->nBufferCol
= (pSublist
? pSublist
->nExpr
: 0);
364 /* Create the ORDER BY clause for the sub-select. This is the concatenation
365 ** of the window PARTITION and ORDER BY clauses. Append the same
366 ** expressions to the sub-select expression list. They are required to
367 ** figure out where boundaries for partitions and sets of peer rows. */
368 pSort
= sqlite3ExprListDup(db
, pMWin
->pPartition
, 0);
369 if( pMWin
->pOrderBy
){
370 pSort
= exprListAppendList(pParse
, pSort
, pMWin
->pOrderBy
);
372 pSublist
= exprListAppendList(pParse
, pSublist
, pSort
);
374 /* Append the arguments passed to each window function to the
375 ** sub-select expression list. Also allocate two registers for each
376 ** window function - one for the accumulator, another for interim
378 for(pWin
=pMWin
; pWin
; pWin
=pWin
->pNextWin
){
379 pWin
->iArgCol
= (pSublist
? pSublist
->nExpr
: 0);
380 pSublist
= exprListAppendList(pParse
, pSublist
, pWin
->pOwner
->x
.pList
);
381 pWin
->regAccum
= ++pParse
->nMem
;
382 pWin
->regResult
= ++pParse
->nMem
;
383 sqlite3VdbeAddOp2(v
, OP_Null
, 0, pWin
->regAccum
);
386 pSub
= sqlite3SelectNew(
387 pParse
, pSublist
, pSrc
, pWhere
, pGroupBy
, pHaving
, pSort
, 0, 0
389 p
->pSrc
= sqlite3SrcListAppend(db
, 0, 0, 0);
393 p
->pSrc
->a
[0].pSelect
= pSub
;
394 sqlite3SrcListAssignCursors(pParse
, p
->pSrc
);
395 if( sqlite3ExpandSubquery(pParse
, &p
->pSrc
->a
[0]) ){
398 pSub
->selFlags
|= SF_Expanded
;
402 sqlite3VdbeAddOp2(v
, OP_OpenEphemeral
, pMWin
->iEphCsr
, pSublist
->nExpr
);
408 void sqlite3WindowDelete(sqlite3
*db
, Window
*p
){
410 sqlite3ExprDelete(db
, p
->pFilter
);
411 sqlite3ExprListDelete(db
, p
->pPartition
);
412 sqlite3ExprListDelete(db
, p
->pOrderBy
);
413 sqlite3ExprDelete(db
, p
->pEnd
);
414 sqlite3ExprDelete(db
, p
->pStart
);
415 sqlite3DbFree(db
, p
);
419 Window
*sqlite3WindowAlloc(
422 int eStart
, Expr
*pStart
,
425 Window
*pWin
= (Window
*)sqlite3DbMallocZero(pParse
->db
, sizeof(Window
));
429 pWin
->eStart
= eStart
;
432 pWin
->pStart
= pStart
;
434 sqlite3ExprDelete(pParse
->db
, pEnd
);
435 sqlite3ExprDelete(pParse
->db
, pStart
);
441 void sqlite3WindowAttach(Parse
*pParse
, Expr
*p
, Window
*pWin
){
445 sqlite3WindowDelete(pParse
->db
, pWin
);
450 ** Return 0 if the two window objects are identical, or non-zero otherwise.
452 int sqlite3WindowCompare(Parse
*pParse
, Window
*p1
, Window
*p2
){
453 if( p1
->eType
!=p2
->eType
) return 1;
454 if( p1
->eStart
!=p2
->eStart
) return 1;
455 if( p1
->eEnd
!=p2
->eEnd
) return 1;
456 if( sqlite3ExprCompare(pParse
, p1
->pStart
, p2
->pStart
, -1) ) return 1;
457 if( sqlite3ExprCompare(pParse
, p1
->pEnd
, p2
->pEnd
, -1) ) return 1;
458 if( sqlite3ExprListCompare(p1
->pPartition
, p2
->pPartition
, -1) ) return 1;
459 if( sqlite3ExprListCompare(p1
->pOrderBy
, p2
->pOrderBy
, -1) ) return 1;
463 static void windowAggInit(Parse
*pParse
, Window
*pMWin
){
465 for(pWin
=pMWin
; pWin
; pWin
=pWin
->pNextWin
){
466 int funcFlags
= pWin
->pFunc
->funcFlags
;
467 if( (funcFlags
& SQLITE_FUNC_MINMAX
) && pWin
->eStart
!=TK_UNBOUNDED
){
468 ExprList
*pList
= pWin
->pOwner
->x
.pList
;
469 KeyInfo
*pKeyInfo
= sqlite3KeyInfoFromExprList(pParse
, pList
, 0, 0);
470 Vdbe
*v
= sqlite3GetVdbe(pParse
);
471 pWin
->csrApp
= pParse
->nTab
++;
472 pWin
->regApp
= pParse
->nMem
+1;
474 if( pKeyInfo
&& pWin
->pFunc
->zName
[1]=='i' ){
475 assert( pKeyInfo
->aSortOrder
[0]==0 );
476 pKeyInfo
->aSortOrder
[0] = 1;
478 sqlite3VdbeAddOp2(v
, OP_OpenEphemeral
, pWin
->csrApp
, 2);
479 sqlite3VdbeAppendP4(v
, pKeyInfo
, P4_KEYINFO
);
480 sqlite3VdbeAddOp2(v
, OP_Integer
, 0, pWin
->regApp
+1);
485 void sqlite3WindowCodeInit(Parse
*pParse
, Window
*pWin
){
486 Vdbe
*v
= sqlite3GetVdbe(pParse
);
487 int nPart
= (pWin
->pPartition
? pWin
->pPartition
->nExpr
: 0);
488 nPart
+= (pWin
->pOrderBy
? pWin
->pOrderBy
->nExpr
: 0);
490 pWin
->regPart
= pParse
->nMem
+1;
491 pParse
->nMem
+= nPart
;
492 sqlite3VdbeAddOp3(v
, OP_Null
, 0, pWin
->regPart
, pWin
->regPart
+nPart
-1);
494 windowAggInit(pParse
, pWin
);
497 static void windowCheckFrameValue(Parse
*pParse
, int reg
, int bEnd
){
498 static const char *azErr
[] = {
499 "frame starting offset must be a non-negative integer",
500 "frame ending offset must be a non-negative integer"
502 Vdbe
*v
= sqlite3GetVdbe(pParse
);
503 int regZero
= ++pParse
->nMem
;
505 sqlite3VdbeAddOp2(v
, OP_Integer
, 0, regZero
);
506 sqlite3VdbeAddOp2(v
, OP_MustBeInt
, reg
, sqlite3VdbeCurrentAddr(v
)+2);
507 sqlite3VdbeAddOp3(v
, OP_Ge
, regZero
, sqlite3VdbeCurrentAddr(v
)+2, reg
);
508 sqlite3VdbeAddOp2(v
, OP_Halt
, SQLITE_ERROR
, OE_Abort
);
509 sqlite3VdbeAppendP4(v
, (void*)azErr
[bEnd
], P4_STATIC
);
513 ** Generate VM code to invoke either xStep() (if bInverse is 0) or
514 ** xInverse (if bInverse is non-zero) for each window function in the
515 ** linked list starting at pMWin.
517 static void windowAggStep(
523 int regPartSize
/* Register containing size of partition */
525 Vdbe
*v
= sqlite3GetVdbe(pParse
);
527 for(pWin
=pMWin
; pWin
; pWin
=pWin
->pNextWin
){
528 int flags
= pWin
->pFunc
->funcFlags
;
530 int nArg
= pWin
->nArg
;
532 if( flags
& SQLITE_FUNC_WINDOW_SIZE
){
533 regArg
= regPartSize
;
537 for(i
=0; i
<pWin
->nArg
; i
++){
538 sqlite3VdbeAddOp3(v
, OP_Column
, csr
, pWin
->iArgCol
+i
, reg
+i
);
542 regArg
= reg
+ pWin
->iArgCol
;
547 sqlite3VdbeAddOp2(v
, OP_AddImm
, pWin
->regApp
+1, 1);
548 sqlite3VdbeAddOp2(v
, OP_SCopy
, regArg
, pWin
->regApp
);
549 sqlite3VdbeAddOp3(v
, OP_MakeRecord
, pWin
->regApp
, 2, pWin
->regApp
+2);
550 sqlite3VdbeAddOp2(v
, OP_IdxInsert
, pWin
->csrApp
, pWin
->regApp
+2);
552 sqlite3VdbeAddOp4Int(v
, OP_SeekGE
, pWin
->csrApp
, 0, regArg
, 1);
553 sqlite3VdbeAddOp1(v
, OP_Delete
, pWin
->csrApp
);
554 sqlite3VdbeJumpHere(v
, sqlite3VdbeCurrentAddr(v
)-2);
557 if( pWin
->pFunc
->funcFlags
& SQLITE_FUNC_NEEDCOLL
){
559 pColl
= sqlite3ExprCollSeq(pParse
, pWin
->pOwner
->x
.pList
->a
[0].pExpr
);
560 sqlite3VdbeAddOp4(v
, OP_CollSeq
, 0,0,0, (const char*)pColl
, P4_COLLSEQ
);
562 sqlite3VdbeAddOp3(v
, OP_AggStep0
, bInverse
, regArg
, pWin
->regAccum
);
563 sqlite3VdbeAppendP4(v
, pWin
->pFunc
, P4_FUNCDEF
);
564 sqlite3VdbeChangeP5(v
, (u8
)nArg
);
569 static void windowAggFinal(Parse
*pParse
, Window
*pMWin
, int bFinal
){
570 Vdbe
*v
= sqlite3GetVdbe(pParse
);
573 for(pWin
=pMWin
; pWin
; pWin
=pWin
->pNextWin
){
575 sqlite3VdbeAddOp2(v
, OP_Null
, 0, pWin
->regResult
);
576 sqlite3VdbeAddOp1(v
, OP_Last
, pWin
->csrApp
);
577 sqlite3VdbeAddOp3(v
, OP_Column
, pWin
->csrApp
, 0, pWin
->regResult
);
578 sqlite3VdbeJumpHere(v
, sqlite3VdbeCurrentAddr(v
)-2);
580 sqlite3VdbeAddOp1(v
, OP_ResetSorter
, pWin
->csrApp
);
584 sqlite3VdbeAddOp2(v
, OP_Null
, 0, pWin
->regResult
);
586 sqlite3VdbeAddOp2(v
, OP_AggFinal
, pWin
->regAccum
, pWin
->nArg
);
587 sqlite3VdbeAppendP4(v
, pWin
->pFunc
, P4_FUNCDEF
);
589 sqlite3VdbeAddOp2(v
, OP_Copy
, pWin
->regAccum
, pWin
->regResult
);
591 sqlite3VdbeChangeP3(v
, -1, pWin
->regResult
);
597 static void windowPartitionCache(
605 Window
*pMWin
= p
->pWin
;
606 Vdbe
*v
= sqlite3GetVdbe(pParse
);
608 int iSubCsr
= p
->pSrc
->a
[0].iCursor
;
609 int nSub
= p
->pSrc
->a
[0].pTab
->nCol
;
612 int reg
= pParse
->nMem
+1;
613 int regRecord
= reg
+nSub
;
614 int regRowid
= regRecord
+1;
616 *pRegSize
= regRowid
;
617 pParse
->nMem
+= nSub
+ 2;
619 /* Martial the row returned by the sub-select into an array of
621 for(k
=0; k
<nSub
; k
++){
622 sqlite3VdbeAddOp3(v
, OP_Column
, iSubCsr
, k
, reg
+k
);
624 sqlite3VdbeAddOp3(v
, OP_MakeRecord
, reg
, nSub
, regRecord
);
626 /* Check if this is the start of a new partition. If so, call the
627 ** flush_partition sub-routine. */
628 if( pMWin
->pPartition
){
630 ExprList
*pPart
= pMWin
->pPartition
;
631 int nPart
= (pPart
? pPart
->nExpr
: 0);
632 int regNewPart
= reg
+ pMWin
->nBufferCol
;
633 KeyInfo
*pKeyInfo
= sqlite3KeyInfoFromExprList(pParse
, pPart
, 0, 0);
635 addr
= sqlite3VdbeAddOp3(v
, OP_Compare
, regNewPart
, pMWin
->regPart
,nPart
);
636 sqlite3VdbeAppendP4(v
, (void*)pKeyInfo
, P4_KEYINFO
);
637 sqlite3VdbeAddOp3(v
, OP_Jump
, addr
+2, addr
+4, addr
+2);
638 sqlite3VdbeAddOp3(v
, OP_Copy
, regNewPart
, pMWin
->regPart
, nPart
-1);
639 sqlite3VdbeAddOp2(v
, OP_Gosub
, regFlushPart
, lblFlushPart
);
642 /* Buffer the current row in the ephemeral table. */
643 sqlite3VdbeAddOp2(v
, OP_NewRowid
, pMWin
->iEphCsr
, regRowid
);
644 sqlite3VdbeAddOp3(v
, OP_Insert
, pMWin
->iEphCsr
, regRecord
, regRowid
);
646 /* End of the input loop */
647 sqlite3WhereEnd(pWInfo
);
649 /* Invoke "flush_partition" to deal with the final (or only) partition */
650 sqlite3VdbeAddOp2(v
, OP_Gosub
, regFlushPart
, lblFlushPart
);
654 ** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
655 ** ----------------------------------------------------
657 ** Pseudo-code for the implementation of this window frame type is as
658 ** follows. sqlite3WhereBegin() has already been called to generate the
659 ** top of the main loop when this function is called.
661 ** Each time the sub-routine at addrGosub is invoked, a single output
662 ** row is generated based on the current row indicated by Window.iEphCsr.
665 ** if( new partition ){
666 ** Gosub flush_partition
668 ** Insert (record in eph-table)
670 ** Gosub flush_partition
674 ** OpenDup (iEphCsr -> csrStart)
675 ** OpenDup (iEphCsr -> csrEnd)
677 ** regStart = <expr1> // PRECEDING expression
678 ** regEnd = <expr2> // FOLLOWING expression
679 ** if( regStart<0 || regEnd<0 ){ error! }
680 ** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
681 ** Next(csrEnd) // if EOF skip Aggstep
683 ** if( (regEnd--)<=0 ){
686 ** Next(csr) // if EOF goto flush_partition_done
687 ** if( (regStart--)<=0 ){
688 ** AggStep (csrStart, xInverse)
692 ** flush_partition_done:
696 ** ROWS BETWEEN <expr> PRECEDING AND CURRENT ROW
697 ** ROWS BETWEEN CURRENT ROW AND <expr> FOLLOWING
698 ** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING
700 ** These are similar to the above. For "CURRENT ROW", intialize the
701 ** register to 0. For "UNBOUNDED PRECEDING" to infinity.
703 ** ROWS BETWEEN <expr> PRECEDING AND UNBOUNDED FOLLOWING
704 ** ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
706 ** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
708 ** Next(csrEnd) // Exit while(1) at EOF
714 ** Next(csr) // if EOF goto flush_partition_done
715 ** if( (regStart--)<=0 ){
716 ** AggStep (csrStart, xInverse)
721 ** For the "CURRENT ROW AND UNBOUNDED FOLLOWING" case, the final if()
722 ** condition is always true (as if regStart were initialized to 0).
724 ** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
726 ** This is the only RANGE case handled by this routine. It modifies the
727 ** second while( 1 ) loop in "ROWS BETWEEN CURRENT ... UNBOUNDED..." to
735 ** Next(csr) // if EOF goto flush_partition_done
736 ** if( new peer ) break;
738 ** while( (regPeer--)>0 ){
739 ** AggStep (csrStart, xInverse)
744 ** ROWS BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING
746 ** regEnd = regEnd - regStart
747 ** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
749 ** Next(csrEnd) // if EOF fall-through
750 ** if( (regEnd--)<=0 ){
751 ** if( (regStart--)<=0 ){
754 ** Next(csr) // if EOF goto flush_partition_done
756 ** AggStep (csrStart, xInverse)
760 ** ROWS BETWEEN <expr> PRECEDING AND <expr> PRECEDING
762 ** Replace the bit after "Rewind" in the above with:
764 ** if( (regEnd--)<=0 ){
770 ** Next(csr) // if EOF goto flush_partition_done
771 ** if( (regStart--)<=0 ){
772 ** AggStep (csr2, xInverse)
777 static void windowCodeRowExprStep(
784 Window
*pMWin
= p
->pWin
;
785 Vdbe
*v
= sqlite3GetVdbe(pParse
);
788 int nSub
= p
->pSrc
->a
[0].pTab
->nCol
;
789 int regFlushPart
; /* Register for "Gosub flush_partition" */
790 int lblFlushPart
; /* Label for "Gosub flush_partition" */
791 int lblFlushDone
; /* Label for "Gosub flush_partition_done" */
796 int csrStart
= pParse
->nTab
++;
797 int csrEnd
= pParse
->nTab
++;
798 int regStart
; /* Value of <expr> PRECEDING */
799 int regEnd
; /* Value of <expr> FOLLOWING */
806 int regPeer
= 0; /* Number of peers in current group */
807 int regPeerVal
= 0; /* Array of values identifying peer group */
808 int iPeer
= 0; /* Column offset in eph-table of peer vals */
809 int nPeerVal
; /* Number of peer values */
813 assert( pMWin
->eStart
==TK_PRECEDING
814 || pMWin
->eStart
==TK_CURRENT
815 || pMWin
->eStart
==TK_FOLLOWING
816 || pMWin
->eStart
==TK_UNBOUNDED
818 assert( pMWin
->eEnd
==TK_FOLLOWING
819 || pMWin
->eEnd
==TK_CURRENT
820 || pMWin
->eEnd
==TK_UNBOUNDED
821 || pMWin
->eEnd
==TK_PRECEDING
824 if( pMWin
->eType
==TK_RANGE
825 && pMWin
->eStart
==TK_CURRENT
826 && pMWin
->eEnd
==TK_UNBOUNDED
831 /* Allocate register and label for the "flush_partition" sub-routine. */
832 regFlushPart
= ++pParse
->nMem
;
833 lblFlushPart
= sqlite3VdbeMakeLabel(v
);
834 lblFlushDone
= sqlite3VdbeMakeLabel(v
);
836 regStart
= ++pParse
->nMem
;
837 regEnd
= ++pParse
->nMem
;
839 windowPartitionCache(pParse
, p
, pWInfo
, regFlushPart
, lblFlushPart
, ®Size
);
841 addrGoto
= sqlite3VdbeAddOp0(v
, OP_Goto
);
843 /* Start of "flush_partition" */
844 sqlite3VdbeResolveLabel(v
, lblFlushPart
);
845 sqlite3VdbeAddOp2(v
, OP_Once
, 0, sqlite3VdbeCurrentAddr(v
)+3);
846 sqlite3VdbeAddOp2(v
, OP_OpenDup
, csrStart
, pMWin
->iEphCsr
);
847 sqlite3VdbeAddOp2(v
, OP_OpenDup
, csrEnd
, pMWin
->iEphCsr
);
849 /* If either regStart or regEnd are not non-negative integers, throw
852 sqlite3ExprCode(pParse
, pMWin
->pStart
, regStart
);
853 windowCheckFrameValue(pParse
, regStart
, 0);
856 sqlite3ExprCode(pParse
, pMWin
->pEnd
, regEnd
);
857 windowCheckFrameValue(pParse
, regEnd
, 1);
860 /* If this is "ROWS <expr1> FOLLOWING AND ROWS <expr2> FOLLOWING", do:
862 ** regEnd = regEnd - regStart;
864 if( pMWin
->pEnd
&& pMWin
->pStart
&& pMWin
->eStart
==TK_FOLLOWING
){
865 assert( pMWin
->eEnd
==TK_FOLLOWING
);
866 sqlite3VdbeAddOp3(v
, OP_Subtract
, regStart
, regEnd
, regEnd
);
869 /* Initialize the accumulator register for each window function to NULL */
871 for(pWin
=pMWin
; pWin
; pWin
=pWin
->pNextWin
){
872 sqlite3VdbeAddOp2(v
, OP_Null
, 0, pWin
->regAccum
);
873 nArg
= MAX(nArg
, pWin
->nArg
);
875 regArg
= pParse
->nMem
+1;
876 pParse
->nMem
+= nArg
;
878 sqlite3VdbeAddOp2(v
, OP_Rewind
, pMWin
->iEphCsr
, lblFlushDone
);
879 sqlite3VdbeAddOp2(v
, OP_Rewind
, csrStart
, lblFlushDone
);
880 sqlite3VdbeChangeP5(v
, 1);
881 sqlite3VdbeAddOp2(v
, OP_Rewind
, csrEnd
, lblFlushDone
);
882 sqlite3VdbeChangeP5(v
, 1);
884 /* Invoke AggStep function for each window function using the row that
885 ** csrEnd currently points to. Or, if csrEnd is already at EOF,
887 addrTop
= sqlite3VdbeCurrentAddr(v
);
888 if( pMWin
->eEnd
==TK_PRECEDING
){
889 addrIfPos1
= sqlite3VdbeAddOp3(v
, OP_IfPos
, regEnd
, 0 , 1);
891 sqlite3VdbeAddOp2(v
, OP_Next
, csrEnd
, sqlite3VdbeCurrentAddr(v
)+2);
892 addr
= sqlite3VdbeAddOp0(v
, OP_Goto
);
893 windowAggStep(pParse
, pMWin
, csrEnd
, 0, regArg
, regSize
);
894 if( pMWin
->eEnd
==TK_UNBOUNDED
){
895 sqlite3VdbeAddOp2(v
, OP_Goto
, 0, addrTop
);
896 sqlite3VdbeJumpHere(v
, addr
);
897 addrTop
= sqlite3VdbeCurrentAddr(v
);
899 sqlite3VdbeJumpHere(v
, addr
);
900 if( pMWin
->eEnd
==TK_PRECEDING
){
901 sqlite3VdbeJumpHere(v
, addrIfPos1
);
905 if( pMWin
->eEnd
==TK_FOLLOWING
){
906 addrIfPos1
= sqlite3VdbeAddOp3(v
, OP_IfPos
, regEnd
, 0 , 1);
908 if( pMWin
->eStart
==TK_FOLLOWING
){
909 addrIfPos2
= sqlite3VdbeAddOp3(v
, OP_IfPos
, regStart
, 0 , 1);
912 assert( pMWin
->eStart
==TK_CURRENT
&& pMWin
->pOrderBy
);
913 regPeer
= ++pParse
->nMem
;
914 regPeerVal
= pParse
->nMem
+1;
915 iPeer
= pMWin
->nBufferCol
+ (pMWin
->pPartition
?pMWin
->pPartition
->nExpr
:0);
916 nPeerVal
= pMWin
->pOrderBy
->nExpr
;
917 pParse
->nMem
+= (2 * nPeerVal
);
918 for(k
=0; k
<nPeerVal
; k
++){
919 sqlite3VdbeAddOp3(v
, OP_Column
, pMWin
->iEphCsr
, iPeer
+k
, regPeerVal
+k
);
921 sqlite3VdbeAddOp2(v
, OP_Integer
, 0, regPeer
);
923 windowAggFinal(pParse
, pMWin
, 0);
925 sqlite3VdbeAddOp2(v
, OP_AddImm
, regPeer
, 1);
927 sqlite3VdbeAddOp2(v
, OP_Gosub
, regGosub
, addrGosub
);
928 sqlite3VdbeAddOp2(v
, OP_Next
, pMWin
->iEphCsr
, sqlite3VdbeCurrentAddr(v
)+2);
929 sqlite3VdbeAddOp2(v
, OP_Goto
, 0, lblFlushDone
);
931 KeyInfo
*pKeyInfo
= sqlite3KeyInfoFromExprList(pParse
, pMWin
->pOrderBy
,0,0);
932 int addrJump
= sqlite3VdbeCurrentAddr(v
)-4;
933 for(k
=0; k
<nPeerVal
; k
++){
934 int iOut
= regPeerVal
+ nPeerVal
+ k
;
935 sqlite3VdbeAddOp3(v
, OP_Column
, pMWin
->iEphCsr
, iPeer
+k
, iOut
);
937 sqlite3VdbeAddOp3(v
, OP_Compare
, regPeerVal
, regPeerVal
+nPeerVal
, nPeerVal
);
938 sqlite3VdbeAppendP4(v
, (void*)pKeyInfo
, P4_KEYINFO
);
939 addr
= sqlite3VdbeCurrentAddr(v
)+1;
940 sqlite3VdbeAddOp3(v
, OP_Jump
, addr
, addrJump
, addr
);
942 if( pMWin
->eStart
==TK_FOLLOWING
){
943 sqlite3VdbeJumpHere(v
, addrIfPos2
);
946 if( pMWin
->eStart
==TK_CURRENT
947 || pMWin
->eStart
==TK_PRECEDING
948 || pMWin
->eStart
==TK_FOLLOWING
950 int addrJumpHere
= 0;
951 if( pMWin
->eStart
==TK_PRECEDING
){
952 addrJumpHere
= sqlite3VdbeAddOp3(v
, OP_IfPos
, regStart
, 0 , 1);
955 sqlite3VdbeAddOp3(v
, OP_IfPos
, regPeer
, sqlite3VdbeCurrentAddr(v
)+2, 1);
956 addrJumpHere
= sqlite3VdbeAddOp0(v
, OP_Goto
);
958 sqlite3VdbeAddOp2(v
, OP_Next
, csrStart
, sqlite3VdbeCurrentAddr(v
)+1);
959 windowAggStep(pParse
, pMWin
, csrStart
, 1, regArg
, regSize
);
961 sqlite3VdbeAddOp2(v
, OP_Goto
, 0, addrJumpHere
-1);
964 sqlite3VdbeJumpHere(v
, addrJumpHere
);
967 if( pMWin
->eEnd
==TK_FOLLOWING
){
968 sqlite3VdbeJumpHere(v
, addrIfPos1
);
970 sqlite3VdbeAddOp2(v
, OP_Goto
, 0, addrTop
);
972 /* flush_partition_done: */
973 sqlite3VdbeResolveLabel(v
, lblFlushDone
);
974 sqlite3VdbeAddOp1(v
, OP_ResetSorter
, pMWin
->iEphCsr
);
975 sqlite3VdbeAddOp1(v
, OP_Return
, regFlushPart
);
977 /* Jump to here to skip over flush_partition */
978 sqlite3VdbeJumpHere(v
, addrGoto
);
982 ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
986 ** OpenDup (iEphCsr -> csrLead)
989 ** foreach row (csrLead){
992 ** for(i=0; i<ctr; i++){
1002 ** AggFinal (xFinalize)
1003 ** for(i=0; i<ctr; i++){
1008 ** ResetSorter (csr)
1011 ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
1012 ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
1013 ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
1017 static void windowCodeCacheStep(
1024 Window
*pMWin
= p
->pWin
;
1025 Vdbe
*v
= sqlite3GetVdbe(pParse
);
1029 ExprList
*pPart
= pMWin
->pPartition
;
1030 ExprList
*pOrderBy
= pMWin
->pOrderBy
;
1031 int nPeer
= pOrderBy
->nExpr
;
1034 int addrGoto
; /* Address of Goto used to jump flush_par.. */
1035 int addrRewind
; /* Address of Rewind that starts loop */
1040 int regArg
; /* Register array to martial function args */
1044 assert( (pMWin
->eStart
==TK_UNBOUNDED
&& pMWin
->eEnd
==TK_CURRENT
)
1047 regNewPeer
= pParse
->nMem
+1;
1048 pParse
->nMem
+= nPeer
;
1050 /* Allocate register and label for the "flush_partition" sub-routine. */
1051 regFlushPart
= ++pParse
->nMem
;
1052 lblFlushPart
= sqlite3VdbeMakeLabel(v
);
1054 csrLead
= pParse
->nTab
++;
1055 regCtr
= ++pParse
->nMem
;
1057 windowPartitionCache(pParse
, p
, pWInfo
, regFlushPart
, lblFlushPart
, ®Size
);
1058 addrGoto
= sqlite3VdbeAddOp0(v
, OP_Goto
);
1060 /* Start of "flush_partition" */
1061 sqlite3VdbeResolveLabel(v
, lblFlushPart
);
1062 sqlite3VdbeAddOp2(v
, OP_Once
, 0, sqlite3VdbeCurrentAddr(v
)+2);
1063 sqlite3VdbeAddOp2(v
, OP_OpenDup
, csrLead
, pMWin
->iEphCsr
);
1065 /* Initialize the accumulator register for each window function to NULL */
1067 for(pWin
=pMWin
; pWin
; pWin
=pWin
->pNextWin
){
1068 sqlite3VdbeAddOp2(v
, OP_Null
, 0, pWin
->regAccum
);
1069 nArg
= MAX(nArg
, pWin
->nArg
);
1071 regArg
= pParse
->nMem
+1;
1072 pParse
->nMem
+= nArg
;
1074 sqlite3VdbeAddOp2(v
, OP_Integer
, 0, regCtr
);
1075 addrRewind
= sqlite3VdbeAddOp1(v
, OP_Rewind
, csrLead
);
1076 sqlite3VdbeAddOp1(v
, OP_Rewind
, pMWin
->iEphCsr
);
1079 int addrJump
; /* Address of OP_Jump below */
1080 int iOff
= pMWin
->nBufferCol
+ (pPart
? pPart
->nExpr
: 0);
1081 int regPeer
= pMWin
->regPart
+ (pPart
? pPart
->nExpr
: 0);
1082 KeyInfo
*pKeyInfo
= sqlite3KeyInfoFromExprList(pParse
, pOrderBy
, 0, 0);
1084 for(k
=0; k
<nPeer
; k
++){
1085 sqlite3VdbeAddOp3(v
, OP_Column
, csrLead
, iOff
+k
, regNewPeer
+k
);
1088 addr
= sqlite3VdbeAddOp3(v
, OP_Compare
, regNewPeer
, regPeer
, nPeer
);
1089 sqlite3VdbeAppendP4(v
, (void*)pKeyInfo
, P4_KEYINFO
);
1090 addrJump
= sqlite3VdbeAddOp3(v
, OP_Jump
, addr
+2, 0, addr
+2);
1091 sqlite3VdbeAddOp3(v
, OP_Copy
, regNewPeer
, regPeer
, nPeer
-1);
1092 windowAggFinal(pParse
, pMWin
, 0);
1093 sqlite3VdbeAddOp3(v
, OP_IfPos
, regCtr
, sqlite3VdbeCurrentAddr(v
)+2 , 1);
1094 sqlite3VdbeAddOp2(v
, OP_Goto
, 0, sqlite3VdbeCurrentAddr(v
)+3);
1095 sqlite3VdbeAddOp2(v
, OP_Gosub
, regGosub
, addrGosub
);
1096 sqlite3VdbeAddOp2(v
, OP_Next
, pMWin
->iEphCsr
, sqlite3VdbeCurrentAddr(v
)-3);
1097 sqlite3VdbeJumpHere(v
, addrJump
);
1100 windowAggStep(pParse
, pMWin
, csrLead
, 0, regArg
, regSize
);
1101 sqlite3VdbeAddOp2(v
, OP_AddImm
, regCtr
, 1);
1103 sqlite3VdbeAddOp2(v
, OP_Next
, csrLead
, addrRewind
+2);
1105 windowAggFinal(pParse
, pMWin
, 1);
1107 sqlite3VdbeAddOp3(v
, OP_IfPos
, regCtr
, sqlite3VdbeCurrentAddr(v
)+2 , 1);
1108 sqlite3VdbeAddOp2(v
, OP_Goto
, 0, sqlite3VdbeCurrentAddr(v
)+3);
1109 sqlite3VdbeAddOp2(v
, OP_Gosub
, regGosub
, addrGosub
);
1110 sqlite3VdbeAddOp2(v
, OP_Next
, pMWin
->iEphCsr
, sqlite3VdbeCurrentAddr(v
)-3);
1112 sqlite3VdbeJumpHere(v
, addrRewind
);
1113 sqlite3VdbeJumpHere(v
, addrRewind
+1);
1114 sqlite3VdbeAddOp1(v
, OP_ResetSorter
, pMWin
->iEphCsr
);
1115 sqlite3VdbeAddOp1(v
, OP_Return
, regFlushPart
);
1117 /* Jump to here to skip over flush_partition */
1118 sqlite3VdbeJumpHere(v
, addrGoto
);
1123 ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
1126 ** if( new partition ){
1127 ** AggFinal (xFinalize)
1129 ** ResetSorter eph-table
1131 ** else if( new peer ){
1132 ** AggFinal (xValue)
1134 ** ResetSorter eph-table
1137 ** Insert (record into eph-table)
1138 ** sqlite3WhereEnd()
1139 ** AggFinal (xFinalize)
1142 ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
1144 ** As above, except take no action for a "new peer". Invoke
1145 ** the sub-routine once only for each partition.
1147 ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
1149 ** As above, except that the "new peer" condition is handled in the
1150 ** same way as "new partition" (so there is no "else if" block).
1152 ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
1154 ** As above, except assume every row is a "new peer".
1156 static void windowCodeDefaultStep(
1163 Window
*pMWin
= p
->pWin
;
1164 Vdbe
*v
= sqlite3GetVdbe(pParse
);
1167 int iSubCsr
= p
->pSrc
->a
[0].iCursor
;
1168 int nSub
= p
->pSrc
->a
[0].pTab
->nCol
;
1169 int reg
= pParse
->nMem
+1;
1170 int regRecord
= reg
+nSub
;
1171 int regRowid
= regRecord
+1;
1173 ExprList
*pPart
= pMWin
->pPartition
;
1174 ExprList
*pOrderBy
= pMWin
->pOrderBy
;
1176 assert( pMWin
->eType
==TK_RANGE
1177 || (pMWin
->eStart
==TK_UNBOUNDED
&& pMWin
->eEnd
==TK_CURRENT
)
1180 assert( (pMWin
->eStart
==TK_UNBOUNDED
&& pMWin
->eEnd
==TK_CURRENT
)
1181 || (pMWin
->eStart
==TK_UNBOUNDED
&& pMWin
->eEnd
==TK_UNBOUNDED
)
1182 || (pMWin
->eStart
==TK_CURRENT
&& pMWin
->eEnd
==TK_CURRENT
)
1183 || (pMWin
->eStart
==TK_CURRENT
&& pMWin
->eEnd
==TK_UNBOUNDED
&& !pOrderBy
)
1186 if( pMWin
->eEnd
==TK_UNBOUNDED
){
1190 pParse
->nMem
+= nSub
+ 2;
1192 /* Martial the row returned by the sub-select into an array of
1194 for(k
=0; k
<nSub
; k
++){
1195 sqlite3VdbeAddOp3(v
, OP_Column
, iSubCsr
, k
, reg
+k
);
1198 /* Check if this is the start of a new partition or peer group. */
1199 if( pPart
|| pOrderBy
){
1200 int nPart
= (pPart
? pPart
->nExpr
: 0);
1203 int nPeer
= (pOrderBy
? pOrderBy
->nExpr
: 0);
1206 int regNewPart
= reg
+ pMWin
->nBufferCol
;
1207 KeyInfo
*pKeyInfo
= sqlite3KeyInfoFromExprList(pParse
, pPart
, 0, 0);
1208 addr
= sqlite3VdbeAddOp3(v
, OP_Compare
, regNewPart
, pMWin
->regPart
,nPart
);
1209 sqlite3VdbeAppendP4(v
, (void*)pKeyInfo
, P4_KEYINFO
);
1210 addrJump
= sqlite3VdbeAddOp3(v
, OP_Jump
, addr
+2, 0, addr
+2);
1211 windowAggFinal(pParse
, pMWin
, 1);
1213 addrGoto
= sqlite3VdbeAddOp0(v
, OP_Goto
);
1218 int regNewPeer
= reg
+ pMWin
->nBufferCol
+ nPart
;
1219 int regPeer
= pMWin
->regPart
+ nPart
;
1221 if( addrJump
) sqlite3VdbeJumpHere(v
, addrJump
);
1222 if( pMWin
->eType
==TK_RANGE
){
1223 KeyInfo
*pKeyInfo
= sqlite3KeyInfoFromExprList(pParse
, pOrderBy
, 0, 0);
1224 addr
= sqlite3VdbeAddOp3(v
, OP_Compare
, regNewPeer
, regPeer
, nPeer
);
1225 sqlite3VdbeAppendP4(v
, (void*)pKeyInfo
, P4_KEYINFO
);
1226 addrJump
= sqlite3VdbeAddOp3(v
, OP_Jump
, addr
+2, 0, addr
+2);
1230 windowAggFinal(pParse
, pMWin
, pMWin
->eStart
==TK_CURRENT
);
1231 if( addrGoto
) sqlite3VdbeJumpHere(v
, addrGoto
);
1234 sqlite3VdbeAddOp2(v
, OP_Gosub
, regGosub
, addrGosub
);
1235 sqlite3VdbeAddOp1(v
, OP_ResetSorter
, pMWin
->iEphCsr
);
1237 v
, OP_Copy
, reg
+pMWin
->nBufferCol
, pMWin
->regPart
, nPart
+nPeer
-1
1240 if( addrJump
) sqlite3VdbeJumpHere(v
, addrJump
);
1243 /* Invoke step function for window functions */
1244 windowAggStep(pParse
, pMWin
, -1, 0, reg
, 0);
1246 /* Buffer the current row in the ephemeral table. */
1247 if( pMWin
->nBufferCol
>0 ){
1248 sqlite3VdbeAddOp3(v
, OP_MakeRecord
, reg
, pMWin
->nBufferCol
, regRecord
);
1250 sqlite3VdbeAddOp2(v
, OP_Blob
, 0, regRecord
);
1251 sqlite3VdbeAppendP4(v
, (void*)"", 0);
1253 sqlite3VdbeAddOp2(v
, OP_NewRowid
, pMWin
->iEphCsr
, regRowid
);
1254 sqlite3VdbeAddOp3(v
, OP_Insert
, pMWin
->iEphCsr
, regRecord
, regRowid
);
1256 /* End the database scan loop. */
1257 sqlite3WhereEnd(pWInfo
);
1259 windowAggFinal(pParse
, pMWin
, 1);
1260 sqlite3VdbeAddOp2(v
, OP_Gosub
, regGosub
, addrGosub
);
1265 ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
1267 ** As above, except take no action for a "new peer". Invoke
1268 ** the sub-routine once only for each partition.
1270 ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
1272 ** As above, except that the "new peer" condition is handled in the
1273 ** same way as "new partition" (so there is no "else if" block).
1275 ** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
1277 ** One way is to just reverse the sort order and do as for BETWEEN
1278 ** UNBOUNDED PRECEDING AND CURRENT ROW. But that is not quite the same for
1279 ** things like group_concat(). And perhaps other user defined aggregates
1283 ** if( new partition ){
1284 ** Gosub flush_partition;
1285 ** ResetSorter eph-table
1288 ** Insert (record into eph-table)
1289 ** sqlite3WhereEnd()
1290 ** Gosub flush_partition
1293 ** OpenDup (csr -> csr2)
1294 ** foreach (record in eph-table) {
1296 ** while( csr2!=csr ){
1297 ** AggStep (xInverse)
1301 ** AggFinal (xValue)
1305 **========================================================================
1307 ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
1309 ** if( new partition ){
1310 ** AggFinal (xFinalize)
1313 ** AggFinal (xValue)
1315 ** sqlite3WhereEnd()
1318 void sqlite3WindowCodeStep(
1326 Window
*pMWin
= p
->pWin
;
1330 if( (pMWin
->eType
==TK_ROWS
1331 && (pMWin
->eStart
!=TK_UNBOUNDED
||pMWin
->eEnd
!=TK_CURRENT
||!pMWin
->pOrderBy
))
1332 || (pMWin
->eStart
==TK_CURRENT
&&pMWin
->eEnd
==TK_UNBOUNDED
&&pMWin
->pOrderBy
)
1334 windowCodeRowExprStep(pParse
, p
, pWInfo
, regGosub
, addrGosub
);
1338 for(pWin
=pMWin
; pWin
; pWin
=pWin
->pNextWin
){
1339 if( pWin
->pFunc
->funcFlags
& SQLITE_FUNC_WINDOW_SIZE
){
1340 windowCodeCacheStep(pParse
, p
, pWInfo
, regGosub
, addrGosub
);
1346 windowCodeDefaultStep(pParse
, p
, pWInfo
, regGosub
, addrGosub
);