MCPcopy Create free account
hub / github.com/FirebirdSQL/firebird / convertNeqAllToNotAny

Method convertNeqAllToNotAny

src/dsql/BoolNodes.cpp:2081–2164  ·  view source on GitHub ↗

Try to convert nodes of expression: select ... from where not in (select from ) (and its variants that uses the same BLR: {NOT (a = ANY b)} and {a <> ALL b}) to: select ... from where not ((x is null and exists (select 1 from )) or exists (select from where = or is null)) Because the second form can use indexes. Returns NULL when not converted, and a

Source from the content-addressed store, hash-verified

2079// Because the second form can use indexes.
2080// Returns NULL when not converted, and a new node to be processed when converted.
2081BoolExprNode* RseBoolNode::convertNeqAllToNotAny(thread_db* tdbb, CompilerScratch* csb)
2082{
2083 SET_TDBB(tdbb);
2084
2085 fb_assert(blrOp == blr_ansi_all);
2086
2087 RseNode* outerRse = rse; // blr_ansi_all rse
2088 ComparativeBoolNode* outerRseNeq;
2089
2090 if (!outerRse ||
2091 outerRse->getType() != RseNode::TYPE || // Reduntant test?
2092 outerRse->rse_relations.getCount() != 1 ||
2093 !outerRse->rse_boolean ||
2094 !(outerRseNeq = nodeAs<ComparativeBoolNode>(outerRse->rse_boolean)) ||
2095 outerRseNeq->blrOp != blr_neq)
2096 {
2097 return NULL;
2098 }
2099
2100 RseNode* innerRse = static_cast<RseNode*>(outerRse->rse_relations[0].getObject()); // user rse
2101
2102 // If the rse is different than we expected, do nothing. Do nothing also if it uses FIRST or
2103 // SKIP, as we can't inject booleans there without changing the behavior.
2104 if (!innerRse || innerRse->getType() != RseNode::TYPE || innerRse->rse_first || innerRse->rse_skip)
2105 return NULL;
2106
2107 NotBoolNode* newNode = FB_NEW_POOL(csb->csb_pool) NotBoolNode(csb->csb_pool);
2108
2109 BinaryBoolNode* orNode = FB_NEW_POOL(csb->csb_pool) BinaryBoolNode(csb->csb_pool, blr_or);
2110
2111 newNode->arg = orNode;
2112
2113 BinaryBoolNode* andNode = FB_NEW_POOL(csb->csb_pool) BinaryBoolNode(csb->csb_pool, blr_and);
2114
2115 orNode->arg1 = andNode;
2116
2117 MissingBoolNode* missNode = FB_NEW_POOL(csb->csb_pool) MissingBoolNode(csb->csb_pool);
2118 missNode->arg = outerRseNeq->arg1;
2119
2120 andNode->arg1 = missNode;
2121
2122 RseNode* newInnerRse1 = innerRse->clone(csb->csb_pool);
2123 newInnerRse1->flags |= RseNode::FLAG_SUB_QUERY;
2124
2125 RseBoolNode* rseBoolNode = FB_NEW_POOL(csb->csb_pool) RseBoolNode(csb->csb_pool, blr_any);
2126 rseBoolNode->rse = newInnerRse1;
2127 rseBoolNode->ownSavepoint = this->ownSavepoint;
2128
2129 andNode->arg2 = rseBoolNode;
2130
2131 RseNode* newInnerRse2 = innerRse->clone(csb->csb_pool);
2132 newInnerRse2->flags |= RseNode::FLAG_SUB_QUERY;
2133
2134 rseBoolNode = FB_NEW_POOL(csb->csb_pool) RseBoolNode(csb->csb_pool, blr_any);
2135 rseBoolNode->rse = newInnerRse2;
2136 rseBoolNode->ownSavepoint = this->ownSavepoint;
2137
2138 orNode->arg2 = rseBoolNode;

Callers

nothing calls this directly

Calls 10

SET_TDBBFunction · 0.85
NotBoolNodeClass · 0.85
MissingBoolNodeClass · 0.85
RseBoolNodeClass · 0.85
BinaryBoolNodeClass · 0.70
getTypeMethod · 0.45
getCountMethod · 0.45
getObjectMethod · 0.45
cloneMethod · 0.45
copyMethod · 0.45

Tested by

no test coverage detected