]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Have where.c ignore any plan from a virtual table that tries to use LIMIT/OFFSET...
authordan <Dan Kennedy>
Fri, 26 Apr 2024 17:19:59 +0000 (17:19 +0000)
committerdan <Dan Kennedy>
Fri, 26 Apr 2024 17:19:59 +0000 (17:19 +0000)
FossilOrigin-Name: 7d30596496c6a7a37b925f13d8d94d5de224ec31bb86594fa4cc07b10082e776

manifest
manifest.uuid
src/where.c
test/bestindexC.test

index 8aa5658ec19d8074a828cae0215046285dbf0148..f0eb8e05e2b7a22a5db7a6b6886e0d4adedf87d6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Further\sfixes\sand\simprovements\sto\sthe\sgenerate_series()\senhancements\son\nthis\sbranch.
-D 2024-04-26T17:09:33.571
+C Have\swhere.c\signore\sany\splan\sfrom\sa\svirtual\stable\sthat\stries\sto\suse\sLIMIT/OFFSET\swithout\salso\susing\sall\sWHERE\sconstraints.
+D 2024-04-26T17:19:59.258
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -836,7 +836,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
 F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
-F src/where.c 447d8761632fb0a18b03077161415d9713cbd0a81bf34a35cee63480e5c401c5
+F src/where.c 0ef9638651b900d64d7e1e877af37cd7900159ff875547ec29b918a1497e5c9c
 F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
 F src/wherecode.c 1f6940349e92a6e056aecd70163b00f331554c815c362b4cc80906c48151d73d
 F src/whereexpr.c e8e26dbdefa3d89c726251c8b9690ad9766ad00b92cfd11c54402e7dd1350ce7
@@ -936,7 +936,7 @@ F test/bestindex8.test 333ad8c6a554b885a49b68c019166eda92b05f493a92b36b0acdf7f76
 F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0
 F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f
 F test/bestindexB.test 328b97b69cd1a20928d5997f9ecb04d2e00f1d18e19ab27f9e9adb44d7bc51ce
-F test/bestindexC.test c4957155d9bd21a3e5bdd7cf32e9753b721fff7a373fdc7a8769a2a072877b7f
+F test/bestindexC.test 6a632d3b58ffce7b9d4492c93901384d5ede891b0db76c30f90805eaccacc3bc
 F test/between.test b9a65fb065391980119e8a781a7409d3fcf059d89968279c750e190a9a1d5263
 F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
@@ -2186,8 +2186,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P a94e2cd02873c283d46bf6c21d0306ad454881d7882bb167d043cc79f79a2396
-R 321007e70e23799770941a10ae3004c2
-U drh
-Z 725229cc9017e5eea01f2ec07aa5dfdd
+P b7d9bd7ee2f4100608063fdf7648f290351465d393bc876a89704f643358853e
+R 730af36fce33d6528809ae8d9bef3e6c
+U dan
+Z 5c5972d6c199bce591c9d5b5a3c5a03a
 # Remove this line to create a well-formed Fossil manifest.
index 269ea1f24e1b21478b0ab0eb461912e2741f110a..a43f8e3abfadd984358ef87c35826567e834303c 100644 (file)
@@ -1 +1 @@
-b7d9bd7ee2f4100608063fdf7648f290351465d393bc876a89704f643358853e
\ No newline at end of file
+7d30596496c6a7a37b925f13d8d94d5de224ec31bb86594fa4cc07b10082e776
\ No newline at end of file
index 39210ddb28c726312fb340be1ce0e88de46f9ff9..820e9224903ed1e2950bfec2e4db8867ee1c21a7 100644 (file)
@@ -4057,6 +4057,21 @@ static int isLimitTerm(WhereTerm *pTerm){
       && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
 }
 
+/*
+** Return true if the first nCons constraints in the pUsage array are
+** marked as in-use (have argvIndex>0). False otherwise.
+*/
+static int allConstraintsUsed(
+  struct sqlite3_index_constraint_usage *aUsage, 
+  int nCons
+){
+  int ii;
+  for(ii=0; ii<nCons; ii++){
+    if( aUsage[ii].argvIndex<=0 ) return 0;
+  }
+  return 1;
+}
+
 /*
 ** Argument pIdxInfo is already populated with all constraints that may
 ** be used by the virtual table identified by pBuilder->pNew->iTab. This
@@ -4197,13 +4212,20 @@ static int whereLoopAddVirtualOne(
         *pbIn = 1; assert( (mExclude & WO_IN)==0 );
       }
 
+      /* Unless pbRetryLimit is non-NULL, there should be no LIMIT/OFFSET
+      ** terms. And if there are any, they should follow all other terms. */
       assert( pbRetryLimit || !isLimitTerm(pTerm) );
-      if( isLimitTerm(pTerm) && *pbIn ){
+      assert( !isLimitTerm(pTerm) || i>=nConstraint-2 );
+      assert( !isLimitTerm(pTerm) || i==nConstraint-1 || isLimitTerm(pTerm+1) );
+
+      if( isLimitTerm(pTerm) && (*pbIn || !allConstraintsUsed(pUsage, i)) ){
         /* If there is an IN(...) term handled as an == (separate call to
         ** xFilter for each value on the RHS of the IN) and a LIMIT or
-        ** OFFSET term handled as well, the plan is unusable. Set output
-        ** variable *pbRetryLimit to true to tell the caller to retry with
-        ** LIMIT and OFFSET disabled. */
+        ** OFFSET term handled as well, the plan is unusable. Similarly,
+        ** if there is a LIMIT/OFFSET and there are other unused terms,
+        ** the plan cannot be used. In these cases set variable *pbRetryLimit
+        ** to true to tell the caller to retry with LIMIT and OFFSET 
+        ** disabled. */
         if( pIdxInfo->needToFreeIdxStr ){
           sqlite3_free(pIdxInfo->idxStr);
           pIdxInfo->idxStr = 0;
index 769f1601db7f2e55ca1deedcc748c00c9bb18e9f..d854216008206f10205e8027915fc22be0a3f7c7 100644 (file)
@@ -1,4 +1,4 @@
-# 2023-10-26
+# 2024-04-26
 #
 # The author disclaims copyright to this source code.  In place of
 # a legal notice, here is a blessing:
@@ -13,7 +13,7 @@
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
-set testprefix bestindexB
+set testprefix bestindexC
 
 ifcapable !vtab {
   finish_test
@@ -154,4 +154,8 @@ do_execsql_test 3.3 {
   SELECT * FROM generate_series(1, 5) WHERE value = (value & 14) LIMIT 3
 } {2 4}
 
+do_execsql_test 3.4 {
+  SELECT value FROM generate_series(1,10) WHERE value>2 LIMIT 4 OFFSET 1;
+} {4 5 6 7}
+
 finish_test