From: drh Date: Wed, 9 Mar 2016 15:34:51 +0000 (+0000) Subject: Slight simplification to the query optimizer logic associated with IN (SELECT). X-Git-Tag: version-3.12.0~73 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=69c355bd9a749eb6349f2a67aeefbc937ca458bb;p=thirdparty%2Fsqlite.git Slight simplification to the query optimizer logic associated with IN (SELECT). FossilOrigin-Name: 2c55c3c2950cafdc256ab540f60dc4609b9c354b --- diff --git a/manifest b/manifest index 75c68eb813..5189ebea8e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sanother\stest\scase\sfor\sbug\s[5e3c8867]. -D 2016-03-09T15:14:54.990 +C Slight\ssimplification\sto\sthe\squery\soptimizer\slogic\sassociated\swith\sIN\s(SELECT). +D 2016-03-09T15:34:51.959 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66 @@ -303,7 +303,7 @@ F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1 F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f -F src/expr.c 4ce9e66a297ec08d234817c3d9f7fa8c3bf4d851 +F src/expr.c c329d581e5d631153456369684d7d4bcd94c907d F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 5cb42d9a59e2a590776fd3fc8ff6f61d40df3c6e F src/func.c 552d300265aed09eea21f68ac742a440550c0062 @@ -1455,7 +1455,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1ed6b06ea3c432f920fb2b66b6042be906c5d21c -R 95d0f94d6b7106c7ee892a8bac9f59f5 -U dan -Z b79fcffb60dd8a57430224ebf643a8ab +P d91e57e49f23414ec9211b775eb11cd6230a4f96 +R c1ca42221fb7dbc6b010dbeefd096918 +U drh +Z 8017c7a46c10555b3cc0af7ce0a6b14d diff --git a/manifest.uuid b/manifest.uuid index 519f37196f..41eb62d748 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d91e57e49f23414ec9211b775eb11cd6230a4f96 \ No newline at end of file +2c55c3c2950cafdc256ab540f60dc4609b9c354b \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 22ca21de01..3672d02df1 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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 . */ Expr *pExpr; /* Expression */ i16 iCol; /* Index of 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) */