| 81 | // @param predicates FunctionVector holding the predicate expressions. |
| 82 | template <typename THit, typename TMiss> |
| 83 | void doApply( |
| 84 | const SelectivityVector& rows, |
| 85 | const ArrayVectorPtr& flatArray, |
| 86 | const VectorPtr& startIndex, |
| 87 | FunctionVector& predicates, |
| 88 | exec::EvalCtx& context, |
| 89 | THit onHit, |
| 90 | TMiss onMiss) const { |
| 91 | const auto* rawNulls = flatArray->rawNulls(); |
| 92 | const auto* rawOffsets = flatArray->rawOffsets(); |
| 93 | const auto* rawSizes = flatArray->rawSizes(); |
| 94 | |
| 95 | const std::vector<VectorPtr> lambdaArgs = {flatArray->elements()}; |
| 96 | const auto numElements = flatArray->elements()->size(); |
| 97 | |
| 98 | VectorPtr matchBits; |
| 99 | exec::LocalDecodedVector bitsDecoder(context); |
| 100 | |
| 101 | // Adjust offsets and sizes according to specified start indices. |
| 102 | StartIndexProcessor startIndexProcessor; |
| 103 | if (startIndex != nullptr) { |
| 104 | startIndexProcessor.process( |
| 105 | startIndex, rows, rawNulls, rawOffsets, rawSizes, context); |
| 106 | rawOffsets = startIndexProcessor.adjustedOffsets->as<vector_size_t>(); |
| 107 | rawSizes = startIndexProcessor.adjustedSizes->as<vector_size_t>(); |
| 108 | } |
| 109 | |
| 110 | // Loop over lambda functions and apply these to elements of the base array, |
| 111 | // in most cases there will be only one function and the loop will run once. |
| 112 | auto it = predicates.iterator(&rows); |
| 113 | while (auto entry = it.next()) { |
| 114 | auto elementRows = toElementRows( |
| 115 | numElements, *entry.rows, rawNulls, rawOffsets, rawSizes); |
| 116 | if (!elementRows.hasSelections()) { |
| 117 | // All arrays are NULL or empty. |
| 118 | entry.rows->applyToSelected([&](vector_size_t row) { onMiss(row); }); |
| 119 | continue; |
| 120 | } |
| 121 | |
| 122 | auto wrapCapture = toWrapCapture<ArrayVector>( |
| 123 | numElements, entry.callable, *entry.rows, flatArray); |
| 124 | |
| 125 | ErrorVectorPtr elementErrors; |
| 126 | entry.callable->applyNoThrow( |
| 127 | elementRows, |
| 128 | nullptr, // No need to preserve any values in 'matchBits'. |
| 129 | wrapCapture, |
| 130 | &context, |
| 131 | lambdaArgs, |
| 132 | elementErrors, |
| 133 | &matchBits); |
| 134 | |
| 135 | bitsDecoder.get()->decode(*matchBits, elementRows); |
| 136 | entry.rows->applyToSelected([&](vector_size_t row) { |
| 137 | if (rawNulls != nullptr && bits::isBitNull(rawNulls, row)) { |
| 138 | onMiss(row); |
| 139 | } else if ( |
| 140 | auto firstMatchingIndex = findFirstMatch( |
nothing calls this directly
no test coverage detected