aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <Dan Kennedy>2024-05-02 14:48:58 +0000
committerdan <Dan Kennedy>2024-05-02 14:48:58 +0000
commitaeb62886c5574c6f60e9d153e43367161b52e1a0 (patch)
treec6f0307291486de43c0b789f509c16186e4aa901 /src
parentd059774365c6e36640b924ca589a5dd815f7b5c9 (diff)
parentf3ea92cceb577524c1d329aed2400127d7fd716a (diff)
downloadsqlite-aeb62886c5574c6f60e9d153e43367161b52e1a0.tar.gz
sqlite-aeb62886c5574c6f60e9d153e43367161b52e1a0.zip
Avoid an OP_Next in cases where an IN(...) query against a UNIQUE index may return at most 1 row.
FossilOrigin-Name: d7648e21605a0b381b1935a47e5a77bdfacc4cc96f03d6bb7956f8f4e6a40648
Diffstat (limited to 'src')
-rw-r--r--src/wherecode.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/src/wherecode.c b/src/wherecode.c
index d95eae279..a895d3935 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -1338,6 +1338,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
** implementation described by pWInfo.
*/
@@ -2084,7 +2105,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
/* 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;
}else if( bRev ){
pLevel->op = OP_Prev;