| 90 | // Extract those booleans and return them to the caller. |
| 91 | |
| 92 | bool findDependentBooleans(CompilerScratch* csb, |
| 93 | const StreamList& rseStreams, |
| 94 | BoolExprNode** parentBoolean, |
| 95 | BoolExprNodeStack& booleanStack) |
| 96 | { |
| 97 | const auto boolean = *parentBoolean; |
| 98 | |
| 99 | const auto binaryNode = nodeAs<BinaryBoolNode>(boolean); |
| 100 | if (binaryNode && binaryNode->blrOp == blr_and) |
| 101 | { |
| 102 | const bool found1 = findDependentBooleans(csb, rseStreams, |
| 103 | binaryNode->arg1.getAddress(), booleanStack); |
| 104 | const bool found2 = findDependentBooleans(csb, rseStreams, |
| 105 | binaryNode->arg2.getAddress(), booleanStack); |
| 106 | |
| 107 | if (!binaryNode->arg1 && !binaryNode->arg2) |
| 108 | *parentBoolean = nullptr; |
| 109 | else if (!binaryNode->arg1) |
| 110 | *parentBoolean = binaryNode->arg2; |
| 111 | else if (!binaryNode->arg2) |
| 112 | *parentBoolean = binaryNode->arg1; |
| 113 | |
| 114 | return (found1 || found2); |
| 115 | } |
| 116 | |
| 117 | if (const auto cmpNode = nodeAs<ComparativeBoolNode>(boolean)) |
| 118 | { |
| 119 | if (cmpNode->blrOp == blr_eql || cmpNode->blrOp == blr_equiv) |
| 120 | { |
| 121 | SortedStreamList streams; |
| 122 | cmpNode->collectStreams(streams); |
| 123 | |
| 124 | for (const auto stream : streams) |
| 125 | { |
| 126 | if (rseStreams.exist(stream)) |
| 127 | { |
| 128 | booleanStack.push(boolean); |
| 129 | *parentBoolean = nullptr; |
| 130 | return true; |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | return false; |
| 137 | } |
| 138 | |
| 139 | // Search through the list of ANDed booleans to find correlated EXISTS/IN sub-queries. |
| 140 | // They are candidates to be converted into semi- or anti-joins. |
no test coverage detected