]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Support other frame types that use "<expr> PRECEDING" or "<expr> FOLLOWING" as
authordan <dan@noemail.net>
Thu, 24 May 2018 17:49:14 +0000 (17:49 +0000)
committerdan <dan@noemail.net>
Thu, 24 May 2018 17:49:14 +0000 (17:49 +0000)
start or end conditions.

FossilOrigin-Name: ec7b648c7f0ee266653561bbb9daa45b9be0d8a1a14f11dc93bce467c35154e6

manifest
manifest.uuid
src/window.c
test/window2.tcl
test/window2.test

index 4b502112030833bcd20bf02d9a7efa22b238e10a..3a161e7fea94664ea353308e5a3c047f7232a8b3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\ssupport\sfor\s"ROWS\sBETWEEN\s<expr>\sPRECEDING\sAND\s<expr>\sFOLLOWING"\swindow\nframes.
-D 2018-05-23T20:55:37.621
+C Support\sother\sframe\stypes\sthat\suse\s"<expr>\sPRECEDING"\sor\s"<expr>\sFOLLOWING"\sas\nstart\sor\send\sconditions.
+D 2018-05-24T17:49:14.994
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
@@ -582,7 +582,7 @@ F src/where.c 60ec752fcbe9f9e0271ac60548d159a540a1ee47a4f9fedc85e88a3d0e392dd1
 F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53
 F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8
 F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
-F src/window.c 1313e941d1e50a44594e6f3e12bc7d0fe6f092ea35c1f3884c31bd224ba66d29
+F src/window.c dc58ad62f2bb06d2e289ce65375b7d0047646b73c11a09fb0325febac0aebba7
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
 F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -1615,8 +1615,8 @@ F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
 F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
 F test/window1.test 5705337783d220b47f6fb4432264543b7557a05be8013d772f57d71f2fded271
-F test/window2.tcl 29e9bb16a52eb1e9e8f376519185af5c64eed88a8e6f0bee54237ba2971803a7
-F test/window2.test f580e1cc96d1ccb6bb220d1e338525ee5541e45e2206ed9ca74417ba862d8a62
+F test/window2.tcl 798cfc8bef0f08a27a0ba64e147d8c72e9409c1673cc4ccff2ee7f150aa084e4
+F test/window2.test ca65b0818ddc948a7b0b07ee16a3c489dafcb958203bf8b75356eacd4696a206
 F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
 F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
 F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
@@ -1733,7 +1733,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 cdb68d2c64e453fdcd29437d5915c5c5ab6fbc7b5ffac52f4cb393f35b4a0124
-R 20d653691e285483f3e3bdb0b082aa4b
+P 3a203660f1e4da3b8d2d605c494f4843f6e00752f28042b49e11d7d6550dd406
+R 91a6e47e9aa2b2bca4e7ec8da35f9bee
 U dan
-Z e628ea8085262c078f67c7957c5a3c95
+Z 468858d850092ff66af7324bc283099f
index 8f6226467bbc021f08188e66f7e7c56c566ac8ce..09eb988a9cffe2d9f59171e022ec0cf88da4bf24 100644 (file)
@@ -1 +1 @@
-3a203660f1e4da3b8d2d605c494f4843f6e00752f28042b49e11d7d6550dd406
\ No newline at end of file
+ec7b648c7f0ee266653561bbb9daa45b9be0d8a1a14f11dc93bce467c35154e6
\ No newline at end of file
index 6af6d4c7ce2d6ded577fd353cc2a80fd6b10496e..47e418191531a9ae8938d618cab8bb11f560c038 100644 (file)
@@ -93,6 +93,50 @@ static void windowCheckFrameValue(Parse *pParse, int reg, int bEnd){
   sqlite3VdbeAppendP4(v, (void*)azErr[bEnd], P4_STATIC);
 }
 
