1
0
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:
dan
2024-05-01 19:48:24 +00:00
parent 8d5fe073d2
commit f3ea92cceb
4 changed files with 142 additions and 8 deletions

View File

@ -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
** 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;