@@ -300,7 +300,6 @@ IQueryPlanStep::UnusedColumnRemovalResult FilterStep::removeUnusedColumns(const
300300 auto split_results = actions_dag.splitPossibleOutputNames (required_outputs);
301301 const auto actions_dag_input_count_before = actions_dag.getInputs ().size ();
302302
303-
304303 const auto required_columns_contains_filter = std::any_of (
305304 split_results.output_names .begin (),
306305 split_results.output_names .end (),
@@ -309,30 +308,49 @@ IQueryPlanStep::UnusedColumnRemovalResult FilterStep::removeUnusedColumns(const
309308 if (!required_columns_contains_filter)
310309 split_results.output_names .push_back (filter_column_name);
311310
312- const auto removed_any_actions = actions_dag.removeUnusedActions (split_results.output_names , remove_inputs);
311+ auto updated_actions = actions_dag.removeUnusedActions (split_results.output_names , remove_inputs);
313312
314- if (!removed_any_actions && output_header.has_value () && output_header->columns () == required_outputs.size ())
313+ const auto & input_header = input_headers.front ();
314+ // Number of input columns that are not removed by actions
315+ const auto pass_through_inputs = input_header.columns () - actions_dag_input_count_before;
316+ const auto has_to_remove_any_pass_through_input = pass_through_inputs > split_results.not_output_names .size ();
317+ const auto has_to_add_input_to_actions = !remove_inputs && has_to_remove_any_pass_through_input;
318+ const auto build_required_inputs_set = [this , ¬_output_names = split_results.not_output_names ]()
319+ {
320+ std::unordered_set<String> required_inputs_set;
321+
322+ for (const auto * input_node : actions_dag.getInputs ())
323+ required_inputs_set.insert (input_node->result_name );
324+
325+ for (const auto & pass_through_input : not_output_names)
326+ required_inputs_set.insert (pass_through_input);
327+
328+ return required_inputs_set;
329+ };
330+
331+ if (has_to_add_input_to_actions)
332+ {
333+ const auto required_inputs_set = build_required_inputs_set ();
334+
335+ for (const auto & name_and_type : input_header)
336+ if (!required_inputs_set.contains (name_and_type.name ))
337+ actions_dag.addInput (name_and_type);
338+
339+ updated_actions = true ;
340+ }
341+
342+ if (!updated_actions && output_header.has_value () && output_header->columns () == required_outputs.size ())
315343 return UnusedColumnRemovalResult{false , false };
316344
317345 // There cannot be more inputs in the DAG than columns in the input header
318346 chassert (actions_dag.getInputs ().size () <= getInputHeaders ().at (0 ).columns ());
319347
320- auto & input_header = input_headers.front ();
321- // Number of columns that are not changed/removed by actions
322- const auto pass_through_inputs = input_header.columns () - actions_dag_input_count_before;
323348 const auto update_inputs = remove_inputs
324349 && (actions_dag.getInputs ().size () < actions_dag_input_count_before || pass_through_inputs > split_results.not_output_names .size ());
325350
326351 if (update_inputs)
327352 {
328- std::unordered_set<String> required_inputs_set;
329-
330- for (const auto * input_node : actions_dag.getInputs ())
331- required_inputs_set.insert (input_node->result_name );
332-
333- for (const auto & pass_through_input : split_results.not_output_names )
334- required_inputs_set.insert (pass_through_input);
335-
353+ const auto required_inputs_set = build_required_inputs_set ();
336354 Header new_input_header{};
337355
338356 for (const auto & col_type_and_name : input_header)
0 commit comments