diff --git a/dbms/src/Interpreters/ExpressionActions.cpp b/dbms/src/Interpreters/ExpressionActions.cpp index ddaba9a0451..03aaa57c648 100644 --- a/dbms/src/Interpreters/ExpressionActions.cpp +++ b/dbms/src/Interpreters/ExpressionActions.cpp @@ -1019,7 +1019,7 @@ void ExpressionActionsChain::finalize() std::unordered_map required_output_indexes; for (size_t j = 0; j < required_output.size(); ++j) required_output_indexes[required_output[j]] = j; - auto & can_remove_required_output = steps[i].can_remove_required_output; + auto & can_remove_required_output = steps[i].not_need_in_future_steps; if (i + 1 < static_cast(steps.size())) { diff --git a/dbms/src/Interpreters/ExpressionActions.h b/dbms/src/Interpreters/ExpressionActions.h index 71d3bad4f9f..02ab6c4f09e 100644 --- a/dbms/src/Interpreters/ExpressionActions.h +++ b/dbms/src/Interpreters/ExpressionActions.h @@ -232,7 +232,10 @@ struct ExpressionActionsChain ExpressionActionsPtr actions; NameSet additional_input; Names required_output; - std::vector> can_remove_required_output; /// Has the same size with required_output, is filled in finalize() + /// Columns which are used only for current steps and not used in next actions (and can be removed from block). + /// Example: filter column for where actions. + /// If not empty, has the same size with required_output; is filled in finalize(). + std::vector not_need_in_future_steps; Step(const ExpressionActionsPtr & actions_ = nullptr, const Names & required_output_ = Names()) : actions(actions_), required_output(required_output_) {} diff --git a/dbms/src/Interpreters/ExpressionAnalyzer.cpp b/dbms/src/Interpreters/ExpressionAnalyzer.cpp index f0c92ddf6c8..235d02e7156 100644 --- a/dbms/src/Interpreters/ExpressionAnalyzer.cpp +++ b/dbms/src/Interpreters/ExpressionAnalyzer.cpp @@ -2429,7 +2429,7 @@ bool ExpressionAnalyzer::appendJoin(ExpressionActionsChain & chain, bool only_ty return true; } -bool ExpressionAnalyzer::appendPrewhere(ExpressionActionsChain & chain, bool only_types, std::shared_ptr & remove_filter) +bool ExpressionAnalyzer::appendPrewhere(ExpressionActionsChain & chain, bool only_types, bool & remove_filter) { assertSelect(); @@ -2441,7 +2441,7 @@ bool ExpressionAnalyzer::appendPrewhere(ExpressionActionsChain & chain, bool onl getRootActions(select_query->prewhere_expression, only_types, false, step.actions); String prewhere_column_name = select_query->prewhere_expression->getColumnName(); step.required_output.push_back(prewhere_column_name); - step.can_remove_required_output = {remove_filter = std::make_shared(true)}; + step.not_need_in_future_steps = {&remove_filter}; { /// Remove unused source_columns from prewhere actions. @@ -2491,7 +2491,7 @@ bool ExpressionAnalyzer::appendPrewhere(ExpressionActionsChain & chain, bool onl return true; } -bool ExpressionAnalyzer::appendWhere(ExpressionActionsChain & chain, bool only_types, std::shared_ptr & remove_filter) +bool ExpressionAnalyzer::appendWhere(ExpressionActionsChain & chain, bool only_types, bool & remove_filter) { assertSelect(); @@ -2502,7 +2502,7 @@ bool ExpressionAnalyzer::appendWhere(ExpressionActionsChain & chain, bool only_t ExpressionActionsChain::Step & step = chain.steps.back(); step.required_output.push_back(select_query->where_expression->getColumnName()); - step.can_remove_required_output = {remove_filter = std::make_shared(true)}; + step.not_need_in_future_steps = {&remove_filter}; getRootActions(select_query->where_expression, only_types, false, step.actions); return true; diff --git a/dbms/src/Interpreters/ExpressionAnalyzer.h b/dbms/src/Interpreters/ExpressionAnalyzer.h index 6e51c0daf7d..90c78c0dfe7 100644 --- a/dbms/src/Interpreters/ExpressionAnalyzer.h +++ b/dbms/src/Interpreters/ExpressionAnalyzer.h @@ -103,8 +103,8 @@ public: /// Before aggregation: bool appendArrayJoin(ExpressionActionsChain & chain, bool only_types); bool appendJoin(ExpressionActionsChain & chain, bool only_types); - bool appendPrewhere(ExpressionActionsChain & chain, bool only_types, std::shared_ptr & remove_filter); - bool appendWhere(ExpressionActionsChain & chain, bool only_types, std::shared_ptr & remove_filter); + bool appendPrewhere(ExpressionActionsChain & chain, bool only_types, bool & remove_filter); + bool appendWhere(ExpressionActionsChain & chain, bool only_types, bool & remove_filter); bool appendGroupBy(ExpressionActionsChain & chain, bool only_types); void appendAggregateFunctionsArguments(ExpressionActionsChain & chain, bool only_types); diff --git a/dbms/src/Interpreters/InterpreterSelectQuery.cpp b/dbms/src/Interpreters/InterpreterSelectQuery.cpp index e9c11182204..e5723d658e8 100644 --- a/dbms/src/Interpreters/InterpreterSelectQuery.cpp +++ b/dbms/src/Interpreters/InterpreterSelectQuery.cpp @@ -250,13 +250,12 @@ InterpreterSelectQuery::AnalysisResult InterpreterSelectQuery::analyzeExpression * throw out unnecessary columns based on the entire query. In unnecessary parts of the query, we will not execute subqueries. */ - std::shared_ptr remove_where_filter; - std::shared_ptr remove_prewhere_filter; + bool remove_prewhere_filter; { ExpressionActionsChain chain; - if (query_analyzer->appendPrewhere(chain, false, remove_prewhere_filter)) + if (query_analyzer->appendPrewhere(chain, !res.first_stage, remove_prewhere_filter)) { res.prewhere_info = std::make_shared( chain.steps.front().actions, query.prewhere_expression->getColumnName()); @@ -274,7 +273,7 @@ InterpreterSelectQuery::AnalysisResult InterpreterSelectQuery::analyzeExpression chain.addStep(); } - if (query_analyzer->appendWhere(chain, !res.first_stage, remove_where_filter)) + if (query_analyzer->appendWhere(chain, !res.first_stage, res.remove_where_filter)) { res.has_where = true; res.before_where = chain.getLastActions(); @@ -320,14 +319,11 @@ InterpreterSelectQuery::AnalysisResult InterpreterSelectQuery::analyzeExpression } if (res.prewhere_info) - res.prewhere_info->remove_prewhere_column = *remove_prewhere_filter; + res.prewhere_info->remove_prewhere_column = remove_prewhere_filter; /// Before executing WHERE and HAVING, remove the extra columns from the block (mostly the aggregation keys). if (res.has_where) - { res.before_where->prependProjectInput(); - res.remove_where_filter = *remove_where_filter; - } if (res.has_having) res.before_having->prependProjectInput();