|
39 | 39 | #include "src/shared/types/types.h" |
40 | 40 | #include "src/shared/types/typespb/wrapper/types_pb_wrapper.h" |
41 | 41 |
|
| 42 | +DEFINE_bool(use_zero_copy_filter, false, "Uses a non optimized, but zero-copy filter that can run on PEMs. If this setting is disabled, this assumes that filters must run on Kelvin"); |
| 43 | + |
42 | 44 | namespace px { |
43 | 45 | namespace carnot { |
44 | 46 | namespace exec { |
@@ -132,42 +134,66 @@ Status PredicateCopyValues<types::STRING>(const types::BoolValueColumnWrapper& p |
132 | 134 | Status FilterNode::ConsumeNextImpl(ExecState* exec_state, const RowBatch& rb, size_t) { |
133 | 135 | // Current implementation does not merge across row batches, we should |
134 | 136 | // consider this for cases where the filter has really low selectivity. |
135 | | - /* PX_ASSIGN_OR_RETURN(auto pred_col, evaluator_->EvaluateSingleExpression( */ |
136 | | - /* exec_state, rb, *plan_node_->expression())); */ |
137 | | - |
138 | | - /* // Verify that the type of the column is boolean. */ |
139 | | - /* DCHECK_EQ(pred_col->data_type(), types::BOOLEAN) << "Predicate expression must be a boolean"; */ |
140 | | - |
141 | | - /* const types::BoolValueColumnWrapper& pred_col_wrapper = */ |
142 | | - /* *static_cast<types::BoolValueColumnWrapper*>(pred_col.get()); */ |
143 | | - /* size_t num_pred = pred_col_wrapper.Size(); */ |
144 | | - |
145 | | - /* DCHECK_EQ(static_cast<size_t>(rb.num_rows()), num_pred); */ |
146 | | - |
147 | | - // Find out how many of them returned true; |
148 | | - size_t num_output_records = rb.num_rows(); |
149 | | - /* for (size_t i = 0; i < num_pred; ++i) { */ |
150 | | - /* if (pred_col_wrapper[i].val) { */ |
151 | | - /* ++num_output_records; */ |
152 | | - /* } */ |
153 | | - /* } */ |
154 | | - |
155 | | - RowBatch output_rb(*output_descriptor_, num_output_records); |
156 | | - DCHECK_EQ(output_descriptor_->size(), plan_node_->selected_cols().size()); |
157 | | - |
158 | | - for (const auto& [output_col_idx, input_col_idx] : Enumerate(plan_node_->selected_cols())) { |
159 | | - auto input_col = rb.ColumnAt(input_col_idx); |
160 | | - PX_RETURN_IF_ERROR(output_rb.AddColumn(input_col)); |
161 | | - /* auto col_type = output_descriptor_->type(output_col_idx); */ |
162 | | -/* #define TYPE_CASE(_dt_) \ */ |
163 | | -/* PX_RETURN_IF_ERROR(PredicateCopyValues<_dt_>(pred_col_wrapper, input_col.get(), &output_rb)); */ |
164 | | -/* PX_SWITCH_FOREACH_DATATYPE(col_type, TYPE_CASE); */ |
165 | | -/* #undef TYPE_CASE */ |
166 | | - } |
| 137 | + if (FLAGS_use_zero_copy_filter) { |
| 138 | + PX_ASSIGN_OR_RETURN(auto pred_col, evaluator_->EvaluateSingleExpression( |
| 139 | + exec_state, rb, *plan_node_->expression())); |
| 140 | + |
| 141 | + // Verify that the type of the column is boolean. |
| 142 | + DCHECK_EQ(pred_col->data_type(), types::BOOLEAN) << "Predicate expression must be a boolean"; |
| 143 | + |
| 144 | + const types::BoolValueColumnWrapper& pred_col_wrapper = |
| 145 | + *static_cast<types::BoolValueColumnWrapper*>(pred_col.get()); |
| 146 | + size_t num_pred = pred_col_wrapper.Size(); |
| 147 | + |
| 148 | + DCHECK_EQ(static_cast<size_t>(rb.num_rows()), num_pred); |
| 149 | + |
| 150 | + std::vector<RowBatch> output_rbs; |
| 151 | + int64_t segment_start = -1; |
| 152 | + for (size_t idx = 0; idx < num_pred; ++idx) { |
| 153 | + if (pred_col_wrapper[idx].val) { |
| 154 | + if (segment_start == -1) { |
| 155 | + segment_start = idx; |
| 156 | + } |
| 157 | + } else { |
| 158 | + if (segment_start != -1) { |
| 159 | + output_rbs.emplace_back(rb.UnsafeSlice(segment_start, idx - segment_start)); |
| 160 | + segment_start = -1; |
| 161 | + } |
| 162 | + } |
| 163 | + } |
| 164 | + |
| 165 | + if (output_rbs.empty() && segment_start != -1) { |
| 166 | + output_rbs.emplace_back(rb.UnsafeSlice(segment_start, num_pred - segment_start)); |
| 167 | + } else if (output_rbs.empty()) { |
| 168 | + // No rows matched the filter. |
| 169 | + PX_ASSIGN_OR_RETURN(auto empty_rb, |
| 170 | + RowBatch::WithZeroRows(*output_descriptor_, rb.eow(), rb.eos())); |
| 171 | + RowBatch& empty_rb_ref = *empty_rb; |
| 172 | + output_rbs.push_back(empty_rb_ref); |
| 173 | + } |
167 | 174 |
|
168 | | - output_rb.set_eow(rb.eow()); |
169 | | - output_rb.set_eos(rb.eos()); |
170 | | - PX_RETURN_IF_ERROR(SendRowBatchToChildren(exec_state, output_rb)); |
| 175 | + auto& back = output_rbs.back(); |
| 176 | + back.set_eow(rb.eow()); |
| 177 | + back.set_eos(rb.eos()); |
| 178 | + |
| 179 | + for (auto it = output_rbs.begin(); it != output_rbs.end(); ++it) { |
| 180 | + auto& output_rb = *it; |
| 181 | + PX_RETURN_IF_ERROR(SendRowBatchToChildren(exec_state, output_rb)); |
| 182 | + } |
| 183 | + } else { |
| 184 | + size_t num_output_records = rb.num_rows(); |
| 185 | + RowBatch output_rb(*output_descriptor_, num_output_records); |
| 186 | + DCHECK_EQ(output_descriptor_->size(), plan_node_->selected_cols().size()); |
| 187 | + |
| 188 | + for (const auto& [output_col_idx, input_col_idx] : Enumerate(plan_node_->selected_cols())) { |
| 189 | + auto input_col = rb.ColumnAt(input_col_idx); |
| 190 | + PX_RETURN_IF_ERROR(output_rb.AddColumn(input_col)); |
| 191 | + } |
| 192 | + |
| 193 | + output_rb.set_eow(rb.eow()); |
| 194 | + output_rb.set_eos(rb.eos()); |
| 195 | + PX_RETURN_IF_ERROR(SendRowBatchToChildren(exec_state, output_rb)); |
| 196 | + } |
171 | 197 | return Status::OK(); |
172 | 198 | } |
173 | 199 |
|
|
0 commit comments