Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -3569,12 +3569,11 @@ int iEphCsr; /* Partition buffer or Peer buffer */ int regAccum; int regResult; int csrApp; /* Function cursor (used by min/max) */ int regApp; /* Function register (also used by min/max) */ - int regPart; /* First in a set of registers holding PARTITION BY - ** and ORDER BY values for the window */ + int regPart; /* Array of registers for PARTITION BY values */ 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; }; Index: src/window.c ================================================================== --- src/window.c +++ src/window.c @@ -1116,16 +1116,18 @@ ** and initialize registers and cursors used by sqlite3WindowCodeStep(). */ void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){ Window *pWin; Vdbe *v = sqlite3GetVdbe(pParse); - int nPart = (pMWin->pPartition ? pMWin->pPartition->nExpr : 0); - nPart += (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); - if( nPart ){ + + /* Allocate registers to use for PARTITION BY values, if any. Initialize + ** said registers to NULL. */ + if( pMWin->pPartition ){ + int nExpr = pMWin->pPartition->nExpr; pMWin->regPart = pParse->nMem+1; - pParse->nMem += nPart; - sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nPart-1); + pParse->nMem += nExpr; + sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nExpr-1); } pMWin->regFirst = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regFirst); @@ -2109,10 +2111,12 @@ ** } ** while( !eof csrCurrent ){ ** RETURN_ROW ** } ** +** The text above leaves out many details. Refer to the code and comments +** below for a more complete picture. */ void sqlite3WindowCodeStep( Parse *pParse, /* Parse context */ Select *p, /* Rewritten SELECT statement */ WhereInfo *pWInfo, /* Context returned by sqlite3WhereBegin() */ @@ -2300,12 +2304,10 @@ } sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regFirst); sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd); - /* Begin generating SECOND_ROW_CODE */ - VdbeModuleComment((pParse->pVdbe, "Begin WindowCodeStep.SECOND_ROW")); sqlite3VdbeJumpHere(v, addrIfNot); if( regPeer ){ windowIfNewPeer(pParse, pOrderBy, regNewPeer, regPeer, lblWhereEnd); } if( pMWin->eStart==TK_FOLLOWING ){ @@ -2352,11 +2354,10 @@ windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); if( regEnd ) sqlite3VdbeJumpHere(v, addr); } } } - VdbeModuleComment((pParse->pVdbe, "End WindowCodeStep.SECOND_ROW")); /* End of the main input loop */ sqlite3VdbeResolveLabel(v, lblWhereEnd); sqlite3WhereEnd(pWInfo); @@ -2364,11 +2365,10 @@ if( pMWin->pPartition ){ addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart); sqlite3VdbeJumpHere(v, addrGosubFlush); } - VdbeModuleComment((pParse->pVdbe, "Begin WindowCodeStep.FLUSH")); addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite); if( pMWin->eEnd==TK_PRECEDING ){ windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0); windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); }else if( pMWin->eStart==TK_FOLLOWING ){ @@ -2411,13 +2411,12 @@ } sqlite3VdbeJumpHere(v, addrEmpty); sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr); sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regFirst); - VdbeModuleComment((pParse->pVdbe, "End WindowCodeStep.FLUSH")); if( pMWin->pPartition ){ sqlite3VdbeChangeP1(v, addrInteger, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); } } #endif /* SQLITE_OMIT_WINDOWFUNC */