]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Allow real values to be used in PRECEDING and FOLLOWING expressions for RANGE window...
authordan <dan@noemail.net>
Tue, 12 Mar 2019 18:28:51 +0000 (18:28 +0000)
committerdan <dan@noemail.net>
Tue, 12 Mar 2019 18:28:51 +0000 (18:28 +0000)
FossilOrigin-Name: 25ff7091cb12c63b1864ce68a9151f8432af5804b5ae905a2175761ab4b9fdd8

manifest
manifest.uuid
src/vdbe.c
src/window.c
test/window8.tcl
test/window8.test

index 4691460a4743a084b3b9c271403caee3e91e6673..ba1585a7b948dc5f9ff19492a364c8c5bf9cbef0 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Expand\son\sheader\scomment\sfor\ssqlite3WindowCodeStep().\sFurther\ssimplify\sthe\simplementation\sof\sthe\ssame.
-D 2019-03-12T15:21:51.703
+C Allow\sreal\svalues\sto\sbe\sused\sin\sPRECEDING\sand\sFOLLOWING\sexpressions\sfor\sRANGE\swindow\sframes.
+D 2019-03-12T18:28:51.117
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 236d2739dc3e823c3c909bca2d6cef93009bafbefd7018a8f3281074ecb92954
@@ -586,7 +586,7 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
 F src/util.c 82a2e3f691a3b654be872e305dab1f455e565dedf5e6a90c818c1ab307c00432
 F src/vacuum.c a9f389f41556c0ec310bc9169dc9476603c30a0a913ad92bfbc75c86886967ca
-F src/vdbe.c f1e7b5320df80ff58c67176e35cb48062cbda2a9c9811f11db5faa48071d3fe4
+F src/vdbe.c 6e7a279ea2f1eab28b19cf41b1012379d38e182de571f50f41adc6b7911ec6c0
 F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237
 F src/vdbeInt.h a76d5eed62c76bcd8de7afd3147fac1bc40c5a870582664bcd7d071ef437c37f
 F src/vdbeapi.c 7a052df80d7e2e55382076174633e888f21fe200feb5d49b1b441b4c38ab851a
@@ -604,7 +604,7 @@ F src/where.c 8a207cb2ca6b99e1edb1e4bbff9b0504385a759cbf66180d1deb34d80ca4b799
 F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88
 F src/wherecode.c ce7b21e1be2b981d62683fc59c4ca73a04a7ff2f1ebec23d41baf2da2349afd6
 F src/whereexpr.c 36b47f7261d6b6f1a72d774c113b74beddf6745aba1018e64b196e29db233442
-F src/window.c 4763c2e81e8bb5d79fc378ba650cfcf076653d78065bd85790d592d441c9ae7a
+F src/window.c 536bc80552d11f95a3524f8a7239727f94115ada67d1dd900e4988196346c225
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
 F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -1687,8 +1687,8 @@ F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652
 F test/window6.test 604890f2b0f976339e6a1774cd90d48840e57a54b4f21a8b4b3047aa2c9787d1
 F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f
 F test/window7.test ce7f865241fdd1c5c4db869cd7bb2986c3be836bc2e73649a6846dd920f63e0f
-F test/window8.tcl d296629022e098c9860933fa1ed61e698b60a7b0d50cf3ea77e9949b87012adc
-F test/window8.test 5bf663c76a9056235ae864f071d97056c7391f8b1dd18b184d4ea907951eaf08
+F test/window8.tcl 2aa94709defda0bbe05883cdb61ec51346ab0bacb4d84d724758fc62818c610a
+F test/window8.test e33941d2b31a8641dbe40ee38ed08430e81cd884ad409ec9eeaec315e7ae1c3b
 F test/windowerr.tcl 4f0b111cdbb8de401a8135cd116604fb8add13042bb47a1f1496dd47a690e864
 F test/windowerr.test 461bc504d4af0ae16a081e0c3bdb3724356cdcfb07bdc4b1b2dc4ad91b69bb7e
 F test/windowfault.test 12ceb6bbb355d13e8fcd88c5731a57256dfdf77b9a7ae20842a76fcd4623df5b
@@ -1812,7 +1812,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 081263538332bb9c07e62630629007ccbba31bef5dc890f60b4ba58a355f70ac
-R b359af1c195991083b8f00df3e4dfe08
+P 5129bcc996b3c9f78ab6b674a4364787e7b353b90f15f027cad4431012022c30
+R f73d694ac4c1f1f064a3ca7465b32f6d
 U dan
-Z 98fef6b18eded687d4fe3a47cb60a7a7
+Z ea7ae61d59972a80f1c852bccb429b9d
index f926fc2d89e7b5e04097704c18fde794591c6177..ac8e6248bf0c67ed3f9f64fe0639b01e5b7d7093 100644 (file)
@@ -1 +1 @@
-5129bcc996b3c9f78ab6b674a4364787e7b353b90f15f027cad4431012022c30
\ No newline at end of file
+25ff7091cb12c63b1864ce68a9151f8432af5804b5ae905a2175761ab4b9fdd8
\ No newline at end of file
index 425a03e0e6ed999953f9374e4b1bd566aa70e454..66d2fc576dcdb147d60f9dff98f036e11d62b510 100644 (file)
@@ -1723,19 +1723,25 @@ case OP_AddImm: {            /* in1 */
   break;
 }
 
