Fix problems with RANGE windows and string, blob and NULL values.

FossilOrigin-Name: cebe09e11cc91d9776f259dd9b87e9c760a460f53ba6fa36481dfe58f77ad417
This commit is contained in:
dan 2019-03-16 20:29:54 +00:00
parent bf84515a2b
commit 1e7cb19be3
8 changed files with 2205 additions and 165 deletions

View File

@ -1,5 +1,5 @@
C In\sorder\sto\sidentify\sthe\sfirst\srow\sof\seach\spartition,\scheck\sif\sthe\srowid\sin\sthe\sephemeral\stable\sis\s1\sinstead\sof\susing\sa\sdedicated\sflag\sregister.
D 2019-03-16T10:15:24.575
C Fix\sproblems\swith\sRANGE\swindows\sand\sstring,\sblob\sand\sNULL\svalues.
D 2019-03-16T20:29:54.997
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 236d2739dc3e823c3c909bca2d6cef93009bafbefd7018a8f3281074ecb92954
@ -504,7 +504,7 @@ F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 422fd8cfa59fb9173eff36a95878904a0eeb0dcc62ba49350acc8b1e51c4dc7b
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
F src/parse.y a2a79da71f0c7c650a7ad84e0586c323441722b1af00ee19ae7dae91e5ae0432
F src/parse.y cff56367d4226fe067eb595151352658af63e6bf55da84e71d3a72c36f3a0b00
F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c a72804486dfa8e4b6bc30d666c97ecf1155f91a4351fc6e48ea4097e4eb304fb
@ -604,7 +604,7 @@ F src/where.c 8a207cb2ca6b99e1edb1e4bbff9b0504385a759cbf66180d1deb34d80ca4b799
F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88
F src/wherecode.c ce7b21e1be2b981d62683fc59c4ca73a04a7ff2f1ebec23d41baf2da2349afd6
F src/whereexpr.c 90859652920f153d2c03f075488744be2926625ebd36911bcbcb17d0d29c891c
F src/window.c 58c0e510d1556e7b6176873afc66df29442a9e99937e5a05a5d3737191f72b98
F src/window.c 3c13b17c47f85ccc2051c123345c7056c168a5ab1e6d237e8d1c59fb4f085470
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@ -1197,7 +1197,7 @@ F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 52d2c37fe8cc07ec7362024c214b04bb69432995b3a984a3fbabc60fa6ada3ee
F test/pg_common.tcl 74f0f59f8eb87450f2b0284ae8c1155699f07f2f3af690f4069137b30c21a009
F test/pg_common.tcl 85fac868078d6d71357642910663aaf95f2cf90b78c9817bcee311fe107f0608
F test/pragma.test c267bf02742c823a191960895b3d52933cebd7beee26757d1ed694f213fcd867
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9
@ -1676,7 +1676,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 d690a34fc6b4e5032eed5eff659a1352d4a858352daeff1596e28910bae48727
F test/window1.test 6c7bbed965407a28fc699d3bab2fd199e75dbd7a5b3fe88dfe8149c583a526eb
F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@ -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 e4b794bdc0e30302d393a1af7593363a4525629a9a1d3a9b6e96f24590d36992
F test/window8.test 1b8de9067bea0e7857d152ced7ef76716bc2c9f1271755016345ab16a56549e3
F test/window8.tcl 3f973e4007cade9e1700434220505bf1ada7f0f13edb1803322cb78069bda7d7
F test/window8.test 118243072b074d76400b4f528322a2d79a36e02e114da95ebba6610785cd10f2
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 9b43c3ee2e054b05715573f4f3893b84aabc5100832333c9a0f2a1628552a978
R 7c14a1c696a17b72f9ba56dd7fcded6e
P f2d5f7a24c7aa483c579706c5bd7268a74da6d53025d78fa8642908c2aed1707
R 1f818016fedca9daa5b8ba9c8e0b3de6
U dan
Z 0c21ffc0cb9db6cb2728e05b5fb3d423
Z 3e69c8f976def5bbb22a7214f3463083

View File

@ -1 +1 @@
f2d5f7a24c7aa483c579706c5bd7268a74da6d53025d78fa8642908c2aed1707
cebe09e11cc91d9776f259dd9b87e9c760a460f53ba6fa36481dfe58f77ad417

View File

@ -1712,7 +1712,7 @@ frame_bound(A) ::= CURRENT ROW. { A.eType = TK_CURRENT ; A.pExpr = 0; }
frame_bound(A) ::= expr(X) FOLLOWING. { A.eType = TK_FOLLOWING; A.pExpr = X; }
%type frame_exclude_opt {u8}
frame_exclude_opt(A) ::= . { A = TK_NO; }
frame_exclude_opt(A) ::= . { A = 0; }
frame_exclude_opt(A) ::= EXCLUDE frame_exclude(X). { A = X; }
%type frame_exclude {u8}

View File

