From d88e19b69d795d8d0c93d4ea0d4c08f9bc4e060e Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Tue, 23 Jun 2020 19:06:56 +0300 Subject: [PATCH] Added actions setting for Explain query. --- src/Interpreters/AggregateDescription.cpp | 80 ++++++++++++++++++++ src/Interpreters/AggregateDescription.h | 2 + src/Interpreters/Aggregator.cpp | 27 +++++++ src/Interpreters/Aggregator.h | 3 + src/Interpreters/InterpreterExplainQuery.cpp | 1 + src/Interpreters/ya.make | 1 + src/Processors/QueryPlan/AggregatingStep.cpp | 5 ++ src/Processors/QueryPlan/AggregatingStep.h | 2 + src/Processors/QueryPlan/IQueryPlanStep.h | 3 + src/Processors/QueryPlan/QueryPlan.cpp | 19 +++++ src/Processors/QueryPlan/QueryPlan.h | 1 + 11 files changed, 144 insertions(+) create mode 100644 src/Interpreters/AggregateDescription.cpp diff --git a/src/Interpreters/AggregateDescription.cpp b/src/Interpreters/AggregateDescription.cpp new file mode 100644 index 00000000000..ed737bd4fa4 --- /dev/null +++ b/src/Interpreters/AggregateDescription.cpp @@ -0,0 +1,80 @@ +#include +#include + +namespace DB +{ + +Strings AggregateDescription::explain() const +{ + Strings res; + String arguments_pos_str; + for (auto arg : arguments) + { + if (!arguments_pos_str.empty()) + arguments_pos_str += ", "; + + arguments_pos_str += std::to_string(arg); + } + + if (arguments_pos_str.empty()) + arguments_pos_str = "none"; + + res.emplace_back("argument positions: " + arguments_pos_str); + + String arguments_names_str; + for (const auto & arg : argument_names) + { + if (!arguments_names_str.empty()) + arguments_names_str += ", "; + + arguments_names_str += arg; + } + + if (arguments_names_str.empty()) + arguments_names_str = "none"; + + res.emplace_back("arguments: " + arguments_names_str); + res.emplace_back("column_name: " + column_name); + + auto get_params_string = [](const Array & arr) + { + String params_str; + for (const auto & param : arr) + { + if (!params_str.empty()) + params_str += ", "; + + params_str += applyVisitor(FieldVisitorToString(), param); + } + + return params_str; + }; + + if (function) + { + String types_str; + for (const auto & type : function->getArgumentTypes()) + { + if (!types_str.empty()) + types_str += ", "; + + types_str += type->getName(); + } + + auto params_str = get_params_string(function->getParameters()); + if (!params_str.empty()) + params_str = "(" + params_str + ")"; + + res.emplace_back("function: " + function->getName() + params_str + '(' + types_str + ") -> " + + function->getReturnType()->getName()); + } + else + res.emplace_back("function: nullptr"); + + if (!parameters.empty()) + res.emplace_back("parameters: " + get_params_string(parameters)); + + return res; +} + +} diff --git a/src/Interpreters/AggregateDescription.h b/src/Interpreters/AggregateDescription.h index dece93c9093..a17e307451d 100644 --- a/src/Interpreters/AggregateDescription.h +++ b/src/Interpreters/AggregateDescription.h @@ -15,6 +15,8 @@ struct AggregateDescription ColumnNumbers arguments; Names argument_names; /// used if no `arguments` are specified. String column_name; /// What name to use for a column with aggregate function values + + Strings explain() const; /// Get description for EXPLAIN query. }; using AggregateDescriptions = std::vector; diff --git a/src/Interpreters/Aggregator.cpp b/src/Interpreters/Aggregator.cpp index c8165632896..c30c8faac12 100644 --- a/src/Interpreters/Aggregator.cpp +++ b/src/Interpreters/Aggregator.cpp @@ -150,6 +150,33 @@ Block Aggregator::Params::getHeader( return materializeBlock(res); } +Strings Aggregator::Params::explain() const +{ + Strings res; + const auto & header = src_header ? src_header + : intermediate_header; + String keys_str; + for (auto key : keys) + { + if (keys_str.empty()) + keys_str += ", "; + + if (key >= header.columns()) + keys_str += "unknown position " + std::to_string(key); + else + keys_str += src_header.getByPosition(key).name; + } + + res.emplace_back("keys: " + std::move(keys_str)); + + for (const auto & aggregate : aggregates) + { + auto aggregate_strings = aggregate.explain(); + res.insert(res.end(), aggregate_strings.begin(), aggregate_strings.end()); + } + + return res; +} Aggregator::Aggregator(const Params & params_) : params(params_), diff --git a/src/Interpreters/Aggregator.h b/src/Interpreters/Aggregator.h index 0546271873b..2b022f98367 100644 --- a/src/Interpreters/Aggregator.h +++ b/src/Interpreters/Aggregator.h @@ -923,6 +923,9 @@ public: { return getHeader(src_header, intermediate_header, keys, aggregates, final); } + + /// Returns keys and aggregated for EXPLAIN query + Strings explain() const; }; Aggregator(const Params & params_); diff --git a/src/Interpreters/InterpreterExplainQuery.cpp b/src/Interpreters/InterpreterExplainQuery.cpp index bbfa83af2e7..45e1d9f13ff 100644 --- a/src/Interpreters/InterpreterExplainQuery.cpp +++ b/src/Interpreters/InterpreterExplainQuery.cpp @@ -120,6 +120,7 @@ struct ExplainSettings { {"header", query_plan_options.header}, {"description", query_plan_options.description}, + {"actions", query_plan_options.actions} }; bool has(const std::string & name) const diff --git a/src/Interpreters/ya.make b/src/Interpreters/ya.make index 394c9c36064..3df3cb7f3dc 100644 --- a/src/Interpreters/ya.make +++ b/src/Interpreters/ya.make @@ -18,6 +18,7 @@ SRCS( ActionsVisitor.cpp addMissingDefaults.cpp addTypeConversionToAST.cpp + AggregateDescription.cpp Aggregator.cpp AnyInputOptimize.cpp ArithmeticOperationsInAgrFuncOptimize.cpp diff --git a/src/Processors/QueryPlan/AggregatingStep.cpp b/src/Processors/QueryPlan/AggregatingStep.cpp index 47cb444654c..757e47e1a6e 100644 --- a/src/Processors/QueryPlan/AggregatingStep.cpp +++ b/src/Processors/QueryPlan/AggregatingStep.cpp @@ -139,4 +139,9 @@ void AggregatingStep::transformPipeline(QueryPipeline & pipeline) pipeline.enableQuotaForCurrentStreams(); } +Strings AggregatingStep::describeActions() const +{ + return params.explain(); +} + } diff --git a/src/Processors/QueryPlan/AggregatingStep.h b/src/Processors/QueryPlan/AggregatingStep.h index df75eee1b3f..54ea7c1424f 100644 --- a/src/Processors/QueryPlan/AggregatingStep.h +++ b/src/Processors/QueryPlan/AggregatingStep.h @@ -28,6 +28,8 @@ public: void transformPipeline(QueryPipeline & pipeline) override; + Strings describeActions() const override; + private: Aggregator::Params params; bool final; diff --git a/src/Processors/QueryPlan/IQueryPlanStep.h b/src/Processors/QueryPlan/IQueryPlanStep.h index 4f9e4d3268c..e64219265c5 100644 --- a/src/Processors/QueryPlan/IQueryPlanStep.h +++ b/src/Processors/QueryPlan/IQueryPlanStep.h @@ -51,6 +51,9 @@ public: const std::string & getStepDescription() const { return step_description; } void setStepDescription(std::string description) { step_description = std::move(description); } + /// Get detailed description of step actions. This is shown in EXPLAIN query with options `actions = 1`. + virtual Strings describeActions() const { return {}; } + protected: DataStreams input_streams; std::optional output_stream; diff --git a/src/Processors/QueryPlan/QueryPlan.cpp b/src/Processors/QueryPlan/QueryPlan.cpp index 887bbf557fb..65b0fc6b33f 100644 --- a/src/Processors/QueryPlan/QueryPlan.cpp +++ b/src/Processors/QueryPlan/QueryPlan.cpp @@ -216,6 +216,25 @@ static void explainStep( buffer.write('\n'); } + + if (options.actions) + { + auto actions = step.describeActions(); + if (!actions.empty()) + { + buffer << "Actions: "; + bool first = true; + + for (auto & action : actions) + { + if (!first) + buffer << ",\n" << prefix << " "; + + first = false; + buffer << action; + } + } + } } void QueryPlan::explain(WriteBuffer & buffer, const ExplainOptions & options) diff --git a/src/Processors/QueryPlan/QueryPlan.h b/src/Processors/QueryPlan/QueryPlan.h index d37b94fea8b..7a6efc1c207 100644 --- a/src/Processors/QueryPlan/QueryPlan.h +++ b/src/Processors/QueryPlan/QueryPlan.h @@ -37,6 +37,7 @@ public: { bool header = false; bool description = true; + bool actions = false; }; void explain(WriteBuffer & buffer, const ExplainOptions & options);