-/* Opcode: MustBeInt P1 P2 * * *
+/* Opcode: MustBeInt P1 P2 * * P5
 ** 
-** Force the value in register P1 to be an integer.  If the value
-** in P1 is not an integer and cannot be converted into an integer
-** without data loss, then jump immediately to P2, or if P2==0
+** If P5 is 0, force the value in register P1 to be an integer. If 
+** the value in P1 is not an integer and cannot be converted into an 
+** integer without data loss, then jump immediately to P2, or if P2==0
 ** raise an SQLITE_MISMATCH exception.
+**
+** Or, if P5 is non-zero, then force the register in P1 to be a number
+** (real or integer). Jump to P2 if this cannot be accomplished without
+** data loss. P2 must be non-zero in this case.
 */
 case OP_MustBeInt: {            /* jump, in1 */
+  u8 f;
+  f = (pOp->p5 ? (MEM_Int|MEM_Real) : MEM_Int);
   pIn1 = &aMem[pOp->p1];
-  if( (pIn1->flags & MEM_Int)==0 ){
+  if( (pIn1->flags & f)==0 ){
     applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
-    VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2);
-    if( (pIn1->flags & MEM_Int)==0 ){
+    VdbeBranchTaken((pIn1->flags&f)==0, 2);
+    if( (pIn1->flags & f)==0 ){
       if( pOp->p2==0 ){
         rc = SQLITE_MISMATCH;
         goto abort_due_to_error;
@@ -1744,7 +1750,7 @@ case OP_MustBeInt: {            /* jump, in1 */
       }
     }
   }
-  MemSetTypeFlag(pIn1, MEM_Int);
+  if( f==MEM_Int ) MemSetTypeFlag(pIn1, MEM_Int);
   break;
 }
 
index c39b7b9b4dbf94c5a578b521edf1681d3706297e..4aef228134289f83ddb214e5bded3079ed26733e 100644 (file)
@@ -1168,6 +1168,12 @@ void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){
   }
 }
 
+#define WINDOW_STARTING_INT  0
+#define WINDOW_ENDING_INT    1
+#define WINDOW_NTH_VALUE_INT 2
+#define WINDOW_STARTING_NUM  3
+#define WINDOW_ENDING_NUM    4
+
 /*
 ** A "PRECEDING <expr>" (eCond==0) or "FOLLOWING <expr>" (eCond==1) or the
 ** value of the second argument to nth_value() (eCond==2) has just been
@@ -1175,18 +1181,21 @@ void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){
 ** code to check that the value is a non-negative integer and throws an
 ** exception if it is not.
 */
-static void windowCheckIntValue(Parse *pParse, int reg, int eCond){
+static void windowCheckValue(Parse *pParse, int reg, int eCond){
   static const char *azErr[] = {
     "frame starting offset must be a non-negative integer",
     "frame ending offset must be a non-negative integer",
-    "second argument to nth_value must be a positive integer"
+    "second argument to nth_value must be a positive integer",
+    "frame starting offset must be a non-negative number",
+    "frame ending offset must be a non-negative number",
   };
-  static int aOp[] = { OP_Ge, OP_Ge, OP_Gt };
+  static int aOp[] = { OP_Ge, OP_Ge, OP_Gt, OP_Ge, OP_Ge };
   Vdbe *v = sqlite3GetVdbe(pParse);
   int regZero = sqlite3GetTempReg(pParse);
-  assert( eCond==0 || eCond==1 || eCond==2 );
+  assert( eCond>=0 && eCond<ArraySize(azErr) );
   sqlite3VdbeAddOp2(v, OP_Integer, 0, regZero);
   sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2);
+  if( eCond>=WINDOW_STARTING_NUM ) sqlite3VdbeChangeP5(v, 1);
   VdbeCoverageIf(v, eCond==0);
   VdbeCoverageIf(v, eCond==1);
   VdbeCoverageIf(v, eCond==2);
@@ -1383,7 +1392,7 @@ static void windowReturnOneRow(
 
       if( pFunc->zName==nth_valueName ){
         sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg);
-        windowCheckIntValue(pParse, tmpReg, 2);
+        windowCheckValue(pParse, tmpReg, 2);
       }else{
         sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg);
       }