+/*
+** ROWS BETWEEN <expr> PRECEDING    AND <expr> FOLLOWING
+**
+**   ...
+**     if( new partition ){
+**       Gosub flush_partition
+**     }
+**     Insert (record in eph-table)
+**   sqlite3WhereEnd()
+**   Gosub flush_partition
+**
+** flush_partition:
+**   OpenDup (csr -> csr2)
+**   OpenDup (csr -> csr3)
+**   regPrec = <expr1>            // PRECEDING expression
+**   regFollow = <expr2>          // FOLLOWING expression
+**   if( regPrec<0 || regFollow<0 ) throw exception!
+**   Rewind (csr,csr2,csr3)       // if EOF goto flush_partition_done
+**     Aggstep (csr3)
+**     Next(csr3)                 // if EOF fall-through
+**     if( (regFollow--)<=0 ){
+**       AggFinal (xValue)
+**       Gosub addrGosub
+**       Next(csr)                // if EOF goto flush_partition_done
+**       if( (regPrec--)<=0 ){
+**         AggStep (csr2, xInverse)
+**         Next(csr2)
+**       }
+**     }
+** flush_partition_done:
+**   Close (csr2)
+**   Close (csr3)
+**   ResetSorter (csr)
+**   Return
+**
+** ROWS BETWEEN <expr> PRECEDING    AND CURRENT ROW
+** ROWS BETWEEN CURRENT ROW         AND <expr> FOLLOWING
+** ROWS BETWEEN <expr> PRECEDING    AND UNBOUNDED FOLLOWING
+** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING
+**
+**   These are similar to the above. For "CURRENT ROW", intialize the
+**   register to 0. For "UNBOUNDED ..." to infinity.
+**
+*/
 static void windowCodeRowExprStep(
   Parse *pParse, 
   Select *p,
@@ -123,6 +167,15 @@ static void windowCodeRowExprStep(
   int addrIfPos1;
   int addrIfPos2;
 
+  assert( pMWin->eStart==TK_PRECEDING 
+       || pMWin->eStart==TK_CURRENT 
+       || pMWin->eStart==TK_UNBOUNDED 
+  );
+  assert( pMWin->eEnd==TK_FOLLOWING 
+       || pMWin->eEnd==TK_CURRENT 
+       || pMWin->eEnd==TK_UNBOUNDED 
+  );
+
   pParse->nMem += nSub + 2;
 
   /* Allocate register and label for the "flush_partition" sub-routine. */
@@ -173,17 +226,22 @@ static void windowCodeRowExprStep(
   sqlite3VdbeAddOp2(v, OP_OpenDup, csrPrec, pMWin->iEphCsr);
   sqlite3VdbeAddOp2(v, OP_OpenDup, csrFollow, pMWin->iEphCsr);
 
-  sqlite3ExprCode(pParse, pMWin->pStart, regPrec);
-  sqlite3ExprCode(pParse, pMWin->pEnd, regFollow);
+  /* If either regPrec or regFollow are not non-negative integers, throw 
+  ** an exception.  */
+  if( pMWin->pStart ){
+    assert( pMWin->eStart==TK_PRECEDING );
+    sqlite3ExprCode(pParse, pMWin->pStart, regPrec);
+    windowCheckFrameValue(pParse, regPrec, 0);
+  }
+  if( pMWin->pEnd ){
+    assert( pMWin->eEnd==TK_FOLLOWING );
+    sqlite3ExprCode(pParse, pMWin->pEnd, regFollow);
+    windowCheckFrameValue(pParse, regFollow, 1);
+  }
 
   sqlite3VdbeAddOp2(v, OP_Null, 0, pMWin->regResult);
   sqlite3VdbeAddOp2(v, OP_Null, 0, pMWin->regAccum);
 
-  /* If either regPrec or regFollow are not non-negative integers, throw an
-  ** exception.  */
-  windowCheckFrameValue(pParse, regPrec, 0);
-  windowCheckFrameValue(pParse, regFollow, 1);
-
   sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, addrDone);
   sqlite3VdbeAddOp2(v, OP_Rewind, csrPrec, addrDone);
   sqlite3VdbeChangeP5(v, 1);
@@ -205,9 +263,17 @@ static void windowCodeRowExprStep(
     sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
     sqlite3VdbeChangeP5(v, (u8)pWin->nArg);
   }
-  sqlite3VdbeJumpHere(v, addrNext+1);
+  if( pMWin->eEnd==TK_UNBOUNDED ){
+    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext);
+    sqlite3VdbeJumpHere(v, addrNext+1);
+    addrNext = sqlite3VdbeCurrentAddr(v);
+  }else{
+    sqlite3VdbeJumpHere(v, addrNext+1);
+  }
 
-  addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regFollow, 0 , 1);
+  if( pMWin->eEnd==TK_FOLLOWING ){
+    addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regFollow, 0 , 1);
+  }
   for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
     sqlite3VdbeAddOp3(v, 
         OP_AggFinal, pWin->regAccum, pWin->nArg, pWin->regResult
@@ -218,20 +284,27 @@ static void windowCodeRowExprStep(
   sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)+2);
   sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);
 
