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
10namespace DB
11{
12
13class Context;
14class ASTFunction;
15
16 /// The case of an explicit enumeration of values.
17SetPtr 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 */
29struct 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
56class ASTIdentifier;
57class ASTFunction;
58class ASTLiteral;
59
60/// Collect ExpressionAction from AST. Returns PreparedSets and SubqueriesForSets too.
61class ActionsMatcher
62{
63public:
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
122private:
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
131using ActionsVisitor = ActionsMatcher::Visitor;
132
133}
134