-C Do\snot\sflatten\ssub-queries\sthat\scontain\swindow\sfunctions.
-D 2018-06-08T16:11:55.013
+C Add\ssupport\sfor\sthe\sWINDOW\sclause.
+D 2018-06-08T20:58:27.833
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f
-F src/expr.c 587b4bc88f2b3b77563166e9058c191098c91f28770a40240d96c0ca74fcd050
+F src/expr.c d6db67ebe0597f87381827513ae168b202956fca35add953e294afc80fa41675
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c b1da9ef8dc834603bb0d28972378a7ce65897847f9a1e89ab800bbdf24c788ee
-F src/func.c 3e8a85f9bfc9117964523a5e17bdbc4b0b9d707830871cbc1dc44b9b538d5d82
+F src/func.c a5ee3864264edea8fea4d2dfdf8296250cff9139343953da78d82837241659a9
F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f
F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388
-F src/parse.y 9eaa457cff322e0dd5f52e363eab0b73f11bcd35bdced58274dead597e1a3d6a
+F src/parse.y 788f41e7558278423931dd0fdb1a4fb4657f451371d2f2c4b1d11824484c419f
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
F src/prepare.c e966ecc97c3671ff0e96227c8c877b83f2d33ea371ee190bbf1698b36b5605c0
F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c 172f4c514b41dabc00cf5ada72f6de6f897881d50de5fd33a94f3d1e5c36dafc
+F src/resolve.c da9b85ec0e1a05384134cece5747a90b8da1fc5750f4705c7812d2294ca20cec
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
-F src/select.c d48879c0a2acb79ed0db384074caef9002902765f2b35a74a7b8f403332f4b1a
+F src/select.c 0b0ce29bd7b8a7232e6f7602ddb447caa954a1fc476ff5e23ce1e5aaa6a0e0ed
F src/shell.c.in 4d0ddf10c403710d241bf920163dcf032c21119aebb61e70840942c0eafecdf9
F src/sqlite.h.in 63b07f76731f2b1e55c48fdb9f0508dcc6fbe3971010b8612ffd847c3c56d9a1
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
-F src/sqliteInt.h 72c13b9833611dfcbb62314f96b2c9343e6dfbbe6d156365609fed82ca4d17f0
+F src/sqliteInt.h 8cdd2f8c920cc7de683c27322d2f146079bc36ad267b63eaf9ee186ee58e287f
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/whereInt.h b09753e74bf92a8b17cf0e41ca94c44432c454544be6699b5311dcc57bf229c6
F src/wherecode.c 3317f2b083a66d3e65a03edf316ade4ccb0a99c9956273282ebb579b95d4ba96
F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
-F src/window.c 141a79da0fac93514a4c3f2530e52d22cb74622daf08fb9023668133ad4e285c
+F src/window.c 31bd22def29a71144056ddd2a9c4344648c2b89f63a76e7695defdf7ed293216
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
F test/window2.test 79747b2edde4ad424e0752b27529aedc86e91f3d8d88846fa17ff0cb67f65086
F test/window3.tcl f2596e9d6bf8d4441eb7a0d3272594185c3b56e8d2413a54b12e6e7557517674
F test/window3.test e43a143131e19a27148215431cf7cec8815c32c7ec04f1cf79d068adff9be028
-F test/window4.tcl 9e5698ffb729676b88290a7048ae9bb9b0d31efe0b630e51f9ce796cca737f8c
-F test/window4.test 316bf0844fa4966488b3c9d2e69a360f5b4de87022ca44f5a96a62243d9db796
+F test/window4.tcl 2da10ad7a6eedc584c3faa551ff6d0a7f8cc18dee95416d05af389f88ef0ac1a
+F test/window4.test bef29a267ee9ac7ca421ef69ba37d19f7e93988f1c052cb09cbb946f309c5cbe
F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
-F tool/mkkeywordhash.c dd4d201d646dd4e236b93be17589e89a19b329a8840e559f91db3bdc361f3c39
+F tool/mkkeywordhash.c a0fd254852ac92ddea42ea04d1f41d50298590fc1121a815ddeb18f9b2af4193
F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 17d1ccc05a926e19e3a9679ea3e4d1aaa15ba753e2fa7363e6e81c80e0ef8b86
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 89bbc9ba8f66853a7530453f146c9df1baacd8558468016cefa7602911f7578a
-R dccf8398447f81129241381719cad17d
+P 236cb75bd1f0d5eb86aa5f52d8d548e7263c34633833dcea9dfc934f142113b8
+R 42923cbfbd64d075a9e38b7b4b4b969d
U dan
-Z 5f65d7a3a3ae3236c28a203eff6b68d3
+Z dee7bf2abe4eeccc35a23aee41391161
-236cb75bd1f0d5eb86aa5f52d8d548e7263c34633833dcea9dfc934f142113b8
\ No newline at end of file
+19c983b511f1c823fdfb051713681b4c779f02fa83b41189afca0a9b8b72048d
\ No newline at end of file
pNew->nSelectRow = p->nSelectRow;
pNew->pWith = withDup(db, p->pWith);
pNew->pWin = 0;
+ pNew->pWinDefn = 0; /* TODO!! */
sqlite3SelectSetName(pNew, p->zSelName);
*pp = pNew;
pp = &pNew->pPrior;
if( pAccum ){
sqlite3 *db = sqlite3_context_db_handle(context);
- int firstTerm = pAccum->nChar==0;
+ int firstTerm = pAccum->mxAlloc==0;
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
if( !firstTerm ){
if( argc==2 ){
pAccum->nChar -= n;
memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar);
}
+ if( pAccum->nChar==0 ) pAccum->mxAlloc = 0;
}
}
static void groupConcatFinalize(sqlite3_context *context){
multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP; /*A-overwrites-OP*/}
%endif SQLITE_OMIT_COMPOUND_SELECT
oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y)
- groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
+ groupby_opt(P) having_opt(Q) windowdefn_opt(R)
+ orderby_opt(Z) limit_opt(L). {
#if SELECTTRACE_ENABLED
Token s = S; /*A-overwrites-S*/
#endif
A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L);
+ if( A ) A->pWinDefn = R;
#if SELECTTRACE_ENABLED
/* Populate the Select.zSelName[] string that is used to help with
** query planner debugging, to differentiate between multiple Select
sqlite3ExprAttachSubtrees(pParse->db, A, E, 0);
}
%endif SQLITE_OMIT_CAST
-expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP window(Z). {
+expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP over_opt(Z). {
if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
}
A->flags |= EP_Distinct;
}
}
-expr(A) ::= id(X) LP STAR RP window(Z). {
+expr(A) ::= id(X) LP STAR RP over_opt(Z). {
A = sqlite3ExprFunction(pParse, 0, &X);
sqlite3WindowAttach(pParse, A, Z);
}
A = sqlite3ExprFunction(pParse, 0, &OP);
}
+%type windowdefn_opt {Window*}
+%destructor windowdefn_opt {sqlite3WindowDelete(pParse->db, $$);}
+windowdefn_opt(A) ::= . { A = 0; }
+windowdefn_opt(A) ::= WINDOW windowdefn_list(B). { A = B; }
+
+%type windowdefn_list {Window*}
+%destructor windowdefn_list {sqlite3WindowDelete(pParse->db, $$);}
+windowdefn_list(A) ::= windowdefn(Z). { A = Z; }
+windowdefn_list(A) ::= windowdefn_list(Y) COMMA windowdefn(Z). {
+ if( Z ) Z->pNextWin = Y;
+ A = Z;
+}
+
+%type windowdefn {Window*}
+%destructor windowdefn {sqlite3WindowDelete(pParse->db, $$);}
+windowdefn(A) ::= nm(X) AS window(Y). {
+ if( Y ){
+ Y->zName = sqlite3DbStrNDup(pParse->db, X.z, X.n);
+ }
+ A = Y;
+}
+
+%type over_opt {Window*}
+%destructor over_opt {sqlite3WindowDelete(pParse->db, $$);}
%type window {Window*}
%destructor window {sqlite3WindowDelete(pParse->db, $$);}
%type frame_opt {Window*}
%destructor frame_opt {sqlite3WindowDelete(pParse->db, $$);}
+%type window_or_nm {Window*}
+%destructor window_or_nm {
+sqlite3WindowDelete(pParse->db, $$);}
+
%type part_opt {ExprList*}
%destructor part_opt {sqlite3ExprListDelete(pParse->db, $$);}
%type frame_bound {struct FrameBound}
%destructor frame_bound {sqlite3ExprDelete(pParse->db, $$.pExpr);}
-window(A) ::= . { A = 0; }
-window(A) ::= filter_opt(W) OVER LP part_opt(X) orderby_opt(Y) frame_opt(Z) RP.{
- if( Z ){
- A = Z;
- A->pFilter = W;
+over_opt(A) ::= . { A = 0; }
+over_opt(A) ::= filter_opt(W) OVER window_or_nm(Z). {
+ A = Z;
+ if( A ) A->pFilter = W;
+}
+
+window_or_nm(A) ::= window(Z). {A = Z;}
+window_or_nm(A) ::= nm(Z). {
+ A = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( A ){
+ A->zName = sqlite3DbStrNDup(pParse->db, Z.z, Z.n);
+ }
+}
+
+window(A) ::= LP part_opt(X) orderby_opt(Y) frame_opt(Z) RP. {
+ A = Z;
+ if( A ){
A->pPartition = X;
A->pOrderBy = Y;
}
sqlite3WalkExprList(pWalker, pList);
if( is_agg ){
if( pExpr->pWin ){
- sqlite3WindowUpdate(pParse, pExpr->pWin, pDef);
- if( 0==pNC->pWin
- || 0==sqlite3WindowCompare(pParse, pNC->pWin, pExpr->pWin)
+ Select *pSel = pNC->pWinSelect;
+ sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef);
+ if( 0==pSel->pWin
+ || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin)
){
- pExpr->pWin->pNextWin = pNC->pWin;
- pNC->pWin = pExpr->pWin;
+ pExpr->pWin->pNextWin = pSel->pWin;
+ pSel->pWin = pExpr->pWin;
}
pExpr->pWin->pFunc = pDef;
pExpr->pWin->nArg = (pExpr->x.pList ? pExpr->x.pList->nExpr : 0);
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
+ sNC.pWinSelect = p;
if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){
return WRC_Abort;
}
return WRC_Abort;
}
- p->pWin = sNC.pWin;
- sNC.pWin = 0;
-
/* Advance to the next term of the compound
*/
p = p->pPrior;
sqlite3ExprDelete(db, p->pHaving);
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit);
+ if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
+ sqlite3WindowListDelete(db, p->pWinDefn);
+ }
if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
pNew->pLimit = pLimit;
pNew->pWith = 0;
pNew->pWin = 0;
+ pNew->pWinDefn = 0;
if( pParse->db->mallocFailed ) {
clearSelect(pParse->db, pNew, pNew!=&standin);
pNew = 0;
int nRef; /* Number of names resolved by this context */
int nErr; /* Number of errors encountered while resolving names */
u16 ncFlags; /* Zero or more NC_* flags defined below */
- Window *pWin; /* List of window functions in this context */
+ Select *pWinSelect; /* SELECT statement for any window functions */
};
/*
Expr *pLimit; /* LIMIT expression. NULL means not used. */
With *pWith; /* WITH clause attached to this select. Or NULL. */
Window *pWin; /* List of window functions */
+ Window *pWinDefn; /* List of named window definitions */
};
/*
#endif /* SQLITE_DEBUG */
struct Window {
- Expr *pFilter;
- ExprList *pPartition;
- ExprList *pOrderBy;
+ char *zName; /* Name of window (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 */
Expr *pStart; /* Expression for "<expr> PRECEDING" */
Expr *pEnd; /* Expression for "<expr> FOLLOWING" */
+
Window *pNextWin; /* Next window function belonging to this SELECT */
+
+ Expr *pFilter;
FuncDef *pFunc;
int nArg;
};
void sqlite3WindowDelete(sqlite3*, Window*);
+void sqlite3WindowListDelete(sqlite3 *db, Window *p);
Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*);
void sqlite3WindowAttach(Parse*, Expr*, Window*);
int sqlite3WindowCompare(Parse*, Window*, Window*);
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
int sqlite3WindowRewrite(Parse*, Select*);
int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
-void sqlite3WindowUpdate(Parse*, Window*, FuncDef*);
+void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
Window *sqlite3WindowDup(sqlite3 *db, Window *p);
/*
sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs));
}
-void sqlite3WindowUpdate(Parse *pParse, Window *pWin, FuncDef *pFunc){
+void sqlite3WindowUpdate(
+ Parse *pParse,
+ Window *pList,
+ Window *pWin,
+ FuncDef *pFunc
+){
+ if( pWin->zName ){
+ 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;
+ }
+ pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0);
+ pWin->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy, 0);
+ pWin->pStart = sqlite3ExprDup(pParse->db, p->pStart, 0);
+ pWin->pEnd = sqlite3ExprDup(pParse->db, p->pEnd, 0);
+ pWin->eStart = p->eStart;
+ pWin->eEnd = p->eEnd;
+ }
if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){
sqlite3 *db = pParse->db;
if( pFunc->xSFunc==row_numberStepFunc || pFunc->xSFunc==ntileStepFunc ){
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pEnd);
sqlite3ExprDelete(db, p->pStart);
+ sqlite3DbFree(db, p->zName);
sqlite3DbFree(db, p);
}
}
+void sqlite3WindowListDelete(sqlite3 *db, Window *p){
+ while( p ){
+ Window *pNext = p->pNextWin;
+ sqlite3WindowDelete(db, p);
+ p = pNext;
+ }
+}
+
Window *sqlite3WindowAlloc(
Parse *pParse,
int eType,
SELECT a, nth_value(c, d) OVER (PARTITION BY b ORDER BY a) FROM t5
}
+execsql_test 3.3 {
+ SELECT a, count(*) OVER abc, count(*) OVER def FROM t5
+ WINDOW abc AS (ORDER BY a),
+ def AS (ORDER BY a DESC)
+ ORDER BY a;
+}
+
finish_test
SELECT a, nth_value(c, d) OVER (PARTITION BY b ORDER BY a) FROM t5
} {1 {} 3 {} 5 one 2 {} 4 four}
+do_execsql_test 3.3 {
+ SELECT a, count(*) OVER abc, count(*) OVER def FROM t5
+ WINDOW abc AS (ORDER BY a),
+ def AS (ORDER BY a DESC)
+ ORDER BY a;
+} {1 1 5 2 2 4 3 3 3 4 4 2 5 5 1}
+
finish_test
{ "VALUES", "TK_VALUES", ALWAYS },
{ "VIEW", "TK_VIEW", VIEW },
{ "VIRTUAL", "TK_VIRTUAL", VTAB },
+ { "WINDOW", "TK_WINDOW", ALWAYS },
{ "WITH", "TK_WITH", CTE },
{ "WITHOUT", "TK_WITHOUT", ALWAYS },
{ "WHEN", "TK_WHEN", ALWAYS },