Skip to content

Commit 90401f7

Browse files
committed
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.
1 parent 63e6ead commit 90401f7

File tree

1 file changed

+49
-41
lines changed

1 file changed

+49
-41
lines changed

src/jrd/optimizer/Retrieval.cpp

Lines changed: 49 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,17 +1414,37 @@ InversionCandidate* Retrieval::makeInversion(InversionCandidateList& inversions)
14141414

14151415
for (auto inversion : inversions)
14161416
{
1417-
const auto indexScratch = inversion->scratch;
1417+
if (const auto indexScratch = inversion->scratch)
1418+
{
1419+
const auto idx = indexScratch->index;
14181420

1419-
// If the explicit plan doesn't mention this index, fake it as used
1420-
// thus excluding it from the cost-based algorithm. Otherwise,
1421-
// given this index is suitable for navigation, also mark it as used.
1421+
// If the explicit plan doesn't mention this index, fake it as used
1422+
// thus excluding it from the cost-based algorithm. Otherwise,
1423+
// given this index is suitable for navigation, also mark it as used.
14221424

1423-
if ((indexScratch &&
1424-
(indexScratch->index->idx_runtime_flags & idx_plan_dont_use)) ||
1425-
(!customPlan && inversion == navigationCandidate))
1426-
{
1427-
inversion->used = true;
1425+
if (((idx->idx_runtime_flags & idx_plan_dont_use)) ||
1426+
(!customPlan && inversion == navigationCandidate))
1427+
{
1428+
inversion->used = true;
1429+
}
1430+
1431+
// If the index is conditional and its condition is also present in
1432+
// some other inversion as a boolean (it represents the OR operation),
1433+
// fake these other inversions as used, so that the full index scan would
1434+
// be preferred to multiple range scans. The cost-based algorithm below
1435+
// cannot handle it currently.
1436+
1437+
if (idx->idx_flags & idx_condition)
1438+
{
1439+
for (auto otherInversion : inversions)
1440+
{
1441+
if (otherInversion->boolean &&
1442+
idx->idx_condition->sameAs(otherInversion->boolean, true))
1443+
{
1444+
otherInversion->used = true;
1445+
}
1446+
}
1447+
}
14281448
}
14291449
}
14301450

@@ -1460,11 +1480,9 @@ InversionCandidate* Retrieval::makeInversion(InversionCandidateList& inversions)
14601480
if (!invCandidate)
14611481
invCandidate = FB_NEW_POOL(getPool()) InversionCandidate(getPool());
14621482

1463-
if (!currentInv->inversion && currentInv->scratch)
1464-
invCandidate->inversion = makeIndexScanNode(currentInv->scratch);
1465-
else
1466-
invCandidate->inversion = currentInv->inversion;
1467-
1483+
const auto inversionNode = (!currentInv->inversion && currentInv->scratch) ?
1484+
makeIndexScanNode(currentInv->scratch) : currentInv->inversion;
1485+
invCandidate->inversion = inversionNode;
14681486
invCandidate->dbkeyRanges.assign(currentInv->dbkeyRanges);
14691487
invCandidate->unique = currentInv->unique;
14701488
invCandidate->selectivity = currentInv->selectivity;
@@ -1653,12 +1671,9 @@ InversionCandidate* Retrieval::makeInversion(InversionCandidateList& inversions)
16531671
if (!invCandidate)
16541672
{
16551673
invCandidate = FB_NEW_POOL(getPool()) InversionCandidate(getPool());
1656-
if (!bestCandidate->inversion && bestCandidate->scratch) {
1657-
invCandidate->inversion = makeIndexScanNode(bestCandidate->scratch);
1658-
}
1659-
else {
1660-
invCandidate->inversion = bestCandidate->inversion;
1661-
}
1674+
const auto inversionNode = (!bestCandidate->inversion && bestCandidate->scratch) ?
1675+
makeIndexScanNode(bestCandidate->scratch) : bestCandidate->inversion;
1676+
invCandidate->inversion = inversionNode;
16621677
invCandidate->dbkeyRanges.assign(bestCandidate->dbkeyRanges);
16631678
invCandidate->unique = bestCandidate->unique;
16641679
invCandidate->selectivity = bestCandidate->selectivity;
@@ -1685,17 +1700,10 @@ InversionCandidate* Retrieval::makeInversion(InversionCandidateList& inversions)
16851700
}
16861701
else if (!bestCandidate->condition)
16871702
{
1688-
if (!bestCandidate->inversion && bestCandidate->scratch)
1689-
{
1690-
invCandidate->inversion = composeInversion(invCandidate->inversion,
1691-
makeIndexScanNode(bestCandidate->scratch), InversionNode::TYPE_AND);
1692-
}
1693-
else
1694-
{
1695-
invCandidate->inversion = composeInversion(invCandidate->inversion,
1696-
bestCandidate->inversion, InversionNode::TYPE_AND);
1697-
}
1698-
1703+
const auto inversionNode = (!bestCandidate->inversion && bestCandidate->scratch) ?
1704+
makeIndexScanNode(bestCandidate->scratch) : bestCandidate->inversion;
1705+
invCandidate->inversion = composeInversion(invCandidate->inversion,
1706+
inversionNode, InversionNode::TYPE_AND);
16991707
invCandidate->dbkeyRanges.join(bestCandidate->dbkeyRanges);
17001708
invCandidate->unique = (invCandidate->unique || bestCandidate->unique);
17011709
invCandidate->selectivity = totalSelectivity;
@@ -1770,6 +1778,16 @@ bool Retrieval::matchBoolean(IndexScratch* indexScratch,
17701778
if (boolean->nodFlags & ExprNode::FLAG_DEOPTIMIZE)
17711779
return false;
17721780

1781+
const auto idx = indexScratch->index;
1782+
1783+
if (idx->idx_flags & idx_condition)
1784+
{
1785+
// If index condition matches the boolean, this should not be
1786+
// considered a match. Full index scan will be used instead.
1787+
if (idx->idx_condition->sameAs(boolean, true))
1788+
return false;
1789+
}
1790+
17731791
const auto cmpNode = nodeAs<ComparativeBoolNode>(boolean);
17741792
const auto missingNode = nodeAs<MissingBoolNode>(boolean);
17751793
const auto listNode = nodeAs<InListBoolNode>(boolean);
@@ -1804,16 +1822,6 @@ bool Retrieval::matchBoolean(IndexScratch* indexScratch,
18041822
ValueExprNode* value2 = (cmpNode && cmpNode->blrOp == blr_between) ?
18051823
cmpNode->arg3 : nullptr;
18061824

1807-
const auto idx = indexScratch->index;
1808-
1809-
if (idx->idx_flags & idx_condition)
1810-
{
1811-
// If index condition matches the boolean, this should not be
1812-
// considered a match. Full index scan will be used instead.
1813-
if (idx->idx_condition->sameAs(boolean, true))
1814-
return false;
1815-
}
1816-
18171825
if (idx->idx_flags & idx_expression)
18181826
{
18191827
// see if one side or the other is matchable to the index expression

0 commit comments

Comments
 (0)