From: drh Date: Tue, 6 Oct 2015 17:27:18 +0000 (+0000) Subject: Fix the LIMIT and OFFSET handling for UNION ALL queries that contain a X-Git-Tag: version-3.9.0~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9f1ef45f6afbea1ef46a963b25bfeb90806e0fca;p=thirdparty%2Fsqlite.git Fix the LIMIT and OFFSET handling for UNION ALL queries that contain a subquery with ORDER BY on the right-hand side. Fix for ticket [b65cb2c8d91f668584]. FossilOrigin-Name: 4b631364354068af95a01630469cb6fbfe8b52fd --- diff --git a/manifest b/manifest index 57806324c5..f4bc8f8a8c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Adjustments\sto\ssqlite3MemoryBarrier()\swhen\scompiling\swith\sMSVC\sand/or\sWinCE. -D 2015-10-06T01:44:53.212 +C Fix\sthe\sLIMIT\sand\sOFFSET\shandling\sfor\sUNION\sALL\squeries\sthat\scontain\sa\s\nsubquery\swith\sORDER\sBY\son\sthe\sright-hand\sside.\s\sFix\sfor\sticket\n[b65cb2c8d91f668584]. +D 2015-10-06T17:27:18.737 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -342,7 +342,7 @@ F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c e49f4af9748c9e0cc1bf864b4190aa94841c8409 +F src/select.c 8fb8cb0230aed9b12b3582ddc366ffbc549041d7 F src/shell.c dfd18e56fcb88dd79378774e9bc3246a9bd52243 F src/sqlite.h.in 4b76d74d69af48c534c58fb723137dc6944bdedc F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad @@ -900,6 +900,7 @@ F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62 F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3 F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1 +F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2 F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394 F test/orderby1.test 870e150450437d3980badbde3d0166b81d9e33f6 F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04 @@ -1391,7 +1392,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f2f0184e9e1c9f121ee2ac864cd28c8cd8efecb5 -R e9c328a2763ce5ce6b257c253eecdcc8 -U mistachkin -Z 85dfdec3788a9562e3ed3a33e9d7dade +P 3168326ebfa1c961d8fc6435453b02be23d910cc +R 3e47dd30d61b7e1fff555418e15c6a1d +U drh +Z e6b33681aca5812f13faee0e253c4fc3 diff --git a/manifest.uuid b/manifest.uuid index 1515ed061b..b73745c378 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3168326ebfa1c961d8fc6435453b02be23d910cc \ No newline at end of file +4b631364354068af95a01630469cb6fbfe8b52fd \ No newline at end of file diff --git a/src/select.c b/src/select.c index 8430a00f37..c6c722cbc5 100644 --- a/src/select.c +++ b/src/select.c @@ -2273,6 +2273,16 @@ static int multiSelect( if( p->iLimit ){ addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); VdbeComment((v, "Jump ahead if LIMIT reached")); + if( p->iOffset ){ + int addr2; + sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1); + addr2 = sqlite3VdbeAddOp1(v, OP_IfPos, p->iOffset); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_SCopy, p->iLimit, p->iOffset+1); + sqlite3VdbeJumpHere(v, addr2); + addr2 = sqlite3VdbeAddOp1(v, OP_IfPos, p->iLimit); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Integer, -1, p->iOffset+1); + sqlite3VdbeJumpHere(v, addr2); + } } explainSetInteger(iSub2, pParse->iNextSelectId); rc = sqlite3Select(pParse, p, &dest); diff --git a/test/offset1.test b/test/offset1.test new file mode 100644 index 0000000000..91dc0b00a1 --- /dev/null +++ b/test/offset1.test @@ -0,0 +1,161 @@ +# 2015-10-06 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file implements test cases for the [b65cb2c8d91f6685841d7d1e13b6] +# bug: Correct handling of LIMIT and OFFSET on a UNION ALL query where +# the right-hand SELECT contains an ORDER BY in a subquery. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +ifcapable !compound { + finish_test + return +} + +do_execsql_test offset1-1.1 { + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'); + CREATE TABLE t2(x,y); + INSERT INTO t2 VALUES(8,'y'),(9,'z'),(6,'w'),(7,'x'); + SELECT count(*) FROM t1, t2; +} {20} + +do_execsql_test offset1-1.2.0 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 0; +} {1 a 2 b 3 c} +do_execsql_test offset1-1.2.1 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 1; +} {2 b 3 c 4 d} +do_execsql_test offset1-1.2.2 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 2; +} {3 c 4 d 5 e} +do_execsql_test offset1-1.2.3 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 3; +} {4 d 5 e 6 w} +do_execsql_test offset1-1.2.4 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 4; +} {5 e 6 w 7 x} +do_execsql_test offset1-1.2.5 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 5; +} {6 w 7 x 8 y} +do_execsql_test offset1-1.2.6 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 6; +} {7 x 8 y 9 z} +do_execsql_test offset1-1.2.7 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 7; +} {8 y 9 z} +do_execsql_test offset1-1.2.8 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 8; +} {9 z} +do_execsql_test offset1-1.2.9 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 9; +} {} + +do_execsql_test offset1-1.3.0 { + SELECT * FROM t1 LIMIT 0; +} {} + +do_execsql_test offset1-1.4.0 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 0 OFFSET 1; +} {} +do_execsql_test offset1-1.4.1 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 1 OFFSET 1; +} {2 b} +do_execsql_test offset1-1.4.2 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 2 OFFSET 1; +} {2 b 3 c} +do_execsql_test offset1-1.4.3 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 3 OFFSET 1; +} {2 b 3 c 4 d} +do_execsql_test offset1-1.4.4 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 4 OFFSET 1; +} {2 b 3 c 4 d 5 e} +do_execsql_test offset1-1.4.5 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 5 OFFSET 1; +} {2 b 3 c 4 d 5 e 6 w} +do_execsql_test offset1-1.4.6 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 6 OFFSET 1; +} {2 b 3 c 4 d 5 e 6 w 7 x} +do_execsql_test offset1-1.4.7 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 7 OFFSET 1; +} {2 b 3 c 4 d 5 e 6 w 7 x 8 y} +do_execsql_test offset1-1.4.8 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 8 OFFSET 1; +} {2 b 3 c 4 d 5 e 6 w 7 x 8 y 9 z} +do_execsql_test offset1-1.4.9 { + SELECT a, b FROM t1 + UNION ALL + SELECT * FROM (SELECT x, y FROM t2 ORDER BY y) + LIMIT 9 OFFSET 1; +} {2 b 3 c 4 d 5 e 6 w 7 x 8 y 9 z} + + + +finish_test