#pragma once #include #include #include #include #include namespace DB { class DataStream; class IQueryPlanStep; using QueryPlanStepPtr = std::unique_ptr; class QueryPipeline; using QueryPipelinePtr = std::unique_ptr; class Context; class WriteBuffer; class QueryPlan; using QueryPlanPtr = std::unique_ptr; class Pipe; struct QueryPlanOptimizationSettings; struct BuildQueryPipelineSettings; /// 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 &&); QueryPlan & operator=(QueryPlan &&); void unitePlans(QueryPlanStepPtr step, std::vector 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); QueryPipelinePtr buildQueryPipeline( const QueryPlanOptimizationSettings & optimization_settings, const BuildQueryPipelineSettings & build_pipeline_settings); /// If initialized, build pipeline and convert to pipe. Otherwise, return empty pipe. Pipe convertToPipe( 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; }; struct ExplainPipelineOptions { /// Show header of output ports. bool header = false; }; void explainPlan(WriteBuffer & buffer, const ExplainPlanOptions & options); void explainPipeline(WriteBuffer & buffer, const ExplainPipelineOptions & options); /// 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 addInterpreterContext(std::shared_ptr context); /// Tree node. Step and it's children. struct Node { QueryPlanStepPtr step; std::vector children = {}; }; using Nodes = std::list; private: Nodes nodes; Node * root = nullptr; void checkInitialized() const; void checkNotCompleted() const; /// Those fields are passed to QueryPipeline. size_t max_threads = 0; std::vector> interpreter_context; }; std::string debugExplainStep(const IQueryPlanStep & step); }