blob: 62d658ddccd8677ac45d181ebe082ef1ba7cb964 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
#pragma once
#include <Core/Names.h>
#include <Interpreters/Context_fwd.h>
#include <Columns/IColumn.h>
#include <QueryPipeline/QueryPlanResourceHolder.h>
#include <list>
#include <memory>
#include <set>
#include <vector>
namespace DB
{
class DataStream;
class IQueryPlanStep;
using QueryPlanStepPtr = std::unique_ptr<IQueryPlanStep>;
class QueryPipelineBuilder;
using QueryPipelineBuilderPtr = std::unique_ptr<QueryPipelineBuilder>;
class WriteBuffer;
class QueryPlan;
using QueryPlanPtr = std::unique_ptr<QueryPlan>;
class Pipe;
struct QueryPlanOptimizationSettings;
struct BuildQueryPipelineSettings;
namespace JSONBuilder
{
class IItem;
using ItemPtr = std::unique_ptr<IItem>;
}
/// A tree of query steps.
/// The goal of QueryPlan is to build QueryPipeline.
/// QueryPlan let delay pipeline creation which is helpful for pipeline-level optimizations.
class QueryPlan
{
public:
QueryPlan();
~QueryPlan();
QueryPlan(QueryPlan &&) noexcept;
QueryPlan & operator=(QueryPlan &&) noexcept;
void unitePlans(QueryPlanStepPtr step, std::vector<QueryPlanPtr> plans);
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())
void optimize(const QueryPlanOptimizationSettings & optimization_settings);
QueryPipelineBuilderPtr buildQueryPipeline(
const QueryPlanOptimizationSettings & optimization_settings,
const BuildQueryPipelineSettings & build_pipeline_settings);
struct ExplainPlanOptions
{
/// Add output header to step.
bool header = false;
/// Add description of step.
bool description = true;
/// Add detailed information about step actions.
bool actions = false;
/// Add information about indexes actions.
bool indexes = false;
/// Add information about sorting
bool sorting = false;
};
struct ExplainPipelineOptions
{
/// Show header of output ports.
bool header = false;
};
JSONBuilder::ItemPtr explainPlan(const ExplainPlanOptions & options);
void explainPlan(WriteBuffer & buffer, const ExplainPlanOptions & options);
void explainPipeline(WriteBuffer & buffer, const ExplainPipelineOptions & options);
void explainEstimate(MutableColumns & columns);
/// Do not allow to change the table while the pipeline alive.
void addTableLock(TableLockHolder lock) { resources.table_locks.emplace_back(std::move(lock)); }
void addInterpreterContext(std::shared_ptr<const Context> context) { resources.interpreter_context.emplace_back(std::move(context)); }
void addStorageHolder(StoragePtr storage) { resources.storage_holders.emplace_back(std::move(storage)); }
void addResources(QueryPlanResourceHolder resources_) { resources = std::move(resources_); }
/// Set upper limit for the recommend number of threads. Will be applied to the newly-created pipelines.
/// TODO: make it in a better way.
void setMaxThreads(size_t max_threads_) { max_threads = max_threads_; }
size_t getMaxThreads() const { return max_threads; }
void setConcurrencyControl(bool concurrency_control_) { concurrency_control = concurrency_control_; }
bool getConcurrencyControl() const { return concurrency_control; }
/// Tree node. Step and it's children.
struct Node
{
QueryPlanStepPtr step;
std::vector<Node *> children = {};
};
using Nodes = std::list<Node>;
Node * getRootNode() const { return root; }
static std::pair<Nodes, QueryPlanResourceHolder> detachNodesAndResources(QueryPlan && plan);
private:
QueryPlanResourceHolder resources;
Nodes nodes;
Node * root = nullptr;
void checkInitialized() const;
void checkNotCompleted() const;
/// Those fields are passed to QueryPipeline.
size_t max_threads = 0;
bool concurrency_control = false;
};
std::string debugExplainStep(const IQueryPlanStep & step);
}
|