]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Do not flatten sub-queries that contain window functions.
authordan <dan@noemail.net>
Fri, 8 Jun 2018 16:11:55 +0000 (16:11 +0000)
committerdan <dan@noemail.net>
Fri, 8 Jun 2018 16:11:55 +0000 (16:11 +0000)
FossilOrigin-Name: 236cb75bd1f0d5eb86aa5f52d8d548e7263c34633833dcea9dfc934f142113b8

manifest
manifest.uuid
src/expr.c
src/select.c
src/sqliteInt.h
src/window.c
test/window1.test

index 557ebd3719799bffce72d00cf7a5aa1ac66c3e65..5f63042a2b555bd16835627d5cd8a9d03da4d79c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fixes\sto\sallow\sgroup_concat()\sto\sbe\sused\sas\sa\swindow\sfunction.
-D 2018-06-08T11:45:28.408
+C Do\snot\sflatten\ssub-queries\sthat\scontain\swindow\sfunctions.
+D 2018-06-08T16:11:55.013
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
@@ -447,7 +447,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
 F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f
-F src/expr.c 7c8880478dfacabff1c3e405fa11dc37e1e244a81bf6d175faecf36adb705ef0
+F src/expr.c 587b4bc88f2b3b77563166e9058c191098c91f28770a40240d96c0ca74fcd050
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c b1da9ef8dc834603bb0d28972378a7ce65897847f9a1e89ab800bbdf24c788ee
 F src/func.c 3e8a85f9bfc9117964523a5e17bdbc4b0b9d707830871cbc1dc44b9b538d5d82
@@ -495,12 +495,12 @@ F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c 172f4c514b41dabc00cf5ada72f6de6f897881d50de5fd33a94f3d1e5c36dafc
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
-F src/select.c 3e7d9bc70fa6baebd6e34cce5ec79879ff1dd4caec0fd05f45fd87b25e53d2b8
+F src/select.c d48879c0a2acb79ed0db384074caef9002902765f2b35a74a7b8f403332f4b1a
 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 94322676f8b66faaeb21ad9bb2b60585ef72320b8e3c5df6f307a06dd231c62a
+F src/sqliteInt.h 72c13b9833611dfcbb62314f96b2c9343e6dfbbe6d156365609fed82ca4d17f0
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -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 4a476f74f11eb02447fa51ef9465c13d1e888b839441d4aa8c742234df8afb48
+F src/window.c 141a79da0fac93514a4c3f2530e52d22cb74622daf08fb9023668133ad4e285c
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
 F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -1617,7 +1617,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
 F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
-F test/window1.test 905fe0842eacfd61e2f30ef7b0a84a7325ffa5cbbcd717ca30f25a142c3bca90
+F test/window1.test 4561399c91f892279fef028e44133f2c73b8eb22dc788afee508563bb7ad1cdc
 F test/window2.tcl 0983de5eade5eeda49469244799d5331bfe3199fca3f6c6d2a836aa08f4fba1b
 F test/window2.test 79747b2edde4ad424e0752b27529aedc86e91f3d8d88846fa17ff0cb67f65086
 F test/window3.tcl f2596e9d6bf8d4441eb7a0d3272594185c3b56e8d2413a54b12e6e7557517674
@@ -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 251022034219819a1dc356542770ff46e3147a080f072eb20af6106771dadd92
-R 71ea60b8da4fc9afa69db85d8c7f3e3f
+P 89bbc9ba8f66853a7530453f146c9df1baacd8558468016cefa7602911f7578a
+R dccf8398447f81129241381719cad17d
 U dan
-Z 1cc277689f8095fe42a1da64c8288583
+Z 5f65d7a3a3ae3236c28a203eff6b68d3
index 4abb1ee7140dbc2ce353d59c98e8e373f54ab696..6a827c374a236a66765223694d554ece3258c035 100644 (file)
@@ -1 +1 @@
-89bbc9ba8f66853a7530453f146c9df1baacd8558468016cefa7602911f7578a
\ No newline at end of file
+236cb75bd1f0d5eb86aa5f52d8d548e7263c34633833dcea9dfc934f142113b8
\ No newline at end of file
index 54e9ced0069fad261cb8dda8f60253b6a46cf9ea..af4201edf7aa5897d31b579a8062f5d78705e58f 100644 (file)
@@ -1182,24 +1182,6 @@ static int dupedExprSize(Expr *p, int flags){
   return nByte;
 }
 
