From: dan Date: Mon, 15 Dec 2025 18:45:22 +0000 (+0000) Subject: Fix for optimizing "SELECT DISTINCT ...cols... FROM vtab" in cases where the virtual... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a1dbb7a93edc724e745a4598bf0c08733b93e6d4;p=thirdparty%2Fsqlite.git Fix for optimizing "SELECT DISTINCT ...cols... FROM vtab" in cases where the virtual table implementation is able to deliver results sorted by "...cols...". FossilOrigin-Name: 80c0d922937615422e813593ac4eb83c3040a417fad97dba18a549de50a91b72 --- diff --git a/manifest b/manifest index d2c6733baf..c87275a261 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\svtablog\sextension\sso\sthat\sit\sshows\sthe\svalue\sof\nsqlite3_vtab_distinct()\sin\sxBestIndex,\sand\sso\sthat\sprovides\sthe\snew\nconsume_order_by\soption\sthat\scan\scause\sxBestIndex\sto\sset\sthe\norderByConsumed\sflag. -D 2025-12-15T17:32:56.417 +C Fix\sfor\soptimizing\s"SELECT\sDISTINCT\s...cols...\sFROM\svtab"\sin\scases\swhere\sthe\svirtual\stable\simplementation\sis\sable\sto\sdeliver\sresults\ssorted\sby\s"...cols...". +D 2025-12-15T18:45:22.198 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -818,7 +818,7 @@ F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab F src/wal.c 505a98fbc599a971d92cb90371cf54546c404cd61e04fd093e7b0c8ff978f9b6 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014 -F src/where.c 287324fe73a0ae8e55b3be89bb2fe4148e3a8394e1e2f10ed2113713a037d8a3 +F src/where.c f289b601590e3d2eab9ae70d47a7a31d0f4883a49cd6fdc466bfbd6f9be67379 F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da F src/wherecode.c 71c5c6804b7f882dec8ec858758accae02fcfca13df3cc720f1f258e663ec7c5 F src/whereexpr.c 5f412da6616e26b8000dd736a5ce5da0018dff0933cd656bbb25f407db16bf93 @@ -911,13 +911,14 @@ F test/bestindex4.test 3039894f2dad50f3a68443dffad1b44c9b067ac03870102df1ce3d9a4 F test/bestindex5.test a0c90b2dad7836e80a01379e200e5f8ec9476d49b349af02c0dbff2fb75dc98d F test/bestindex6.test 16942535b551273f3ad9df8d7cc4b7f22b1fcd8882714358859eb049a6f99dd4 F test/bestindex7.test f094c669a6400777f4d2ddc3ed28e39169f1adb5be3d59b55f22ccf8c414b71e -F test/bestindex8.test b63a4f171a2c83d481bb14c431a8b72e85d27b2ffdaa0435a95d58ca941678f9 +F test/bestindex8.test b61b0aa136440752eb611aa60fe90d63b07ecdb911496792699eebd500d15065 F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0 F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f F test/bestindexB.test 328b97b69cd1a20928d5997f9ecb04d2e00f1d18e19ab27f9e9adb44d7bc51ce F test/bestindexC.test 95b4a527b1a5d07951d731604a6d4cf7e5a806b39cea0e7819d4c9667e11c3fc F test/bestindexD.test 6a8f6f84990bcf17dfa59652a1f935beddb7afd96f8302830fbc86b0a13df3c3 F test/bestindexE.test 297f3ea8500a8f3c17d6f78e55bdfee089064c6144ee84a110bd005a03338f49 +F test/bestindexF.test f4c03a029d8748a1860565c81b617d9bbfdacf0699122dfd9cc30c83924c7709 F test/between.test e7587149796101cbe8d5f8abae8d2a7b87f04d8226610aa1091615005dcf4d54 F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc @@ -2184,8 +2185,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 881534858de8bccffca53e7256a725378a98a354e792374d972b120880c2ae78 -R 516b4041a52e0f6a1c6a30026e823eb8 -U drh -Z 2dd134e29e053422231bfb06d9c85c41 +P b158fe929929ae209f2603b11a2c4f44ad9147f6b2ce09a10ec1f92429402631 +R 87e950431c946f719f368f65df2a4ac5 +U dan +Z 4fe9c24f00a542c21fce94ac75a3f7f8 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b1dafb2f7a..8e660a57b0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b158fe929929ae209f2603b11a2c4f44ad9147f6b2ce09a10ec1f92429402631 +80c0d922937615422e813593ac4eb83c3040a417fad97dba18a549de50a91b72 diff --git a/src/where.c b/src/where.c index c4f2c55435..ceb876ba16 100644 --- a/src/where.c +++ b/src/where.c @@ -5100,9 +5100,7 @@ static i8 wherePathSatisfiesOrderBy( pLoop = pLast; } if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ - if( pLoop->u.vtab.isOrdered - && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY) - ){ + if( pLoop->u.vtab.isOrdered && pWInfo->pOrderBy==pOrderBy ){ obSat = obDone; }else{ /* No further ORDER BY terms may be matched. So this call should diff --git a/test/bestindex8.test b/test/bestindex8.test index 3ed7f6703e..d7b6f3e925 100644 --- a/test/bestindex8.test +++ b/test/bestindex8.test @@ -80,8 +80,8 @@ do_execsql_test 1.0 { foreach {tn sql bDistinct idxinsert bConsumed res} { 1 "SELECT a, b FROM vt1" 0 0 0 {a b c d a b c d} - 2 "SELECT DISTINCT a, b FROM vt1" 2 1 1 {a b c d} - 3 "SELECT DISTINCT a FROM vt1" 2 1 1 {a c} + 2 "SELECT DISTINCT a, b FROM vt1" 2 0 1 {a b c d} + 3 "SELECT DISTINCT a FROM vt1" 2 0 1 {a c} 4 "SELECT DISTINCT b FROM vt1" 2 1 0 {b d} 5 "SELECT DISTINCT b FROM vt1 ORDER BY a" 0 1 1 {b d} 6 "SELECT DISTINCT t0.c0 FROM vt1, t0 ORDER BY vt1.a" 0 1 1 {1 0} @@ -89,8 +89,8 @@ foreach {tn sql bDistinct idxinsert bConsumed res} { 8 "SELECT DISTINCT a, b FROM vt1 ORDER BY a" 0 1 1 {a b c d} 9 "SELECT DISTINCT a FROM vt1 ORDER BY a, b" 0 1 1 {a c} - 10 "SELECT DISTINCT a, b FROM vt1 WHERE b='b'" 2 1 1 {a b} - 11 "SELECT DISTINCT a, b FROM vt1 WHERE +b='b'" 2 1 1 {a b} + 10 "SELECT DISTINCT a, b FROM vt1 WHERE b='b'" 2 0 1 {a b} + 11 "SELECT DISTINCT a, b FROM vt1 WHERE +b='b'" 2 0 1 {a b} } { set ::lBestIndexDistinct "" set ::lOrderByConsumed 0 diff --git a/test/bestindexF.test b/test/bestindexF.test new file mode 100644 index 0000000000..6854af0bba --- /dev/null +++ b/test/bestindexF.test @@ -0,0 +1,97 @@ +# 2025-12-15 +# +# 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. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix bestindexF + +ifcapable !vtab { + finish_test + return +} + + +proc vtab_command {method args} { + switch -- $method { + xConnect { + return "CREATE TABLE t1(a, b, c)" + } + + xBestIndex { + set hdl [lindex $args 0] + set ::vtab_orderby [$hdl orderby] + set ::vtab_distinct [$hdl distinct] + + if {$::vtab_orderby == "{column 0 desc 0} {column 1 desc 0}" + || $::vtab_orderby == "{column 0 desc 0}" + } { + return [list orderby 1] + } + + return "" + } + + xFilter { + set sql { + SELECT 1, 1, 'a', 555 + UNION ALL + SELECT 2, 1, 'a', NULL + UNION ALL + SELECT 3, 1, 'b', 'text' + UNION ALL + SELECT 4, 2, 'a', 3.14 + UNION ALL + SELECT 5, 2, 'b', 0 + } + return [list sql $sql] + } + } + + return {} +} + +register_tcl_module db + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING tcl(vtab_command) +} + +proc uses_idxinsert {sql} { + return [expr [lsearch [db eval "explain $sql"] IdxInsert]>=0] +} +proc do_idxinsert_test {tn sql res} { + set uses [uses_idxinsert $sql] + uplevel [list do_execsql_test $tn "SELECT $uses ; $sql" $res] +} + +do_idxinsert_test 1.1.1 { + SELECT DISTINCT a, b FROM t1 +} {0 1 a 1 b 2 a 2 b} + +do_test 1.1.2 { + list $::vtab_distinct $::vtab_orderby +} {2 {{column 0 desc 0} {column 1 desc 0}}} + +do_execsql_test 1.3 { + CREATE TABLE t0(c0); + INSERT INTO t0 VALUES(0); + INSERT INTO t0 VALUES(1); +} + +do_idxinsert_test 1.4.1 { + SELECT DISTINCT t0.c0 FROM t1, t0 ORDER BY t1.a; +} {1 0 1} +do_test 1.4.2 { + list $::vtab_distinct $::vtab_orderby +} {0 {{column 0 desc 0}}} + +finish_test