#pragma once #include #include #include #include #include #include #include #include #include #include namespace DB { /// Checks if SELECT has stateful functions class ASTFunctionStatefulData { public: using TypeToVisit = ASTFunction; const Context & context; bool & is_stateful; void visit(ASTFunction & ast_function, ASTPtr &) { if (ast_function.name == "any" || ast_function.name == "groupArray") { is_stateful = true; return; } const auto & function = FunctionFactory::instance().tryGet(ast_function.name, context); if (function && function->isStateful()) { is_stateful = true; return; } } }; using ASTFunctionStatefulMatcher = OneTypeMatcher; using ASTFunctionStatefulVisitor = InDepthNodeVisitor; /// Erases unnecessary ORDER BY from subquery class DuplicateOrderByFromSubqueriesData { public: using TypeToVisit = ASTSelectQuery; bool done = false; void visit(ASTSelectQuery & select_query, ASTPtr &) { if (done) return; if (select_query.orderBy() && !select_query.limitBy() && !select_query.limitByOffset() && !select_query.limitByLength() && !select_query.limitLength() && !select_query.limitOffset()) { select_query.setExpression(ASTSelectQuery::Expression::ORDER_BY, nullptr); } done = true; } }; using DuplicateOrderByFromSubqueriesMatcher = OneTypeMatcher; using DuplicateOrderByFromSubqueriesVisitor = InDepthNodeVisitor; /// Finds SELECT that can be optimized class DuplicateOrderByData { public: using TypeToVisit = ASTSelectQuery; const Context & context; bool done = false; void visit(ASTSelectQuery & select_query, ASTPtr &) { if (done) return; /// Disable optimization for distributed tables for (const auto & elem : select_query.children) { if (elem->as() && !elem->as()->is_standalone) return; } if (select_query.orderBy() || select_query.groupBy()) { for (auto & elem : select_query.children) { if (elem->as()) { bool is_stateful = false; ASTFunctionStatefulVisitor::Data data{context, is_stateful}; ASTFunctionStatefulVisitor(data).visit(elem); if (is_stateful) return; } } if (auto select_table_ptr = select_query.tables()) { if (auto * select_table = select_table_ptr->as()) { if (!select_table->children.empty()) { DuplicateOrderByFromSubqueriesVisitor::Data data{false}; DuplicateOrderByFromSubqueriesVisitor(data).visit(select_table->children[0]); } } } } } }; using DuplicateOrderByMatcher = OneTypeMatcher; using DuplicateOrderByVisitor = InDepthNodeVisitor; }