mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Avoid an OP_Next in cases where an IN(...) query against a UNIQUE index may return at most 1 row.
FossilOrigin-Name: 560f64157d2fe40e107582eebb6526185c9c43305e364f4132e182dbec5b210a
This commit is contained in:
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
|||||||
C Avoid\s32-bit\soverflow\swhen\scalculating\sncycle\sfor\s".scanstats\svm".
|
C Avoid\san\sOP_Next\sin\scases\swhere\san\sIN(...)\squery\sagainst\sa\sUNIQUE\sindex\smay\sreturn\sat\smost\s1\srow.
|
||||||
D 2024-04-30T19:34:15.474
|
D 2024-05-01T19:48:24.190
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -838,7 +838,7 @@ F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
|||||||
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
||||||
F src/where.c 0ef9638651b900d64d7e1e877af37cd7900159ff875547ec29b918a1497e5c9c
|
F src/where.c 0ef9638651b900d64d7e1e877af37cd7900159ff875547ec29b918a1497e5c9c
|
||||||
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
|
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
|
||||||
F src/wherecode.c 1f6940349e92a6e056aecd70163b00f331554c815c362b4cc80906c48151d73d
|
F src/wherecode.c b73b5bcd0840491e8faa126fbf933e3bda0d9bf85222ddc7ff608154f0f86d1e
|
||||||
F src/whereexpr.c 67d15caf88a1a9528283d68ff578e024cf9fe810b517bb0343e5aaf695ad97dd
|
F src/whereexpr.c 67d15caf88a1a9528283d68ff578e024cf9fe810b517bb0343e5aaf695ad97dd
|
||||||
F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2
|
F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
@ -1278,6 +1278,7 @@ F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
|||||||
F test/in4.test bb767ec1cfd1730256f0a83219f0acda36bc251b63f8b8bb7d8c7cff17875a4f
|
F test/in4.test bb767ec1cfd1730256f0a83219f0acda36bc251b63f8b8bb7d8c7cff17875a4f
|
||||||
F test/in5.test 4fd79c70dfa0681313e8cdca07f5ff0400bdc0e20f808a5c59eaef1e4b48082a
|
F test/in5.test 4fd79c70dfa0681313e8cdca07f5ff0400bdc0e20f808a5c59eaef1e4b48082a
|
||||||
F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
|
F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
|
||||||
|
F test/in7.test e0b3bd735c13547f038f386440152ad2642a066e9f96366552763bb5455117d0
|
||||||
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
|
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
|
||||||
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
|
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
|
||||||
F test/incrblob3.test 67621a04b3084113bf38ce03797d70eca012d9d8f948193b8f655df577b0da6f
|
F test/incrblob3.test 67621a04b3084113bf38ce03797d70eca012d9d8f948193b8f655df577b0da6f
|
||||||
@ -2186,8 +2187,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 5f6c079d847e3664ec5acaf1b3e989efe0d548c211ae4a18936162b36df89065
|
P 2858efa06d4fc7b412b892f35f5e9a766b467b4a5b74d602a030d25443f9efb4
|
||||||
R 903fbc18fbeeda59fd5e86360c55f235
|
R 5dedafa0dd1df259fa093801bd417269
|
||||||
|
T *branch * unique-in-opt
|
||||||
|
T *sym-unique-in-opt *
|
||||||
|
T -sym-trunk *
|
||||||
U dan
|
U dan
|
||||||
Z 0ade4d9c1bbdd68ad336341e8aad91d0
|
Z 057540a67356c4bc1a4b77adc8c49f86
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
2858efa06d4fc7b412b892f35f5e9a766b467b4a5b74d602a030d25443f9efb4
|
560f64157d2fe40e107582eebb6526185c9c43305e364f4132e182dbec5b210a
|
@ -1337,6 +1337,27 @@ static SQLITE_NOINLINE void filterPullDown(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...)
|
||||||
|
** operator. Return true if level pLoop is guaranteed to visit only one
|
||||||
|
** row for each key generated for the index.
|
||||||
|
*/
|
||||||
|
static int whereLoopIsOneRow(WhereLoop *pLoop){
|
||||||
|
if( pLoop->u.btree.pIndex->onError
|
||||||
|
&& pLoop->nSkip==0
|
||||||
|
&& pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol
|
||||||
|
){
|
||||||
|
int ii;
|
||||||
|
for(ii=0; ii<pLoop->u.btree.nEq; ii++){
|
||||||
|
if( pLoop->aLTerm[ii]->eOperator & (WO_IS|WO_ISNULL) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate code for the start of the iLevel-th loop in the WHERE clause
|
** Generate code for the start of the iLevel-th loop in the WHERE clause
|
||||||
** implementation described by pWInfo.
|
** implementation described by pWInfo.
|
||||||
@ -2084,7 +2105,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Record the instruction used to terminate the loop. */
|
/* Record the instruction used to terminate the loop. */
|
||||||
if( pLoop->wsFlags & WHERE_ONEROW ){
|
if( (pLoop->wsFlags & WHERE_ONEROW)
|
||||||
|
|| (pLevel->u.in.nIn && whereLoopIsOneRow(pLoop))
|
||||||
|
){
|
||||||
pLevel->op = OP_Noop;
|
pLevel->op = OP_Noop;
|
||||||
}else if( bRev ){
|
}else if( bRev ){
|
||||||
pLevel->op = OP_Prev;
|
pLevel->op = OP_Prev;
|
||||||
|
107
test/in7.test
Normal file
107
test/in7.test
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# 2024-05-01
|
||||||
|
#
|
||||||
|
# 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 in7
|
||||||
|
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
CREATE TABLE t1(a, b, c PRIMARY KEY);
|
||||||
|
CREATE TABLE t2(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach {tn nNext idx sql} {
|
||||||
|
1 1 {
|
||||||
|
CREATE INDEX i1 ON t1(a, b);
|
||||||
|
} {
|
||||||
|
SELECT * FROM t1 WHERE (a, b) IN (SELECT x, y FROM t2)
|
||||||
|
}
|
||||||
|
|
||||||
|
2 0 {
|
||||||
|
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||||
|
} {
|
||||||
|
SELECT * FROM t1 WHERE (a, b) IN (SELECT x, y FROM t2)
|
||||||
|
}
|
||||||
|
|
||||||
|
3 0 {
|
||||||
|
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||||
|
} {
|
||||||
|
SELECT * FROM t1 WHERE a = ? AND b = ?
|
||||||
|
}
|
||||||
|
|
||||||
|
3 1 {
|
||||||
|
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||||
|
} {
|
||||||
|
SELECT * FROM t1 WHERE a = ? AND b IS ?
|
||||||
|
}
|
||||||
|
|
||||||
|
4 0 {
|
||||||
|
CREATE UNIQUE INDEX i1 ON t1(a, b);
|
||||||
|
} {
|
||||||
|
SELECT * FROM t1 WHERE a = ? AND b IN (?, ?, ?);
|
||||||
|
}
|
||||||
|
|
||||||
|
5 1 {
|
||||||
|
CREATE UNIQUE INDEX i1 ON t1(a, b, c);
|
||||||
|
} {
|
||||||
|
SELECT * FROM t1 WHERE a = ? AND b = ?
|
||||||
|
}
|
||||||
|
|
||||||
|
6 0 {
|
||||||
|
} {
|
||||||
|
SELECT * FROM t1 WHERE c IN (SELECT z FROM t2)
|
||||||
|
}
|
||||||
|
|
||||||
|
7 0 {
|
||||||
|
} {
|
||||||
|
SELECT * FROM t1 WHERE (a, c) IN (SELECT z, x FROM t2)
|
||||||
|
}
|
||||||
|
|
||||||
|
8 1 {
|
||||||
|
} {
|
||||||
|
SELECT * FROM t1 WHERE a IN (SELECT z FROM t2)
|
||||||
|
}
|
||||||
|
} {
|
||||||
|
do_test 1.1.$tn {
|
||||||
|
execsql BEGIN
|
||||||
|
execsql $idx
|
||||||
|
|
||||||
|
catch { array unset root_to_tbl }
|
||||||
|
catch { array unset csr_to_root }
|
||||||
|
|
||||||
|
db eval {SELECT rootpage, tbl_name FROM sqlite_schema} {
|
||||||
|
set root_to_tbl($rootpage) $tbl_name
|
||||||
|
}
|
||||||
|
|
||||||
|
set nSeen 0
|
||||||
|
db eval "explain $sql" {
|
||||||
|
if {$opcode=="OpenRead"} {
|
||||||
|
set csr_to_root($p1) $p2
|
||||||
|
}
|
||||||
|
if {$opcode=="Next"} {
|
||||||
|
catch {
|
||||||
|
set root $csr_to_root($p1)
|
||||||
|
set tbl $root_to_tbl($root)
|
||||||
|
if {$tbl=="t1"} {incr nSeen}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
execsql ROLLBACK
|
||||||
|
|
||||||
|
set nSeen
|
||||||
|
} $nNext
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
Reference in New Issue
Block a user