blob: ecbbb9c35ffe59159858982fccc63afc80e22900 [file] [log] [blame]
dan86fb6e12018-05-16 20:58:07 +00001/*
2**
3** The author disclaims copyright to this source code. In place of
4** a legal notice, here is a blessing:
5**
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.
9**
10*************************************************************************
11*/
12#include "sqliteInt.h"
13
14void sqlite3WindowDelete(sqlite3 *db, Window *p){
15 if( p ){
16 sqlite3ExprDelete(db, p->pFilter);
17 sqlite3ExprListDelete(db, p->pPartition);
18 sqlite3ExprListDelete(db, p->pOrderBy);
19 sqlite3ExprDelete(db, p->pEnd);
20 sqlite3ExprDelete(db, p->pStart);
21 sqlite3DbFree(db, p);
22 }
23}
24
25Window *sqlite3WindowAlloc(
26 Parse *pParse,
27 int eType,
danc3a20c12018-05-23 20:55:37 +000028 int eStart, Expr *pStart,
29 int eEnd, Expr *pEnd
dan86fb6e12018-05-16 20:58:07 +000030){
31 Window *pWin = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
32
33 if( pWin ){
34 pWin->eType = eType;
35 pWin->eStart = eStart;
36 pWin->eEnd = eEnd;
37 pWin->pEnd = pEnd;
38 pWin->pStart = pStart;
39 }else{
40 sqlite3ExprDelete(pParse->db, pEnd);
41 sqlite3ExprDelete(pParse->db, pStart);
42 }
43
44 return pWin;
45}
46
47void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
48 if( p ){
49 p->pWin = pWin;
50 }else{
51 sqlite3WindowDelete(pParse->db, pWin);
52 }
53}
dane2f781b2018-05-17 19:24:08 +000054
55/*
56** Return 0 if the two window objects are identical, or non-zero otherwise.
57*/
58int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){
59 if( p1->eType!=p2->eType ) return 1;
60 if( p1->eStart!=p2->eStart ) return 1;
61 if( p1->eEnd!=p2->eEnd ) return 1;
62 if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1;
63 if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1;
64 if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1;
65 if( sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1) ) return 1;
66 return 0;
67}
68
danf9eae182018-05-21 19:45:11 +000069void sqlite3WindowCodeInit(Parse *pParse, Window *pWin){
70 Vdbe *v = sqlite3GetVdbe(pParse);
71 int nPart = (pWin->pPartition ? pWin->pPartition->nExpr : 0);
72 nPart += (pWin->pOrderBy ? pWin->pOrderBy->nExpr : 0);
73 if( nPart ){
74 pWin->regPart = pParse->nMem+1;
75 pParse->nMem += nPart;
76 sqlite3VdbeAddOp3(v, OP_Null, 0, pWin->regPart, pWin->regPart+nPart-1);
77 }
78}
79
danc3a20c12018-05-23 20:55:37 +000080static void windowCheckFrameValue(Parse *pParse, int reg, int bEnd){
81 static const char *azErr[] = {
82 "frame starting offset must be a non-negative integer",
83 "frame ending offset must be a non-negative integer"
84 };
85 Vdbe *v = sqlite3GetVdbe(pParse);
86 int regZero = ++pParse->nMem;
87
88
89 sqlite3VdbeAddOp2(v, OP_Integer, 0, regZero);
90 sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2);
91 sqlite3VdbeAddOp3(v, OP_Ge, regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
92 sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
93 sqlite3VdbeAppendP4(v, (void*)azErr[bEnd], P4_STATIC);
94}
95
dan31f56392018-05-24 21:10:57 +000096static void windowAggStep(
97 Parse *pParse,
98 Window *pMWin,
99 int csr,
100 int bInverse,
101 int reg
102){
103 Vdbe *v = sqlite3GetVdbe(pParse);
104 Window *pWin;
105 for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
106 int i;
107 for(i=0; i<pWin->nArg; i++){
108 sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i);
109 }
110 sqlite3VdbeAddOp3(v, OP_AggStep0, bInverse, reg, pWin->regAccum);
111 sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
112 sqlite3VdbeChangeP5(v, (u8)pWin->nArg);
113 }
114}
115
dan99652dd2018-05-24 17:49:14 +0000116/*
dan09590aa2018-05-25 20:30:17 +0000117** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
118** ----------------------------------------------------
dan99652dd2018-05-24 17:49:14 +0000119**
dan09590aa2018-05-25 20:30:17 +0000120** Pseudo-code for the implementation of this window frame type is as
121** follows. sqlite3WhereBegin() has already been called to generate the
122** top of the main loop when this function is called.
123**
124** Each time the sub-routine at addrGosub is invoked, a single output
125** row is generated based on the current row indicated by Window.iEphCsr.
126**
127** ...
128** if( new partition ){
129** Gosub flush_partition
130** }
131** Insert (record in eph-table)
132** sqlite3WhereEnd()
133** Gosub flush_partition
134**
135** flush_partition:
136** Once {
137** OpenDup (iEphCsr -> csrStart)
138** OpenDup (iEphCsr -> csrEnd)
dan99652dd2018-05-24 17:49:14 +0000139** }
dan09590aa2018-05-25 20:30:17 +0000140** regStart = <expr1> // PRECEDING expression
141** regEnd = <expr2> // FOLLOWING expression
142** if( regStart<0 || regEnd<0 ){ error! }
143** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
144** Next(csrEnd) // if EOF skip Aggstep
145** Aggstep (csrEnd)
146** if( (regEnd--)<=0 ){
147** AggFinal (xValue)
148** Gosub addrGosub
149** Next(csr) // if EOF goto flush_partition_done
150** if( (regStart--)<=0 ){
151** AggStep (csrStart, xInverse)
152** Next(csrStart)
153** }
154** }
155** flush_partition_done:
156** ResetSorter (csr)
157** Return
dan99652dd2018-05-24 17:49:14 +0000158**
dan09590aa2018-05-25 20:30:17 +0000159** ROWS BETWEEN <expr> PRECEDING AND CURRENT ROW
160** ROWS BETWEEN CURRENT ROW AND <expr> FOLLOWING
161** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING
162**
163** These are similar to the above. For "CURRENT ROW", intialize the
164** register to 0. For "UNBOUNDED PRECEDING" to infinity.
165**
166** ROWS BETWEEN <expr> PRECEDING AND UNBOUNDED FOLLOWING
167** ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
168**
169** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
170** while( 1 ){
171** Next(csrEnd) // Exit while(1) at EOF
172** Aggstep (csrEnd)
173** }
174** while( 1 ){
dan99652dd2018-05-24 17:49:14 +0000175** AggFinal (xValue)
176** Gosub addrGosub
dan09590aa2018-05-25 20:30:17 +0000177** Next(csr) // if EOF goto flush_partition_done
dan31f56392018-05-24 21:10:57 +0000178** if( (regStart--)<=0 ){
179** AggStep (csrStart, xInverse)
180** Next(csrStart)
dan99652dd2018-05-24 17:49:14 +0000181** }
182** }
dan99652dd2018-05-24 17:49:14 +0000183**
dan09590aa2018-05-25 20:30:17 +0000184** For the "CURRENT ROW AND UNBOUNDED FOLLOWING" case, the final if()
185** condition is always true (as if regStart were initialized to 0).
dan99652dd2018-05-24 17:49:14 +0000186**
dan09590aa2018-05-25 20:30:17 +0000187** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
188**
189** This is the only RANGE case handled by this routine. It modifies the
190** second while( 1 ) loop in "ROWS BETWEEN CURRENT ... UNBOUNDED..." to
191** be:
192**
193** while( 1 ){
194** AggFinal (xValue)
195** while( 1 ){
196** regPeer++
197** Gosub addrGosub
198** Next(csr) // if EOF goto flush_partition_done
199** if( new peer ) break;
200** }
201** while( (regPeer--)>0 ){
202** AggStep (csrStart, xInverse)
203** Next(csrStart)
204** }
205** }
dan99652dd2018-05-24 17:49:14 +0000206**
dan31f56392018-05-24 21:10:57 +0000207** ROWS BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING
208**
209** regEnd = regEnd - regStart
210** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
211** Aggstep (csrEnd)
212** Next(csrEnd) // if EOF fall-through
213** if( (regEnd--)<=0 ){
dan31f56392018-05-24 21:10:57 +0000214** if( (regStart--)<=0 ){
215** AggFinal (xValue)
216** Gosub addrGosub
217** Next(csr) // if EOF goto flush_partition_done
218** }
dane105dd72018-05-25 09:29:11 +0000219** AggStep (csrStart, xInverse)
220** Next (csrStart)
dan31f56392018-05-24 21:10:57 +0000221** }
222**
223** ROWS BETWEEN <expr> PRECEDING AND <expr> PRECEDING
224**
225** Replace the bit after "Rewind" in the above with:
226**
227** if( (regEnd--)<=0 ){
228** AggStep (csrEnd)
229** Next (csrEnd)
230** }
231** AggFinal (xValue)
232** Gosub addrGosub
233** Next(csr) // if EOF goto flush_partition_done
234** if( (regStart--)<=0 ){
235** AggStep (csr2, xInverse)
236** Next (csr2)
237** }
238**
dan99652dd2018-05-24 17:49:14 +0000239*/
danc3a20c12018-05-23 20:55:37 +0000240static void windowCodeRowExprStep(
241 Parse *pParse,
242 Select *p,
243 WhereInfo *pWInfo,
244 int regGosub,
245 int addrGosub
246){
247 Window *pMWin = p->pWin;
248 Vdbe *v = sqlite3GetVdbe(pParse);
249 Window *pWin;
250 int k;
251 int iSubCsr = p->pSrc->a[0].iCursor;
252 int nSub = p->pSrc->a[0].pTab->nCol;
253 int regFlushPart; /* Register for "Gosub flush_partition" */
dan31f56392018-05-24 21:10:57 +0000254 int lblFlushPart; /* Label for "Gosub flush_partition" */
255 int lblFlushDone; /* Label for "Gosub flush_partition_done" */
danc3a20c12018-05-23 20:55:37 +0000256
257 int reg = pParse->nMem+1;
258 int regRecord = reg+nSub;
259 int regRowid = regRecord+1;
260 int addr;
dan31f56392018-05-24 21:10:57 +0000261 int csrStart = pParse->nTab++;
262 int csrEnd = pParse->nTab++;
263 int regStart; /* Value of <expr> PRECEDING */
264 int regEnd; /* Value of <expr> FOLLOWING */
danc3a20c12018-05-23 20:55:37 +0000265 int addrNext;
266 int addrGoto;
dan31f56392018-05-24 21:10:57 +0000267 int addrTop;
danc3a20c12018-05-23 20:55:37 +0000268 int addrIfPos1;
269 int addrIfPos2;
270
dan09590aa2018-05-25 20:30:17 +0000271 int regPeer = 0; /* Number of peers in current group */
272 int regPeerVal = 0; /* Array of values identifying peer group */
273 int iPeer = 0; /* Column offset in eph-table of peer vals */
274 int nPeerVal; /* Number of peer values */
275
dan99652dd2018-05-24 17:49:14 +0000276 assert( pMWin->eStart==TK_PRECEDING
277 || pMWin->eStart==TK_CURRENT
dane105dd72018-05-25 09:29:11 +0000278 || pMWin->eStart==TK_FOLLOWING
dan99652dd2018-05-24 17:49:14 +0000279 || pMWin->eStart==TK_UNBOUNDED
280 );
281 assert( pMWin->eEnd==TK_FOLLOWING
282 || pMWin->eEnd==TK_CURRENT
283 || pMWin->eEnd==TK_UNBOUNDED
dan31f56392018-05-24 21:10:57 +0000284 || pMWin->eEnd==TK_PRECEDING
dan99652dd2018-05-24 17:49:14 +0000285 );
286
danc3a20c12018-05-23 20:55:37 +0000287 pParse->nMem += nSub + 2;
288
289 /* Allocate register and label for the "flush_partition" sub-routine. */
290 regFlushPart = ++pParse->nMem;
dan31f56392018-05-24 21:10:57 +0000291 lblFlushPart = sqlite3VdbeMakeLabel(v);
292 lblFlushDone = sqlite3VdbeMakeLabel(v);
danc3a20c12018-05-23 20:55:37 +0000293
dan31f56392018-05-24 21:10:57 +0000294 regStart = ++pParse->nMem;
295 regEnd = ++pParse->nMem;
danc3a20c12018-05-23 20:55:37 +0000296
297 /* Martial the row returned by the sub-select into an array of
298 ** registers. */
299 for(k=0; k<nSub; k++){
300 sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k);
301 }
302 sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, nSub, regRecord);
303
304 /* Check if this is the start of a new partition. If so, call the
305 ** flush_partition sub-routine. */
306 if( pMWin->pPartition ){
307 ExprList *pPart = pMWin->pPartition;
308 int nPart = (pPart ? pPart->nExpr : 0);
309 int addrJump = 0;
310 int regNewPart = reg + pMWin->nBufferCol;
311 KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0);
312
313 addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart);
314 sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
315 addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2);
dan31f56392018-05-24 21:10:57 +0000316 sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart);
danc3a20c12018-05-23 20:55:37 +0000317 sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart);
318 }
319
320 /* Buffer the current row in the ephemeral table. */
321 sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid);
322 sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid);
323
324 /* End of the input loop */
325 sqlite3WhereEnd(pWInfo);
326
327 /* Invoke "flush_partition" to deal with the final (or only) partition */
dan31f56392018-05-24 21:10:57 +0000328 sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart);
danc3a20c12018-05-23 20:55:37 +0000329 addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
330
331 /* flush_partition: */
dan31f56392018-05-24 21:10:57 +0000332 sqlite3VdbeResolveLabel(v, lblFlushPart);
danc3a20c12018-05-23 20:55:37 +0000333 sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+3);
dan31f56392018-05-24 21:10:57 +0000334 sqlite3VdbeAddOp2(v, OP_OpenDup, csrStart, pMWin->iEphCsr);
335 sqlite3VdbeAddOp2(v, OP_OpenDup, csrEnd, pMWin->iEphCsr);
danc3a20c12018-05-23 20:55:37 +0000336
dan31f56392018-05-24 21:10:57 +0000337 /* If either regStart or regEnd are not non-negative integers, throw
dan99652dd2018-05-24 17:49:14 +0000338 ** an exception. */
339 if( pMWin->pStart ){
dan31f56392018-05-24 21:10:57 +0000340 sqlite3ExprCode(pParse, pMWin->pStart, regStart);
341 windowCheckFrameValue(pParse, regStart, 0);
dan99652dd2018-05-24 17:49:14 +0000342 }
343 if( pMWin->pEnd ){
dan31f56392018-05-24 21:10:57 +0000344 sqlite3ExprCode(pParse, pMWin->pEnd, regEnd);
345 windowCheckFrameValue(pParse, regEnd, 1);
dane105dd72018-05-25 09:29:11 +0000346 if( pMWin->pStart && pMWin->eStart==TK_FOLLOWING ){
347 assert( pMWin->eEnd==TK_FOLLOWING );
348 sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd);
349 }
dan99652dd2018-05-24 17:49:14 +0000350 }
danc3a20c12018-05-23 20:55:37 +0000351
dan31f56392018-05-24 21:10:57 +0000352 for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
353 sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
354 sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
355 }
danc3a20c12018-05-23 20:55:37 +0000356
dan31f56392018-05-24 21:10:57 +0000357 sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblFlushDone);
358 sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, lblFlushDone);
danc3a20c12018-05-23 20:55:37 +0000359 sqlite3VdbeChangeP5(v, 1);
dan31f56392018-05-24 21:10:57 +0000360 sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, lblFlushDone);
danc3a20c12018-05-23 20:55:37 +0000361 sqlite3VdbeChangeP5(v, 1);
362
363 /* Invoke AggStep function for each window function using the row that
dan31f56392018-05-24 21:10:57 +0000364 ** csrEnd currently points to. Or, if csrEnd is already at EOF,
danc3a20c12018-05-23 20:55:37 +0000365 ** do nothing. */
dan31f56392018-05-24 21:10:57 +0000366 addrTop = sqlite3VdbeCurrentAddr(v);
367 if( pMWin->eEnd==TK_PRECEDING ){
368 addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1);
danc3a20c12018-05-23 20:55:37 +0000369 }
dan31f56392018-05-24 21:10:57 +0000370 sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+2);
371 addr = sqlite3VdbeAddOp0(v, OP_Goto);
372 windowAggStep(pParse, pMWin, csrEnd, 0, reg);
dan99652dd2018-05-24 17:49:14 +0000373 if( pMWin->eEnd==TK_UNBOUNDED ){
dan31f56392018-05-24 21:10:57 +0000374 sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
375 sqlite3VdbeJumpHere(v, addr);
376 addrTop = sqlite3VdbeCurrentAddr(v);
dan99652dd2018-05-24 17:49:14 +0000377 }else{
dan31f56392018-05-24 21:10:57 +0000378 sqlite3VdbeJumpHere(v, addr);
379 if( pMWin->eEnd==TK_PRECEDING ){
380 sqlite3VdbeJumpHere(v, addrIfPos1);
381 }
dan99652dd2018-05-24 17:49:14 +0000382 }
danc3a20c12018-05-23 20:55:37 +0000383
dan99652dd2018-05-24 17:49:14 +0000384 if( pMWin->eEnd==TK_FOLLOWING ){
dan31f56392018-05-24 21:10:57 +0000385 addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1);
dan99652dd2018-05-24 17:49:14 +0000386 }
dane105dd72018-05-25 09:29:11 +0000387 if( pMWin->eStart==TK_FOLLOWING ){
388 addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1);
389 }
dan09590aa2018-05-25 20:30:17 +0000390 if( pMWin->eType==TK_RANGE ){
391 assert( pMWin->eStart==TK_CURRENT && pMWin->pOrderBy );
392 regPeer = ++pParse->nMem;
393 regPeerVal = pParse->nMem+1;
394 iPeer = pMWin->nBufferCol + (pMWin->pPartition?pMWin->pPartition->nExpr:0);
395 nPeerVal = pMWin->pOrderBy->nExpr;
396 pParse->nMem += (2 * nPeerVal);
397 for(k=0; k<nPeerVal; k++){
398 sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, iPeer+k, regPeerVal+k);
399 }
400 sqlite3VdbeAddOp2(v, OP_Integer, 0, regPeer);
401 }
danc3a20c12018-05-23 20:55:37 +0000402 for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
dane105dd72018-05-25 09:29:11 +0000403 sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
danc3a20c12018-05-23 20:55:37 +0000404 sqlite3VdbeAddOp3(v,
405 OP_AggFinal, pWin->regAccum, pWin->nArg, pWin->regResult
406 );
407 sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
408 }
dan09590aa2018-05-25 20:30:17 +0000409 if( pMWin->eType==TK_RANGE ){
410 sqlite3VdbeAddOp2(v, OP_AddImm, regPeer, 1);
411 }
danc3a20c12018-05-23 20:55:37 +0000412 sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
413 sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)+2);
dan31f56392018-05-24 21:10:57 +0000414 sqlite3VdbeAddOp2(v, OP_Goto, 0, lblFlushDone);
dan09590aa2018-05-25 20:30:17 +0000415 if( pMWin->eType==TK_RANGE ){
416 KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pMWin->pOrderBy,0,0);
417 int addrJump = sqlite3VdbeCurrentAddr(v)-4;
418 for(k=0; k<nPeerVal; k++){
419 int iOut = regPeerVal + nPeerVal + k;
420 sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, iPeer+k, iOut);
421 }
422 sqlite3VdbeAddOp3(v, OP_Compare, regPeerVal, regPeerVal+nPeerVal, nPeerVal);
423 sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
424 addr = sqlite3VdbeCurrentAddr(v)+1;
425 sqlite3VdbeAddOp3(v, OP_Jump, addr, addrJump, addr);
426 }
dane105dd72018-05-25 09:29:11 +0000427 if( pMWin->eStart==TK_FOLLOWING ){
428 sqlite3VdbeJumpHere(v, addrIfPos2);
429 }
danc3a20c12018-05-23 20:55:37 +0000430
dane105dd72018-05-25 09:29:11 +0000431 if( pMWin->eStart==TK_CURRENT
432 || pMWin->eStart==TK_PRECEDING
433 || pMWin->eStart==TK_FOLLOWING
434 ){
dan09590aa2018-05-25 20:30:17 +0000435 int addrJumpHere = 0;
dan99652dd2018-05-24 17:49:14 +0000436 if( pMWin->eStart==TK_PRECEDING ){
dan09590aa2018-05-25 20:30:17 +0000437 addrJumpHere = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1);
438 }
439 if( pMWin->eType==TK_RANGE ){
440 sqlite3VdbeAddOp3(v, OP_IfPos, regPeer, sqlite3VdbeCurrentAddr(v)+2, 1);
441 addrJumpHere = sqlite3VdbeAddOp0(v, OP_Goto);
danc3a20c12018-05-23 20:55:37 +0000442 }
dan31f56392018-05-24 21:10:57 +0000443 sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1);
444 windowAggStep(pParse, pMWin, csrStart, 1, reg);
dan09590aa2018-05-25 20:30:17 +0000445 if( pMWin->eType==TK_RANGE ){
446 sqlite3VdbeAddOp2(v, OP_Goto, 0, addrJumpHere-1);
447 }
448 if( addrJumpHere ){
449 sqlite3VdbeJumpHere(v, addrJumpHere);
dan99652dd2018-05-24 17:49:14 +0000450 }
danc3a20c12018-05-23 20:55:37 +0000451 }
dan99652dd2018-05-24 17:49:14 +0000452 if( pMWin->eEnd==TK_FOLLOWING ){
453 sqlite3VdbeJumpHere(v, addrIfPos1);
454 }
dan31f56392018-05-24 21:10:57 +0000455 sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
danc3a20c12018-05-23 20:55:37 +0000456
457 /* flush_partition_done: */
dan31f56392018-05-24 21:10:57 +0000458 sqlite3VdbeResolveLabel(v, lblFlushDone);
danc3a20c12018-05-23 20:55:37 +0000459 sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr);
460 sqlite3VdbeAddOp1(v, OP_Return, regFlushPart);
461
462 /* Jump to here to skip over flush_partition */
463 sqlite3VdbeJumpHere(v, addrGoto);
464}
465
466static void windowCodeDefaultStep(
467 Parse *pParse,
468 Select *p,
469 WhereInfo *pWInfo,
470 int regGosub,
471 int addrGosub
472){
473 Window *pMWin = p->pWin;
474 Vdbe *v = sqlite3GetVdbe(pParse);
475 Window *pWin;
476 int k;
477 int iSubCsr = p->pSrc->a[0].iCursor;
478 int nSub = p->pSrc->a[0].pTab->nCol;
479 int reg = pParse->nMem+1;
480 int regRecord = reg+nSub;
481 int regRowid = regRecord+1;
482 int addr;
483
484 pParse->nMem += nSub + 2;
485
486 /* Martial the row returned by the sub-select into an array of
487 ** registers. */
488 for(k=0; k<nSub; k++){
489 sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k);
490 }
491
492 /* Check if this is the start of a new partition or peer group. */
493 if( pMWin->regPart ){
494 ExprList *pPart = pMWin->pPartition;
495 int nPart = (pPart ? pPart->nExpr : 0);
496 ExprList *pOrderBy = pMWin->pOrderBy;
497 int nPeer = (pOrderBy ? pOrderBy->nExpr : 0);
498 int addrGoto = 0;
499 int addrJump = 0;
500
501 if( pPart ){
502 int regNewPart = reg + pMWin->nBufferCol;
503 KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0);
504 addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart);
505 sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
506 addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2);
507 for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
508 sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, pWin->nArg);
509 sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
510 sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult);
511 }
512 if( pOrderBy ){
513 addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
514 }
515 }
516
517 if( pOrderBy ){
518 int regNewPeer = reg + pMWin->nBufferCol + nPart;
519 int regPeer = pMWin->regPart + nPart;
520
521 KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0);
522 if( addrJump ) sqlite3VdbeJumpHere(v, addrJump);
523 addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer);
524 sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
525 addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2);
526 for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
527 sqlite3VdbeAddOp3(v,
528 OP_AggFinal, pWin->regAccum, pWin->nArg, pWin->regResult
529 );
530 sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
531 }
532 if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto);
533 }
534
535 sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
536 sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr);
537 sqlite3VdbeAddOp3(
538 v, OP_Copy, reg+pMWin->nBufferCol, pMWin->regPart, nPart+nPeer-1
539 );
540
541 sqlite3VdbeJumpHere(v, addrJump);
542 }
543
544 /* Invoke step function for window functions */
545 for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
546 sqlite3VdbeAddOp3(v, OP_AggStep0, 0, reg+pWin->iArgCol, pWin->regAccum);
547 sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
548 sqlite3VdbeChangeP5(v, (u8)pWin->nArg);
549 }
550
551 /* Buffer the current row in the ephemeral table. */
552 if( pMWin->nBufferCol>0 ){
553 sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, pMWin->nBufferCol, regRecord);
554 }else{
555 sqlite3VdbeAddOp2(v, OP_Blob, 0, regRecord);
556 sqlite3VdbeAppendP4(v, (void*)"", 0);
557 }
558 sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid);
559 sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid);
560
561 /* End the database scan loop. */
562 sqlite3WhereEnd(pWInfo);
563
564 for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
565 sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, pWin->nArg);
566 sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
567 sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult);
568 }
569 sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
570}
571
572
danf9eae182018-05-21 19:45:11 +0000573/*
574** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
575**
576** ...
577** if( new partition ){
578** AggFinal (xFinalize)
579** Gosub addrGosub
580** ResetSorter eph-table
581** }
582** else if( new peer ){
583** AggFinal (xValue)
584** Gosub addrGosub
585** ResetSorter eph-table
586** }
587** AggStep
588** Insert (record into eph-table)
589** sqlite3WhereEnd()
590** AggFinal (xFinalize)
591** Gosub addrGosub
592**
593** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
594**
595** As above, except take no action for a "new peer". Invoke
596** the sub-routine once only for each partition.
597**
598** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
599**
600** As above, except that the "new peer" condition is handled in the
601** same way as "new partition" (so there is no "else if" block).
602**
603** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
604**
605** One way is to just reverse the sort order and do as for BETWEEN
606** UNBOUNDED PRECEDING AND CURRENT ROW. But that is not quite the same for
607** things like group_concat(). And perhaps other user defined aggregates
608** as well.
609**
610** ...
611** if( new partition ){
612** Gosub flush_partition;
613** ResetSorter eph-table
614** }
615** AggStep
616** Insert (record into eph-table)
617** sqlite3WhereEnd()
618** Gosub flush_partition
619**
620** flush_partition:
621** OpenDup (csr -> csr2)
622** foreach (record in eph-table) {
623** if( new peer ){
624** while( csr2!=csr ){
625** AggStep (xInverse)
626** Next (csr2)
627** }
628** }
629** AggFinal (xValue)
630** Gosub addrGosub
631** }
632**
633**========================================================================
634**
635** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
636** ...
637** if( new partition ){
638** AggFinal (xFinalize)
639** }
640** AggStep
641** AggFinal (xValue)
642** Gosub addrGosub
643** sqlite3WhereEnd()
644**
danf9eae182018-05-21 19:45:11 +0000645*/
646void sqlite3WindowCodeStep(
647 Parse *pParse,
648 Select *p,
649 WhereInfo *pWInfo,
650 int regGosub,
danc3a20c12018-05-23 20:55:37 +0000651 int addrGosub,
652 int *pbLoop
danf9eae182018-05-21 19:45:11 +0000653){
danf9eae182018-05-21 19:45:11 +0000654 Window *pMWin = p->pWin;
danf9eae182018-05-21 19:45:11 +0000655
dan09590aa2018-05-25 20:30:17 +0000656 if( (pMWin->eType==TK_ROWS
657 && (pMWin->eStart!=TK_UNBOUNDED || pMWin->eEnd!=TK_CURRENT))
658 || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED)
659 ){
danc3a20c12018-05-23 20:55:37 +0000660 *pbLoop = 0;
661 windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub);
662 return;
danf9eae182018-05-21 19:45:11 +0000663 }
664
danc3a20c12018-05-23 20:55:37 +0000665 *pbLoop = 1;
666 windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub);
danf9eae182018-05-21 19:45:11 +0000667}
668
dane2f781b2018-05-17 19:24:08 +0000669