1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Remove "cache mode" from the window frame code generator. Handle the same cases by editing the window frame specification itself.

FossilOrigin-Name: 081263538332bb9c07e62630629007ccbba31bef5dc890f60b4ba58a355f70ac
This commit is contained in:
dan
2019-03-11 19:50:54 +00:00
parent a786e453a4
commit cc7a850f2e
4 changed files with 110 additions and 149 deletions

View File

@@ -1,5 +1,5 @@
C Simplify\sthe\swindows\sframe\scode\ssome.\sAdd\sa\scomment\sexplaining\ssome\sof\sthe\sVM\scode\sgenerated\sby\ssqlite3WindowCodeStep().
D 2019-03-11T18:17:04.702
C Remove\s"cache\smode"\sfrom\sthe\swindow\sframe\scode\sgenerator.\sHandle\sthe\ssame\scases\sby\sediting\sthe\swindow\sframe\sspecification\sitself.
D 2019-03-11T19:50:54.722
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 236d2739dc3e823c3c909bca2d6cef93009bafbefd7018a8f3281074ecb92954
@@ -520,7 +520,7 @@ F src/shell.c.in 01c0cc01391d00d247fdf640052d38c267fc16d975bc4f3154a02277c232dbe
F src/sqlite.h.in 02be315feaf20c06028aacf3b032b5e7211e9aae066284eef77b081646b43ea0
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
F src/sqliteInt.h 24a4818574031facb6ec4fc5fc3b20b8f68c9ec4c85b662a41d1dc4a2ba0524b
F src/sqliteInt.h 45d85aa38f1148cb7ba514efe39f5d709456c2a5064cb228ead68c59c4628836
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -604,7 +604,7 @@ F src/where.c 8a207cb2ca6b99e1edb1e4bbff9b0504385a759cbf66180d1deb34d80ca4b799
F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88
F src/wherecode.c ce7b21e1be2b981d62683fc59c4ca73a04a7ff2f1ebec23d41baf2da2349afd6
F src/whereexpr.c 36b47f7261d6b6f1a72d774c113b74beddf6745aba1018e64b196e29db233442
F src/window.c ca0d94d256bc52b7815b3c73b00468d0de84021f0d7be1d18588584dc96996b4
F src/window.c f41e0b36e6c26aa8b858f488498aa8152d6441a09c0e96baa5979269e1f0d199
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -1812,7 +1812,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P e7bced731aa071c95bc398cdecd53c939841bf0c52fbcd06e47ba68f8c5cc35a
R c7a0f784b83bf2fca5c90a7c55a81175
P 6bd1a07949ff3d394056bfcc813444401ef00806e3f0e0423ff6962541e84bdb
R 895a04edfc289d379068084b0a252ef5
U dan
Z ca63593942babec716fd2593022c4696
Z ab8b6521d2f2f661581dab04391f3c9a

View File

@@ -1 +1 @@
6bd1a07949ff3d394056bfcc813444401ef00806e3f0e0423ff6962541e84bdb
081263538332bb9c07e62630629007ccbba31bef5dc890f60b4ba58a355f70ac

View File

@@ -1691,7 +1691,6 @@ struct FuncDestructor {
#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
/*
@@ -3577,9 +3576,7 @@ struct Window {
Expr *pOwner; /* Expression object this window is attached to */
int nBufferCol; /* Number of columns in buffer table */
int iArgCol; /* Offset of first argument for this function */
int regFirst;
int regSize;
};
#ifndef SQLITE_OMIT_WINDOWFUNC

View File

