mirror of https://github.com/sqlite/sqlite
Omit tables from the FROM clause of a join if their presence makes no difference
in the final output. FossilOrigin-Name: 6505e2ab0200736c525b5cfcf1cb62c0bd4d18ee
This commit is contained in:
commit
692b9a43dd
16
manifest
16
manifest
|
@ -1,5 +1,5 @@
|
|||
C Cut\sover\sthe\snext\sgeneration\squery\splanner.\s\sIncrease\sthe\sversion\snumber\nto\s3.8.0.
|
||||
D 2013-06-26T11:43:18.908
|
||||
C Omit\stables\sfrom\sthe\sFROM\sclause\sof\sa\sjoin\sif\stheir\spresence\smakes\sno\sdifference\nin\sthe\sfinal\soutput.
|
||||
D 2013-06-26T11:49:45.741
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
|
@ -215,12 +215,12 @@ F src/printf.c bff529ed47657098c55c9910b9c69b1b3b1a1353
|
|||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c 89f9003e8316ee3a172795459efc2a0274e1d5a8
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c d5a1b9bc3fb451e68ce907df253c6ac17e7310f7
|
||||
F src/select.c 91b62654caf8dfe292fb8882715e575d34ad3874
|
||||
F src/shell.c ab6eea968c8745be3aa74e45fedb37d057b4cd0d
|
||||
F src/sqlite.h.in 5b390ca5d94e09e56e7fee6a51ddde4721b89f8e
|
||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||
F src/sqlite3ext.h d936f797812c28b81b26ed18345baf8db28a21a5
|
||||
F src/sqliteInt.h 82a0f3e7c3410cc748c80268e0831dba5ea98cb4
|
||||
F src/sqliteInt.h e6f069b07fdef1ab54034940b7a6e7be2b4efd57
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
|
@ -289,7 +289,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
|
|||
F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
|
||||
F src/where.c 8d6c07d9641bf107e03a2b613550d90b8c7f4a82
|
||||
F src/where.c 9bcfcb4ec6a14dd0111bf287bee02be88d5709f9
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||
|
@ -1097,7 +1097,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
|||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P 096ae1d8f9a08f92daedece6b0615f4d22b05023 19ab4811d542ba781aeb6a4eb3c74642677225e1
|
||||
R f73808040fac6ead247f9d2a50c342d8
|
||||
P 0fe31f60cadc5fe5a9d87e110bfaed5fd026cba1 d929df9b1ba214c27d8c437099a53ee9b07aa169
|
||||
R ecf2ce720691ade8fe3e2ee9fb8dd238
|
||||
U drh
|
||||
Z e52529fd895183a80c4903c58cf391c1
|
||||
Z ab0b31ee952c7e0dabeb8c9962096a79
|
||||
|
|
|
@ -1 +1 @@
|
|||
0fe31f60cadc5fe5a9d87e110bfaed5fd026cba1
|
||||
6505e2ab0200736c525b5cfcf1cb62c0bd4d18ee
|
|
@ -4261,15 +4261,16 @@ int sqlite3Select(
|
|||
|
||||
if( !isAgg && pGroupBy==0 ){
|
||||
/* No aggregate functions and no GROUP BY clause */
|
||||
ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0);
|
||||
u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
|
||||
|
||||
/* Begin the database scan. */
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, p->pEList,
|
||||
wctrlFlags, 0);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
|
||||
p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
|
||||
}
|
||||
if( sqlite3WhereIsDistinct(pWInfo) ){
|
||||
if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
|
||||
sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
|
||||
}
|
||||
if( pOrderBy && sqlite3WhereIsOrdered(pWInfo) ) pOrderBy = 0;
|
||||
|
|
|
@ -1024,6 +1024,7 @@ struct sqlite3 {
|
|||
#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
|
||||
#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
|
||||
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
|
||||
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
|
||||
#define SQLITE_AllOpts 0xffff /* All optimizations */
|
||||
|
||||
/*
|
||||
|
@ -1974,6 +1975,7 @@ struct SrcList {
|
|||
#define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */
|
||||
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
|
||||
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
|
||||
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
|
||||
|
||||
/* Allowed return values from sqlite3WhereIsDistinct()
|
||||
*/
|
||||
|
|
96
src/where.c
96
src/where.c
|
@ -383,7 +383,7 @@ struct WhereInfo {
|
|||
Parse *pParse; /* Parsing and code generating context */
|
||||
SrcList *pTabList; /* List of tables in the join */
|
||||
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
|
||||
ExprList *pDistinct; /* DISTINCT ON values, or NULL */
|
||||
ExprList *pResultSet; /* Result set. DISTINCT operates on these */
|
||||
WhereLoop *pLoops; /* List of all WhereLoop objects */
|
||||
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
|
||||
WhereCost nRowOut; /* Estimated number of output rows */
|
||||
|
@ -392,10 +392,10 @@ struct WhereInfo {
|
|||
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
|
||||
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
|
||||
u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
|
||||
u8 nLevel; /* Number of nested loop */
|
||||
int iTop; /* The very beginning of the WHERE loop */
|
||||
int iContinue; /* Jump here to continue with next record */
|
||||
int iBreak; /* Jump here to break out of the loop */
|
||||
int nLevel; /* Number of nested loop */
|
||||
int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
|
||||
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
|
||||
WhereClause sWC; /* Decomposition of the WHERE clause */
|
||||
|
@ -3928,9 +3928,9 @@ static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){
|
|||
int nb = 1+(pTabList->nSrc+7)/8;
|
||||
struct SrcList_item *pItem = pTabList->a + p->iTab;
|
||||
Table *pTab = pItem->pTab;
|
||||
sqlite3DebugPrintf("%c %2d.%0*llx.%0*llx", p->cId,
|
||||
sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
|
||||
p->iTab, nb, p->maskSelf, nb, p->prereq);
|
||||
sqlite3DebugPrintf(" %8s",
|
||||
sqlite3DebugPrintf(" %12s",
|
||||
pItem->zAlias ? pItem->zAlias : pTab->zName);
|
||||
if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
|
||||
if( p->u.btree.pIndex ){
|
||||
|
@ -3941,9 +3941,9 @@ static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){
|
|||
while( zName[i]!='_' ) i--;
|
||||
zName += i;
|
||||
}
|
||||
sqlite3DebugPrintf(".%-12s %2d", zName, p->u.btree.nEq);
|
||||
sqlite3DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq);
|
||||
}else{
|
||||
sqlite3DebugPrintf("%16s","");
|
||||
sqlite3DebugPrintf("%20s","");
|
||||
}
|
||||
}else{
|
||||
char *z;
|
||||
|
@ -3953,10 +3953,10 @@ static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){
|
|||
}else{
|
||||
z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
|
||||
}
|
||||
sqlite3DebugPrintf(" %-15s", z);
|
||||
sqlite3DebugPrintf(" %-19s", z);
|
||||
sqlite3_free(z);
|
||||
}
|
||||
sqlite3DebugPrintf(" fg %05x N %d", p->wsFlags, p->nLTerm);
|
||||
sqlite3DebugPrintf(" f %04x N %d", p->wsFlags, p->nLTerm);
|
||||
sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
|
||||
}
|
||||
#endif
|
||||
|
@ -5370,12 +5370,13 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
|||
pLevel->iFrom = pWLoop->iTab;
|
||||
pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
|
||||
}
|
||||
if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0
|
||||
&& pWInfo->pDistinct
|
||||
if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0
|
||||
&& (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0
|
||||
&& pWInfo->eDistinct==WHERE_DISTINCT_NOOP
|
||||
&& nRowEst
|
||||
){
|
||||
Bitmask notUsed;
|
||||
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinct, pFrom,
|
||||
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
|
||||
WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used);
|
||||
if( rc==1 ) pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
|
||||
}
|
||||
|
@ -5464,7 +5465,9 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|
|||
pWInfo->a[0].iTabCur = iCur;
|
||||
pWInfo->nRowOut = 1;
|
||||
if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1;
|
||||
if( pWInfo->pDistinct ) pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||
if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
pLoop->cId = '0';
|
||||
#endif
|
||||
|
@ -5554,10 +5557,10 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|
|||
*/
|
||||
WhereInfo *sqlite3WhereBegin(
|
||||
Parse *pParse, /* The parser context */
|
||||
SrcList *pTabList, /* A list of all tables to be scanned */
|
||||
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
|
||||
Expr *pWhere, /* The WHERE clause */
|
||||
ExprList *pOrderBy, /* An ORDER BY clause, or NULL */
|
||||
ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
|
||||
ExprList *pResultSet, /* Result set of the query */
|
||||
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
|
||||
int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */
|
||||
){
|
||||
|
@ -5569,15 +5572,23 @@ WhereInfo *sqlite3WhereBegin(
|
|||
WhereLoopBuilder sWLB; /* The WhereLoop builder */
|
||||
WhereMaskSet *pMaskSet; /* The expression mask set */
|
||||
WhereLevel *pLevel; /* A single level in pWInfo->a[] */
|
||||
WhereLoop *pLoop; /* Pointer to a single WhereLoop object */
|
||||
int ii; /* Loop counter */
|
||||
sqlite3 *db; /* Database connection */
|
||||
int rc; /* Return code */
|
||||
|
||||
|
||||
/* Variable initialization */
|
||||
db = pParse->db;
|
||||
memset(&sWLB, 0, sizeof(sWLB));
|
||||
sWLB.pOrderBy = pOrderBy;
|
||||
|
||||
/* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
|
||||
** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
|
||||
if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
|
||||
wctrlFlags &= ~WHERE_WANT_DISTINCT;
|
||||
}
|
||||
|
||||
/* The number of tables in the FROM clause is limited by the number of
|
||||
** bits in a Bitmask
|
||||
*/
|
||||
|
@ -5601,7 +5612,6 @@ WhereInfo *sqlite3WhereBegin(
|
|||
** field (type Bitmask) it must be aligned on an 8-byte boundary on
|
||||
** some architectures. Hence the ROUND8() below.
|
||||
*/
|
||||
db = pParse->db;
|
||||
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
|
||||
pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
|
||||
if( db->mallocFailed ){
|
||||
|
@ -5613,7 +5623,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||
pWInfo->pParse = pParse;
|
||||
pWInfo->pTabList = pTabList;
|
||||
pWInfo->pOrderBy = pOrderBy;
|
||||
pWInfo->pDistinct = pDistinct;
|
||||
pWInfo->pResultSet = pResultSet;
|
||||
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
|
||||
pWInfo->wctrlFlags = wctrlFlags;
|
||||
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
|
||||
|
@ -5626,10 +5636,6 @@ WhereInfo *sqlite3WhereBegin(
|
|||
sWLB.pNew->cId = '*';
|
||||
#endif
|
||||
|
||||
/* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
|
||||
** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
|
||||
if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0;
|
||||
|
||||
/* Split the WHERE clause into separate subexpressions where each
|
||||
** subexpression is separated by an AND operator.
|
||||
*/
|
||||
|
@ -5650,7 +5656,9 @@ WhereInfo *sqlite3WhereBegin(
|
|||
*/
|
||||
if( nTabList==0 ){
|
||||
if( pOrderBy ) pWInfo->bOBSat = 1;
|
||||
if( pDistinct ) pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||
if( wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign a bit from the bitmask to every term in the FROM clause.
|
||||
|
@ -5697,7 +5705,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||
** expressions, then we won't be able to satisfy it using indices, so
|
||||
** go ahead and disable it now.
|
||||
*/
|
||||
if( pOrderBy && pDistinct ){
|
||||
if( pOrderBy && (wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){
|
||||
for(ii=0; ii<pOrderBy->nExpr; ii++){
|
||||
Expr *pExpr = sqlite3ExprSkipCollate(pOrderBy->a[ii].pExpr);
|
||||
if( pExpr->op!=TK_COLUMN ){
|
||||
|
@ -5709,17 +5717,14 @@ WhereInfo *sqlite3WhereBegin(
|
|||
}
|
||||
}
|
||||
|
||||
/* Check if the DISTINCT qualifier, if there is one, is redundant.
|
||||
** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
|
||||
** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
|
||||
*/
|
||||
if( pDistinct ){
|
||||
if( isDistinctRedundant(pParse,pTabList,&pWInfo->sWC,pDistinct) ){
|
||||
pDistinct = 0;
|
||||
if( wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
|
||||
/* The DISTINCT marking is pointless. Ignore it. */
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||
}else if( pOrderBy==0 ){
|
||||
/* Try to ORDER BY the result set to make distinct processing easier */
|
||||
pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
|
||||
pWInfo->pOrderBy = pDistinct;
|
||||
pWInfo->pOrderBy = pResultSet;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5733,11 +5738,11 @@ WhereInfo *sqlite3WhereBegin(
|
|||
#ifdef WHERETRACE_ENABLED
|
||||
if( sqlite3WhereTrace ){
|
||||
WhereLoop *p;
|
||||
int i = 0;
|
||||
int i;
|
||||
static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
|
||||
for(p=pWInfo->pLoops; p; p=p->pNextLoop){
|
||||
p->cId = zLabel[(i++)%sizeof(zLabel)];
|
||||
for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
|
||||
p->cId = zLabel[i%sizeof(zLabel)];
|
||||
whereLoopPrint(p, pTabList);
|
||||
}
|
||||
}
|
||||
|
@ -5778,11 +5783,32 @@ WhereInfo *sqlite3WhereBegin(
|
|||
}
|
||||
}
|
||||
sqlite3DebugPrintf("\n");
|
||||
for(ii=0; ii<nTabList; ii++){
|
||||
for(ii=0; ii<pWInfo->nLevel; ii++){
|
||||
whereLoopPrint(pWInfo->a[ii].pWLoop, pTabList);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Attempt to omit tables from the join that do not effect the result */
|
||||
if( pWInfo->nLevel>=2
|
||||
&& pResultSet!=0
|
||||
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
|
||||
){
|
||||
Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet);
|
||||
if( pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, pOrderBy);
|
||||
while( pWInfo->nLevel>=2 ){
|
||||
pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop;
|
||||
if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break;
|
||||
if( (wctrlFlags & WHERE_WANT_DISTINCT)==0
|
||||
&& (pLoop->wsFlags & WHERE_ONEROW)==0
|
||||
){
|
||||
break;
|
||||
}
|
||||
if( (tabUsed & pLoop->maskSelf)!=0 ) break;
|
||||
WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
|
||||
pWInfo->nLevel--;
|
||||
nTabList--;
|
||||
}
|
||||
}
|
||||
WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
|
||||
pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
|
||||
|
||||
|
@ -5951,7 +5977,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|||
|
||||
/* Close all of the cursors that were opened by sqlite3WhereBegin.
|
||||
*/
|
||||
assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
|
||||
assert( pWInfo->nLevel<=pTabList->nSrc );
|
||||
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
|
||||
Index *pIdx = 0;
|
||||
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
|
||||
|
|
Loading…
Reference in New Issue