Add support for FILTER clause on aggregate window functions.

FossilOrigin-Name: ceaf798ea09184bc0e7d3dcf3ad4d909d2e4e7018754a8417a813f33010140a7
This commit is contained in:
dan 2018-06-09 17:43:45 +00:00
parent e3bf632cc2
commit 8b98560d6e
8 changed files with 419 additions and 15 deletions

View File

@ -1,5 +1,5 @@
C Add\ssupport\sfor\sthe\sWINDOW\sclause.
D 2018-06-08T20:58:27.833
C Add\ssupport\sfor\sFILTER\sclause\son\saggregate\swindow\sfunctions.
D 2018-06-09T17:43:45.368
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
@ -583,7 +583,7 @@ F src/where.c 7dcb13bbcfd8c926546946556014c8f5aa0829eb8b65a6c18f8d187d265200a5
F src/whereInt.h b09753e74bf92a8b17cf0e41ca94c44432c454544be6699b5311dcc57bf229c6
F src/wherecode.c 3317f2b083a66d3e65a03edf316ade4ccb0a99c9956273282ebb579b95d4ba96
F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
F src/window.c 31bd22def29a71144056ddd2a9c4344648c2b89f63a76e7695defdf7ed293216
F src/window.c 72c08229b59a447db5ffb8e87680105549465df502092e0e24f9451e6b082031
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@ -1617,13 +1617,13 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 4561399c91f892279fef028e44133f2c73b8eb22dc788afee508563bb7ad1cdc
F test/window1.test 6c648f3fa79b29ef114c4e73ae8adefae70e4d3aae4cc36a3318ab237b64e9c5
F test/window2.tcl 0983de5eade5eeda49469244799d5331bfe3199fca3f6c6d2a836aa08f4fba1b
F test/window2.test 79747b2edde4ad424e0752b27529aedc86e91f3d8d88846fa17ff0cb67f65086
F test/window3.tcl f2596e9d6bf8d4441eb7a0d3272594185c3b56e8d2413a54b12e6e7557517674
F test/window3.test e43a143131e19a27148215431cf7cec8815c32c7ec04f1cf79d068adff9be028
F test/window4.tcl 2da10ad7a6eedc584c3faa551ff6d0a7f8cc18dee95416d05af389f88ef0ac1a
F test/window4.test bef29a267ee9ac7ca421ef69ba37d19f7e93988f1c052cb09cbb946f309c5cbe
F test/window3.tcl 654d61d73e10db089b22514d498bb23ec310f720c0f4b5f69f67fda83d672048
F test/window3.test 41727668ee31d2ba50f78efcb5bf1bda2c5cffd889aa65243511004669d1ac25
F test/window4.tcl e459eb2fe561d7731008a80d071e2d995c3554706de764c9f456f54357e70316
F test/window4.test 207ab5e54ba0fec5e1157d136489b615a0e88dc8f9fb81cd77e11f20d2ddd72e
F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
@ -1740,7 +1740,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 236cb75bd1f0d5eb86aa5f52d8d548e7263c34633833dcea9dfc934f142113b8
R 42923cbfbd64d075a9e38b7b4b4b969d
P 19c983b511f1c823fdfb051713681b4c779f02fa83b41189afca0a9b8b72048d
R 4922e87ad399c6f94f1076fca5cd38fd
U dan
Z dee7bf2abe4eeccc35a23aee41391161
Z db6d4e8c44c5703bb20011e4b4391c5c

View File

@ -1 +1 @@
19c983b511f1c823fdfb051713681b4c779f02fa83b41189afca0a9b8b72048d
ceaf798ea09184bc0e7d3dcf3ad4d909d2e4e7018754a8417a813f33010140a7

View File

