| 109 | } // namespace |
| 110 | |
| 111 | void ConjunctExpr::evalSpecialForm( |
| 112 | const SelectivityVector& rows, |
| 113 | EvalCtx& context, |
| 114 | VectorPtr& result) { |
| 115 | // TODO Revisit error handling |
| 116 | bool throwOnError = *context.mutableThrowOnError(); |
| 117 | ScopedVarSetter saveError(context.mutableThrowOnError(), false); |
| 118 | context.ensureWritable(rows, type(), result); |
| 119 | auto flatResult = result->asFlatVector<bool>(); |
| 120 | // clear nulls from the result for the active rows. |
| 121 | if (flatResult->mayHaveNulls()) { |
| 122 | auto& nulls = flatResult->mutableNulls(rows.end()); |
| 123 | rows.clearNulls(nulls); |
| 124 | } |
| 125 | // Initialize result to all true for AND and all false for OR. |
| 126 | auto values = flatResult->mutableValues(rows.end())->asMutable<uint64_t>(); |
| 127 | if (isAnd_) { |
| 128 | bits::orBits(values, rows.asRange().bits(), rows.begin(), rows.end()); |
| 129 | } else { |
| 130 | bits::andWithNegatedBits( |
| 131 | values, rows.asRange().bits(), rows.begin(), rows.end()); |
| 132 | } |
| 133 | |
| 134 | // OR: fix finalSelection at "rows" unless already fixed |
| 135 | // isNegatedRelation() is true mean not(and) |
| 136 | ScopedFinalSelectionSetter scopedFinalSelectionSetter( |
| 137 | context, &rows, !isAnd_ || context.isNegatedRelation()); |
| 138 | |
| 139 | bool handleErrors = false; |
| 140 | LocalSelectivityVector errorRows(context); |
| 141 | LocalSelectivityVector activeRowsHolder(context, rows); |
| 142 | auto activeRows = activeRowsHolder.get(); |
| 143 | BOLT_DCHECK(activeRows != nullptr); |
| 144 | int32_t numActive = activeRows->countSelected(); |
| 145 | for (int32_t i = 0; i < inputs_.size(); ++i) { |
| 146 | VectorPtr inputResult; |
| 147 | VectorRecycler inputResultRecycler(inputResult, context.vectorPool()); |
| 148 | ErrorVectorPtr errors; |
| 149 | if (handleErrors) { |
| 150 | context.swapErrors(errors); |
| 151 | } |
| 152 | |
| 153 | SelectivityTimer timer(selectivity_[inputOrder_[i]], numActive); |
| 154 | if (evaluatesArgumentsOnNonIncreasingSelection()) { |
| 155 | // Exclude loading rows that we know for sure will have a false result. |
| 156 | for (auto* field : inputs_[inputOrder_[i]]->distinctFields()) { |
| 157 | if (multiplyReferencedFields_.count(field) > 0) { |
| 158 | context.ensureFieldLoaded(field->index(context), *activeRows); |
| 159 | } |
| 160 | } |
| 161 | } |
| 162 | inputs_[inputOrder_[i]]->eval(*activeRows, context, inputResult); |
| 163 | if (context.errors()) { |
| 164 | handleErrors = true; |
| 165 | } |
| 166 | uint64_t* extraActive = nullptr; |
| 167 | if (handleErrors) { |
| 168 | // Add rows with new errors to activeRows and merge these with |
nothing calls this directly
no test coverage detected