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

Extend windowCodeStep() to handle any ROWS PRECEDING/FOLLOWING frame specification.

FossilOrigin-Name: af0ea1363548461b2aad8fd54ee3f2f616111dcae2d6480f5294da44c87a0a5d
This commit is contained in:
dan
2019-03-05 19:29:36 +00:00
parent 4e72e62f3b
commit b25a214dec
3 changed files with 119 additions and 36 deletions

View File

@@ -1,5 +1,5 @@
C Merge\strunk\schanges\sinto\sthis\sbranch. C Extend\swindowCodeStep()\sto\shandle\sany\sROWS\sPRECEDING/FOLLOWING\sframe\sspecification.
D 2019-03-04T21:08:53.342 D 2019-03-05T19:29:36.660
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 1ad7263f38329c0ecea543c80f30af839ee714ea77fc391bf1a3fbb919a5b6b5 F Makefile.in 1ad7263f38329c0ecea543c80f30af839ee714ea77fc391bf1a3fbb919a5b6b5
@@ -604,7 +604,7 @@ F src/where.c 8a207cb2ca6b99e1edb1e4bbff9b0504385a759cbf66180d1deb34d80ca4b799
F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88 F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88
F src/wherecode.c ce7b21e1be2b981d62683fc59c4ca73a04a7ff2f1ebec23d41baf2da2349afd6 F src/wherecode.c ce7b21e1be2b981d62683fc59c4ca73a04a7ff2f1ebec23d41baf2da2349afd6
F src/whereexpr.c 36b47f7261d6b6f1a72d774c113b74beddf6745aba1018e64b196e29db233442 F src/whereexpr.c 36b47f7261d6b6f1a72d774c113b74beddf6745aba1018e64b196e29db233442
F src/window.c b2316f6082849e6a98a7f46209528721082533297c3c8b535edd5581863610d7 F src/window.c d722f9b0cb3f12ee3fab8cc2d05407078d99346969e9c7e2030da21d0588675f
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -1809,7 +1809,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P e7a91f12282afb5d5d7d78397a11d18e0268ee0c931d85e21fce00d13929494e 906d1fd8650874236e0bf5734d5347dcc45ec036164a56570fec37da4ffeaf8f P 9b4d561f68febdab6624d8c567fb4357bf67dda500664cf708d16a76f37b8ec1
R 30a9373810c2da7278ca9b29b61f206e R f1949de6e35750b066f9dbae4754f91b
T +closed d661659f6934dd7a7ef67d1090e078343fc05e85c3ce3586883921ed32484d13
U dan U dan
Z 5d336602dfcf4b9ecdc6fcf657926dd9 Z 8f284cc4f98c73f741a81ab913586d8b

View File

@@ -1 +1 @@
9b4d561f68febdab6624d8c567fb4357bf67dda500664cf708d16a76f37b8ec1 af0ea1363548461b2aad8fd54ee3f2f616111dcae2d6480f5294da44c87a0a5d

View File

