1#pragma once
2
3#include "DatabaseAndTableWithAlias.h"
4#include <Parsers/ASTSelectQuery.h>
5#include <map>
6
7namespace DB
8{
9
10class ASTIdentifier;
11class ASTSubquery;
12class Context;
13
14/** This class provides functions for Push-Down predicate expressions
15 *
16 * The Example:
17 * - Query before optimization :
18 * SELECT id_1, name_1 FROM (SELECT id_1, name_1 FROM table_a UNION ALL SELECT id_2, name_2 FROM table_b)
19 * WHERE id_1 = 1
20 * - Query after optimization :
21 * SELECT id_1, name_1 FROM (SELECT id_1, name_1 FROM table_a WHERE id_1 = 1 UNION ALL SELECT id_2, name_2 FROM table_b WHERE id_2 = 1)
22 * WHERE id_1 = 1
23 * For more details : https://github.com/ClickHouse/ClickHouse/pull/2015#issuecomment-374283452
24 */
25class PredicateExpressionsOptimizer
26{
27 using ProjectionWithAlias = std::pair<ASTPtr, String>;
28 using SubqueriesProjectionColumns = std::map<ASTSelectQuery *, std::vector<ProjectionWithAlias>>;
29 using IdentifierWithQualifier = std::pair<ASTIdentifier *, String>;
30
31 /// Extracts settings, mostly to show which are used and which are not.
32 struct ExtractedSettings
33 {
34 /// QueryNormalizer settings
35 const UInt64 max_ast_depth;
36 const UInt64 max_expanded_ast_elements;
37 const String count_distinct_implementation;
38
39 /// for PredicateExpressionsOptimizer
40 const bool enable_optimize_predicate_expression;
41 const bool enable_optimize_predicate_expression_to_final_subquery;
42 const bool join_use_nulls;
43
44 template<typename T>
45 ExtractedSettings(const T & settings_)
46 : max_ast_depth(settings_.max_ast_depth),
47 max_expanded_ast_elements(settings_.max_expanded_ast_elements),
48 count_distinct_implementation(settings_.count_distinct_implementation),
49 enable_optimize_predicate_expression(settings_.enable_optimize_predicate_expression),
50 enable_optimize_predicate_expression_to_final_subquery(settings_.enable_optimize_predicate_expression_to_final_subquery),
51 join_use_nulls(settings_.join_use_nulls)
52 {}
53 };
54
55public:
56 PredicateExpressionsOptimizer(ASTSelectQuery * ast_select_, ExtractedSettings && settings_, const Context & context_);
57
58 bool optimize();
59
60private:
61 ASTSelectQuery * ast_select;
62 const ExtractedSettings settings;
63 const Context & context;
64
65 enum OptimizeKind
66 {
67 NONE,
68 PUSH_TO_PREWHERE,
69 PUSH_TO_WHERE,
70 PUSH_TO_HAVING,
71 };
72
73 bool isArrayJoinFunction(const ASTPtr & node);
74
75 std::vector<ASTPtr> splitConjunctionPredicate(const ASTPtr & predicate_expression);
76
77 std::vector<IdentifierWithQualifier> getDependenciesAndQualifiers(ASTPtr & expression,
78 std::vector<TableWithColumnNames> & tables_with_aliases);
79
80 bool optimizeExpression(const ASTPtr & outer_expression, ASTSelectQuery * subquery, ASTSelectQuery::Expression expr);
81
82 bool optimizeImpl(const ASTPtr & outer_expression, const SubqueriesProjectionColumns & subqueries_projection_columns, OptimizeKind optimize_kind);
83
84 bool allowPushDown(
85 const ASTSelectQuery * subquery,
86 const ASTPtr & outer_predicate,
87 const std::vector<ProjectionWithAlias> & subquery_projection_columns,
88 const std::vector<IdentifierWithQualifier> & outer_predicate_dependencies,
89 OptimizeKind & optimize_kind);
90
91 bool checkDependencies(
92 const std::vector<ProjectionWithAlias> & projection_columns,
93 const std::vector<IdentifierWithQualifier> & dependencies,
94 OptimizeKind & optimize_kind);
95
96 void setNewAliasesForInnerPredicate(const std::vector<ProjectionWithAlias> & projection_columns,
97 const std::vector<IdentifierWithQualifier> & inner_predicate_dependencies);
98
99 SubqueriesProjectionColumns getAllSubqueryProjectionColumns();
100
101 void getSubqueryProjectionColumns(const ASTPtr & subquery, SubqueriesProjectionColumns & all_subquery_projection_columns);
102
103 ASTs getSelectQueryProjectionColumns(ASTPtr & ast);
104
105 ASTs evaluateAsterisk(ASTSelectQuery * select_query, const ASTPtr & asterisk);
106
107 void cleanExpressionAlias(ASTPtr & expression);
108};
109
110}
111