mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-18 10:21:03 +03:00
For the OR-optimization, avoid generating OP_OpenRead opcodes that reopen
exactly the same index. FossilOrigin-Name: b67a6e33f23ce5f5d9a545fa9d6700a7ed636901
This commit is contained in:
19
src/where.c
19
src/where.c
@@ -3422,6 +3422,7 @@ static Bitmask codeOneLoopStart(
|
||||
int iRetInit; /* Address of regReturn init */
|
||||
int untestedTerms = 0; /* Some terms not completely tested */
|
||||
int ii; /* Loop counter */
|
||||
int subWctrlFlags; /* wctrlFlags for sub-queries */
|
||||
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
|
||||
Table *pTab = pTabItem->pTab;
|
||||
|
||||
@@ -3517,6 +3518,8 @@ static Bitmask codeOneLoopStart(
|
||||
** eliminating duplicates from other WHERE clauses, the action for each
|
||||
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
|
||||
*/
|
||||
subWctrlFlags = WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
|
||||
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY;
|
||||
for(ii=0; ii<pOrWc->nTerm; ii++){
|
||||
WhereTerm *pOrTerm = &pOrWc->a[ii];
|
||||
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
|
||||
@@ -3529,8 +3532,7 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
/* Loop through table entries that match term pOrTerm. */
|
||||
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
|
||||
WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
|
||||
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
|
||||
subWctrlFlags, iCovCur);
|
||||
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
|
||||
if( pSubWInfo ){
|
||||
WhereLoop *pSubLoop;
|
||||
@@ -3621,6 +3623,7 @@ static Bitmask codeOneLoopStart(
|
||||
){
|
||||
assert( pSubWInfo->a[0].iIdxCur==iCovCur );
|
||||
pCov = pSubLoop->u.btree.pIndex;
|
||||
subWctrlFlags |= WHERE_OR_INDEX_OPEN;
|
||||
}else{
|
||||
pCov = 0;
|
||||
}
|
||||
@@ -6212,6 +6215,18 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pWInfo->aiCurOnePass[1] = iIndexCur;
|
||||
}else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
|
||||
iIndexCur = iIdxCur;
|
||||
if( (wctrlFlags & WHERE_OR_INDEX_OPEN)!=0 ){
|
||||
/* For 2nd and subsequent subqueries for processing OR terms,
|
||||
** try to reuse the previous OP_OpenRead, if there is one. The
|
||||
** WHERE_OR_INDEX_OPEN bit will only be set if there is a prior
|
||||
** OP_OpenRead opcode on cursor iIndexCur, so the while() loop
|
||||
** below is guaranteed to terminate.
|
||||
*/
|
||||
VdbeOp *pOp = sqlite3VdbeGetOp(v, -1);
|
||||
while( pOp->opcode!=OP_OpenRead || pOp->p1!=iIndexCur ) pOp--;
|
||||
assert( pOp->p3==iDb );
|
||||
if( pOp->p2==pIx->tnum ) op = 0;
|
||||
}
|
||||
}else{
|
||||
iIndexCur = pParse->nTab++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user