mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Add support for chaining of WINDOW definitions.
FossilOrigin-Name: c155125fd5dddb438c09d40f5137c47d88defb7a6ede4261f09d7bdaad250d37
This commit is contained in:
27
manifest
27
manifest
@ -1,5 +1,5 @@
|
||||
C Improved\soversized\scell\sdetection\swhen\supdating\sptrmap\spages\sin\nbalance_nonroot().
|
||||
D 2019-02-14T15:27:12.650
|
||||
C Add\ssupport\sfor\schaining\sof\sWINDOW\sdefinitions.
|
||||
D 2019-02-16T17:27:51.404
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in 178d8eb6840771149cee40b322d1b3be30d330198c522c903c1b66fb5a1bfca4
|
||||
@ -503,7 +503,7 @@ F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 38022624ac9fba1f601d3068d7c393fcc909727fccab556242c93d9c7897b640
|
||||
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
|
||||
F src/parse.y 741a270b7f2f85bc5d026d06fb5a9ccba5335304ff2831e1cb44b36cd0da6006
|
||||
F src/parse.y deae85a1917e53e8533e7eed55ffb4405e2e375c022afb1cc3fecb280ee5cd7a
|
||||
F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
|
||||
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
|
||||
F src/pcache1.c a72804486dfa8e4b6bc30d666c97ecf1155f91a4351fc6e48ea4097e4eb304fb
|
||||
@ -519,7 +519,7 @@ F src/shell.c.in f2c1adbee3f6f36686b4a38d2168ebfc25298b4ad1e6d95199fc4e95b539251
|
||||
F src/sqlite.h.in 7da74fd5bd7a9dbe92297060f036935520b26e240457287c5e67c7b9db51a986
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
|
||||
F src/sqliteInt.h 8628c582eafa5ca93523cdaa7c45b2f38a11132e419c7923850706da7fa36bc2
|
||||
F src/sqliteInt.h f44de7fea38d4fd03ee8db7f851f2727b701d4ec3fc21a8335e8d3888dda7176
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
@ -603,7 +603,7 @@ F src/where.c 8a207cb2ca6b99e1edb1e4bbff9b0504385a759cbf66180d1deb34d80ca4b799
|
||||
F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88
|
||||
F src/wherecode.c a571d8d7c19d6db786a201f2df8788b320fefcb2842f2a1eb9a85b85e91bc35f
|
||||
F src/whereexpr.c 36b47f7261d6b6f1a72d774c113b74beddf6745aba1018e64b196e29db233442
|
||||
F src/window.c df2456386e0b1553a8d1fcf3a0ddc4c058fe2c650ea8c74b6bf8862082ddafc9
|
||||
F src/window.c a96e58c91e77690726512e1dc5de2f95ece975097171e8554a9e8dbd3cdfb0d9
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@ -1675,11 +1675,11 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/window1.test 2798c8249e0f122c9bacce6aa7324765a5cd9106e49e7aacc81f6033d281577b
|
||||
F test/window1.test 4d98700cf287144be87942b587431fed6d0a262ba8ee72fae7ee860ca9ea5282
|
||||
F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
|
||||
F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
|
||||
F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823
|
||||
F test/window3.test e274b7f8952ca4ed25996e0e45c047192b066e0aaff2a822d4293c8c4f1d8d98
|
||||
F test/window3.tcl 3bf7fc5b86024f47bb5834efc90015c9a64f57d696b82e26a1a4b648b7cd058a
|
||||
F test/window3.test ee56c741e934a0b872fffd7de99f137f9c7788d50885f99f54da4075d951e8ee
|
||||
F test/window4.tcl 511425f6b0abf9b953df54cc9c7295cc7c25d78f4ed6f7a74b094eec0120eccb
|
||||
F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c191a62
|
||||
F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e
|
||||
@ -1804,7 +1804,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 167b91df77fff1a84791f6ab5f72239b90475475be690a838248119b6dd312f0
|
||||
R 5fce60e5e60143c7168638176073d3e9
|
||||
U drh
|
||||
Z 1127274df05b3c005a32360404b93266
|
||||
P aa61435a4c3800f023788081c1342ad6a05a41449a424fa6c039d5ca46072256
|
||||
R f8f3f55ce4dbb9bcc0042a3bde2239b1
|
||||
T *branch * window-functions
|
||||
T *sym-window-functions *
|
||||
T -sym-trunk *
|
||||
U dan
|
||||
Z b3b312efff88db643f5cb6a825d2a2ac
|
||||
|
@ -1 +1 @@
|
||||
aa61435a4c3800f023788081c1342ad6a05a41449a424fa6c039d5ca46072256
|
||||
c155125fd5dddb438c09d40f5137c47d88defb7a6ede4261f09d7bdaad250d37
|
31
src/parse.y
31
src/parse.y
@ -1633,13 +1633,14 @@ wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
|
||||
windowdefn_list(A) ::= windowdefn(Z). { A = Z; }
|
||||
windowdefn_list(A) ::= windowdefn_list(Y) COMMA windowdefn(Z). {
|
||||
assert( Z!=0 );
|
||||
sqlite3WindowChain(pParse, Z, Y);
|
||||
Z->pNextWin = Y;
|
||||
A = Z;
|
||||
}
|
||||
|
||||
%type windowdefn {Window*}
|
||||
%destructor windowdefn {sqlite3WindowDelete(pParse->db, $$);}
|
||||
windowdefn(A) ::= nm(X) AS window(Y). {
|
||||
windowdefn(A) ::= nm(X) AS LP window(Y) RP. {
|
||||
if( ALWAYS(Y) ){
|
||||
Y->zName = sqlite3DbStrNDup(pParse->db, X.z, X.n);
|
||||
}
|
||||
@ -1667,19 +1668,27 @@ windowdefn(A) ::= nm(X) AS window(Y). {
|
||||
%type frame_bound_e {struct FrameBound}
|
||||
%destructor frame_bound_e {sqlite3ExprDelete(pParse->db, $$.pExpr);}
|
||||
|
||||
window(A) ::= LP part_opt(X) orderby_opt(Y) frame_opt(Z) RP. {
|
||||
window(A) ::= PARTITION BY nexprlist(X) orderby_opt(Y) frame_opt(Z). {
|
||||
A = sqlite3WindowAssemble(pParse, Z, X, Y, 0);
|
||||
}
|
||||
window(A) ::= nm(W) PARTITION BY nexprlist(X) orderby_opt(Y) frame_opt(Z). {
|
||||
A = sqlite3WindowAssemble(pParse, Z, X, Y, &W);
|
||||
}
|
||||
window(A) ::= ORDER BY sortlist(Y) frame_opt(Z). {
|
||||
A = sqlite3WindowAssemble(pParse, Z, 0, Y, 0);
|
||||
}
|
||||
window(A) ::= nm(W) ORDER BY sortlist(Y) frame_opt(Z). {
|
||||
A = sqlite3WindowAssemble(pParse, Z, 0, Y, &W);
|
||||
}
|
||||
window(A) ::= frame_opt(Z). {
|
||||
A = Z;
|
||||
if( ALWAYS(A) ){
|
||||
A->pPartition = X;
|
||||
A->pOrderBy = Y;
|
||||
}
|
||||
}
|
||||
window(A) ::= nm(W) frame_opt(Z). {
|
||||
A = sqlite3WindowAssemble(pParse, Z, 0, 0, &W);
|
||||
}
|
||||
|
||||
part_opt(A) ::= PARTITION BY nexprlist(X). { A = X; }
|
||||
part_opt(A) ::= . { A = 0; }
|
||||
|
||||
frame_opt(A) ::= . {
|
||||
A = sqlite3WindowAlloc(pParse, TK_RANGE, TK_UNBOUNDED, 0, TK_CURRENT, 0);
|
||||
A = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0);
|
||||
}
|
||||
frame_opt(A) ::= range_or_rows(X) frame_bound_s(Y). {
|
||||
A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, TK_CURRENT, 0);
|
||||
@ -1707,7 +1716,7 @@ window_clause(A) ::= WINDOW windowdefn_list(B). { A = B; }
|
||||
|
||||
%type over_clause {Window*}
|
||||
%destructor over_clause {sqlite3WindowDelete(pParse->db, $$);}
|
||||
over_clause(A) ::= filter_opt(W) OVER window(Z). {
|
||||
over_clause(A) ::= filter_opt(W) OVER LP window(Z) RP. {
|
||||
A = Z;
|
||||
assert( A!=0 );
|
||||
A->pFilter = W;
|
||||
|
@ -3555,11 +3555,13 @@ struct TreeView {
|
||||
*/
|
||||
struct Window {
|
||||
char *zName; /* Name of window (may be NULL) */
|
||||
char *zBase; /* Name of base window for chaining (may be NULL) */
|
||||
ExprList *pPartition; /* PARTITION BY clause */
|
||||
ExprList *pOrderBy; /* ORDER BY clause */
|
||||
u8 eType; /* TK_RANGE or TK_ROWS */
|
||||
u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
|
||||
u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
|
||||
u8 bImplicitFrame; /* True if frame was implicitly specified */
|
||||
Expr *pStart; /* Expression for "<expr> PRECEDING" */
|
||||
Expr *pEnd; /* Expression for "<expr> FOLLOWING" */
|
||||
Window *pNextWin; /* Next window function belonging to this SELECT */
|
||||
@ -3591,6 +3593,8 @@ void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
|
||||
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
|
||||
Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
|
||||
void sqlite3WindowFunctions(void);
|
||||
void sqlite3WindowChain(Parse*, Window*, Window*);
|
||||
Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
|
||||
#else
|
||||
# define sqlite3WindowDelete(a,b)
|
||||
# define sqlite3WindowFunctions()
|
||||
|
95
src/window.c
95
src/window.c
@ -512,6 +512,17 @@ void sqlite3WindowFunctions(void){
|
||||
sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs));
|
||||
}
|
||||
|
||||
static Window *windowFind(Parse *pParse, Window *pList, const char *zName){
|
||||
Window *p;
|
||||
for(p=pList; p; p=p->pNextWin){
|
||||
if( sqlite3StrICmp(p->zName, zName)==0 ) break;
|
||||
}
|
||||
if( p==0 ){
|
||||
sqlite3ErrorMsg(pParse, "no such window: %s", zName);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called immediately after resolving the function name
|
||||
** for a window function within a SELECT statement. Argument pList is a
|
||||
@ -536,14 +547,8 @@ void sqlite3WindowUpdate(
|
||||
FuncDef *pFunc /* Window function definition */
|
||||
){
|
||||
if( pWin->zName && pWin->eType==0 ){
|
||||
Window *p;
|
||||
for(p=pList; p; p=p->pNextWin){
|
||||
if( sqlite3StrICmp(p->zName, pWin->zName)==0 ) break;
|
||||
}
|
||||
if( p==0 ){
|
||||
sqlite3ErrorMsg(pParse, "no such window: %s", pWin->zName);
|
||||
return;
|
||||
}
|
||||
Window *p = windowFind(pParse, pList, pWin->zName);
|
||||
if( p==0 ) return;
|
||||
pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0);
|
||||
pWin->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy, 0);
|
||||
pWin->pStart = sqlite3ExprDup(pParse->db, p->pStart, 0);
|
||||
@ -551,6 +556,8 @@ void sqlite3WindowUpdate(
|
||||
pWin->eStart = p->eStart;
|
||||
pWin->eEnd = p->eEnd;
|
||||
pWin->eType = p->eType;
|
||||
}else{
|
||||
sqlite3WindowChain(pParse, pWin, pList);
|
||||
}
|
||||
if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){
|
||||
sqlite3 *db = pParse->db;
|
||||
@ -856,6 +863,7 @@ void sqlite3WindowDelete(sqlite3 *db, Window *p){
|
||||
sqlite3ExprDelete(db, p->pEnd);
|
||||
sqlite3ExprDelete(db, p->pStart);
|
||||
sqlite3DbFree(db, p->zName);
|
||||
sqlite3DbFree(db, p->zBase);
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
}
|
||||
@ -899,9 +907,10 @@ Window *sqlite3WindowAlloc(
|
||||
Expr *pEnd /* End window size if TK_FOLLOWING or PRECEDING */
|
||||
){
|
||||
Window *pWin = 0;
|
||||
int bImplicitFrame = 0;
|
||||
|
||||
/* Parser assures the following: */
|
||||
assert( eType==TK_RANGE || eType==TK_ROWS );
|
||||
assert( eType==0 || eType==TK_RANGE || eType==TK_ROWS );
|
||||
assert( eStart==TK_CURRENT || eStart==TK_PRECEDING
|
||||
|| eStart==TK_UNBOUNDED || eStart==TK_FOLLOWING );
|
||||
assert( eEnd==TK_CURRENT || eEnd==TK_FOLLOWING
|
||||
@ -909,6 +918,10 @@ Window *sqlite3WindowAlloc(
|
||||
assert( (eStart==TK_PRECEDING || eStart==TK_FOLLOWING)==(pStart!=0) );
|
||||
assert( (eEnd==TK_FOLLOWING || eEnd==TK_PRECEDING)==(pEnd!=0) );
|
||||
|
||||
if( eType==0 ){
|
||||
bImplicitFrame = 1;
|
||||
eType = TK_RANGE;
|
||||
}
|
||||
|
||||
/* If a frame is declared "RANGE" (not "ROWS"), then it may not use
|
||||
** either "<expr> PRECEDING" or "<expr> FOLLOWING".
|
||||
@ -944,6 +957,7 @@ Window *sqlite3WindowAlloc(
|
||||
pWin->eType = eType;
|
||||
pWin->eStart = eStart;
|
||||
pWin->eEnd = eEnd;
|
||||
pWin->bImplicitFrame = bImplicitFrame;
|
||||
pWin->pEnd = sqlite3WindowOffsetExpr(pParse, pEnd);
|
||||
pWin->pStart = sqlite3WindowOffsetExpr(pParse, pStart);
|
||||
return pWin;
|
||||
@ -954,6 +968,69 @@ windowAllocErr:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attach PARTITION and ORDER BY clauses pPartition and pOrderBy to window
|
||||
** pWin. Also, if parameter pBase is not NULL, set pWin->zBase to the
|
||||
** equivalent nul-terminated string.
|
||||
*/
|
||||
Window *sqlite3WindowAssemble(
|
||||
Parse *pParse,
|
||||
Window *pWin,
|
||||
ExprList *pPartition,
|
||||
ExprList *pOrderBy,
|
||||
Token *pBase
|
||||
){
|
||||
if( pWin ){
|
||||
pWin->pPartition = pPartition;
|
||||
pWin->pOrderBy = pOrderBy;
|
||||
if( pBase ){
|
||||
pWin->zBase = sqlite3DbStrNDup(pParse->db, pBase->z, pBase->n);
|
||||
}
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, pPartition);
|
||||
sqlite3ExprListDelete(pParse->db, pOrderBy);
|
||||
}
|
||||
return pWin;
|
||||
}
|
||||
|
||||
/*
|
||||
** Window *pWin has just been created from a WINDOW clause. Tokne pBase
|
||||
** is the base window. Earlier windows from the same WINDOW clause are
|
||||
** stored in the linked list starting at pWin->pNextWin. This function
|
||||
** either updates *pWin according to the base specification, or else
|
||||
** leaves an error in pParse.
|
||||
*/
|
||||
void sqlite3WindowChain(Parse *pParse, Window *pWin, Window *pList){
|
||||
if( pWin->zBase ){
|
||||
sqlite3 *db = pParse->db;
|
||||
Window *pExist = windowFind(pParse, pList, pWin->zBase);
|
||||
if( pExist ){
|
||||
const char *zErr = 0;
|
||||
/* Check for errors */
|
||||
if( pWin->pPartition ){
|
||||
zErr = "PARTITION clause";
|
||||
}else if( pExist->pOrderBy && pWin->pOrderBy ){
|
||||
zErr = "ORDER BY clause";
|
||||
}else if( pExist->bImplicitFrame==0 ){
|
||||
zErr = "frame specification";
|
||||
}
|
||||
if( zErr ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"cannot override %s of window: %s", zErr, pWin->zBase
|
||||
);
|
||||
}else{
|
||||
pWin->pPartition = sqlite3ExprListDup(db, pExist->pPartition, 0);
|
||||
if( pExist->pOrderBy ){
|
||||
assert( pWin->pOrderBy==0 );
|
||||
pWin->pOrderBy = sqlite3ExprListDup(db, pExist->pOrderBy, 0);
|
||||
}
|
||||
sqlite3DbFree(db, pWin->zBase);
|
||||
pWin->zBase = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Attach window object pWin to expression p.
|
||||
*/
|
||||
|
@ -700,5 +700,106 @@ do_execsql_test 16.2 {
|
||||
3 101
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test error cases from chaining window definitions.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 17.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER);
|
||||
INSERT INTO t1 VALUES(1, 'odd', 'one', 1);
|
||||
INSERT INTO t1 VALUES(2, 'even', 'two', 2);
|
||||
INSERT INTO t1 VALUES(3, 'odd', 'three', 3);
|
||||
INSERT INTO t1 VALUES(4, 'even', 'four', 4);
|
||||
INSERT INTO t1 VALUES(5, 'odd', 'five', 5);
|
||||
INSERT INTO t1 VALUES(6, 'even', 'six', 6);
|
||||
}
|
||||
|
||||
foreach {tn sql error} {
|
||||
1 {
|
||||
SELECT c, sum(d) OVER win2 FROM t1
|
||||
WINDOW win1 AS (ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING),
|
||||
win2 AS (win1 ORDER BY b)
|
||||
} {cannot override frame specification of window: win1}
|
||||
|
||||
2 {
|
||||
SELECT c, sum(d) OVER win2 FROM t1
|
||||
WINDOW win1 AS (),
|
||||
win2 AS (win4 ORDER BY b)
|
||||
} {no such window: win4}
|
||||
|
||||
3 {
|
||||
SELECT c, sum(d) OVER win2 FROM t1
|
||||
WINDOW win1 AS (),
|
||||
win2 AS (win1 PARTITION BY d)
|
||||
} {cannot override PARTITION clause of window: win1}
|
||||
|
||||
4 {
|
||||
SELECT c, sum(d) OVER win2 FROM t1
|
||||
WINDOW win1 AS (ORDER BY b),
|
||||
win2 AS (win1 ORDER BY d)
|
||||
} {cannot override ORDER BY clause of window: win1}
|
||||
} {
|
||||
do_catchsql_test 17.1.$tn $sql [list 1 $error]
|
||||
}
|
||||
|
||||
foreach {tn sql error} {
|
||||
1 {
|
||||
SELECT c, sum(d) OVER (win1 ORDER BY b) FROM t1
|
||||
WINDOW win1 AS (ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
|
||||
} {cannot override frame specification of window: win1}
|
||||
|
||||
2 {
|
||||
SELECT c, sum(d) OVER (win4 ORDER BY b) FROM t1
|
||||
WINDOW win1 AS ()
|
||||
} {no such window: win4}
|
||||
|
||||
3 {
|
||||
SELECT c, sum(d) OVER (win1 PARTITION BY d) FROM t1
|
||||
WINDOW win1 AS ()
|
||||
} {cannot override PARTITION clause of window: win1}
|
||||
|
||||
4 {
|
||||
SELECT c, sum(d) OVER (win1 ORDER BY d) FROM t1
|
||||
WINDOW win1 AS (ORDER BY b)
|
||||
} {cannot override ORDER BY clause of window: win1}
|
||||
} {
|
||||
do_catchsql_test 17.2.$tn $sql [list 1 $error]
|
||||
}
|
||||
|
||||
do_execsql_test 17.3.1 {
|
||||
SELECT group_concat(c, '.') OVER (PARTITION BY b ORDER BY c)
|
||||
FROM t1
|
||||
} {four four.six four.six.two five five.one five.one.three}
|
||||
|
||||
do_execsql_test 17.3.2 {
|
||||
SELECT group_concat(c, '.') OVER (win1 ORDER BY c)
|
||||
FROM t1
|
||||
WINDOW win1 AS (PARTITION BY b)
|
||||
} {four four.six four.six.two five five.one five.one.three}
|
||||
|
||||
do_execsql_test 17.3.3 {
|
||||
SELECT group_concat(c, '.') OVER win2
|
||||
FROM t1
|
||||
WINDOW win1 AS (PARTITION BY b),
|
||||
win2 AS (win1 ORDER BY c)
|
||||
} {four four.six four.six.two five five.one five.one.three}
|
||||
|
||||
do_execsql_test 17.3.4 {
|
||||
SELECT group_concat(c, '.') OVER (win2)
|
||||
FROM t1
|
||||
WINDOW win1 AS (PARTITION BY b),
|
||||
win2 AS (win1 ORDER BY c)
|
||||
} {four four.six four.six.two five five.one five.one.three}
|
||||
|
||||
do_execsql_test 17.3.5 {
|
||||
SELECT group_concat(c, '.') OVER win5
|
||||
FROM t1
|
||||
WINDOW win1 AS (PARTITION BY b),
|
||||
win2 AS (win1),
|
||||
win3 AS (win2),
|
||||
win4 AS (win3),
|
||||
win5 AS (win4 ORDER BY c)
|
||||
} {four four.six four.six.two five five.one five.one.three}
|
||||
|
||||
finish_test
|
||||
|
@ -21,7 +21,6 @@ execsql_test 1.0 {
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER);
|
||||
INSERT INTO t2(a, b) VALUES
|
||||
(1,0), (2,74), (3,41), (4,74), (5,23), (6,99), (7,26), (8,33), (9,2),
|
||||
(10,89), (11,81), (12,96), (13,59), (14,38), (15,68), (16,39), (17,62),
|
||||
(18,91), (19,46), (20,6), (21,99), (22,97), (23,27), (24,46), (25,78),
|
||||
(26,54), (27,97), (28,8), (29,67), (30,29), (31,93), (32,84), (33,77),
|
||||
@ -307,6 +306,28 @@ foreach {tn window} {
|
||||
SELECT string_agg(CAST(b AS TEXT), '.') OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2
|
||||
"
|
||||
|
||||
execsql_test 1.$tn.14.7 "
|
||||
SELECT string_agg(CAST(b AS TEXT), '.') OVER (win1 ORDER BY b%10 $window)
|
||||
FROM t2
|
||||
WINDOW win1 AS (PARTITION BY b%2,a)
|
||||
ORDER BY 1
|
||||
"
|
||||
|
||||
execsql_test 1.$tn.14.8 "
|
||||
SELECT string_agg(CAST(b AS TEXT), '.') OVER (win1 $window)
|
||||
FROM t2
|
||||
WINDOW win1 AS (PARTITION BY b%2,a ORDER BY b%10)
|
||||
ORDER BY 1
|
||||
"
|
||||
|
||||
execsql_test 1.$tn.14.9 "
|
||||
SELECT string_agg(CAST(b AS TEXT), '.') OVER win2
|
||||
FROM t2
|
||||
WINDOW win1 AS (PARTITION BY b%2,a ORDER BY b%10),
|
||||
win2 AS (win1 $window)
|
||||
ORDER BY 1
|
||||
"
|
||||
|
||||
execsql_test 1.$tn.15.1 "
|
||||
SELECT count(*) OVER win, string_agg(CAST(b AS TEXT), '.')
|
||||
FILTER (WHERE a%2=0) OVER win FROM t2
|
||||
|
2997
test/window3.test
2997
test/window3.test
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user