Add json=1 setting for explain actions

This commit is contained in:
Nikolai Kochetov 2021-04-09 17:44:58 +03:00
parent e279040813
commit 66b6d53a93
4 changed files with 80 additions and 1 deletions

View File

@ -18,6 +18,9 @@
#include <Processors/QueryPlan/BuildQueryPipelineSettings.h> #include <Processors/QueryPlan/BuildQueryPipelineSettings.h>
#include <Processors/printPipeline.h> #include <Processors/printPipeline.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
namespace DB namespace DB
{ {
@ -121,6 +124,7 @@ struct QueryPlanSettings
/// Apply query plan optimizations. /// Apply query plan optimizations.
bool optimize = true; bool optimize = true;
bool json = false;
constexpr static char name[] = "PLAN"; constexpr static char name[] = "PLAN";
@ -130,6 +134,7 @@ struct QueryPlanSettings
{"description", query_plan_options.description}, {"description", query_plan_options.description},
{"actions", query_plan_options.actions}, {"actions", query_plan_options.actions},
{"optimize", optimize}, {"optimize", optimize},
{"json", json}
}; };
}; };
@ -255,7 +260,15 @@ BlockInputStreamPtr InterpreterExplainQuery::executeImpl()
if (settings.optimize) if (settings.optimize)
plan.optimize(QueryPlanOptimizationSettings::fromContext(context)); plan.optimize(QueryPlanOptimizationSettings::fromContext(context));
plan.explainPlan(buf, settings.query_plan_options); if (settings.json)
{
auto tree = plan.explainPlan();
std::stringstream out;
boost::property_tree::json_parser::write_json(out, tree);
buf.str() = out.str();
}
else
plan.explainPlan(buf, settings.query_plan_options);
} }
else if (ast.getKind() == ASTExplainQuery::QueryPipeline) else if (ast.getKind() == ASTExplainQuery::QueryPipeline)
{ {

View File

@ -3,6 +3,8 @@
#include <Core/SortDescription.h> #include <Core/SortDescription.h>
#include <Processors/QueryPlan/BuildQueryPipelineSettings.h> #include <Processors/QueryPlan/BuildQueryPipelineSettings.h>
#include <boost/property_tree/ptree_fwd.hpp>
namespace DB namespace DB
{ {
@ -96,6 +98,8 @@ public:
const bool write_header = false; const bool write_header = false;
}; };
virtual void describeActions(boost::property_tree::ptree & /*tree*/) const {}
/// Get detailed description of step actions. This is shown in EXPLAIN query with options `actions = 1`. /// Get detailed description of step actions. This is shown in EXPLAIN query with options `actions = 1`.
virtual void describeActions(FormatSettings & /*settings*/) const {} virtual void describeActions(FormatSettings & /*settings*/) const {}

View File

@ -9,6 +9,7 @@
#include <Processors/QueryPlan/Optimizations/Optimizations.h> #include <Processors/QueryPlan/Optimizations/Optimizations.h>
#include <Processors/QueryPlan/Optimizations/QueryPlanOptimizationSettings.h> #include <Processors/QueryPlan/Optimizations/QueryPlanOptimizationSettings.h>
#include <Processors/QueryPlan/BuildQueryPipelineSettings.h> #include <Processors/QueryPlan/BuildQueryPipelineSettings.h>
#include <boost/property_tree/ptree.hpp>
namespace DB namespace DB
{ {
@ -200,6 +201,65 @@ void QueryPlan::addInterpreterContext(std::shared_ptr<Context> context)
} }
static boost::property_tree::ptree explainStep(const IQueryPlanStep & step)
{
boost::property_tree::ptree tree;
tree.put("Node Type", step.getName());
const auto & description = step.getStepDescription();
if (!description.empty())
tree.put("Description", description);
step.describeActions(tree);
return tree;
}
boost::property_tree::ptree QueryPlan::explainPlan()
{
checkInitialized();
struct Frame
{
Node * node;
size_t next_child = 0;
boost::property_tree::ptree node_tree = {};
boost::property_tree::ptree children_trees = {};
};
std::stack<Frame> stack;
stack.push(Frame{.node = root});
boost::property_tree::ptree tree;
while (!stack.empty())
{
auto & frame = stack.top();
if (frame.next_child == 0)
frame.node_tree = explainStep(*frame.node->step);
if (frame.next_child < frame.node->children.size())
{
stack.push(Frame{frame.node->children[frame.next_child]});
++frame.next_child;
}
else
{
if (!frame.children_trees.empty())
frame.node_tree.add_child("Plans", frame.children_trees);
tree.swap(frame.node_tree);
stack.pop();
if (!stack.empty())
stack.top().children_trees.add_child("", tree);
}
}
return tree;
}
static void explainStep( static void explainStep(
const IQueryPlanStep & step, const IQueryPlanStep & step,
IQueryPlanStep::FormatSettings & settings, IQueryPlanStep::FormatSettings & settings,

View File

@ -3,6 +3,7 @@
#include <list> #include <list>
#include <vector> #include <vector>
#include <set> #include <set>
#include <boost/property_tree/ptree_fwd.hpp>
#include <Core/Names.h> #include <Core/Names.h>
@ -73,6 +74,7 @@ public:
bool header = false; bool header = false;
}; };
boost::property_tree::ptree explainPlan();
void explainPlan(WriteBuffer & buffer, const ExplainPlanOptions & options); void explainPlan(WriteBuffer & buffer, const ExplainPlanOptions & options);
void explainPipeline(WriteBuffer & buffer, const ExplainPipelineOptions & options); void explainPipeline(WriteBuffer & buffer, const ExplainPipelineOptions & options);