@@ -233,7 +233,7 @@ static void rankValueFunc(sqlite3_context *pCtx){
** Implementation of built-in window function percent_rank(). Assumes that
** the window frame has been set to:
**
** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
** GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
*/
static void percent_rankStepFunc(
sqlite3_context *pCtx,
@@ -241,38 +241,42 @@ static void percent_rankStepFunc(
sqlite3_value **apArg
){
struct CallCount *p;
UNUSED_PARAMETER(nArg); assert( nArg==1 );
UNUSED_PARAMETER(nArg); assert( nArg==0 );
p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
if( p ){
if( p->nTotal==0 ){
p->nTotal = sqlite3_value_int64(apArg[0]);
p->nTotal++;
}
}
static void percent_rankInvFunc(
sqlite3_context *pCtx,
int nArg,
sqlite3_value **apArg
){
struct CallCount *p;
UNUSED_PARAMETER(nArg); assert( nArg==0 );
p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
p->nStep++;
if( p->nValue==0 ){
p->nValue = p->nStep;
}
}
}
static void percent_rankValueFunc(sqlite3_context *pCtx){
struct CallCount *p;
p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
if( p ){
p->nValue = p->nStep;
if( p->nTotal>1 ){
double r = (double)(p->nValue-1) / (double)(p->nTotal-1);
double r = (double)p->nValue / (double)(p->nTotal-1);
sqlite3_result_double(pCtx, r);
}else{
sqlite3_result_double(pCtx, 0.0);
}
p->nValue = 0;
}
}
#define percent_rankFinalizeFunc percent_rankValueFunc
/*
** Implementation of built-in window function cume_dist(). Assumes that
** the window frame has been set to:
**
** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
** GROUPS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING
*/
static void cume_distStepFunc(
sqlite3_context *pCtx,
@@ -280,16 +284,22 @@ static void cume_distStepFunc(
sqlite3_value **apArg
){
struct CallCount *p;
assert( nArg==1 ); UNUSED_PARAMETER(nArg);
UNUSED_PARAMETER(nArg); assert( nArg==0 );
p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
if( p ){
if( p->nTotal==0 ){
p->nTotal = sqlite3_value_int64(apArg[0]);
p->nTotal++;
}
}
static void cume_distInvFunc(
sqlite3_context *pCtx,
int nArg,
sqlite3_value **apArg
){
struct CallCount *p;
UNUSED_PARAMETER(nArg); assert( nArg==0 );
p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
p->nStep++;
}
}
static void cume_distValueFunc(sqlite3_context *pCtx){
struct CallCount *p;
p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
@@ -298,6 +308,7 @@ static void cume_distValueFunc(sqlite3_context *pCtx){
sqlite3_result_double(pCtx, r);
}
}
#define cume_distFinalizeFunc cume_distValueFunc
/*
** Context object for ntile() window function.
@@ -312,7 +323,7 @@ struct NtileCtx {
** Implementation of ntile(). This assumes that the window frame has
** been coerced to:
**
** ROWS UNBOUNDED PRECEDING AND CURRENT ROW
** ROWS CURRENT ROW AND UNBOUNDED FOLLOWING
*/
static void ntileStepFunc(
sqlite3_context *pCtx,
@@ -320,32 +331,41 @@ static void ntileStepFunc(
sqlite3_value **apArg
){
struct NtileCtx *p;
assert( nArg==2 ); UNUSED_PARAMETER(nArg);
assert( nArg==1 ); UNUSED_PARAMETER(nArg);
p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
if( p ){
if( p->nTotal==0 ){
p->nParam = sqlite3_value_int64(apArg[0]);
p->nTotal = sqlite3_value_int64(apArg[1]);
if( p->nParam<=0 ){
sqlite3_result_error(
pCtx, "argument of ntile must be a positive integer", -1
);
}
}
p->iRow++;
p->nTotal++;
}
}
static void ntileInvFunc(
sqlite3_context *pCtx,
int nArg,
sqlite3_value **apArg
){
struct NtileCtx *p;
assert( nArg==1 ); UNUSED_PARAMETER(nArg);
p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
p->iRow++;
}
static void ntileValueFunc(sqlite3_context *pCtx){
struct NtileCtx *p;
p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
if( p && p->nParam>0 ){
int nSize = (p->nTotal / p->nParam);
if( nSize==0 ){
sqlite3_result_int64(pCtx, p->iRow);
sqlite3_result_int64(pCtx, p->iRow+1);
}else{
i64 nLarge = p->nTotal - p->nParam*nSize;
i64 iSmall = nLarge*(nSize+1);
i64 iRow = p->iRow-1;
i64 iRow = p->iRow;
assert( (nLarge*(nSize+1) + (p->nParam-nLarge)*nSize)==p->nTotal );
@@ -357,6 +377,7 @@ static void ntileValueFunc(sqlite3_context *pCtx){
}
}
}
#define ntileFinalizeFunc ntileValueFunc
/*
** Context object for last_value() window function.
@@ -496,9 +517,12 @@ void sqlite3WindowFunctions(void){
WINDOWFUNCX(row_number, 0, 0),
WINDOWFUNCX(dense_rank, 0, 0),
WINDOWFUNCX(rank, 0, 0),
WINDOWFUNCX(percent_rank, 0, SQLITE_FUNC_WINDOW_SIZE),
WINDOWFUNCX(cume_dist, 0, SQLITE_FUNC_WINDOW_SIZE),
WINDOWFUNCX(ntile, 1, SQLITE_FUNC_WINDOW_SIZE),
// WINDOWFUNCX(percent_rank, 0, SQLITE_FUNC_WINDOW_SIZE),
WINDOWFUNCALL(percent_rank, 0, 0),
WINDOWFUNCALL(cume_dist, 0, 0),
WINDOWFUNCALL(ntile, 1, 0),
// WINDOWFUNCX(cume_dist, 0, SQLITE_FUNC_WINDOW_SIZE),
// WINDOWFUNCX(ntile, 1, SQLITE_FUNC_WINDOW_SIZE),
WINDOWFUNCALL(last_value, 1, 0),
WINDOWFUNCNOOP(nth_value, 2, 0),
WINDOWFUNCNOOP(first_value, 1, 0),
@@ -573,25 +597,36 @@ void sqlite3WindowUpdate(
sqlite3ErrorMsg(pParse,
"FILTER clause may only be used with aggregate window functions"
);
}else
if( pFunc->zName==row_numberName || pFunc->zName==ntileName ){
}else{
struct WindowUpdate {
const char *zFunc;
int eType;
int eStart;
int eEnd;
} aUp[] = {
{ row_numberName, TK_ROWS, TK_UNBOUNDED, TK_CURRENT },
{ dense_rankName, TK_RANGE, TK_UNBOUNDED, TK_CURRENT },
{ rankName, TK_RANGE, TK_UNBOUNDED, TK_CURRENT },
{ percent_rankName, TK_GROUPS, TK_CURRENT, TK_UNBOUNDED },
{ cume_distName, TK_GROUPS, TK_FOLLOWING, TK_UNBOUNDED },
{ ntileName, TK_ROWS, TK_CURRENT, TK_UNBOUNDED },
{ leadName, TK_ROWS, TK_UNBOUNDED, TK_UNBOUNDED },
};
int i;
for(i=0; i<ArraySize(aUp); i++){
if( pFunc->zName==aUp[i].zFunc ){
sqlite3ExprDelete(db, pWin->pStart);
sqlite3ExprDelete(db, pWin->pEnd);
pWin->pStart = pWin->pEnd = 0;
pWin->eType = TK_ROWS;
pWin->eStart = TK_UNBOUNDED;
pWin->eEnd = TK_CURRENT;
}else
if( pFunc->zName==dense_rankName || pFunc->zName==rankName
|| pFunc->zName==percent_rankName || pFunc->zName==cume_distName
){
sqlite3ExprDelete(db, pWin->pStart);
sqlite3ExprDelete(db, pWin->pEnd);
pWin->pStart = pWin->pEnd = 0;
pWin->eType = TK_RANGE;
pWin->eStart = TK_UNBOUNDED;
pWin->eEnd = TK_CURRENT;
pWin->pEnd = pWin->pStart = 0;
pWin->eType = aUp[i].eType;
pWin->eStart = aUp[i].eStart;
pWin->eEnd = aUp[i].eEnd;
if( pWin->eStart==TK_FOLLOWING ){
pWin->pStart = sqlite3Expr(db, TK_INTEGER, "1");
}
break;
}
}
}
}
pWin->pFunc = pFunc;
@@ -1092,8 +1127,6 @@ void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){
pMWin->regFirst = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regFirst);
pMWin->regSize = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regSize);
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
FuncDef *p = pWin->pFunc;
@@ -1206,7 +1239,6 @@ static void windowAggStep(
Vdbe *v = sqlite3GetVdbe(pParse);
Window *pWin;
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
int flags = pWin->pFunc->funcFlags;
int regArg;
int nArg = windowArgCount(pWin);
@@ -1216,16 +1248,7 @@ static void windowAggStep(
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i);
}
regArg = reg;
if( flags & SQLITE_FUNC_WINDOW_SIZE ){
if( nArg==0 ){
regArg = regPartSize;
}else{
sqlite3VdbeAddOp2(v, OP_SCopy, regPartSize, reg+nArg);
}
nArg++;
}
}else{
assert( !(flags & SQLITE_FUNC_WINDOW_SIZE) );
regArg = reg + pWin->iArgCol;
}
@@ -1440,18 +1463,18 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){
return regArg;
}
#if 0
/*
** Return true if the entire partition should be cached in the ephemeral
** table before processing any rows.
** Return true if the current frame should be cached in the ephemeral table,
** even if there are no xInverse() calls required.
*/
static int windowCachePartition(Window *pMWin){
static int windowCacheFrame(Window *pMWin){
Window *pWin;
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
FuncDef *pFunc = pWin->pFunc;
if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE)
|| (pFunc->zName==nth_valueName)
if( (pFunc->zName==nth_valueName)
|| (pFunc->zName==first_valueName)
|| (pFunc->zName==leadName)
|| (pFunc->zName==leadName) */
|| (pFunc->zName==lagName)
){
return 1;
@@ -1459,6 +1482,7 @@ static int windowCachePartition(Window *pMWin){
}
return 0;
}
#endif
/*
** regOld and regNew are each the first register in an array of size
@@ -1659,13 +1683,13 @@ static int windowCodeOp(
case WINDOW_AGGINVERSE:
csr = p->start.csr;
reg = p->start.reg;
windowAggStep(pParse, pMWin, csr, 1, p->regArg, pMWin->regSize);
windowAggStep(pParse, pMWin, csr, 1, p->regArg, 0);
break;
case WINDOW_AGGSTEP:
csr = p->end.csr;
reg = p->end.reg;
windowAggStep(pParse, pMWin, csr, 0, p->regArg, pMWin->regSize);
windowAggStep(pParse, pMWin, csr, 0, p->regArg, 0);
break;
}
@@ -1922,26 +1946,6 @@ Window *sqlite3WindowListDup(sqlite3 *db, Window *p){
** while( !eof csrCurrent ){
** RETURN_ROW
** }
**
** Sometimes, this function generates code to run in "cache mode" - meaning
** the entire partition is cached in the ephemeral table before any of its
** rows are processed, instead of processing rows as the sub-select delivers
** them. This is required by certain built-in window functions, for example
** percent_rank() or lead(). In that case, the relevant pseudo-code above
** is modified to:
**
** ... loop started by sqlite3WhereBegin() ...
** if( new partition ){
** Gosub flush
** }
** Insert new row into eph table.
** }
** flush:
** for each row in eph table {
**
** followed immediately by the code that usually follows the "Insert new row
** into eph table." line.
**
*/
void sqlite3WindowCodeStep(
Parse *pParse, /* Parse context */
@@ -1953,7 +1957,6 @@ void sqlite3WindowCodeStep(
Window *pMWin = p->pWin;
ExprList *pOrderBy = pMWin->pOrderBy;
Vdbe *v = sqlite3GetVdbe(pParse);
int bCache; /* True if generating "cache-mode" code */
int regFlushPart; /* Register for "Gosub flush_partition" */
int csrWrite; /* Cursor used to write to eph. table */
int csrInput = p->pSrc->a[0].iCursor; /* Cursor of sub-select */
@@ -1963,8 +1966,6 @@ void sqlite3WindowCodeStep(
int addrIfNot; /* Address of OP_IfNot */
int addrGosubFlush; /* Address of OP_Gosub to flush: */
int addrInteger; /* Address of OP_Integer */
int addrCacheRewind; /* Address of OP_Rewind used in cache-mode */
int addrCacheNext; /* Jump here for next row in cache-mode */
int addrShortcut = 0;
int addrEmpty = 0; /* Address of OP_Rewind in flush: */
int addrPeerJump = 0; /* Address of jump taken if not new peer */
@@ -1986,7 +1987,6 @@ void sqlite3WindowCodeStep(
/* Determine whether or not each partition will be cached before beginning
** to process rows within it. */
bCache = windowCachePartition(pMWin);
/* Fill in the context object */
memset(&s, 0, sizeof(WindowCodeArg));
@@ -2061,19 +2061,8 @@ void sqlite3WindowCodeStep(
/* Insert the new row into the ephemeral table */
sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, regRowid);
sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regSize, 1);
if( bCache ){
sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regFirst);
sqlite3WhereEnd(pWInfo);
addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart);
if( pMWin->pPartition ){
sqlite3VdbeJumpHere(v, addrGosubFlush);
}
addrCacheRewind = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
}else{
addrIfNot = sqlite3VdbeAddOp1(v, OP_IfNot, pMWin->regFirst);
}
/* This block is run for the first row of each partition */
s.regArg = windowInitAccum(pParse, pMWin);
@@ -2091,16 +2080,9 @@ void sqlite3WindowCodeStep(
int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le);
int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd);
windowAggFinal(pParse, pMWin, 0);
if( bCache ){
sqlite3VdbeAddOp2(v, OP_Rowid, csrWrite, regRowid);
sqlite3VdbeAddOp3(v, OP_NotExists, s.current.csr, 0, regRowid);
windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
sqlite3VdbeAddOp2(v, OP_Next, csrWrite, addrCacheRewind+1);
}else{
sqlite3VdbeAddOp2(v, OP_Rewind, s.current.csr, 1);
windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr);
}
addrShortcut = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, addrGe);
}
@@ -2115,11 +2097,7 @@ void sqlite3WindowCodeStep(
sqlite3VdbeAddOp2(v, OP_Rewind, s.current.csr, 1);
sqlite3VdbeAddOp2(v, OP_Rewind, s.end.csr, 1);
if( regPeer && pOrderBy ){
if( bCache ){
windowReadPeerValues(&s, csrWrite, regPeer);
}else{
sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, pOrderBy->nExpr-1);
}
sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.start.reg, pOrderBy->nExpr-1);
sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.current.reg, pOrderBy->nExpr-1);
sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.end.reg, pOrderBy->nExpr-1);
@@ -2130,14 +2108,7 @@ void sqlite3WindowCodeStep(
/* Begin generating SECOND_ROW_CODE */
VdbeModuleComment((pParse->pVdbe, "Begin WindowCodeStep.SECOND_ROW"));
if( bCache ){
addrCacheNext = sqlite3VdbeCurrentAddr(v);
if( pMWin->eType!=TK_ROWS ){
windowReadPeerValues(&s, csrWrite, regNewPeer);
}
}else{
sqlite3VdbeJumpHere(v, addrIfNot);
}
if( regPeer ){
addrPeerJump = windowIfNewPeer(pParse, pOrderBy, regNewPeer, regPeer);
}
@@ -2194,16 +2165,11 @@ void sqlite3WindowCodeStep(
/* End of the main input loop */
sqlite3VdbeJumpHere(v, addrGoto);
if( bCache ){
sqlite3VdbeAddOp2(v, OP_Next, csrWrite, addrCacheNext);
sqlite3VdbeJumpHere(v, addrCacheRewind);
}else{
if( addrShortcut>0 ) sqlite3VdbeJumpHere(v, addrShortcut);
sqlite3WhereEnd(pWInfo);
}
/* Fall through */
if( pMWin->pPartition && bCache==0 ){
if( pMWin->pPartition ){
addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart);
sqlite3VdbeJumpHere(v, addrGosubFlush);
}
@@ -2254,10 +2220,8 @@ void sqlite3WindowCodeStep(
sqlite3VdbeJumpHere(v, addrEmpty);
if( bCache && addrShortcut>0 ) sqlite3VdbeJumpHere(v, addrShortcut);
sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr);
sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regSize);
if( bCache==0 ) sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regFirst);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regFirst);
VdbeModuleComment((pParse->pVdbe, "End WindowCodeStep.FLUSH"));
if( pMWin->pPartition ){
sqlite3VdbeChangeP1(v, addrInteger, sqlite3VdbeCurrentAddr(v));