From: dan Date: Fri, 26 Apr 2024 17:19:59 +0000 (+0000) Subject: Have where.c ignore any plan from a virtual table that tries to use LIMIT/OFFSET... X-Git-Tag: version-3.46.0~40^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=297472a2fcae79eb2e531d8c93fdb7f36725afdb;p=thirdparty%2Fsqlite.git Have where.c ignore any plan from a virtual table that tries to use LIMIT/OFFSET without also using all WHERE constraints. FossilOrigin-Name: 7d30596496c6a7a37b925f13d8d94d5de224ec31bb86594fa4cc07b10082e776 --- diff --git a/manifest b/manifest index 8aa5658ec1..f0eb8e05e2 100644 --- 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. diff --git a/manifest.uuid b/manifest.uuid index 269ea1f24e..a43f8e3abf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b7d9bd7ee2f4100608063fdf7648f290351465d393bc876a89704f643358853e \ No newline at end of file +7d30596496c6a7a37b925f13d8d94d5de224ec31bb86594fa4cc07b10082e776 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 39210ddb28..820e922490 100644 --- a/src/where.c +++ b/src/where.c @@ -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; iipNew->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; diff --git a/test/bestindexC.test b/test/bestindexC.test index 769f1601db..d854216008 100644 --- a/test/bestindexC.test +++ b/test/bestindexC.test @@ -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