]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix another issue to do with window-functions in aggregate queries.
authordan <dan@noemail.net>
Tue, 12 Jun 2018 20:53:38 +0000 (20:53 +0000)
committerdan <dan@noemail.net>
Tue, 12 Jun 2018 20:53:38 +0000 (20:53 +0000)
FossilOrigin-Name: 6413e38a174044c28fa9b8b937e6c972d144547a246e6f2882e782538300d042

manifest
manifest.uuid
src/btree.c
src/window.c
test/window4.tcl
test/window4.test

index 7cc7cd4f7fe70f40f0bf4034810b702b88bbbc29..27851dacfd500eb814dbe1b3d3f57fa48e6788ec 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\ssome\sproblems\swith\susing\swindow-functions\sin\saggregate\squeries.
-D 2018-06-12T18:40:17.751
+C Fix\sanother\sissue\sto\sdo\swith\swindow-functions\sin\saggregate\squeries.
+D 2018-06-12T20:53:38.832
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 498b77b89a8cb42f2ee20fcd6317f279a45c0d6ff40d27825f94b69884c09bbe
@@ -436,7 +436,7 @@ F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8
 F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c 671207d68ac2fb32c782f9b65cd6f8a861757044b1448098cb08fab4fcf02947
+F src/btree.c 50425f7f26b10919bd14fa1af534b92c339bf7aac4b1ac8c70404f4e6f8220d8
 F src/btree.h 7b557914561f60a0eb76c2e22c23ab5b82f87b734a91c1b9385654b6474fdf7f
 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
 F src/build.c 3b3bfa88800739e1f11313dcecfba5ef8e4757b6c929cdf7de9fcfc01002b81f
@@ -583,7 +583,7 @@ F src/where.c fe1a6f97c12cc9472ccce86166ba3f827cf61d6ae770c036a6396b63863baac4
 F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
 F src/wherecode.c 3317f2b083a66d3e65a03edf316ade4ccb0a99c9956273282ebb579b95d4ba96
 F src/whereexpr.c 6f022d6cc9daf56495f191b199352f783aff5cf268ba136b4d8cea3fb62d8c7d
-F src/window.c 5fc1e9a4367bdd6c5afd318a36ec0b1f702fa1e3384621501873ec6b3e94651a
+F src/window.c 45d149fe9926b7e9c610ef5234b6eef08f22cbdff855aa3f367b6af17499e90b
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
 F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -1622,8 +1622,8 @@ F test/window2.tcl 0983de5eade5eeda49469244799d5331bfe3199fca3f6c6d2a836aa08f4fb
 F test/window2.test 79747b2edde4ad424e0752b27529aedc86e91f3d8d88846fa17ff0cb67f65086
 F test/window3.tcl 654d61d73e10db089b22514d498bb23ec310f720c0f4b5f69f67fda83d672048
 F test/window3.test 41727668ee31d2ba50f78efcb5bf1bda2c5cffd889aa65243511004669d1ac25
-F test/window4.tcl e64db87bac34d9a726f2b97c40f4adbfc21650a26b7015b18f357062266a0062
-F test/window4.test 36df9adf8b305b427fee8c9604a958e8fecb85c2ba21f6819ad3e87610253001
+F test/window4.tcl a77a7ab3c60517abe06307e4204d65d11f5474c8062f30f536755dd083bf8224
+F test/window4.test 0fb98450ff5478f91b4f8c9440d4463ded30a7337029da4272894ccff0f227e2
 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 0cd55e98a478740032f5569ddc00fa5b0e063e90db6e00ac7598c9b7c2fffeee
-R a9e6944f8f988df57ad1f0cd1beda118
+P fe7081e0952950f577234fcbb58f3c1efa4579267654fd2f713dc4804e470e7e
+R 7cbc79b684a204310b1cd3eb56d614ea
 U dan
