1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-10 01:02:56 +03:00

Slight simplification to the query optimizer logic associated with IN (SELECT).

FossilOrigin-Name: 2c55c3c2950cafdc256ab540f60dc4609b9c354b
This commit is contained in:
drh
2016-03-09 15:34:51 +00:00
parent ab8aa11b96
commit 69c355bd9a
3 changed files with 23 additions and 27 deletions

View File

@@ -1568,24 +1568,22 @@ int sqlite3IsRowid(const char *z){
}
/*
** Return true if we are able to the IN operator optimization on a
** query of the form
**
** x IN (SELECT ...)
**
** Where the SELECT... clause is as specified by the parameter to this
** routine.
**
** The Select object passed in has already been preprocessed and no
** errors have been found.
** pX is the RHS of an IN operator. If pX is a SELECT statement
** that can be simplified to a direct table access, then return
** a pointer to the SELECT statement. If pX is not a SELECT statement,
** or if the SELECT statement needs to be manifested into a transient
** table, then return NULL.
*/
#ifndef SQLITE_OMIT_SUBQUERY
static int isCandidateForInOpt(Select *p){
static Select *isCandidateForInOpt(Expr *pX){
Select *p;
SrcList *pSrc;
ExprList *pEList;
Expr *pRes;
Table *pTab;
Expr *pRes; /* Result expression */
if( p==0 ) return 0; /* right-hand side of IN is SELECT */
if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */
if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */
p = pX->x.pSelect;
if( p->pPrior ) return 0; /* Not a compound SELECT */
if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
@@ -1601,15 +1599,15 @@ static int isCandidateForInOpt(Select *p){
if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
pTab = pSrc->a[0].pTab;
if( NEVER(pTab==0) ) return 0;
assert( pTab!=0 );
assert( pTab->pSelect==0 ); /* FROM clause is not a view */
if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
pEList = p->pEList;
if( pEList->nExpr!=1 ) return 0; /* One column in the result set */
pRes = pEList->a[0].pExpr;
if( pRes->op!=TK_COLUMN ) return 0; /* Result is a column */
if( pRes->iTable!=pSrc->a[0].iCursor ) return 0; /* Not a correlated subq */
return 1;
assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */
return p;
}
#endif /* SQLITE_OMIT_SUBQUERY */
@@ -1741,15 +1739,13 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){
** satisfy the query. This is preferable to generating a new
** ephemeral table.
*/
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
if( pParse->nErr==0 && isCandidateForInOpt(p) ){
if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){
sqlite3 *db = pParse->db; /* Database connection */
Table *pTab; /* Table <table>. */
Expr *pExpr; /* Expression <column> */
i16 iCol; /* Index of column <column> */
i16 iDb; /* Database idx for pTab */
assert( p ); /* Because of isCandidateForInOpt(p) */
assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */