| 126 | } |
| 127 | |
| 128 | void MergeJoin::initializeFilter( |
| 129 | const core::TypedExprPtr& filter, |
| 130 | const RowTypePtr& leftType, |
| 131 | const RowTypePtr& rightType) { |
| 132 | std::vector<core::TypedExprPtr> filters = {filter}; |
| 133 | filter_ = |
| 134 | std::make_unique<ExprSet>(std::move(filters), operatorCtx_->execCtx()); |
| 135 | |
| 136 | column_index_t filterChannel = 0; |
| 137 | std::vector<std::string> names; |
| 138 | std::vector<TypePtr> types; |
| 139 | auto numFields = filter_->expr(0)->distinctFields().size(); |
| 140 | names.reserve(numFields); |
| 141 | types.reserve(numFields); |
| 142 | |
| 143 | // This function is called in a loop for all columns used in a filter |
| 144 | // expression. For each column, 'channel' specifies column index in the left |
| 145 | // or right side of the join input, 'outputs' specifies the mapping from input |
| 146 | // columns of that side of the join to the output of the join; 'filters' |
| 147 | // specifies the mapping from input columns to the 'filterInput_' for columns |
| 148 | // that are not projected to the output. |
| 149 | // |
| 150 | // This function checks whether the column is projected to the output and if |
| 151 | // so adds an entry to 'filterInputToOutputChannel_'. Otherwise, adds an entry |
| 152 | // to 'filters'. |
| 153 | // |
| 154 | // At the end of the loop, each column used in a filter appears either in: |
| 155 | // |
| 156 | // - filterInputToOutputChannel_: in case the column is projected to the join |
| 157 | // output; |
| 158 | // - filterLeftInputs_: in case the column is not projected to the join |
| 159 | // output and it comes from the left side of the join; |
| 160 | // - filterRightInputs_: in case the column is not projected to the join |
| 161 | // output and it comes from the right side of the join. |
| 162 | auto addChannel = [&](column_index_t channel, |
| 163 | const std::vector<IdentityProjection>& outputs, |
| 164 | std::vector<IdentityProjection>& filters, |
| 165 | const RowTypePtr& inputType) { |
| 166 | names.emplace_back(inputType->nameOf(channel)); |
| 167 | types.emplace_back(inputType->childAt(channel)); |
| 168 | |
| 169 | for (const auto& [inputChannel, outputChannel] : outputs) { |
| 170 | if (inputChannel == channel) { |
| 171 | filterInputToOutputChannel_.emplace(filterChannel++, outputChannel); |
| 172 | return; |
| 173 | } |
| 174 | } |
| 175 | filters.emplace_back(channel, filterChannel++); |
| 176 | }; |
| 177 | |
| 178 | for (const auto& field : filter_->expr(0)->distinctFields()) { |
| 179 | const auto& name = field->field(); |
| 180 | auto channel = leftType->getChildIdxIfExists(name); |
| 181 | if (channel.has_value()) { |
| 182 | addChannel( |
| 183 | channel.value(), leftProjections_, filterLeftInputs_, leftType); |
| 184 | continue; |
| 185 | } |
nothing calls this directly
no test coverage detected