-Z e98e199ae454a383acf0272ef0289805
+Z 4b5b4b6d9afcbd2c7bfd885559718021
index 1fb6535a25091e4b07b27712d53244e90aecc9b9..5adea5b5a2a61219c972d20ea419cadcbe4f20f9 100644 (file)
@@ -1 +1 @@
-fe7081e0952950f577234fcbb58f3c1efa4579267654fd2f713dc4804e470e7e
\ No newline at end of file
+6413e38a174044c28fa9b8b937e6c972d144547a246e6f2882e782538300d042
\ No newline at end of file
index 0e0d0431044bb91206d1b3a40317c476e88c8456..35e13478b6d959a2bfbd68d231e1d7ba4b112789 100644 (file)
@@ -5185,6 +5185,11 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
   return rc;
 }
 
+/*
+** This function is a no-op if cursor pCur does not point to a valid row.
+** Otherwise, if pCur is valid, configure it so that the next call to
+** sqlite3BtreeNext() is a no-op.
+*/
 void sqlite3BtreeSkipNext(BtCursor *pCur){
   if( pCur->eState==CURSOR_VALID ){
     pCur->eState = CURSOR_SKIPNEXT;
index 6d66fb82d7daba67a62748bee00660d21cbaa5c5..de3b778226f3c4b4eaf8884c469e398404d10165 100644 (file)
 **     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
 **
 **   See sqlite3WindowUpdate() for details.
+**
+**   As well as some of the built-in window functions, aggregate window
+**   functions min() and max() are implemented using VDBE instructions if
+**   the start of the window frame is declared as anything other than 
+**   UNBOUNDED PRECEDING.
 */
 
 /*
@@ -471,11 +476,28 @@ void sqlite3WindowFunctions(void){
   sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs));
 }
 
+/*
+** This function is called immediately after resolving the function name
+** for a window function within a SELECT statement. Argument pList is a
+** linked list of WINDOW definitions for the current SELECT statement.
+** Argument pFunc is the function definition just resolved and pWin
+** is the Window object representing the associated OVER clause. This
+** function updates the contents of pWin as follows:
+**
+**   * If the OVER clause refered to a named window (as in "max(x) OVER win"),
+**     search list pList for a matching WINDOW definition, and update pWin
+**     accordingly. If no such WINDOW clause can be found, leave an error
+**     in pParse.
+**
+**   * If the function is a built-in window function that requires the
+**     window to be coerced (see "BUILT-IN WINDOW FUNCTIONS" at the top
+**     of this file), pWin is updated here.
+*/
 void sqlite3WindowUpdate(
   Parse *pParse, 
-  Window *pList, 
-  Window *pWin, 
-  FuncDef *pFunc
+  Window *pList,                  /* List of named windows for this SELECT */
+  Window *pWin,                   /* Window frame to update */
+  FuncDef *pFunc                  /* Window function definition */
 ){
   if( pWin->zName ){
     Window *p;
@@ -523,16 +545,21 @@ void sqlite3WindowUpdate(
   pWin->pFunc = pFunc;
 }
 
+/*
+** Context object passed through sqlite3WalkExprList() to
+** selectWindowRewriteExprCb() by selectWindowRewriteEList().
+*/
 typedef struct WindowRewrite WindowRewrite;
 struct WindowRewrite {
   Window *pWin;
   ExprList *pSub;
 };
 
-static int selectWindowRewriteSelectCb(Walker *pWalker, Select *pSelect){
-  return WRC_Prune;
-}
-
+/*
+** Callback function used by selectWindowRewriteEList(). If necessary,
+** this function appends to the output expression-list and updates 
+** expression (*ppExpr) in place.
+*/
 static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
   struct WindowRewrite *p = pWalker->u.pRewrite;
   Parse *pParse = pWalker->pParse;
@@ -578,7 +605,24 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
 
   return WRC_Continue;
 }
+static int selectWindowRewriteSelectCb(Walker *pWalker, Select *pSelect){
+  return WRC_Prune;
+}
+
 
+/*
+** Iterate through each expression in expression-list pEList. For each:
+**
+**   * TK_COLUMN,
+**   * aggregate function, or
+**   * window function with a Window object that is not a member of the 
+**     linked list passed as the second argument (pWin)
+**
+** Append the node to output expression-list (*ppSub). And replace it
+** with a TK_COLUMN that reads the (N-1)th element of table 
+** pWin->iEphCsr, where N is the number of elements in (*ppSub) after
+** appending the new one.
+*/
 static int selectWindowRewriteEList(
   Parse *pParse, 
   Window *pWin,
@@ -606,6 +650,10 @@ static int selectWindowRewriteEList(
   return rc;
 }
 
+/*
+** Append a copy of each expression in expression-list pAppend to
+** expression list pList. Return a pointer to the result list.
+*/
 static ExprList *exprListAppendList(
   Parse *pParse,          /* Parsing context */
   ExprList *pList,        /* List to which to append. Might be NULL */
@@ -627,21 +675,8 @@ static ExprList *exprListAppendList(
 ** If the SELECT statement passed as the second argument does not invoke
 ** any SQL window functions, this function is a no-op. Otherwise, it 
 ** rewrites the SELECT statement so that window function xStep functions
-** are invoked in the correct order. The simplest version of the 
-** transformation is:
-**
-**   SELECT win(args...) OVER (<list1>) FROM <src> ORDER BY <list2>
-**
-** to
-**
-**   SELECT win(args...) FROM (
-**     SELECT args... FROM <src> ORDER BY <list1>
-**   ) ORDER BY <list2>
-**
-** where <src> may contain WHERE, GROUP BY and HAVING clauses, and <list1>
-** is the concatenation of the PARTITION BY and ORDER BY clauses in the
-** OVER clause.
-**
+** are invoked in the correct order as described under "SELECT REWRITING"
+** at the top of this file.
 */
 int sqlite3WindowRewrite(Parse *pParse, Select *p){
   int rc = SQLITE_OK;
@@ -726,6 +761,9 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
   return rc;
 }
 
+/*
+** Free the Window object passed as the second argument.
+*/
 void sqlite3WindowDelete(sqlite3 *db, Window *p){
   if( p ){
     sqlite3ExprDelete(db, p->pFilter);
@@ -738,6 +776,9 @@ void sqlite3WindowDelete(sqlite3 *db, Window *p){
   }
 }
 
+/*
+** Free the linked list of Window objects starting at the second argument.
+*/
 void sqlite3WindowListDelete(sqlite3 *db, Window *p){
   while( p ){
     Window *pNext = p->pNextWin;
@@ -746,6 +787,9 @@ void sqlite3WindowListDelete(sqlite3 *db, Window *p){
   }
 }
 
+/*
+** Allocate and return a new Window object.
+*/
 Window *sqlite3WindowAlloc(
   Parse *pParse, 
   int eType,
@@ -768,6 +812,9 @@ Window *sqlite3WindowAlloc(
   return pWin;
 }
 
+/*
+** Attach window object pWin to expression p.
+*/
 void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
   if( p ){
     p->pWin = pWin;
index c0eb2b7abb8b26b25f40cd223a3ec13275283290..fcb6e612125f9281a014a182c43ec8b1c2d17def 100644 (file)
@@ -149,6 +149,14 @@ execsql_test 4.1 {
   SELECT max(c), max(b) OVER (ORDER BY b) FROM ttt GROUP BY b;
 }
 
+execsql_test 4.2 {
+  SELECT max(b) OVER (ORDER BY max(c)) FROM ttt GROUP BY b;
+}
+
+execsql_test 4.3 {
+  SELECT abs(max(b) OVER (ORDER BY b)) FROM ttt GROUP BY b;
+}
+
 
 finish_test
 
index 307465e843370602c4d476306c2ba1b48711b8f8..f29bce75256a22174b40c4e830da5fa5bda04c3a 100644 (file)
@@ -231,4 +231,12 @@ do_execsql_test 4.1 {
   SELECT max(c), max(b) OVER (ORDER BY b) FROM ttt GROUP BY b;
 } {3 1   4 2   5 3}
 
+do_execsql_test 4.2 {
+  SELECT max(b) OVER (ORDER BY max(c)) FROM ttt GROUP BY b;
+} {1   2   3}
+
+do_execsql_test 4.3 {
+  SELECT abs(max(b) OVER (ORDER BY b)) FROM ttt GROUP BY b;
+} {1   2   3}
+
 finish_test