Fix problems with RANGE windows and string, blob and NULL values.
FossilOrigin-Name: cebe09e11cc91d9776f259dd9b87e9c760a460f53ba6fa36481dfe58f77ad417
This commit is contained in:
parent
bf84515a2b
commit
1e7cb19be3
22
manifest
22
manifest
@ -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
|
||||
|
@ -1 +1 @@
|
||||
f2d5f7a24c7aa483c579706c5bd7268a74da6d53025d78fa8642908c2aed1707
|
||||
cebe09e11cc91d9776f259dd9b87e9c760a460f53ba6fa36481dfe58f77ad417
|
@ -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}
|
||||
|
33
src/window.c
33
src/window.c
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
2195
test/window8.test
2195
test/window8.test
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user