]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem causing the planner to generate sub-optimal plans for some queries
authordan <dan@noemail.net>
Fri, 16 Dec 2016 15:05:40 +0000 (15:05 +0000)
committerdan <dan@noemail.net>
Fri, 16 Dec 2016 15:05:40 +0000 (15:05 +0000)
that use recursive WITH sub-queries with LIMIT clauses.

FossilOrigin-Name: 053a149cc8244a7f85137129cfcb8622efe90306

manifest
manifest.uuid
src/select.c
test/with3.test

index ca47317dffcbff25019b3d6ebc43d0ef5306b9a4..b952a95fe58710a1ff0b71ae8ddca5670e3dbb76 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C All\stemp.sqlite_master\sto\sbe\sused\sas\san\salias\sfor\ssqlite_temp_master.
-D 2016-12-16T01:00:21.326
+C Fix\sa\sproblem\scausing\sthe\splanner\sto\sgenerate\ssub-optimal\splans\sfor\ssome\squeries\nthat\suse\srecursive\sWITH\ssub-queries\swith\sLIMIT\sclauses.
+D 2016-12-16T15:05:40.539
 F Makefile.in c194b58fe00c370a48ac6ae6945e92a7781db1c8
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
@@ -388,7 +388,7 @@ F src/printf.c f94da4935d1dd25420ac50c6745db1deb35e07c1
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c bb070cf5f23611c44ab7e4788803684e385fc3fb
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
-F src/select.c 204491a5e09a66380a067943d8651af8bda1d358
+F src/select.c e4c687333c5fa33b1ce05c37bfbea6e09d3dbee9
 F src/shell.c f1c7fde7a83421e6ed620df41d200674a2327e65
 F src/sqlite.h.in e8e2d108d82647f0a812fdb74accf91c1ec08ddc
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
@@ -1436,7 +1436,7 @@ F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
 F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
 F test/with1.test cef099a491eac9874f2c28bd2dc86394fb3e47b3
 F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87
-F test/with3.test 511bacdbe41c49cf34f9fd1bd3245fe1575bca98
+F test/with3.test e71604a0e53cba82bc04c703987cb1d6751ec0b6
 F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
 F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701
 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
@@ -1536,7 +1536,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 4e3749127e7249f46e17bfabc614b0876f60565a
-R 27200c6ed9ee619c25ffbd7fc5b77433
-U drh
-Z dbd7760e0bb1a8efbcd514dce9f9a0ad
+P 8d646905b830d5bb29092e103ac5cb499b3c7e5a
+R 147fd014e993bf990284d024622f7825
+U dan
+Z ececc9941f2e958f0280d3f055b0e66d
index da81604870d75efed9d11421cf795ea5dc413129..7e8bf801a0e23c7f5c644e94ab12629db394f6e3 100644 (file)
@@ -1 +1 @@
-8d646905b830d5bb29092e103ac5cb499b3c7e5a
\ No newline at end of file
+053a149cc8244a7f85137129cfcb8622efe90306
\ No newline at end of file
index 83d9540cf047d26f982f115563280945cf9882cc..18344b7d43bfb95797842cd7752b388c90d1224f 100644 (file)
@@ -2037,6 +2037,7 @@ static void generateWithRecursiveQuery(
 
   /* Process the LIMIT and OFFSET clauses, if they exist */
   addrBreak = sqlite3VdbeMakeLabel(v);
+  p->nSelectRow = 320;  /* 4 billion rows */
   computeLimitRegisters(pParse, p, addrBreak);
   pLimit = p->pLimit;
   pOffset = p->pOffset;
@@ -5170,7 +5171,9 @@ int sqlite3Select(
   /* Set the limiter.
   */
   iEnd = sqlite3VdbeMakeLabel(v);
-  p->nSelectRow = 320;  /* 4 billion rows */
+  if( (p->selFlags & SF_FixedLimit)==0 ){
+    p->nSelectRow = 320;  /* 4 billion rows */
+  }
   computeLimitRegisters(pParse, p, iEnd);
   if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
     sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen);
index 62e88441ab41c5f1c9bb6bc635203586a4ce1c58..5540a7fca6de6a561d94e9c36ba44f2cc7ab6e3e 100644 (file)
@@ -61,4 +61,60 @@ do_execsql_test 2.1 {
   SELECT * FROM t1;
 } {200}
 
+#-------------------------------------------------------------------------
+# Test that the planner notices LIMIT clauses on recursive WITH queries.
+#
+
+ifcapable analyze {
+  do_execsql_test 3.1.1 {
+    CREATE TABLE y1(a, b);
+    CREATE INDEX y1a ON y1(a);
+
+    WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000)
+      INSERT INTO y1 SELECT i%10, i FROM cnt;
+    ANALYZE;
+
+  }
+
+  do_eqp_test 3.1.2 {
+    WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1)
+    SELECT * FROM cnt, y1 WHERE i=a
+  } {
+    3 0 0 {SCAN TABLE cnt} 
+    1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)}
+    0 0 0 {SCAN SUBQUERY 1} 
+    0 1 1 {SEARCH TABLE y1 USING INDEX y1a (a=?)}
+  }
+
+  do_eqp_test 3.1.3 {
+    WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000000)
+    SELECT * FROM cnt, y1 WHERE i=a
+  } {
+    3 0 0 {SCAN TABLE cnt} 
+    1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)}
+    0 0 1 {SCAN TABLE y1} 
+    0 1 0 {SEARCH SUBQUERY 1 USING AUTOMATIC COVERING INDEX (i=?)}
+  }
+}
+
+do_execsql_test 3.2.1 {
+  CREATE TABLE w1(pk INTEGER PRIMARY KEY, x INTEGER);
+  CREATE TABLE w2(pk INTEGER PRIMARY KEY);
+}
+
+do_eqp_test 3.2.2 {
+  WITH RECURSIVE c(w,id) AS (SELECT 0, (SELECT pk FROM w2 LIMIT 1)
+     UNION ALL SELECT c.w + 1, x FROM w1, c LIMIT 1)
+     SELECT * FROM c, w2, w1
+     WHERE c.id=w2.pk AND c.id=w1.pk;
+} {
+  2 0 0 {EXECUTE SCALAR SUBQUERY 3} 
+  3 0 0 {SCAN TABLE w2} 
+  4 0 0 {SCAN TABLE w1}
+  4 1 1 {SCAN TABLE c} 
+  1 0 0 {COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)} 0 0 0 {SCAN SUBQUERY 1}
+  0 1 1 {SEARCH TABLE w2 USING INTEGER PRIMARY KEY (rowid=?)} 
+  0 2 2 {SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?)}
+}
+
 finish_test