-  addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regPrec, 0 , 1);
-  sqlite3VdbeAddOp2(v, OP_Next, csrPrec, sqlite3VdbeCurrentAddr(v)+1);
-  for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
-    int i;
-    for(i=0; i<pWin->nArg; i++){
-      sqlite3VdbeAddOp3(v, OP_Column, csrPrec, pWin->iArgCol+i, reg+i);
+  if( pMWin->eStart==TK_CURRENT || pMWin->eStart==TK_PRECEDING ){
+    if( pMWin->eStart==TK_PRECEDING ){
+      addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regPrec, 0 , 1);
+    }
+    sqlite3VdbeAddOp2(v, OP_Next, csrPrec, sqlite3VdbeCurrentAddr(v)+1);
+    for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
+      int i;
+      for(i=0; i<pWin->nArg; i++){
+        sqlite3VdbeAddOp3(v, OP_Column, csrPrec, pWin->iArgCol+i, reg+i);
+      }
+      sqlite3VdbeAddOp3(v, OP_AggStep0, 1, reg, pWin->regAccum);
+      sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
+      sqlite3VdbeChangeP5(v, (u8)pWin->nArg);
+    }
+    if( pMWin->eStart==TK_PRECEDING ){
+      sqlite3VdbeJumpHere(v, addrIfPos2);
     }
-    sqlite3VdbeAddOp3(v, OP_AggStep0, 1, reg, pWin->regAccum);
-    sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
-    sqlite3VdbeChangeP5(v, (u8)pWin->nArg);
   }
-  sqlite3VdbeJumpHere(v, addrIfPos2);
-
-  sqlite3VdbeJumpHere(v, addrIfPos1);
+  if( pMWin->eEnd==TK_FOLLOWING ){
+    sqlite3VdbeJumpHere(v, addrIfPos1);
+  }
   sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext);
 
   /* flush_partition_done: */
@@ -428,48 +501,6 @@ static void windowCodeDefaultStep(
 **
 **========================================================================
 **
-** ROWS BETWEEN <expr> PRECEDING    AND <expr> FOLLOWING
-**
-**   ...
-**     if( new partition ){
-**       Gosub flush_partition
-**     }
-**     Insert (record in eph-table)
-**   sqlite3WhereEnd()
-**   Gosub flush_partition
-**
-** flush_partition:
-**   OpenDup (csr -> csr2)
-**   OpenDup (csr -> csr3)
-**   regPrec = <expr1>            // PRECEDING expression
-**   regFollow = <expr2>          // FOLLOWING expression
-**   if( regPrec<0 || regFollow<0 ) throw exception!
-**   Rewind (csr,csr2,csr3)       // if EOF goto flush_partition_done
-**     Aggstep (csr3)
-**     Next(csr3)                 // if EOF fall-through
-**     if( (regFollow--)<=0 ){
-**       AggFinal (xValue)
-**       Gosub addrGosub
-**       Next(csr)                // if EOF goto flush_partition_done
-**       if( (regPrec--)<=0 ){
-**         AggStep (csr2, xInverse)
-**         Next(csr2)
-**       }
-**     }
-** flush_partition_done:
-**   Close (csr2)
-**   Close (csr3)
-**   ResetSorter (csr)
-**   Return
-**
-** ROWS BETWEEN <expr> PRECEDING    AND CURRENT ROW
-** ROWS BETWEEN CURRENT ROW         AND <expr> FOLLOWING
-** ROWS BETWEEN <expr> PRECEDING    AND UNBOUNDED FOLLOWING
-** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING
-**
-**   These are similar to the above. For "CURRENT ROW", intialize the
-**   register to 0. For "UNBOUNDED ..." to infinity.
-**
 ** ROWS BETWEEN <expr> PRECEDING    AND <expr> PRECEDING
 **
 **   Replace the bit after "Rewind" in the above with:
@@ -522,8 +553,8 @@ void sqlite3WindowCodeStep(
   Window *pMWin = p->pWin;
 
   if( pMWin->eType==TK_ROWS 
-   && pMWin->eStart==TK_PRECEDING
-   && pMWin->eEnd==TK_FOLLOWING
+   && (pMWin->eStart==TK_PRECEDING || pMWin->eEnd==TK_FOLLOWING)
+   && (pMWin->eStart!=TK_FOLLOWING || pMWin->eEnd==TK_PRECEDING)
   ){
     *pbLoop = 0;
     windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub);
index 4d2503715b4be90b6eef1945c81da0197ffcb7d2..44a13cbf54c78ea0fea14fa3a72e647ebe2a88a0 100644 (file)
@@ -184,6 +184,44 @@ execsql_test 2.7 {
   ) FROM t1
 }
 
+execsql_test 2.8 {
+  SELECT a, sum(d) OVER (
+    ORDER BY d 
+    ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING
+  ) FROM t1
+}
+
+execsql_test 2.9 {
+  SELECT a, sum(d) OVER (
+    ORDER BY d 
+    ROWS BETWEEN UNBOUNDED PRECEDING AND 2 FOLLOWING
+  ) FROM t1
+}
+
+execsql_test 2.10 {
+  SELECT a, sum(d) OVER (
+    ORDER BY d 
+    ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING
+  ) FROM t1
+}
+
+execsql_test 2.11 {
+  SELECT a, sum(d) OVER (
+    ORDER BY d 
+    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
+  ) FROM t1
+}
+
+execsql_test 2.13 {
+  SELECT a, sum(d) OVER (
+    ORDER BY d 
+    ROWS BETWEEN 2 PRECEDING AND UNBOUNDED FOLLOWING
+  ) FROM t1
+}
+
+
+==========
+
 puts $::fd finish_test
 ==========
 
index db4eb44dc7a88ca42abfc5160f4aee148ffc69e4..a5d4ee853e0c98574f32126cc281915b8dd4eb53 100644 (file)
@@ -95,42 +95,65 @@ do_execsql_test 2.7 {
   ) FROM t1
 } {2 2   4 4   6 6   1 1   3 3   5 5}
 
