1#include <Common/typeid_cast.h>
2#include <Parsers/ASTLiteral.h>
3#include <Parsers/ASTFunction.h>
4#include <Parsers/ASTWithAlias.h>
5#include <Parsers/ASTSubquery.h>
6#include <IO/WriteHelpers.h>
7#include <IO/WriteBufferFromString.h>
8
9
10namespace DB
11{
12
13void ASTFunction::appendColumnNameImpl(WriteBuffer & ostr) const
14{
15 writeString(name, ostr);
16
17 if (parameters)
18 {
19 writeChar('(', ostr);
20 for (auto it = parameters->children.begin(); it != parameters->children.end(); ++it)
21 {
22 if (it != parameters->children.begin())
23 writeCString(", ", ostr);
24 (*it)->appendColumnName(ostr);
25 }
26 writeChar(')', ostr);
27 }
28
29 writeChar('(', ostr);
30 for (auto it = arguments->children.begin(); it != arguments->children.end(); ++it)
31 {
32 if (it != arguments->children.begin())
33 writeCString(", ", ostr);
34 (*it)->appendColumnName(ostr);
35 }
36 writeChar(')', ostr);
37}
38
39/** Get the text that identifies this element. */
40String ASTFunction::getID(char delim) const
41{
42 return "Function" + (delim + name);
43}
44
45ASTPtr ASTFunction::clone() const
46{
47 auto res = std::make_shared<ASTFunction>(*this);
48 res->children.clear();
49
50 if (arguments) { res->arguments = arguments->clone(); res->children.push_back(res->arguments); }
51 if (parameters) { res->parameters = parameters->clone(); res->children.push_back(res->parameters); }
52
53 return res;
54}
55
56
57/** A special hack. If it's LIKE or NOT LIKE expression and the right hand side is a string literal,
58 * we will highlight unescaped metacharacters % and _ in string literal for convenience.
59 * Motivation: most people are unaware that _ is a metacharacter and forgot to properly escape it with two backslashes.
60 * With highlighting we make it clearly obvious.
61 *
62 * Another case is regexp match. Suppose the user types match(URL, 'www.yandex.ru'). It often means that the user is unaware that . is a metacharacter.
63 */
64static bool highlightStringLiteralWithMetacharacters(const ASTPtr & node, const IAST::FormatSettings & settings, const char * metacharacters)
65{
66 if (const auto * literal = node->as<ASTLiteral>())
67 {
68 if (literal->value.getType() == Field::Types::String)
69 {
70 auto string = applyVisitor(FieldVisitorToString(), literal->value);
71
72 unsigned escaping = 0;
73 for (auto c : string)
74 {
75 if (c == '\\')
76 {
77 settings.ostr << c;
78 if (escaping == 2)
79 escaping = 0;
80 ++escaping;
81 }
82 else if (nullptr != strchr(metacharacters, c))
83 {
84 if (escaping == 2) /// Properly escaped metacharacter
85 settings.ostr << c;
86 else /// Unescaped metacharacter
87 settings.ostr << "\033[1;35m" << c << "\033[0m";
88 escaping = 0;
89 }
90 else
91 {
92 settings.ostr << c;
93 escaping = 0;
94 }
95 }
96
97 return true;
98 }
99 }
100
101 return false;
102}
103
104
105void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
106{
107 FormatStateStacked nested_need_parens = frame;
108 FormatStateStacked nested_dont_need_parens = frame;
109 nested_need_parens.need_parens = true;
110 nested_dont_need_parens.need_parens = false;
111
112 /// Should this function to be written as operator?
113 bool written = false;
114 if (arguments && !parameters)
115 {
116 if (arguments->children.size() == 1)
117 {
118 const char * operators[] =
119 {
120 "negate", "-",
121 "not", "NOT ",
122 nullptr
123 };
124
125 for (const char ** func = operators; *func; func += 2)
126 {
127 if (0 == strcmp(name.c_str(), func[0]))
128 {
129 if (frame.need_parens)
130 settings.ostr << '(';
131
132 settings.ostr << (settings.hilite ? hilite_operator : "") << func[1] << (settings.hilite ? hilite_none : "");
133
134 /** A particularly stupid case. If we have a unary minus before a literal that is a negative number
135 * "-(-1)" or "- -1", this can not be formatted as `--1`, since this will be interpreted as a comment.
136 * Instead, add a space.
137 * PS. You can not just ask to add parentheses - see formatImpl for ASTLiteral.
138 */
139 if (name == "negate" && arguments->children[0]->as<ASTLiteral>())
140 settings.ostr << ' ';
141
142 arguments->formatImpl(settings, state, nested_need_parens);
143 written = true;
144
145 if (frame.need_parens)
146 settings.ostr << ')';
147 }
148 }
149 }
150
151 /** need_parens - do we need parentheses around the expression with the operator.
152 * They are needed only if this expression is included in another expression with the operator.
153 */
154
155 if (!written && arguments->children.size() == 2)
156 {
157 const char * operators[] =
158 {
159 "multiply", " * ",
160 "divide", " / ",
161 "modulo", " % ",
162 "plus", " + ",
163 "minus", " - ",
164 "notEquals", " != ",
165 "lessOrEquals", " <= ",
166 "greaterOrEquals", " >= ",
167 "less", " < ",
168 "greater", " > ",
169 "equals", " = ",
170 "like", " LIKE ",
171 "notLike", " NOT LIKE ",
172 "in", " IN ",
173 "notIn", " NOT IN ",
174 "globalIn", " GLOBAL IN ",
175 "globalNotIn", " GLOBAL NOT IN ",
176 nullptr
177 };
178
179 for (const char ** func = operators; *func; func += 2)
180 {
181 if (0 == strcmp(name.c_str(), func[0]))
182 {
183 if (frame.need_parens)
184 settings.ostr << '(';
185 arguments->children[0]->formatImpl(settings, state, nested_need_parens);
186 settings.ostr << (settings.hilite ? hilite_operator : "") << func[1] << (settings.hilite ? hilite_none : "");
187
188 bool special_hilite = settings.hilite
189 && (name == "like" || name == "notLike")
190 && highlightStringLiteralWithMetacharacters(arguments->children[1], settings, "%_");
191
192 /// Format x IN 1 as x IN (1): put parens around rhs even if there is a single element in set.
193 const auto * second_arg_func = arguments->children[1]->as<ASTFunction>();
194 const auto * second_arg_literal = arguments->children[1]->as<ASTLiteral>();
195 bool extra_parents_around_in_rhs = (name == "in" || name == "notIn" || name == "globalIn" || name == "globalNotIn")
196 && !(second_arg_func && second_arg_func->name == "tuple")
197 && !(second_arg_literal && second_arg_literal->value.getType() == Field::Types::Tuple)
198 && !arguments->children[1]->as<ASTSubquery>();
199
200 if (extra_parents_around_in_rhs)
201 {
202 settings.ostr << '(';
203 arguments->children[1]->formatImpl(settings, state, nested_dont_need_parens);
204 settings.ostr << ')';
205 }
206
207 if (!special_hilite && !extra_parents_around_in_rhs)
208 arguments->children[1]->formatImpl(settings, state, nested_need_parens);
209
210 if (frame.need_parens)
211 settings.ostr << ')';
212 written = true;
213 }
214 }
215
216 if (!written && 0 == strcmp(name.c_str(), "arrayElement"))
217 {
218 if (frame.need_parens)
219 settings.ostr << '(';
220
221 arguments->children[0]->formatImpl(settings, state, nested_need_parens);
222 settings.ostr << (settings.hilite ? hilite_operator : "") << '[' << (settings.hilite ? hilite_none : "");
223 arguments->children[1]->formatImpl(settings, state, nested_dont_need_parens);
224 settings.ostr << (settings.hilite ? hilite_operator : "") << ']' << (settings.hilite ? hilite_none : "");
225 written = true;
226
227 if (frame.need_parens)
228 settings.ostr << ')';
229 }
230
231 if (!written && 0 == strcmp(name.c_str(), "tupleElement"))
232 {
233 /// It can be printed in a form of 'x.1' only if right hand side is unsigned integer literal.
234 if (const auto * lit = arguments->children[1]->as<ASTLiteral>())
235 {
236 if (lit->value.getType() == Field::Types::UInt64)
237 {
238 if (frame.need_parens)
239 settings.ostr << '(';
240
241 arguments->children[0]->formatImpl(settings, state, nested_need_parens);
242 settings.ostr << (settings.hilite ? hilite_operator : "") << "." << (settings.hilite ? hilite_none : "");
243 arguments->children[1]->formatImpl(settings, state, nested_dont_need_parens);
244 written = true;
245
246 if (frame.need_parens)
247 settings.ostr << ')';
248 }
249 }
250 }
251
252 if (!written && 0 == strcmp(name.c_str(), "lambda"))
253 {
254 /// Special case: one-element tuple in lhs of lambda is printed as its element.
255
256 if (frame.need_parens)
257 settings.ostr << '(';
258
259 const auto * first_arg_func = arguments->children[0]->as<ASTFunction>();
260 if (first_arg_func
261 && first_arg_func->name == "tuple"
262 && first_arg_func->arguments
263 && first_arg_func->arguments->children.size() == 1)
264 {
265 first_arg_func->arguments->children[0]->formatImpl(settings, state, nested_need_parens);
266 }
267 else
268 arguments->children[0]->formatImpl(settings, state, nested_need_parens);
269
270 settings.ostr << (settings.hilite ? hilite_operator : "") << " -> " << (settings.hilite ? hilite_none : "");
271 arguments->children[1]->formatImpl(settings, state, nested_need_parens);
272 if (frame.need_parens)
273 settings.ostr << ')';
274 written = true;
275 }
276 }
277
278 if (!written && arguments->children.size() >= 2)
279 {
280 const char * operators[] =
281 {
282 "and", " AND ",
283 "or", " OR ",
284 nullptr
285 };
286
287 for (const char ** func = operators; *func; func += 2)
288 {
289 if (0 == strcmp(name.c_str(), func[0]))
290 {
291 if (frame.need_parens)
292 settings.ostr << '(';
293 for (size_t i = 0; i < arguments->children.size(); ++i)
294 {
295 if (i != 0)
296 settings.ostr << (settings.hilite ? hilite_operator : "") << func[1] << (settings.hilite ? hilite_none : "");
297 arguments->children[i]->formatImpl(settings, state, nested_need_parens);
298 }
299 if (frame.need_parens)
300 settings.ostr << ')';
301 written = true;
302 }
303 }
304 }
305
306 if (!written && 0 == strcmp(name.c_str(), "array"))
307 {
308 settings.ostr << (settings.hilite ? hilite_operator : "") << '[' << (settings.hilite ? hilite_none : "");
309 for (size_t i = 0; i < arguments->children.size(); ++i)
310 {
311 if (i != 0)
312 settings.ostr << ", ";
313 arguments->children[i]->formatImpl(settings, state, nested_dont_need_parens);
314 }
315 settings.ostr << (settings.hilite ? hilite_operator : "") << ']' << (settings.hilite ? hilite_none : "");
316 written = true;
317 }
318
319 if (!written && arguments->children.size() >= 2 && 0 == strcmp(name.c_str(), "tuple"))
320 {
321 settings.ostr << (settings.hilite ? hilite_operator : "") << '(' << (settings.hilite ? hilite_none : "");
322 for (size_t i = 0; i < arguments->children.size(); ++i)
323 {
324 if (i != 0)
325 settings.ostr << ", ";
326 arguments->children[i]->formatImpl(settings, state, nested_dont_need_parens);
327 }
328 settings.ostr << (settings.hilite ? hilite_operator : "") << ')' << (settings.hilite ? hilite_none : "");
329 written = true;
330 }
331 }
332
333 if (!written)
334 {
335 settings.ostr << (settings.hilite ? hilite_function : "") << name;
336
337 if (parameters)
338 {
339 settings.ostr << '(' << (settings.hilite ? hilite_none : "");
340 parameters->formatImpl(settings, state, nested_dont_need_parens);
341 settings.ostr << (settings.hilite ? hilite_function : "") << ')';
342 }
343
344 if (arguments)
345 {
346 settings.ostr << '(' << (settings.hilite ? hilite_none : "");
347
348 bool special_hilite_regexp = settings.hilite
349 && (name == "match" || name == "extract" || name == "extractAll" || name == "replaceRegexpOne" || name == "replaceRegexpAll");
350
351 for (size_t i = 0, size = arguments->children.size(); i < size; ++i)
352 {
353 if (i != 0)
354 settings.ostr << ", ";
355
356 bool special_hilite = false;
357 if (i == 1 && special_hilite_regexp)
358 special_hilite = highlightStringLiteralWithMetacharacters(arguments->children[i], settings, "|()^$.[]?*+{:-");
359
360 if (!special_hilite)
361 arguments->children[i]->formatImpl(settings, state, nested_dont_need_parens);
362 }
363
364 settings.ostr << (settings.hilite ? hilite_function : "") << ')';
365 }
366
367 settings.ostr << (settings.hilite ? hilite_none : "");
368 }
369}
370
371}
372