Lines 4048-4053
Link Here
|
4048 |
int bestJ = -1; /* The value of j */ |
4048 |
int bestJ = -1; /* The value of j */ |
4049 |
Bitmask m; /* Bitmask value for j or bestJ */ |
4049 |
Bitmask m; /* Bitmask value for j or bestJ */ |
4050 |
int isOptimal; /* Iterator for optimal/non-optimal search */ |
4050 |
int isOptimal; /* Iterator for optimal/non-optimal search */ |
|
|
4051 |
int nUnconstrained; /* Number tables without INDEXED BY */ |
4052 |
Bitmask notIndexed; /* Mask of tables that cannot use an index */ |
4051 |
|
4053 |
|
4052 |
memset(&bestPlan, 0, sizeof(bestPlan)); |
4054 |
memset(&bestPlan, 0, sizeof(bestPlan)); |
4053 |
bestPlan.rCost = SQLITE_BIG_DBL; |
4055 |
bestPlan.rCost = SQLITE_BIG_DBL; |
Lines 4089-4094
Link Here
|
4089 |
** algorithm may choose to use t2 for the outer loop, which is a much |
4091 |
** algorithm may choose to use t2 for the outer loop, which is a much |
4090 |
** costlier approach. |
4092 |
** costlier approach. |
4091 |
*/ |
4093 |
*/ |
|
|
4094 |
nUnconstrained = 0; |
4095 |
notIndexed = 0; |
4092 |
for(isOptimal=(iFrom<nTabList-1); isOptimal>=0; isOptimal--){ |
4096 |
for(isOptimal=(iFrom<nTabList-1); isOptimal>=0; isOptimal--){ |
4093 |
Bitmask mask; /* Mask of tables not yet ready */ |
4097 |
Bitmask mask; /* Mask of tables not yet ready */ |
4094 |
for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){ |
4098 |
for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){ |
Lines 4105-4110
Link Here
|
4105 |
} |
4109 |
} |
4106 |
mask = (isOptimal ? m : notReady); |
4110 |
mask = (isOptimal ? m : notReady); |
4107 |
pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0); |
4111 |
pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0); |
|
|
4112 |
if( pTabItem->pIndex==0 ) nUnconstrained++; |
4108 |
|
4113 |
|
4109 |
assert( pTabItem->pTab ); |
4114 |
assert( pTabItem->pTab ); |
4110 |
#ifndef SQLITE_OMIT_VIRTUALTABLE |
4115 |
#ifndef SQLITE_OMIT_VIRTUALTABLE |
Lines 4118-4126
Link Here
|
4118 |
} |
4123 |
} |
4119 |
assert( isOptimal || (sCost.used¬Ready)==0 ); |
4124 |
assert( isOptimal || (sCost.used¬Ready)==0 ); |
4120 |
|
4125 |
|
4121 |
if( (sCost.used¬Ready)==0 |
4126 |
/* If an INDEXED BY clause is present, then the plan must use that |
4122 |
&& (bestJ<0 || sCost.rCost<bestPlan.rCost |
4127 |
** index if it uses any index at all */ |
4123 |
|| (sCost.rCost<=bestPlan.rCost && sCost.nRow<bestPlan.nRow)) |
4128 |
assert( pTabItem->pIndex==0 |
|
|
4129 |
|| (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 |
4130 |
|| sCost.plan.u.pIdx==pTabItem->pIndex ); |
4131 |
|
4132 |
if( isOptimal && (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ |
4133 |
notIndexed |= m; |
4134 |
} |
4135 |
|
4136 |
/* Conditions under which this table becomes the best so far: |
4137 |
** |
4138 |
** (1) The table must not depend on other tables that have not |
4139 |
** yet run. |
4140 |
** |
4141 |
** (2) A full-table-scan plan cannot supercede another plan unless |
4142 |
** it is an "optimal" plan as defined above. |
4143 |
** |
4144 |
** (3) All tables have an INDEXED BY clause or this table lacks an |
4145 |
** INDEXED BY clause or this table uses the specific |
4146 |
** index specified by its INDEXED BY clause. This rule ensures |
4147 |
** that a best-so-far is always selected even if an impossible |
4148 |
** combination of INDEXED BY clauses are given. The error |
4149 |
** will be detected and relayed back to the application later. |
4150 |
** The NEVER() comes about because rule (2) above prevents |
4151 |
** An indexable full-table-scan from reaching rule (3). |
4152 |
** |
4153 |
** (4) The plan cost must be lower than prior plans or else the |
4154 |
** cost must be the same and the number of rows must be lower. |
4155 |
*/ |
4156 |
if( (sCost.used¬Ready)==0 /* (1) */ |
4157 |
&& (bestJ<0 || (notIndexed&m)!=0 /* (2) */ |
4158 |
|| (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0) |
4159 |
&& (nUnconstrained==0 || pTabItem->pIndex==0 /* (3) */ |
4160 |
|| NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)) |
4161 |
&& (bestJ<0 || sCost.rCost<bestPlan.rCost /* (4) */ |
4162 |
|| (sCost.rCost<=bestPlan.rCost && sCost.nRow<bestPlan.nRow)) |
4124 |
){ |
4163 |
){ |
4125 |
WHERETRACE(("... best so far with cost=%g and nRow=%g\n", |
4164 |
WHERETRACE(("... best so far with cost=%g and nRow=%g\n", |
4126 |
sCost.rCost, sCost.nRow)); |
4165 |
sCost.rCost, sCost.nRow)); |