-static Window *winDup(sqlite3 *db, Window *p){
-  Window *pNew = 0;
-  if( p ){
-    pNew = sqlite3DbMallocZero(db, sizeof(Window));
-    if( pNew ){
-      pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
-      pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
-      pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0);
-      pNew->eType = p->eType;
-      pNew->eEnd = p->eEnd;
-      pNew->eStart = p->eStart;
-      pNew->pStart = sqlite3ExprDup(db, pNew->pStart, 0);
-      pNew->pEnd = sqlite3ExprDup(db, pNew->pEnd, 0);
-    }
-  }
-  return pNew;
-}
-
 /*
 ** This function is similar to sqlite3ExprDup(), except that if pzBuffer 
 ** is not NULL then *pzBuffer is assumed to point to a buffer large enough 
@@ -1289,7 +1271,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
       if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){
         pNew->pWin = 0;
       }else{
-        pNew->pWin = winDup(db, p->pWin);
+        pNew->pWin = sqlite3WindowDup(db, p->pWin);
       }
       if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
         if( pNew->op==TK_SELECT_COLUMN ){
index 5e99c949a621c5f042cb1165ef567e6b459aa4c1..fcafe742d72d1fe438d4ca62941464a93e8e3ee1 100644 (file)
@@ -3712,7 +3712,7 @@ static int flattenSubquery(
   pSub = pSubitem->pSelect;
   assert( pSub!=0 );
 
-  if( p->pWin ) return 0;
+  if( p->pWin || pSub->pWin ) return 0;
 
   pSubSrc = pSub->pSrc;
   assert( pSubSrc );
@@ -5898,26 +5898,18 @@ int sqlite3Select(
     assert( p->pEList==pEList );
     if( pWin ){
       int addrGosub = sqlite3VdbeMakeLabel(v);
+      int iCont = sqlite3VdbeMakeLabel(v);
       int regGosub = ++pParse->nMem;
       int addr = 0;
-      int bLoop = 0;
 
-      sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub, &bLoop);
+      sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub);
 
-      sqlite3VdbeAddOp0(v, OP_Goto);
+      addr = sqlite3VdbeAddOp0(v, OP_Goto);
       sqlite3VdbeResolveLabel(v, addrGosub);
-      if( bLoop ){
-        addr = sqlite3VdbeAddOp1(v, OP_Rewind, pWin->iEphCsr);
-      }else{
-        addr = sqlite3VdbeCurrentAddr(v);
-      }
-      selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, addr+1, 0);
-      if( bLoop ){
-        sqlite3VdbeAddOp2(v, OP_Next, pWin->iEphCsr, addr+1);
-        sqlite3VdbeJumpHere(v, addr);
-      }
+      selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, 0);
+      sqlite3VdbeResolveLabel(v, iCont);
       sqlite3VdbeAddOp1(v, OP_Return, regGosub);
-      sqlite3VdbeJumpHere(v, addr-1);       /* OP_Goto jumps here */
+      sqlite3VdbeJumpHere(v, addr);
 
     }else{
       /* Use the standard inner loop. */
index d69b569f6e41d873f85950690220ecb57ddbac71..d2b7730888557dae7629284613197fc3c78b333f 100644 (file)
@@ -3502,10 +3502,11 @@ Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*);
 void sqlite3WindowAttach(Parse*, Expr*, Window*);
 int sqlite3WindowCompare(Parse*, Window*, Window*);
 void sqlite3WindowCodeInit(Parse*, Window*);
-void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int, int*);
+void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
 int sqlite3WindowRewrite(Parse*, Select*);
 int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
 void sqlite3WindowUpdate(Parse*, Window*, FuncDef*);
+Window *sqlite3WindowDup(sqlite3 *db, Window *p);
 
 /*
 ** Assuming zIn points to the first byte of a UTF-8 character,
index 269074717584a67fe57ddfe3fd2808bbca7c0394..d2b6e23a642255a5a2cc3f61b94af015f5b6a20a 100644 (file)
@@ -1560,7 +1560,10 @@ static void windowCodeDefaultStep(
       if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto);
     }
 
+    sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3);
     sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
+    sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1);
+
     sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr);
     sqlite3VdbeAddOp3(
         v, OP_Copy, reg+pMWin->nBufferCol, pMWin->regPart, nPart+nPeer-1
@@ -1586,9 +1589,28 @@ static void windowCodeDefaultStep(
   sqlite3WhereEnd(pWInfo);
 
   windowAggFinal(pParse, pMWin, 1);
+  sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3);
   sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
+  sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1);
 }
 
+Window *sqlite3WindowDup(sqlite3 *db, Window *p){
+  Window *pNew = 0;
+  if( p ){
+    pNew = sqlite3DbMallocZero(db, sizeof(Window));
+    if( pNew ){
+      pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
+      pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
+      pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0);
+      pNew->eType = p->eType;
+      pNew->eEnd = p->eEnd;
+      pNew->eStart = p->eStart;
+      pNew->pStart = sqlite3ExprDup(db, pNew->pStart, 0);
+      pNew->pEnd = sqlite3ExprDup(db, pNew->pEnd, 0);
+    }
+  }
+  return pNew;
+}
 
 /*
 ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
@@ -1649,13 +1671,11 @@ void sqlite3WindowCodeStep(
   Select *p,
   WhereInfo *pWInfo,
   int regGosub, 
-  int addrGosub,
-  int *pbLoop
+  int addrGosub
 ){
   Window *pMWin = p->pWin;
   Window *pWin;
 
-  *pbLoop = 0;
   if( (pMWin->eType==TK_ROWS 
    && (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy))
    || (pMWin->eStart==TK_CURRENT&&pMWin->eEnd==TK_UNBOUNDED&&pMWin->pOrderBy)
@@ -1677,7 +1697,6 @@ void sqlite3WindowCodeStep(
     }
   }
 
-  *pbLoop = 1;
   windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub);
 }
 
index a159fdaeba8444d4226428b2e8175a1e60dd7b0b..93db98a72f44df7597df51beec5c0447972610c7 100644 (file)
@@ -195,5 +195,24 @@ do_execsql_test 5.4 {
   SELECT ntile(1) OVER (ORDER BY a) FROM t4;
 } {}
 
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 6.1 {
+  CREATE TABLE t1(x);
+  INSERT INTO t1 VALUES(7), (6), (5), (4), (3), (2), (1);
+
+  CREATE TABLE t2(x);
+  INSERT INTO t2 VALUES('b'), ('a');
+
+  SELECT x, count(*) OVER (ORDER BY x) FROM t1;
+} {1 1 2 2 3 3 4 4 5 5 6 6 7 7}
+
+do_execsql_test 6.2 {
+  SELECT * FROM t2, (SELECT x, count(*) OVER (ORDER BY x) FROM t1);
+} {
+  b 1 1 b 2 2 b 3 3 b 4 4 b 5 5 b 6 6 b 7 7
+  a 1 1 a 2 2 a 3 3 a 4 4 a 5 5 a 6 6 a 7 7
+}
+
 
 finish_test