diff --git a/src/Analyzer/IQueryTreePass.h b/src/Analyzer/IQueryTreePass.h index 39b3d743ed3..4293934c32d 100644 --- a/src/Analyzer/IQueryTreePass.h +++ b/src/Analyzer/IQueryTreePass.h @@ -16,7 +16,7 @@ namespace DB * Dependencies between passes must be avoided. */ class IQueryTreePass; -using QueryTreePassPtr = std::shared_ptr; +using QueryTreePassPtr = std::unique_ptr; using QueryTreePasses = std::vector; class IQueryTreePass diff --git a/src/Analyzer/QueryTreePassManager.cpp b/src/Analyzer/QueryTreePassManager.cpp index 853b4a23f38..9dc9cda44a3 100644 --- a/src/Analyzer/QueryTreePassManager.cpp +++ b/src/Analyzer/QueryTreePassManager.cpp @@ -18,6 +18,9 @@ #include #include +#include +#include +#include namespace DB { @@ -25,6 +28,38 @@ namespace DB namespace ErrorCodes { extern const int BAD_ARGUMENTS; + extern const int LOGICAL_ERROR; +} + +namespace +{ + +#ifndef NDEBUG + +/** This visitor checks if Query Tree structure is valid after each pass + * in debug build. + */ +class ValidationChecker : public InDepthQueryTreeVisitor +{ + String pass_name; +public: + explicit ValidationChecker(String pass_name_) + : pass_name(std::move(pass_name_)) + {} + + void visitImpl(QueryTreeNodePtr & node) const + { + auto * column = node->as(); + if (!column) + return; + if (column->getColumnSourceOrNull() == nullptr) + throw Exception(ErrorCodes::LOGICAL_ERROR, + "Column {} {} query tree node does not have valid source node after running {} pass", + column->getColumnName(), column->getColumnType(), pass_name); + } +}; +#endif + } /** ClickHouse query tree pass manager. @@ -61,7 +96,12 @@ void QueryTreePassManager::run(QueryTreeNodePtr query_tree_node) size_t passes_size = passes.size(); for (size_t i = 0; i < passes_size; ++i) + { passes[i]->run(query_tree_node, current_context); +#ifndef NDEBUG + ValidationChecker(passes[i]->getName()).visit(query_tree_node); +#endif + } } void QueryTreePassManager::run(QueryTreeNodePtr query_tree_node, size_t up_to_pass_index) @@ -75,7 +115,12 @@ void QueryTreePassManager::run(QueryTreeNodePtr query_tree_node, size_t up_to_pa auto current_context = getContext(); for (size_t i = 0; i < up_to_pass_index; ++i) + { passes[i]->run(query_tree_node, current_context); +#ifndef NDEBUG + ValidationChecker(passes[i]->getName()).visit(query_tree_node); +#endif + } } void QueryTreePassManager::dump(WriteBuffer & buffer) @@ -114,38 +159,38 @@ void addQueryTreePasses(QueryTreePassManager & manager) auto context = manager.getContext(); const auto & settings = context->getSettingsRef(); - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); if (settings.optimize_functions_to_subcolumns) - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); if (settings.count_distinct_optimization) - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); if (settings.optimize_rewrite_sum_if_to_count_if) - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); if (settings.optimize_normalize_count_variants) - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); if (settings.optimize_arithmetic_operations_in_aggregate_functions) - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); if (settings.optimize_injective_functions_inside_uniq) - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); if (settings.optimize_multiif_to_if) - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); if (settings.optimize_if_chain_to_multiif) - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); - manager.addPass(std::make_shared()); - manager.addPass(std::make_shared()); + manager.addPass(std::make_unique()); + manager.addPass(std::make_unique()); } }