mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-18 21:51:57 +00:00
Add QueryPlan.
This commit is contained in:
parent
108575c8ad
commit
4c179e454a
@ -51,4 +51,5 @@ protected:
|
|||||||
std::optional<DataStream> output_stream;
|
std::optional<DataStream> output_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using QueryPlanStepPtr = std::unique_ptr<IQueryPlanStep>;
|
||||||
}
|
}
|
||||||
|
112
src/Processors/QueryPlan/QueryPlan.cpp
Normal file
112
src/Processors/QueryPlan/QueryPlan.cpp
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#include <Processors/QueryPlan/QueryPlan.h>
|
||||||
|
#include <Processors/QueryPlan/IQueryPlanStep.h>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int LOGICAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryPlan::checkInitialized() const
|
||||||
|
{
|
||||||
|
if (!isInitialized())
|
||||||
|
throw Exception("QueryPlan was not initialized", ErrorCodes::LOGICAL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryPlan::checkNotCompleted() const
|
||||||
|
{
|
||||||
|
if (isCompleted())
|
||||||
|
throw Exception("QueryPlan was already completed", ErrorCodes::LOGICAL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QueryPlan::isCompleted() const
|
||||||
|
{
|
||||||
|
return isInitialized() && !root->step->hasOutputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
const DataStream & QueryPlan::getCurrentDataStream() const
|
||||||
|
{
|
||||||
|
checkInitialized();
|
||||||
|
checkNotCompleted();
|
||||||
|
return root->step->getOutputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryPlan::addStep(QueryPlanStepPtr step)
|
||||||
|
{
|
||||||
|
checkNotCompleted();
|
||||||
|
|
||||||
|
size_t num_input_streams = step->getInputStreams().size();
|
||||||
|
|
||||||
|
if (num_input_streams == 0)
|
||||||
|
{
|
||||||
|
if (isInitialized())
|
||||||
|
throw Exception("Cannot add step " + step->getName() + " to QueryPlan because "
|
||||||
|
"step has no inputs, but QueryPlan is already initialised", ErrorCodes::LOGICAL_ERROR);
|
||||||
|
|
||||||
|
nodes.emplace_back(Node{.step = std::move(step)});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_input_streams == 1)
|
||||||
|
{
|
||||||
|
if (!isInitialized())
|
||||||
|
throw Exception("Cannot add step " + step->getName() + " to QueryPlan because "
|
||||||
|
"step has input, but QueryPlan is not initialised", ErrorCodes::LOGICAL_ERROR);
|
||||||
|
|
||||||
|
const auto & root_header = root->step->getOutputStream().header;
|
||||||
|
const auto & step_header = step->getInputStreams().front().header;
|
||||||
|
if (!blocksHaveEqualStructure(root_header, step_header))
|
||||||
|
throw Exception("Cannot add step " + step->getName() + " to QueryPlan because "
|
||||||
|
"it has incompatible header with root step " + root->step->getName() + " "
|
||||||
|
"root header: " + root_header.dumpStructure() +
|
||||||
|
"step header: " + step_header.dumpStructure(), ErrorCodes::LOGICAL_ERROR);
|
||||||
|
|
||||||
|
nodes.emplace_back(Node{.step = std::move(step), .children = {root}});
|
||||||
|
root = &nodes.back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Exception("Cannot add step " + step->getName() + " to QueryPlan because it has " +
|
||||||
|
std::to_string(num_input_streams) + " inputs but " + std::to_string(isInitialized() ? 1 : 0) +
|
||||||
|
" input expected", ErrorCodes::LOGICAL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryPipelinePtr QueryPlan::buildQueryPipeline()
|
||||||
|
{
|
||||||
|
checkInitialized();
|
||||||
|
|
||||||
|
struct Frame
|
||||||
|
{
|
||||||
|
Node * node;
|
||||||
|
QueryPipelines pipelines;
|
||||||
|
};
|
||||||
|
|
||||||
|
QueryPipelinePtr last_pipeline;
|
||||||
|
|
||||||
|
std::stack<Frame> stack;
|
||||||
|
stack.push({.node = root});
|
||||||
|
|
||||||
|
while (!stack.empty())
|
||||||
|
{
|
||||||
|
auto & frame = stack.top();
|
||||||
|
|
||||||
|
if (last_pipeline)
|
||||||
|
frame.pipelines.emplace_back(std::move(last_pipeline));
|
||||||
|
|
||||||
|
size_t next_child = frame.pipelines.size();
|
||||||
|
if (next_child == frame.node->children.size())
|
||||||
|
{
|
||||||
|
last_pipeline = frame.node->step->updatePipeline(std::move(frame.pipelines));
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stack.push({.node = frame.node->children[next_child]});
|
||||||
|
}
|
||||||
|
|
||||||
|
return last_pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
45
src/Processors/QueryPlan/QueryPlan.h
Normal file
45
src/Processors/QueryPlan/QueryPlan.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class DataStream;
|
||||||
|
|
||||||
|
class IQueryPlanStep;
|
||||||
|
using QueryPlanStepPtr = std::unique_ptr<IQueryPlanStep>;
|
||||||
|
|
||||||
|
class QueryPipeline;
|
||||||
|
using QueryPipelinePtr = std::unique_ptr<QueryPipeline>;
|
||||||
|
|
||||||
|
/// A tree of query steps.
|
||||||
|
class QueryPlan
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void addStep(QueryPlanStepPtr step);
|
||||||
|
|
||||||
|
bool isInitialized() const { return root != nullptr; } /// Tree is not empty
|
||||||
|
bool isCompleted() const; /// Tree is not empty and root hasOutputStream()
|
||||||
|
const DataStream & getCurrentDataStream() const; /// Checks that (isInitialized() && !isCompleted())
|
||||||
|
|
||||||
|
QueryPipelinePtr buildQueryPipeline();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
QueryPlanStepPtr step;
|
||||||
|
std::vector<Node *> children;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Nodes = std::list<Node>;
|
||||||
|
Nodes nodes;
|
||||||
|
|
||||||
|
Node * root = nullptr;
|
||||||
|
|
||||||
|
void checkInitialized() const;
|
||||||
|
void checkNotCompleted() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -135,6 +135,7 @@ SRCS(
|
|||||||
Transforms/SortingTransform.cpp
|
Transforms/SortingTransform.cpp
|
||||||
Transforms/TotalsHavingTransform.cpp
|
Transforms/TotalsHavingTransform.cpp
|
||||||
QueryPlan/IQueryPlanStep.cpp
|
QueryPlan/IQueryPlanStep.cpp
|
||||||
|
QueryPlan/QueryPlan.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
END()
|
END()
|
||||||
|
Loading…
Reference in New Issue
Block a user