@ -1076,7 +1076,6 @@ Window *sqlite3WindowAlloc(
pWin->bImplicitFrame = bImplicitFrame;
pWin->pEnd = sqlite3WindowOffsetExpr(pParse, pEnd);
pWin->pStart = sqlite3WindowOffsetExpr(pParse, pStart);
/* pWin->eExclude = 1; */
return pWin;
windowAllocErr:
@ -1742,11 +1741,14 @@ static void windowIfNewPeer(
/*
** This function is called as part of generating VM programs for RANGE
** offset PRECEDING/FOLLOWING frame boundaries. It generates code equivalent
** to:
** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for
** the ORDER BY term in the window, it generates code equivalent to:
**
** if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl;
** if( csr1.rowid >= csr2.rowid ) goto lbl;
**
** A special type of arithmetic is used such that if csr.peerVal is not
** a numeric type (real or integer), then the result of the addition is
** a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
WindowCodeArg *p,
@ -1761,6 +1763,10 @@ static void windowCodeRangeTest(
int reg1 = sqlite3GetTempReg(pParse);
int reg2 = sqlite3GetTempReg(pParse);
int arith = OP_Add;
int addrGe;
int addrNotNull;
int regString = ++pParse->nMem;
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
assert( p->pMWin->pOrderBy && p->pMWin->pOrderBy->nExpr==1 );
@ -1775,11 +1781,24 @@ static void windowCodeRangeTest(
windowReadPeerValues(p, csr1, reg1);
windowReadPeerValues(p, csr2, reg2);
/* Check if the peer value for csr1 value is a text or blob by comparing
** it to the smallest possible string - ''. */
sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
if( op==OP_Le ){
sqlite3VdbeAddOp2(v, OP_IsNull, reg1, lbl);
}
if( op==OP_Ge ){
sqlite3VdbeAddOp2(v, OP_NotNull, reg1, sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl);
}
sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
sqlite3VdbeJumpHere(v, addrGe);
sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1);
sqlite3VdbeAddOp2(v, OP_Rowid, csr1, reg1);
sqlite3VdbeAddOp2(v, OP_Rowid, csr2, reg2);
sqlite3VdbeAddOp3(v, OP_Gt, reg2, lbl, reg1);
sqlite3ReleaseTempReg(pParse, reg1);
sqlite3ReleaseTempReg(pParse, reg2);
}

View File

@ -40,17 +40,26 @@ proc execsql {sql} {
#puts $lSql
set ret ""
set nChar 0
foreach stmt $lSql {
set res [pg_exec $::db $stmt]
set err [pg_result $res -error]
if {$err!=""} { error $err }
for {set i 0} {$i < [pg_result $res -numTuples]} {incr i} {
if {$i==0} {
set ret [pg_result $res -getTuple 0]
set t [pg_result $res -getTuple $i]
set nNew [string length $t]
if {$nChar>0 && ($nChar+$nNew+3)>75} {
append ret "\n "
set nChar 0
} else {
append ret " [pg_result $res -getTuple $i]"
if {$nChar>0} {
append ret " "
incr nChar 3
}
# lappend ret {*}[pg_result $res -getTuple $i]
}
incr nChar $nNew
append ret $t
}
pg_result $res -clear
}

View File

@ -849,4 +849,81 @@ do_execsql_test 18.3.5 {
win5 AS (win4 ORDER BY c)
} {four four.six four.six.two five five.one five.one.three}
#-------------------------------------------------------------------------
# Test RANGE <expr> PRECEDING/FOLLOWING when there are string, blob
# and NULL values in the dataset.
#
reset_db
do_execsql_test 19.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES
(1, 1), (2, 2), (3, 3), (4, 4), (5, 5),
('a', 6), ('b', 7), ('c', 8), ('d', 9), ('e', 10);
}
do_execsql_test 19.1 {
SELECT a, sum(b) OVER (ORDER BY a) FROM t1;
} {1 1 2 3 3 6 4 10 5 15 a 21 b 28 c 36 d 45 e 55}
do_execsql_test 19.2.1 {
SELECT a, sum(b) OVER (
ORDER BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
) FROM t1;
} {1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}
do_execsql_test 19.2.2 {
SELECT a, sum(b) OVER (
ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
) FROM t1 ORDER BY a ASC;
} {1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}
do_execsql_test 19.3.1 {
SELECT a, sum(b) OVER (
ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING
) FROM t1;
} {1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}
do_execsql_test 19.3.2 {
SELECT a, sum(b) OVER (
ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 2 FOLLOWING
) FROM t1 ORDER BY a ASC;
} {1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}
reset_db
do_execsql_test 20.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES
(NULL, 100), (NULL, 100),
(1, 1), (2, 2), (3, 3), (4, 4), (5, 5),
('a', 6), ('b', 7), ('c', 8), ('d', 9), ('e', 10);
}
do_execsql_test 20.1 {
SELECT a, sum(b) OVER (ORDER BY a) FROM t1;
} {
{} 200 {} 200 1 201 2 203 3 206 4 210 5 215
a 221 b 228 c 236 d 245 e 255
}
do_execsql_test 20.2.1 {
SELECT a, sum(b) OVER (
ORDER BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
) FROM t1;
} {{} 200 {} 200 1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}
do_execsql_test 20.2.2 {
SELECT a, sum(b) OVER (
ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
) FROM t1 ORDER BY a ASC;
} {{} 200 {} 200 1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}
do_execsql_test 20.3.1 {
SELECT a, sum(b) OVER (
ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING
) FROM t1;
} {{} 200 {} 200 1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}
do_execsql_test 20.3.2 {
SELECT a, sum(b) OVER (
ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 2 FOLLOWING
) FROM t1 ORDER BY a ASC;
} {{} 200 {} 200 1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}
finish_test

View File

@ -122,6 +122,14 @@ foreach {tn ex} {
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING $ex
)
"
execsql_test 2.$tn.3 "
SELECT min(c) OVER win, max(c) OVER win, sum(c) OVER win FROM t3
WINDOW win AS (
ORDER BY c, b, a
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW $ex
) ORDER BY a, b, c;
"
}
==========
@ -154,6 +162,20 @@ foreach {tn frame} {
"
}
==========
execsql_test 4.0 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INTEGER, b INTEGER);
INSERT INTO t1 VALUES
(NULL, 1), (NULL, 2), (NULL, 3), (10, 4), (10, 5);
}
execsql_test 4.1 {
SELECT sum(b) OVER (
ORDER BY a RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING
) FROM t1 ORDER BY 1;
}
finish_test

File diff suppressed because it is too large Load Diff