mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 12:43:02 +01:00
Postfix for #7804: The partial index is not involved when filtering conditions through OR. Use the full index scan instead of multiple range scans ORed afterwards.
This commit is contained in:
parent
63e6ead37b
commit
90401f7210
@ -1414,17 +1414,37 @@ InversionCandidate* Retrieval::makeInversion(InversionCandidateList& inversions)
|
||||
|
||||
for (auto inversion : inversions)
|
||||
{
|
||||
const auto indexScratch = inversion->scratch;
|
||||
|
||||
// If the explicit plan doesn't mention this index, fake it as used
|
||||
// thus excluding it from the cost-based algorithm. Otherwise,
|
||||
// given this index is suitable for navigation, also mark it as used.
|
||||
|
||||
if ((indexScratch &&
|
||||
(indexScratch->index->idx_runtime_flags & idx_plan_dont_use)) ||
|
||||
(!customPlan && inversion == navigationCandidate))
|
||||
if (const auto indexScratch = inversion->scratch)
|
||||
{
|
||||
inversion->used = true;
|
||||
const auto idx = indexScratch->index;
|
||||
|
||||
// If the explicit plan doesn't mention this index, fake it as used
|
||||
// thus excluding it from the cost-based algorithm. Otherwise,
|
||||
// given this index is suitable for navigation, also mark it as used.
|
||||
|
||||
if (((idx->idx_runtime_flags & idx_plan_dont_use)) ||
|
||||
(!customPlan && inversion == navigationCandidate))
|
||||
{
|
||||
inversion->used = true;
|
||||
}
|
||||
|
||||
// If the index is conditional and its condition is also present in
|
||||
// some other inversion as a boolean (it represents the OR operation),
|
||||
// fake these other inversions as used, so that the full index scan would
|
||||
// be preferred to multiple range scans. The cost-based algorithm below
|
||||
// cannot handle it currently.
|
||||
|
||||
if (idx->idx_flags & idx_condition)
|
||||
{
|
||||
for (auto otherInversion : inversions)
|
||||
{
|
||||
if (otherInversion->boolean &&
|
||||
idx->idx_condition->sameAs(otherInversion->boolean, true))
|
||||
{
|
||||
otherInversion->used = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1460,11 +1480,9 @@ InversionCandidate* Retrieval::makeInversion(InversionCandidateList& inversions)
|
||||
if (!invCandidate)
|
||||
invCandidate = FB_NEW_POOL(getPool()) InversionCandidate(getPool());
|
||||
|
||||
if (!currentInv->inversion && currentInv->scratch)
|
||||
invCandidate->inversion = makeIndexScanNode(currentInv->scratch);
|
||||
else
|
||||
invCandidate->inversion = currentInv->inversion;
|
||||
|
||||
const auto inversionNode = (!currentInv->inversion && currentInv->scratch) ?
|
||||
makeIndexScanNode(currentInv->scratch) : currentInv->inversion;
|
||||
invCandidate->inversion = inversionNode;
|
||||
invCandidate->dbkeyRanges.assign(currentInv->dbkeyRanges);
|
||||
invCandidate->unique = currentInv->unique;
|
||||
invCandidate->selectivity = currentInv->selectivity;
|
||||
@ -1653,12 +1671,9 @@ InversionCandidate* Retrieval::makeInversion(InversionCandidateList& inversions)
|
||||
if (!invCandidate)
|
||||
{
|
||||
invCandidate = FB_NEW_POOL(getPool()) InversionCandidate(getPool());
|
||||
if (!bestCandidate->inversion && bestCandidate->scratch) {
|
||||
invCandidate->inversion = makeIndexScanNode(bestCandidate->scratch);
|
||||
}
|
||||
else {
|
||||
invCandidate->inversion = bestCandidate->inversion;
|
||||
}
|
||||
const auto inversionNode = (!bestCandidate->inversion && bestCandidate->scratch) ?
|
||||
makeIndexScanNode(bestCandidate->scratch) : bestCandidate->inversion;
|
||||
invCandidate->inversion = inversionNode;
|
||||
invCandidate->dbkeyRanges.assign(bestCandidate->dbkeyRanges);
|
||||
invCandidate->unique = bestCandidate->unique;
|
||||
invCandidate->selectivity = bestCandidate->selectivity;
|
||||
@ -1685,17 +1700,10 @@ InversionCandidate* Retrieval::makeInversion(InversionCandidateList& inversions)
|
||||
}
|
||||
else if (!bestCandidate->condition)
|
||||
{
|
||||
if (!bestCandidate->inversion && bestCandidate->scratch)
|
||||
{
|
||||
invCandidate->inversion = composeInversion(invCandidate->inversion,
|
||||
makeIndexScanNode(bestCandidate->scratch), InversionNode::TYPE_AND);
|
||||
}
|
||||
else
|
||||
{
|
||||
invCandidate->inversion = composeInversion(invCandidate->inversion,
|
||||
bestCandidate->inversion, InversionNode::TYPE_AND);
|
||||
}
|
||||
|
||||
const auto inversionNode = (!bestCandidate->inversion && bestCandidate->scratch) ?
|
||||
makeIndexScanNode(bestCandidate->scratch) : bestCandidate->inversion;
|
||||
invCandidate->inversion = composeInversion(invCandidate->inversion,
|
||||
inversionNode, InversionNode::TYPE_AND);
|
||||
invCandidate->dbkeyRanges.join(bestCandidate->dbkeyRanges);
|
||||
invCandidate->unique = (invCandidate->unique || bestCandidate->unique);
|
||||
invCandidate->selectivity = totalSelectivity;
|
||||
@ -1770,6 +1778,16 @@ bool Retrieval::matchBoolean(IndexScratch* indexScratch,
|
||||
if (boolean->nodFlags & ExprNode::FLAG_DEOPTIMIZE)
|
||||
return false;
|
||||
|
||||
const auto idx = indexScratch->index;
|
||||
|
||||
if (idx->idx_flags & idx_condition)
|
||||
{
|
||||
// If index condition matches the boolean, this should not be
|
||||
// considered a match. Full index scan will be used instead.
|
||||
if (idx->idx_condition->sameAs(boolean, true))
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto cmpNode = nodeAs<ComparativeBoolNode>(boolean);
|
||||
const auto missingNode = nodeAs<MissingBoolNode>(boolean);
|
||||
const auto listNode = nodeAs<InListBoolNode>(boolean);
|
||||
@ -1804,16 +1822,6 @@ bool Retrieval::matchBoolean(IndexScratch* indexScratch,
|
||||
ValueExprNode* value2 = (cmpNode && cmpNode->blrOp == blr_between) ?
|
||||
cmpNode->arg3 : nullptr;
|
||||
|
||||
const auto idx = indexScratch->index;
|
||||
|
||||
if (idx->idx_flags & idx_condition)
|
||||
{
|
||||
// If index condition matches the boolean, this should not be
|
||||
// considered a match. Full index scan will be used instead.
|
||||
if (idx->idx_condition->sameAs(boolean, true))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (idx->idx_flags & idx_expression)
|
||||
{
|
||||
// see if one side or the other is matchable to the index expression
|
||||
|
Loading…
Reference in New Issue
Block a user