@@ -2214,11 +2223,11 @@ void sqlite3WindowCodeStep(
 
   if( regStart ){
     sqlite3ExprCode(pParse, pMWin->pStart, regStart);
-    windowCheckIntValue(pParse, regStart, 0);
+    windowCheckValue(pParse, regStart, 0 + (pMWin->eType==TK_RANGE ? 3 : 0));
   }
   if( regEnd ){
     sqlite3ExprCode(pParse, pMWin->pEnd, regEnd);
-    windowCheckIntValue(pParse, regEnd, 1);
+    windowCheckValue(pParse, regEnd, 1 + (pMWin->eType==TK_RANGE ? 3 : 0));
   }
 
   if( pMWin->eStart==pMWin->eEnd && regStart && regEnd ){
index 51db4e225ab7382cbccea130c9755a5ca361e29b..1230be09c29f975260d58762ac087ac4e267d14b 100644 (file)
@@ -93,7 +93,7 @@ foreach {tn frame} {
 
 execsql_test 2.0 {
   DROP TABLE IF EXISTS t1;
-  CREATE TABLE t1(a INTEGER, b INTEGER);
+  CREATE TABLE t1(a REAL, b INTEGER);
   INSERT INTO t1 VALUES
       (5, 10), (10, 20), (13, 26), (13, 26), 
       (15, 30), (20, 40), (22,80), (30, 90);
@@ -106,8 +106,17 @@ foreach {tn frame} {
   4 { ORDER BY a DESC RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING }
   5 { ORDER BY a DESC RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING }
   6 { ORDER BY a DESC RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING }
+
+  7  { ORDER BY a RANGE BETWEEN 5.1 PRECEDING AND 5.3 FOLLOWING }
+  8  { ORDER BY a RANGE BETWEEN 10.2 PRECEDING AND 5.4 PRECEDING }
+  9  { ORDER BY a RANGE BETWEEN 2.6 FOLLOWING AND 3.5 FOLLOWING }
+  10 { ORDER BY a DESC RANGE BETWEEN 5.7 PRECEDING AND 5.8 FOLLOWING }
+  11 { ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND 5.9 PRECEDING }
+  12 { ORDER BY a DESC RANGE BETWEEN 2.1 FOLLOWING AND UNBOUNDED FOLLOWING }
 } {
-  execsql_test 2.$tn "SELECT a, sum(b) OVER win FROM t1 WINDOW win AS ($frame)"
+  execsql_test 2.$tn "
+    SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ($frame)
+  "
 }
 
 
index e26e2673bda14cb2ebb9f2d0a9931647f113f174..71c8598de1c18263e4eff3ba7b30d2480c2d2dc0 100644 (file)
@@ -437,34 +437,58 @@ do_execsql_test 1.19.5 {
 
 do_execsql_test 2.0 {
   DROP TABLE IF EXISTS t1;
-  CREATE TABLE t1(a INTEGER, b INTEGER);
+  CREATE TABLE t1(a REAL, b INTEGER);
   INSERT INTO t1 VALUES
       (5, 10), (10, 20), (13, 26), (13, 26), 
       (15, 30), (20, 40), (22,80), (30, 90);
 } {}
 
 do_execsql_test 2.1 {
-  SELECT a, sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING )
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING )
 } {5 30   10 112   13 102   13 102   15 142   20 150   22 120   30 90}
 
 do_execsql_test 2.2 {
-  SELECT a, sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING )
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING )
 } {5 {}   10 10   13 10   13 10   15 30   20 102   22 82   30 120}
 
 do_execsql_test 2.3 {
-  SELECT a, sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING )
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING )
 } {5 {}   10 52   13 30   13 30   15 {}   20 80   22 {}   30 {}}
 
 do_execsql_test 2.4 {
-  SELECT a, sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING )
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING )
 } {30 90   22 120   20 150   15 142   13 102   13 102   10 112   5 30}
 
 do_execsql_test 2.5 {
-  SELECT a, sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING )
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING )
 } {30 {}   22 90   20 90   15 120   13 120   13 120   10 70   5 102}
 
 do_execsql_test 2.6 {
-  SELECT a, sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING )
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING )
 } {30 {}   22 40   20 {}   15 52   13 20   13 20   10 {}   5 {}}
 
+do_execsql_test 2.7 {
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 5.1 PRECEDING AND 5.3 FOLLOWING )
+} {5 30   10 112   13 102   13 102   15 142   20 150   22 120   30 90}
+
+do_execsql_test 2.8 {
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 10.2 PRECEDING AND 5.4 PRECEDING )
+} {5 {}   10 {}   13 10   13 10   15 10   20 72   22 82   30 120}
+
+do_execsql_test 2.9 {
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a RANGE BETWEEN 2.6 FOLLOWING AND 3.5 FOLLOWING )
+} {5 {}   10 52   13 {}   13 {}   15 {}   20 {}   22 {}   30 {}}
+
+do_execsql_test 2.10 {
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 5.7 PRECEDING AND 5.8 FOLLOWING )
+} {30 90   22 120   20 150   15 142   13 102   13 102   10 112   5 30}
+
+do_execsql_test 2.11 {
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND 5.9 PRECEDING )
+} {30 {}   22 90   20 90   15 170   13 210   13 210   10 210   5 292}
+
+do_execsql_test 2.12 {
+  SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ( ORDER BY a DESC RANGE BETWEEN 2.1 FOLLOWING AND UNBOUNDED FOLLOWING )
+} {30 232   22 112   20 112   15 30   13 30   13 30   10 10   5 {}}
+
 finish_test