+do_execsql_test 2.8 {
+  SELECT a, sum(d) OVER (
+    ORDER BY d 
+    ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING
+  ) FROM t1
+} {1 6   2 9   3 12   4 15   5 11   6 6}
+
+do_execsql_test 2.9 {
+  SELECT a, sum(d) OVER (
+    ORDER BY d 
+    ROWS BETWEEN UNBOUNDED PRECEDING AND 2 FOLLOWING
+  ) FROM t1
+} {1 6   2 10   3 15   4 21   5 21   6 21}
+
+do_execsql_test 2.10 {
+  SELECT a, sum(d) OVER (
+    ORDER BY d 
+    ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING
+  ) FROM t1
+} {1 6   2 9   3 12   4 15   5 11   6 6}
+
+do_execsql_test 2.11 {
+  SELECT a, sum(d) OVER (
+    ORDER BY d 
+    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
+  ) FROM t1
+} {1 1   2 3   3 6   4 9   5 12   6 15}
+
+do_execsql_test 2.13 {
+  SELECT a, sum(d) OVER (
+    ORDER BY d 
+    ROWS BETWEEN 2 PRECEDING AND UNBOUNDED FOLLOWING
+  ) FROM t1
+} {1 21   2 21   3 21   4 20   5 18   6 15}
+
+#==========================================================================
+
 finish_test
 #==========================================================================
 
-do_execsql_test 2.1 {
+do_execsql_test 3.1 {
   SELECT a, sum(d) OVER (
     PARTITION BY b ORDER BY d
     RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
   ) FROM t1
 } {2 12   4 10   6 6   1 9   3 8   5 5}
 
-do_execsql_test 2.2 {
+do_execsql_test 3.2 {
   SELECT a, sum(d) OVER (
     ORDER BY b
     RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
   ) FROM t1
 } {2 21   4 21   6 21   1 9   3 9   5 9}
 
-do_execsql_test 2.3 {
+do_execsql_test 3.3 {
   SELECT a, sum(d) OVER (
     ORDER BY d
     ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
   ) FROM t1
 } {1 21   2 21   3 21   4 21   5 21   6 21}
 
-do_execsql_test 2.4 {
-  SELECT a, sum(d) OVER (
-    ORDER BY d
-    ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
-  ) FROM t1
-} {1 3   2 6   3 9   4 12   5 15   6 11}
-
-do_execsql_test 2.5 {
-  SELECT a, sum(d) OVER (
-    ORDER BY d
-    ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING
-  ) FROM t1
-} {1 {}   2 1   3 2   4 3   5 4   6 5}
-
 finish_test