From: dan Date: Tue, 12 Mar 2019 18:28:51 +0000 (+0000) Subject: Allow real values to be used in PRECEDING and FOLLOWING expressions for RANGE window... X-Git-Tag: version-3.28.0~88^2~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bb40727857e4a507e64bbc01e0681d7afdd57af9;p=thirdparty%2Fsqlite.git Allow real values to be used in PRECEDING and FOLLOWING expressions for RANGE window frames. FossilOrigin-Name: 25ff7091cb12c63b1864ce68a9151f8432af5804b5ae905a2175761ab4b9fdd8 --- diff --git a/manifest b/manifest index 4691460a47..ba1585a7b9 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index f926fc2d89..ac8e6248bf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5129bcc996b3c9f78ab6b674a4364787e7b353b90f15f027cad4431012022c30 \ No newline at end of file +25ff7091cb12c63b1864ce68a9151f8432af5804b5ae905a2175761ab4b9fdd8 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 425a03e0e6..66d2fc576d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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; } diff --git a/src/window.c b/src/window.c index c39b7b9b4d..4aef228134 100644 --- a/src/window.c +++ b/src/window.c @@ -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 " (eCond==0) or "FOLLOWING " (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=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 ){ diff --git a/test/window8.tcl b/test/window8.tcl index 51db4e225a..1230be09c2 100644 --- a/test/window8.tcl +++ b/test/window8.tcl @@ -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) + " } diff --git a/test/window8.test b/test/window8.test index e26e2673bd..71c8598de1 100644 --- a/test/window8.test +++ b/test/window8.test @@ -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