1 | #pragma once |
2 | |
3 | #include <Parsers/IAST.h> |
4 | #include <Interpreters/PreparedSets.h> |
5 | #include <Interpreters/ExpressionActions.h> |
6 | #include <Interpreters/SubqueryForSet.h> |
7 | #include <Interpreters/InDepthNodeVisitor.h> |
8 | |
9 | |
10 | namespace DB |
11 | { |
12 | |
13 | class Context; |
14 | class ASTFunction; |
15 | |
16 | /// The case of an explicit enumeration of values. |
17 | SetPtr makeExplicitSet( |
18 | const ASTFunction * node, const Block & sample_block, bool create_ordered_set, |
19 | const Context & context, const SizeLimits & limits, PreparedSets & prepared_sets); |
20 | |
21 | |
22 | /** For ActionsVisitor |
23 | * A stack of ExpressionActions corresponding to nested lambda expressions. |
24 | * The new action should be added to the highest possible level. |
25 | * For example, in the expression "select arrayMap(x -> x + column1 * column2, array1)" |
26 | * calculation of the product must be done outside the lambda expression (it does not depend on x), |
27 | * and the calculation of the sum is inside (depends on x). |
28 | */ |
29 | struct ScopeStack |
30 | { |
31 | struct Level |
32 | { |
33 | ExpressionActionsPtr actions; |
34 | NameSet new_columns; |
35 | }; |
36 | |
37 | using Levels = std::vector<Level>; |
38 | |
39 | Levels stack; |
40 | |
41 | const Context & context; |
42 | |
43 | ScopeStack(const ExpressionActionsPtr & actions, const Context & context_); |
44 | |
45 | void pushLevel(const NamesAndTypesList & input_columns); |
46 | |
47 | size_t getColumnLevel(const std::string & name); |
48 | |
49 | void addAction(const ExpressionAction & action); |
50 | |
51 | ExpressionActionsPtr popLevel(); |
52 | |
53 | const Block & getSampleBlock() const; |
54 | }; |
55 | |
56 | class ASTIdentifier; |
57 | class ASTFunction; |
58 | class ASTLiteral; |
59 | |
60 | /// Collect ExpressionAction from AST. Returns PreparedSets and SubqueriesForSets too. |
61 | class ActionsMatcher |
62 | { |
63 | public: |
64 | using Visitor = ConstInDepthNodeVisitor<ActionsMatcher, true>; |
65 | |
66 | struct Data |
67 | { |
68 | const Context & context; |
69 | SizeLimits set_size_limit; |
70 | size_t subquery_depth; |
71 | const NamesAndTypesList & source_columns; |
72 | PreparedSets & prepared_sets; |
73 | SubqueriesForSets & subqueries_for_sets; |
74 | bool no_subqueries; |
75 | bool only_consts; |
76 | bool no_storage_or_local; |
77 | size_t visit_depth; |
78 | ScopeStack actions_stack; |
79 | |
80 | Data(const Context & context_, SizeLimits set_size_limit_, size_t subquery_depth_, |
81 | const NamesAndTypesList & source_columns_, const ExpressionActionsPtr & actions, |
82 | PreparedSets & prepared_sets_, SubqueriesForSets & subqueries_for_sets_, |
83 | bool no_subqueries_, bool only_consts_, bool no_storage_or_local_) |
84 | : context(context_), |
85 | set_size_limit(set_size_limit_), |
86 | subquery_depth(subquery_depth_), |
87 | source_columns(source_columns_), |
88 | prepared_sets(prepared_sets_), |
89 | subqueries_for_sets(subqueries_for_sets_), |
90 | no_subqueries(no_subqueries_), |
91 | only_consts(only_consts_), |
92 | no_storage_or_local(no_storage_or_local_), |
93 | visit_depth(0), |
94 | actions_stack(actions, context) |
95 | {} |
96 | |
97 | void updateActions(ExpressionActionsPtr & actions) |
98 | { |
99 | actions = actions_stack.popLevel(); |
100 | } |
101 | |
102 | void addAction(const ExpressionAction & action) |
103 | { |
104 | actions_stack.addAction(action); |
105 | } |
106 | |
107 | const Block & getSampleBlock() const |
108 | { |
109 | return actions_stack.getSampleBlock(); |
110 | } |
111 | |
112 | /// Does result of the calculation already exists in the block. |
113 | bool hasColumn(const String & columnName) const |
114 | { |
115 | return actions_stack.getSampleBlock().has(columnName); |
116 | } |
117 | }; |
118 | |
119 | static void visit(const ASTPtr & ast, Data & data); |
120 | static bool needChildVisit(const ASTPtr & node, const ASTPtr & child); |
121 | |
122 | private: |
123 | |
124 | static void visit(const ASTIdentifier & identifier, const ASTPtr & ast, Data & data); |
125 | static void visit(const ASTFunction & node, const ASTPtr & ast, Data & data); |
126 | static void visit(const ASTLiteral & literal, const ASTPtr & ast, Data & data); |
127 | |
128 | static SetPtr makeSet(const ASTFunction & node, Data & data, bool no_subqueries); |
129 | }; |
130 | |
131 | using ActionsVisitor = ActionsMatcher::Visitor; |
132 | |
133 | } |
134 | |