@@ -1871,7 +1871,8 @@ static void windowCodeStep(
int addrIfStart; int addrIfStart;
int addrGosubFlush; int addrGosubFlush;
int addrInteger; int addrInteger;
int addrGoto2;
int addrShortcut = 0;
int reg = pParse->nMem+1; int reg = pParse->nMem+1;
int regRecord = reg+nSub; int regRecord = reg+nSub;
@@ -1931,55 +1932,133 @@ static void windowCodeStep(
reg+pMWin->nBufferCol, pMWin->regPart, pMWin->pPartition->nExpr-1 reg+pMWin->nBufferCol, pMWin->regPart, pMWin->pPartition->nExpr-1
); );
} }
sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, 1); sqlite3VdbeChangeP5(v, 1);
sqlite3VdbeAddOp2(v, OP_Rewind, csrCurrent, 1); sqlite3VdbeChangeP5(v, 1);
sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, 1);
regArg = windowInitAccum(pParse, pMWin); regArg = windowInitAccum(pParse, pMWin);
sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regFirst);
sqlite3ExprCode(pParse, pMWin->pStart, regStart); sqlite3ExprCode(pParse, pMWin->pStart, regStart);
windowCheckIntValue(pParse, regStart, 0); windowCheckIntValue(pParse, regStart, 0);
sqlite3ExprCode(pParse, pMWin->pEnd, regEnd); sqlite3ExprCode(pParse, pMWin->pEnd, regEnd);
windowCheckIntValue(pParse, regEnd, 1); windowCheckIntValue(pParse, regEnd, 1);
if( pMWin->eStart==TK_FOLLOWING || pMWin->eEnd==TK_PRECEDING ){
int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le);
int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd);
windowAggFinal(pParse, pMWin, 0);
sqlite3VdbeAddOp2(v, OP_Rewind, csrCurrent, 1);
windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
sqlite3VdbeAddOp1(v, OP_ResetSorter, csrCurrent);
addrShortcut = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, addrGe);
}
if( pMWin->eStart==TK_FOLLOWING ){
sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regStart);
}
sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, 1); sqlite3VdbeChangeP5(v, 1);
sqlite3VdbeAddOp2(v, OP_Rewind, csrCurrent, 1); sqlite3VdbeChangeP5(v, 1);
sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, 1); sqlite3VdbeChangeP5(v, 1);
sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regFirst);
addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
/* This block is run for the second and subsequent rows of each partition */ /* This block is run for the second and subsequent rows of each partition */
sqlite3VdbeJumpHere(v, addrIf); sqlite3VdbeJumpHere(v, addrIf);
sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+1);
addrIfEnd = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1); if( pMWin->eStart==TK_FOLLOWING ){
windowAggFinal(pParse, pMWin, 0); addrIfEnd = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1);
sqlite3VdbeAddOp2(v, OP_Next, csrCurrent, sqlite3VdbeCurrentAddr(v)+1); windowAggFinal(pParse, pMWin, 0);
windowReturnOneRow(pParse, pMWin, regGosub, addrGosub); sqlite3VdbeAddOp2(v, OP_Next, csrCurrent, sqlite3VdbeCurrentAddr(v)+1);
addrIfStart = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0, 1); windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1); sqlite3VdbeJumpHere(v, addrIfEnd);
windowAggStep(pParse, pMWin, csrStart, 1, regArg, 0);
sqlite3VdbeJumpHere(v, addrIfStart); addrIfStart = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0, 1);
sqlite3VdbeJumpHere(v, addrIfEnd); sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1);
windowAggStep(pParse, pMWin, csrStart, 1, regArg, 0);
sqlite3VdbeJumpHere(v, addrIfStart);
}else
if( pMWin->eEnd==TK_PRECEDING ){
addrIfEnd = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1);
sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+1);
windowAggStep(pParse, pMWin, csrEnd, 0, regArg, 0);
sqlite3VdbeJumpHere(v, addrIfEnd);
windowAggFinal(pParse, pMWin, 0);
sqlite3VdbeAddOp2(v, OP_Next, csrCurrent, sqlite3VdbeCurrentAddr(v)+1);
windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
addrIfStart = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0, 1);
sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1);
windowAggStep(pParse, pMWin, csrStart, 1, regArg, 0);
sqlite3VdbeJumpHere(v, addrIfStart);
}else{
addrIfEnd = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1);
windowAggFinal(pParse, pMWin, 0);
sqlite3VdbeAddOp2(v, OP_Next, csrCurrent, sqlite3VdbeCurrentAddr(v)+1);
windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
addrIfStart = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0, 1);
sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1);
windowAggStep(pParse, pMWin, csrStart, 1, regArg, 0);
sqlite3VdbeJumpHere(v, addrIfStart);
sqlite3VdbeJumpHere(v, addrIfEnd);
}
sqlite3VdbeJumpHere(v, addrGoto); sqlite3VdbeJumpHere(v, addrGoto);
windowAggStep(pParse, pMWin, csrEnd, 0, regArg, 0); if( pMWin->eEnd!=TK_PRECEDING ){
sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+1);
windowAggStep(pParse, pMWin, csrEnd, 0, regArg, 0);
}
/* End of the main input loop */ /* End of the main input loop */
if( addrShortcut>0 ) sqlite3VdbeJumpHere(v, addrShortcut);
sqlite3WhereEnd(pWInfo); sqlite3WhereEnd(pWInfo);
/* Fall through */ /* Fall through */
if( pMWin->pPartition ){ if( pMWin->pPartition ){
addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart); addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart);
sqlite3VdbeJumpHere(v, addrGosubFlush); sqlite3VdbeJumpHere(v, addrGosubFlush);
} }
sqlite3VdbeAddOp2(v, OP_Next, csrCurrent, sqlite3VdbeCurrentAddr(v)+2); if( pMWin->eStart==TK_FOLLOWING ){
addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); int addrBreak;
windowAggFinal(pParse, pMWin, 0); addrIfEnd = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1);
windowReturnOneRow(pParse, pMWin, regGosub, addrGosub); sqlite3VdbeAddOp2(v, OP_Next, csrCurrent, sqlite3VdbeCurrentAddr(v)+2);
addrIfStart = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0, 1); addrBreak = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+2); windowAggFinal(pParse, pMWin, 0);
addrGoto2 = sqlite3VdbeAddOp0(v, OP_Goto); windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
windowAggStep(pParse, pMWin, csrStart, 1, regArg, 0); sqlite3VdbeJumpHere(v, addrIfEnd);
sqlite3VdbeJumpHere(v, addrIfStart);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrGoto-1); addrIfStart = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0, 1);
sqlite3VdbeJumpHere(v, addrGoto); sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeJumpHere(v, addrGoto2); sqlite3VdbeAddOp0(v, OP_Goto);
windowAggStep(pParse, pMWin, csrStart, 1, regArg, 0);
sqlite3VdbeJumpHere(v, addrIfStart);
sqlite3VdbeJumpHere(v, addrIfStart+2);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrIfEnd);
sqlite3VdbeJumpHere(v, addrBreak);
}else{
sqlite3VdbeAddOp2(v, OP_Next, csrCurrent, sqlite3VdbeCurrentAddr(v)+2);
addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
if( pMWin->eEnd==TK_PRECEDING ){
addrIfEnd = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1);
sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+1);
windowAggStep(pParse, pMWin, csrEnd, 0, regArg, 0);
sqlite3VdbeJumpHere(v, addrIfEnd);
windowAggFinal(pParse, pMWin, 0);
windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
}else{
windowAggFinal(pParse, pMWin, 0);
windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
addrIfStart = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0, 1);
sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1);
windowAggStep(pParse, pMWin, csrStart, 1, regArg, 0);
sqlite3VdbeJumpHere(v, addrIfStart);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrGoto-1);
}
sqlite3VdbeJumpHere(v, addrGoto);
}
sqlite3VdbeAddOp1(v, OP_ResetSorter, csrCurrent); sqlite3VdbeAddOp1(v, OP_ResetSorter, csrCurrent);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regFirst); sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regFirst);
@@ -2465,7 +2544,10 @@ void sqlite3WindowCodeStep(
break; break;
} }
} }
if( bCache || pMWin->eStart!=TK_PRECEDING || pMWin->eEnd!=TK_FOLLOWING ){ if( bCache
|| (pMWin->eStart!=TK_PRECEDING && pMWin->eStart!=TK_FOLLOWING)
|| (pMWin->eEnd!=TK_FOLLOWING && pMWin->eEnd!=TK_PRECEDING)
){
VdbeModuleComment((pParse->pVdbe, "Begin RowExprStep()")); VdbeModuleComment((pParse->pVdbe, "Begin RowExprStep()"));
windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub); windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub);
VdbeModuleComment((pParse->pVdbe, "End RowExprStep()")); VdbeModuleComment((pParse->pVdbe, "End RowExprStep()"));