@@ -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