diff options
author | dan <Dan Kennedy> | 2024-05-02 14:48:58 +0000 |
---|---|---|
committer | dan <Dan Kennedy> | 2024-05-02 14:48:58 +0000 |
commit | aeb62886c5574c6f60e9d153e43367161b52e1a0 (patch) | |
tree | c6f0307291486de43c0b789f509c16186e4aa901 /src | |
parent | d059774365c6e36640b924ca589a5dd815f7b5c9 (diff) | |
parent | f3ea92cceb577524c1d329aed2400127d7fd716a (diff) | |
download | sqlite-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.c | 25 |
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; |