@ -411,6 +411,11 @@ void sqlite3WindowUpdate(
}
if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){
sqlite3 *db = pParse->db;
if( pWin->pFilter ){
sqlite3ErrorMsg(pParse,
"FILTER clause may only be used with aggregate window functions"
);
}else
if( pFunc->xSFunc==row_numberStepFunc || pFunc->xSFunc==ntileStepFunc ){
sqlite3ExprDelete(db, pWin->pStart);
sqlite3ExprDelete(db, pWin->pEnd);
@ -418,7 +423,7 @@ void sqlite3WindowUpdate(
pWin->eType = TK_ROWS;
pWin->eStart = TK_UNBOUNDED;
pWin->eEnd = TK_CURRENT;
}
}else
if( pFunc->xSFunc==dense_rankStepFunc || pFunc->xSFunc==rankStepFunc
|| pFunc->xSFunc==percent_rankStepFunc || pFunc->xSFunc==cume_distStepFunc
@ -602,6 +607,10 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList);
if( pWin->pFilter ){
Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0);
pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter);
}
pWin->regAccum = ++pParse->nMem;
pWin->regResult = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
@ -819,14 +828,29 @@ static void windowAggStep(
){
/* no-op */
}else{
int addrIf = 0;
if( pWin->pFilter ){
int regTmp;
if( csr>0 ){
regTmp = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+pWin->nArg,regTmp);
}else{
regTmp = regArg + pWin->nArg;
}
addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
if( csr>0 ){
sqlite3ReleaseTempReg(pParse, regTmp);
}
}
if( pWin->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl;
pColl = sqlite3ExprCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr);
pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr);
sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp3(v, OP_AggStep0, bInverse, regArg, pWin->regAccum);
sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
}
}
}
@ -855,6 +879,7 @@ static void windowAggFinal(Parse *pParse, Window *pMWin, int bFinal){
sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
if( bFinal ){
sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult);
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
}else{
sqlite3VdbeChangeP3(v, -1, pWin->regResult);
}

View File

@ -214,5 +214,9 @@ do_execsql_test 6.2 {
a 1 1 a 2 2 a 3 3 a 4 4 a 5 5 a 6 6 a 7 7
}
do_catchsql_test 3.5 {
SELECT x, lag(x) FILTER (WHERE (x%2)=0) OVER w FROM t1
WINDOW w AS (ORDER BY x)
} {1 {FILTER clause may only be used with aggregate window functions}}
finish_test

View File

@ -284,7 +284,6 @@ foreach {tn window} {
execsql_test 1.$tn.14.1 "
SELECT string_agg(CAST(b AS TEXT), '.') OVER (ORDER BY a $window) FROM t2
"
execsql_test 1.$tn.14.2 "
SELECT string_agg(CAST(b AS TEXT), '.') OVER (PARTITION BY b%10 ORDER BY a $window) FROM t2
"
@ -300,6 +299,26 @@ foreach {tn window} {
execsql_test 1.$tn.14.6 "
SELECT string_agg(CAST(b AS TEXT), '.') OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2
"
execsql_test 1.$tn.15.1 "
SELECT string_agg(CAST(b AS TEXT), '.')
FILTER (WHERE a%2=0) OVER (ORDER BY a $window) FROM t2
"
execsql_test 1.$tn.15.2 "
SELECT string_agg(CAST(b AS TEXT), '.')
FILTER (WHERE 0=1) OVER (ORDER BY a $window) FROM t2
"
execsql_test 1.$tn.15.3 "
SELECT string_agg(CAST(b AS TEXT), '.')
FILTER (WHERE 1=0) OVER (PARTITION BY (a%10) ORDER BY a $window) FROM t2
"
execsql_test 1.$tn.15.4 "
SELECT string_agg(CAST(b AS TEXT), '.')
FILTER (WHERE a%2=0) OVER (PARTITION BY (a%10) ORDER BY a $window) FROM t2
"
}
finish_test

File diff suppressed because one or more lines are too long

View File

@ -97,5 +97,11 @@ execsql_test 3.3 {
ORDER BY a;
}
execsql_test 3.4 {
SELECT a, max(a) FILTER (WHERE (a%2)=0) OVER w FROM t5
WINDOW w AS (ORDER BY a)
}
finish_test

View File

@ -176,4 +176,14 @@ do_execsql_test 3.3 {
ORDER BY a;
} {1 1 5 2 2 4 3 3 3 4 4 2 5 5 1}
explain_i {
SELECT a, max(a) FILTER (WHERE (a%2)=0) OVER w FROM t5
WINDOW w AS (ORDER BY a)
}
breakpoint
do_execsql_test 3.4 {
SELECT a, max(a) FILTER (WHERE (a%2)=0) OVER w FROM t5
WINDOW w AS (ORDER BY a)
} {1 {} 2 2 3 2 4 4 5 4}
finish_test