mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Fix "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" window frame
processing. FossilOrigin-Name: b4e9c686697a5211a3bfa47e63f0684e3d4241d8c292cffe1a967bc39ad7cd8f
This commit is contained in:
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Merge\slatest\strunk\schanges\sinto\sthis\sbranch.
|
C Fix\s"RANGE\sBETWEEN\sCURRENT\sROW\sAND\sUNBOUNDED\sFOLLOWING"\swindow\sframe\nprocessing.
|
||||||
D 2018-05-25T09:36:27.522
|
D 2018-05-25T20:30:17.495
|
||||||
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 bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
|
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
|
||||||
@@ -582,7 +582,7 @@ F src/where.c 60ec752fcbe9f9e0271ac60548d159a540a1ee47a4f9fedc85e88a3d0e392dd1
|
|||||||
F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53
|
F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53
|
||||||
F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8
|
F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8
|
||||||
F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
|
F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
|
||||||
F src/window.c 4f9f7ceffb08db3a51d3b6450d464206de335122ac9a3e1e70545eda27abd34f
|
F src/window.c 793ad5ffe29cf09f33db392f2e21f42de76f7292a1819e50b12740bff337b9d7
|
||||||
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
|
||||||
@@ -1615,8 +1615,8 @@ F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
|||||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||||
F test/window1.test 5705337783d220b47f6fb4432264543b7557a05be8013d772f57d71f2fded271
|
F test/window1.test 5705337783d220b47f6fb4432264543b7557a05be8013d772f57d71f2fded271
|
||||||
F test/window2.tcl fd079901ac103a99761803477161834208a243bdd6ec0fbbbd0fc93c7dca1945
|
F test/window2.tcl 4d0fd12b30cb1cf3f0e125dc8ff7f88c048fdc6a9301df7542abea26627c1f9a
|
||||||
F test/window2.test 4f5efb59714ec741e510f12a24a3196316b90715860d79acb904fb5cc45a3dca
|
F test/window2.test 47bb1eb149a605d2082794c7036bdd130a4e6c7ee59ded740748c79b37013aac
|
||||||
F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
|
F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
|
||||||
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
|
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
|
||||||
F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
|
F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
|
||||||
@@ -1733,7 +1733,7 @@ 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 5ac44872fd5c4f92851e7bf57d7207bb4d67de88ea2b5c746ff97f20bd6352e1 b816023ce07d01024d5769e16db924374a49bf909edd12dc1344a0a1ef693db5
|
P 6232519899efc568465d8fcc9fcd79d46a2ce4ec05109d26d5eb1ebd239cd596
|
||||||
R 08a95b4b6cfd3d911449e2174d41c045
|
R 89fd55d38159d271a1d4c5a8e0028929
|
||||||
U dan
|
U dan
|
||||||
Z 91662d48d0166ff2fae671b2e45e9cba
|
Z b9c949b19ea308875db3121f11330208
|
||||||
|
@@ -1 +1 @@
|
|||||||
6232519899efc568465d8fcc9fcd79d46a2ce4ec05109d26d5eb1ebd239cd596
|
b4e9c686697a5211a3bfa47e63f0684e3d4241d8c292cffe1a967bc39ad7cd8f
|
204
src/window.c
204
src/window.c
@@ -114,47 +114,95 @@ static void windowAggStep(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** ROWS BETWEEN <expr> PRECEDING AND <expr> FOLLOWING
|
** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
|
||||||
|
** ----------------------------------------------------
|
||||||
**
|
**
|
||||||
** ...
|
** Pseudo-code for the implementation of this window frame type is as
|
||||||
** if( new partition ){
|
** follows. sqlite3WhereBegin() has already been called to generate the
|
||||||
** Gosub flush_partition
|
** top of the main loop when this function is called.
|
||||||
|
**
|
||||||
|
** Each time the sub-routine at addrGosub is invoked, a single output
|
||||||
|
** row is generated based on the current row indicated by Window.iEphCsr.
|
||||||
|
**
|
||||||
|
** ...
|
||||||
|
** if( new partition ){
|
||||||
|
** Gosub flush_partition
|
||||||
|
** }
|
||||||
|
** Insert (record in eph-table)
|
||||||
|
** sqlite3WhereEnd()
|
||||||
|
** Gosub flush_partition
|
||||||
|
**
|
||||||
|
** flush_partition:
|
||||||
|
** Once {
|
||||||
|
** OpenDup (iEphCsr -> csrStart)
|
||||||
|
** OpenDup (iEphCsr -> csrEnd)
|
||||||
** }
|
** }
|
||||||
** Insert (record in eph-table)
|
** regStart = <expr1> // PRECEDING expression
|
||||||
** sqlite3WhereEnd()
|
** regEnd = <expr2> // FOLLOWING expression
|
||||||
** Gosub flush_partition
|
** if( regStart<0 || regEnd<0 ){ error! }
|
||||||
|
** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
|
||||||
|
** Next(csrEnd) // if EOF skip Aggstep
|
||||||
|
** Aggstep (csrEnd)
|
||||||
|
** if( (regEnd--)<=0 ){
|
||||||
|
** AggFinal (xValue)
|
||||||
|
** Gosub addrGosub
|
||||||
|
** Next(csr) // if EOF goto flush_partition_done
|
||||||
|
** if( (regStart--)<=0 ){
|
||||||
|
** AggStep (csrStart, xInverse)
|
||||||
|
** Next(csrStart)
|
||||||
|
** }
|
||||||
|
** }
|
||||||
|
** flush_partition_done:
|
||||||
|
** ResetSorter (csr)
|
||||||
|
** Return
|
||||||
**
|
**
|
||||||
** flush_partition:
|
** ROWS BETWEEN <expr> PRECEDING AND CURRENT ROW
|
||||||
** Once {
|
** ROWS BETWEEN CURRENT ROW AND <expr> FOLLOWING
|
||||||
** OpenDup (iEphCsr -> csrStart)
|
** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING
|
||||||
** OpenDup (iEphCsr -> csrEnd)
|
**
|
||||||
** }
|
** These are similar to the above. For "CURRENT ROW", intialize the
|
||||||
** regStart = <expr1> // PRECEDING expression
|
** register to 0. For "UNBOUNDED PRECEDING" to infinity.
|
||||||
** regEnd = <expr2> // FOLLOWING expression
|
**
|
||||||
** if( regStart<0 || regEnd<0 ) throw exception!
|
** ROWS BETWEEN <expr> PRECEDING AND UNBOUNDED FOLLOWING
|
||||||
** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
|
** ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||||
** Aggstep (csrEnd)
|
**
|
||||||
** Next(csrEnd) // if EOF fall-through
|
** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
|
||||||
** if( (regEnd--)<=0 ){
|
** while( 1 ){
|
||||||
|
** Next(csrEnd) // Exit while(1) at EOF
|
||||||
|
** Aggstep (csrEnd)
|
||||||
|
** }
|
||||||
|
** while( 1 ){
|
||||||
** AggFinal (xValue)
|
** AggFinal (xValue)
|
||||||
** Gosub addrGosub
|
** Gosub addrGosub
|
||||||
** Next(csr) // if EOF goto flush_partition_done
|
** Next(csr) // if EOF goto flush_partition_done
|
||||||
** if( (regStart--)<=0 ){
|
** if( (regStart--)<=0 ){
|
||||||
** AggStep (csrStart, xInverse)
|
** AggStep (csrStart, xInverse)
|
||||||
** Next(csrStart)
|
** Next(csrStart)
|
||||||
** }
|
** }
|
||||||
** }
|
** }
|
||||||
** flush_partition_done:
|
|
||||||
** ResetSorter (csr)
|
|
||||||
** Return
|
|
||||||
**
|
**
|
||||||
** ROWS BETWEEN <expr> PRECEDING AND CURRENT ROW
|
** For the "CURRENT ROW AND UNBOUNDED FOLLOWING" case, the final if()
|
||||||
** ROWS BETWEEN CURRENT ROW AND <expr> FOLLOWING
|
** condition is always true (as if regStart were initialized to 0).
|
||||||
** ROWS BETWEEN <expr> PRECEDING AND UNBOUNDED FOLLOWING
|
|
||||||
** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING
|
|
||||||
**
|
**
|
||||||
** These are similar to the above. For "CURRENT ROW", intialize the
|
** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||||
** register to 0. For "UNBOUNDED ..." to infinity.
|
**
|
||||||
|
** This is the only RANGE case handled by this routine. It modifies the
|
||||||
|
** second while( 1 ) loop in "ROWS BETWEEN CURRENT ... UNBOUNDED..." to
|
||||||
|
** be:
|
||||||
|
**
|
||||||
|
** while( 1 ){
|
||||||
|
** AggFinal (xValue)
|
||||||
|
** while( 1 ){
|
||||||
|
** regPeer++
|
||||||
|
** Gosub addrGosub
|
||||||
|
** Next(csr) // if EOF goto flush_partition_done
|
||||||
|
** if( new peer ) break;
|
||||||
|
** }
|
||||||
|
** while( (regPeer--)>0 ){
|
||||||
|
** AggStep (csrStart, xInverse)
|
||||||
|
** Next(csrStart)
|
||||||
|
** }
|
||||||
|
** }
|
||||||
**
|
**
|
||||||
** ROWS BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING
|
** ROWS BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING
|
||||||
**
|
**
|
||||||
@@ -220,6 +268,11 @@ static void windowCodeRowExprStep(
|
|||||||
int addrIfPos1;
|
int addrIfPos1;
|
||||||
int addrIfPos2;
|
int addrIfPos2;
|
||||||
|
|
||||||
|
int regPeer = 0; /* Number of peers in current group */
|
||||||
|
int regPeerVal = 0; /* Array of values identifying peer group */
|
||||||
|
int iPeer = 0; /* Column offset in eph-table of peer vals */
|
||||||
|
int nPeerVal; /* Number of peer values */
|
||||||
|
|
||||||
assert( pMWin->eStart==TK_PRECEDING
|
assert( pMWin->eStart==TK_PRECEDING
|
||||||
|| pMWin->eStart==TK_CURRENT
|
|| pMWin->eStart==TK_CURRENT
|
||||||
|| pMWin->eStart==TK_FOLLOWING
|
|| pMWin->eStart==TK_FOLLOWING
|
||||||
@@ -334,6 +387,18 @@ static void windowCodeRowExprStep(
|
|||||||
if( pMWin->eStart==TK_FOLLOWING ){
|
if( pMWin->eStart==TK_FOLLOWING ){
|
||||||
addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1);
|
addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1);
|
||||||
}
|
}
|
||||||
|
if( pMWin->eType==TK_RANGE ){
|
||||||
|
assert( pMWin->eStart==TK_CURRENT && pMWin->pOrderBy );
|
||||||
|
regPeer = ++pParse->nMem;
|
||||||
|
regPeerVal = pParse->nMem+1;
|
||||||
|
iPeer = pMWin->nBufferCol + (pMWin->pPartition?pMWin->pPartition->nExpr:0);
|
||||||
|
nPeerVal = pMWin->pOrderBy->nExpr;
|
||||||
|
pParse->nMem += (2 * nPeerVal);
|
||||||
|
for(k=0; k<nPeerVal; k++){
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, iPeer+k, regPeerVal+k);
|
||||||
|
}
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Integer, 0, regPeer);
|
||||||
|
}
|
||||||
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
||||||
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
|
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
|
||||||
sqlite3VdbeAddOp3(v,
|
sqlite3VdbeAddOp3(v,
|
||||||
@@ -341,9 +406,24 @@ static void windowCodeRowExprStep(
|
|||||||
);
|
);
|
||||||
sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
|
sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
|
||||||
}
|
}
|
||||||
|
if( pMWin->eType==TK_RANGE ){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_AddImm, regPeer, 1);
|
||||||
|
}
|
||||||
sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
|
sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
|
||||||
sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)+2);
|
sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)+2);
|
||||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, lblFlushDone);
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, lblFlushDone);
|
||||||
|
if( pMWin->eType==TK_RANGE ){
|
||||||
|
KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pMWin->pOrderBy,0,0);
|
||||||
|
int addrJump = sqlite3VdbeCurrentAddr(v)-4;
|
||||||
|
for(k=0; k<nPeerVal; k++){
|
||||||
|
int iOut = regPeerVal + nPeerVal + k;
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, iPeer+k, iOut);
|
||||||
|
}
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Compare, regPeerVal, regPeerVal+nPeerVal, nPeerVal);
|
||||||
|
sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
|
||||||
|
addr = sqlite3VdbeCurrentAddr(v)+1;
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Jump, addr, addrJump, addr);
|
||||||
|
}
|
||||||
if( pMWin->eStart==TK_FOLLOWING ){
|
if( pMWin->eStart==TK_FOLLOWING ){
|
||||||
sqlite3VdbeJumpHere(v, addrIfPos2);
|
sqlite3VdbeJumpHere(v, addrIfPos2);
|
||||||
}
|
}
|
||||||
@@ -352,13 +432,21 @@ static void windowCodeRowExprStep(
|
|||||||
|| pMWin->eStart==TK_PRECEDING
|
|| pMWin->eStart==TK_PRECEDING
|
||||||
|| pMWin->eStart==TK_FOLLOWING
|
|| pMWin->eStart==TK_FOLLOWING
|
||||||
){
|
){
|
||||||
|
int addrJumpHere = 0;
|
||||||
if( pMWin->eStart==TK_PRECEDING ){
|
if( pMWin->eStart==TK_PRECEDING ){
|
||||||
addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1);
|
addrJumpHere = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1);
|
||||||
|
}
|
||||||
|
if( pMWin->eType==TK_RANGE ){
|
||||||
|
sqlite3VdbeAddOp3(v, OP_IfPos, regPeer, sqlite3VdbeCurrentAddr(v)+2, 1);
|
||||||
|
addrJumpHere = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1);
|
sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1);
|
||||||
windowAggStep(pParse, pMWin, csrStart, 1, reg);
|
windowAggStep(pParse, pMWin, csrStart, 1, reg);
|
||||||
if( pMWin->eStart==TK_PRECEDING ){
|
if( pMWin->eType==TK_RANGE ){
|
||||||
sqlite3VdbeJumpHere(v, addrIfPos2);
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrJumpHere-1);
|
||||||
|
}
|
||||||
|
if( addrJumpHere ){
|
||||||
|
sqlite3VdbeJumpHere(v, addrJumpHere);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( pMWin->eEnd==TK_FOLLOWING ){
|
if( pMWin->eEnd==TK_FOLLOWING ){
|
||||||
@@ -554,52 +642,6 @@ static void windowCodeDefaultStep(
|
|||||||
** Gosub addrGosub
|
** Gosub addrGosub
|
||||||
** sqlite3WhereEnd()
|
** sqlite3WhereEnd()
|
||||||
**
|
**
|
||||||
** ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
|
||||||
** ROWS BETWEEN CURRENT ROW AND CURRENT ROW
|
|
||||||
** ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
|
||||||
**
|
|
||||||
**========================================================================
|
|
||||||
**
|
|
||||||
** ROWS BETWEEN <expr> PRECEDING AND <expr> PRECEDING
|
|
||||||
**
|
|
||||||
** Replace the bit after "Rewind" in the above with:
|
|
||||||
**
|
|
||||||
** if( (regEnd--)<=0 ){
|
|
||||||
** AggStep (csr3)
|
|
||||||
** Next (csr3)
|
|
||||||
** }
|
|
||||||
** AggFinal (xValue)
|
|
||||||
** Gosub addrGosub
|
|
||||||
** Next(csr) // if EOF goto flush_partition_done
|
|
||||||
** if( (regStart--)<=0 ){
|
|
||||||
** AggStep (csr2, xInverse)
|
|
||||||
** Next (csr2)
|
|
||||||
** }
|
|
||||||
**
|
|
||||||
** ROWS BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING
|
|
||||||
**
|
|
||||||
** regEnd = regEnd - regStart
|
|
||||||
** Rewind (csr,csr2,csr3) // if EOF goto flush_partition_done
|
|
||||||
** Aggstep (csr3)
|
|
||||||
** Next(csr3) // if EOF fall-through
|
|
||||||
** if( (regEnd--)<=0 ){
|
|
||||||
** AggStep (csr2, xInverse)
|
|
||||||
** Next (csr2)
|
|
||||||
** if( (regStart--)<=0 ){
|
|
||||||
** AggFinal (xValue)
|
|
||||||
** Gosub addrGosub
|
|
||||||
** Next(csr) // if EOF goto flush_partition_done
|
|
||||||
** }
|
|
||||||
** }
|
|
||||||
**
|
|
||||||
** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> PRECEDING
|
|
||||||
** ROWS BETWEEN <expr> FOLLOWING AND UNBOUNDED FOLLOWING
|
|
||||||
**
|
|
||||||
** Similar to the above, except with regStart or regEnd set to infinity,
|
|
||||||
** as appropriate.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
**
|
|
||||||
*/
|
*/
|
||||||
void sqlite3WindowCodeStep(
|
void sqlite3WindowCodeStep(
|
||||||
Parse *pParse,
|
Parse *pParse,
|
||||||
@@ -611,8 +653,10 @@ void sqlite3WindowCodeStep(
|
|||||||
){
|
){
|
||||||
Window *pMWin = p->pWin;
|
Window *pMWin = p->pWin;
|
||||||
|
|
||||||
if( pMWin->pStart || pMWin->pEnd ){
|
if( (pMWin->eType==TK_ROWS
|
||||||
assert( pMWin->eType==TK_ROWS );
|
&& (pMWin->eStart!=TK_UNBOUNDED || pMWin->eEnd!=TK_CURRENT))
|
||||||
|
|| (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED)
|
||||||
|
){
|
||||||
*pbLoop = 0;
|
*pbLoop = 0;
|
||||||
windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub);
|
windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub);
|
||||||
return;
|
return;
|
||||||
|
@@ -288,6 +288,64 @@ execsql_test 2.22 {
|
|||||||
) FROM t1
|
) FROM t1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
execsql_test 2.23 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
}
|
||||||
|
|
||||||
|
execsql_test 2.24 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
PARTITION BY a%2
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
}
|
||||||
|
|
||||||
|
execsql_test 2.25 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
}
|
||||||
|
|
||||||
|
execsql_test 2.26 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
PARTITION BY b
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
}
|
||||||
|
|
||||||
|
execsql_test 2.27 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN CURRENT ROW AND CURRENT ROW
|
||||||
|
) FROM t1
|
||||||
|
}
|
||||||
|
|
||||||
|
execsql_test 2.28 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
PARTITION BY b
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN CURRENT ROW AND CURRENT ROW
|
||||||
|
) FROM t1
|
||||||
|
}
|
||||||
|
|
||||||
|
execsql_test 2.29 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
ORDER BY d
|
||||||
|
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
}
|
||||||
|
execsql_test 2.30 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
ORDER BY b
|
||||||
|
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
}
|
||||||
|
|
||||||
==========
|
==========
|
||||||
puts $::fd finish_test
|
puts $::fd finish_test
|
||||||
==========
|
==========
|
||||||
|
@@ -199,6 +199,65 @@ do_execsql_test 2.22 {
|
|||||||
) FROM t1
|
) FROM t1
|
||||||
} {2 10 4 6 6 {} 1 8 3 5 5 {}}
|
} {2 10 4 6 6 {} 1 8 3 5 5 {}}
|
||||||
|
|
||||||
|
do_execsql_test 2.23 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
} {1 21 2 20 3 18 4 15 5 11 6 6}
|
||||||
|
|
||||||
|
do_execsql_test 2.24 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
PARTITION BY a%2
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
} {2 12 4 10 6 6 1 9 3 8 5 5}
|
||||||
|
|
||||||
|
do_execsql_test 2.25 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
} {1 21 2 21 3 21 4 21 5 21 6 21}
|
||||||
|
|
||||||
|
do_execsql_test 2.26 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
PARTITION BY b
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
} {2 12 4 12 6 12 1 9 3 9 5 9}
|
||||||
|
|
||||||
|
do_execsql_test 2.27 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN CURRENT ROW AND CURRENT ROW
|
||||||
|
) FROM t1
|
||||||
|
} {1 1 2 2 3 3 4 4 5 5 6 6}
|
||||||
|
|
||||||
|
do_execsql_test 2.28 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
PARTITION BY b
|
||||||
|
ORDER BY d
|
||||||
|
ROWS BETWEEN CURRENT ROW AND CURRENT ROW
|
||||||
|
) FROM t1
|
||||||
|
} {2 2 4 4 6 6 1 1 3 3 5 5}
|
||||||
|
|
||||||
|
do_execsql_test 2.29 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
ORDER BY d
|
||||||
|
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
} {1 21 2 20 3 18 4 15 5 11 6 6}
|
||||||
|
|
||||||
|
do_execsql_test 2.30 {
|
||||||
|
SELECT a, sum(d) OVER (
|
||||||
|
ORDER BY b
|
||||||
|
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||||
|
) FROM t1
|
||||||
|
} {2 21 4 21 6 21 1 9 3 9 5 9}
|
||||||
|
|
||||||
#==========================================================================
|
#==========================================================================
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
Reference in New Issue
Block a user