2015-08-05 21:39:42 +00:00
|
|
|
|
#include <DB/Parsers/ASTLiteral.h>
|
|
|
|
|
#include <DB/Parsers/ASTFunction.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
|
2016-05-03 23:19:14 +00:00
|
|
|
|
namespace ErrorCodes
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
extern const int INVALID_FUNCTION_GENUS;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String ASTFunction::getColumnName() const
|
|
|
|
|
{
|
|
|
|
|
String res;
|
|
|
|
|
WriteBufferFromString wb(res);
|
|
|
|
|
writeString(name, wb);
|
|
|
|
|
|
|
|
|
|
if (parameters)
|
|
|
|
|
{
|
|
|
|
|
writeChar('(', wb);
|
|
|
|
|
for (ASTs::const_iterator it = parameters->children.begin(); it != parameters->children.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (it != parameters->children.begin())
|
|
|
|
|
writeCString(", ", wb);
|
|
|
|
|
writeString((*it)->getColumnName(), wb);
|
|
|
|
|
}
|
|
|
|
|
writeChar(')', wb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
writeChar('(', wb);
|
|
|
|
|
for (ASTs::const_iterator it = arguments->children.begin(); it != arguments->children.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (it != arguments->children.begin())
|
|
|
|
|
writeCString(", ", wb);
|
|
|
|
|
writeString((*it)->getColumnName(), wb);
|
|
|
|
|
}
|
|
|
|
|
writeChar(')', wb);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Получить текст, который идентифицирует этот элемент. */
|
|
|
|
|
String ASTFunction::getID() const
|
|
|
|
|
{
|
|
|
|
|
return "Function_" + name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASTPtr ASTFunction::clone() const
|
|
|
|
|
{
|
|
|
|
|
ASTFunction * res = new ASTFunction(*this);
|
|
|
|
|
ASTPtr ptr{res};
|
|
|
|
|
|
|
|
|
|
res->children.clear();
|
|
|
|
|
|
|
|
|
|
if (arguments) { res->arguments = arguments->clone(); res->children.push_back(res->arguments); }
|
|
|
|
|
if (parameters) { res->parameters = parameters->clone(); res->children.push_back(res->parameters); }
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-06 23:46:15 +00:00
|
|
|
|
void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
|
2015-08-06 03:26:27 +00:00
|
|
|
|
{
|
|
|
|
|
FormatStateStacked nested_need_parens = frame;
|
|
|
|
|
FormatStateStacked nested_dont_need_parens = frame;
|
|
|
|
|
nested_need_parens.need_parens = true;
|
|
|
|
|
nested_dont_need_parens.need_parens = false;
|
|
|
|
|
|
2016-05-03 23:19:14 +00:00
|
|
|
|
if ((genus == Genus::CASE_WITH_EXPR) || (genus == Genus::CASE_WITHOUT_EXPR))
|
|
|
|
|
{
|
|
|
|
|
formatCase(settings, state, frame);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
/// Стоит ли записать эту функцию в виде оператора?
|
|
|
|
|
bool written = false;
|
|
|
|
|
if (arguments && !parameters)
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-12-24 17:14:10 +00:00
|
|
|
|
if (0 == strcmp(name.data(), "CAST"))
|
|
|
|
|
{
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << name;
|
|
|
|
|
|
|
|
|
|
settings.ostr << '(' << (settings.hilite ? hilite_none : "");
|
|
|
|
|
|
|
|
|
|
arguments->children.front()->formatImpl(settings, state, nested_need_parens);
|
|
|
|
|
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << " AS "
|
|
|
|
|
<< (settings.hilite ? hilite_none : "");
|
|
|
|
|
|
2015-12-25 14:45:58 +00:00
|
|
|
|
settings.ostr << (settings.hilite ? hilite_function : "")
|
2015-12-24 17:14:10 +00:00
|
|
|
|
<< typeid_cast<const ASTLiteral &>(*arguments->children.back()).value.safeGet<String>()
|
|
|
|
|
<< (settings.hilite ? hilite_none : "");
|
|
|
|
|
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << ')'
|
|
|
|
|
<< (settings.hilite ? hilite_none : "");
|
|
|
|
|
|
|
|
|
|
written = true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (arguments->children.size() == 1)
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
const char * operators[] =
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
"negate", "-",
|
|
|
|
|
"not", "NOT ",
|
|
|
|
|
nullptr
|
|
|
|
|
};
|
2015-08-05 21:39:42 +00:00
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
for (const char ** func = operators; *func; func += 2)
|
|
|
|
|
{
|
|
|
|
|
if (0 == strcmp(name.c_str(), func[0]))
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
settings.ostr << (settings.hilite ? hilite_operator : "") << func[1] << (settings.hilite ? hilite_none : "");
|
|
|
|
|
|
|
|
|
|
/** Особо дурацкий случай. Если у нас унарный минус перед литералом, являющимся отрицательным числом:
|
|
|
|
|
* "-(-1)" или "- -1", то это нельзя форматировать как --1, так как это будет воспринято как комментарий.
|
|
|
|
|
* Вместо этого, добавим пробел.
|
|
|
|
|
* PS. Нельзя просто попросить добавить скобки - см. formatImpl для ASTLiteral.
|
|
|
|
|
*/
|
|
|
|
|
if (name == "negate" && typeid_cast<const ASTLiteral *>(&*arguments->children[0]))
|
|
|
|
|
settings.ostr << ' ';
|
|
|
|
|
|
|
|
|
|
arguments->formatImpl(settings, state, nested_need_parens);
|
|
|
|
|
written = true;
|
2015-08-05 21:39:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-08-06 03:26:27 +00:00
|
|
|
|
}
|
2015-08-05 21:39:42 +00:00
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
/** need_parens - нужны ли скобки вокруг выражения с оператором.
|
|
|
|
|
* Они нужны, только если это выражение входит в другое выражение с оператором.
|
|
|
|
|
*/
|
2015-08-05 21:39:42 +00:00
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (!written && arguments->children.size() == 2)
|
|
|
|
|
{
|
|
|
|
|
const char * operators[] =
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
"multiply", " * ",
|
|
|
|
|
"divide", " / ",
|
|
|
|
|
"modulo", " % ",
|
|
|
|
|
"plus", " + ",
|
|
|
|
|
"minus", " - ",
|
|
|
|
|
"notEquals", " != ",
|
|
|
|
|
"lessOrEquals", " <= ",
|
|
|
|
|
"greaterOrEquals", " >= ",
|
|
|
|
|
"less", " < ",
|
|
|
|
|
"greater", " > ",
|
|
|
|
|
"equals", " = ",
|
|
|
|
|
"like", " LIKE ",
|
|
|
|
|
"notLike", " NOT LIKE ",
|
|
|
|
|
"in", " IN ",
|
|
|
|
|
"notIn", " NOT IN ",
|
|
|
|
|
"globalIn", " GLOBAL IN ",
|
|
|
|
|
"globalNotIn", " GLOBAL NOT IN ",
|
|
|
|
|
nullptr
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (const char ** func = operators; *func; func += 2)
|
|
|
|
|
{
|
|
|
|
|
if (0 == strcmp(name.c_str(), func[0]))
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (frame.need_parens)
|
|
|
|
|
settings.ostr << '(';
|
2015-08-05 21:39:42 +00:00
|
|
|
|
arguments->children[0]->formatImpl(settings, state, nested_need_parens);
|
2015-08-06 03:26:27 +00:00
|
|
|
|
settings.ostr << (settings.hilite ? hilite_operator : "") << func[1] << (settings.hilite ? hilite_none : "");
|
2015-08-05 21:39:42 +00:00
|
|
|
|
arguments->children[1]->formatImpl(settings, state, nested_need_parens);
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (frame.need_parens)
|
|
|
|
|
settings.ostr << ')';
|
2015-08-05 21:39:42 +00:00
|
|
|
|
written = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (!written && 0 == strcmp(name.c_str(), "arrayElement"))
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
arguments->children[0]->formatImpl(settings, state, nested_need_parens);
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_operator : "") << '[' << (settings.hilite ? hilite_none : "");
|
|
|
|
|
arguments->children[1]->formatImpl(settings, state, nested_need_parens);
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_operator : "") << ']' << (settings.hilite ? hilite_none : "");
|
|
|
|
|
written = true;
|
2015-08-05 21:39:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (!written && 0 == strcmp(name.c_str(), "tupleElement"))
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
arguments->children[0]->formatImpl(settings, state, nested_need_parens);
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_operator : "") << "." << (settings.hilite ? hilite_none : "");
|
|
|
|
|
arguments->children[1]->formatImpl(settings, state, nested_need_parens);
|
2015-08-05 21:39:42 +00:00
|
|
|
|
written = true;
|
|
|
|
|
}
|
2015-08-06 03:26:27 +00:00
|
|
|
|
}
|
2015-08-05 21:39:42 +00:00
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (!written && arguments->children.size() >= 2)
|
|
|
|
|
{
|
|
|
|
|
const char * operators[] =
|
|
|
|
|
{
|
|
|
|
|
"and", " AND ",
|
|
|
|
|
"or", " OR ",
|
|
|
|
|
nullptr
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (const char ** func = operators; *func; func += 2)
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (0 == strcmp(name.c_str(), func[0]))
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (frame.need_parens)
|
|
|
|
|
settings.ostr << '(';
|
|
|
|
|
for (size_t i = 0; i < arguments->children.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
if (i != 0)
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_operator : "") << func[1] << (settings.hilite ? hilite_none : "");
|
|
|
|
|
arguments->children[i]->formatImpl(settings, state, nested_need_parens);
|
|
|
|
|
}
|
|
|
|
|
if (frame.need_parens)
|
|
|
|
|
settings.ostr << ')';
|
|
|
|
|
written = true;
|
2015-08-05 21:39:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (!written && arguments->children.size() >= 1 && 0 == strcmp(name.c_str(), "array"))
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
settings.ostr << (settings.hilite ? hilite_operator : "") << '[' << (settings.hilite ? hilite_none : "");
|
|
|
|
|
for (size_t i = 0; i < arguments->children.size(); ++i)
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (i != 0)
|
|
|
|
|
settings.ostr << ", ";
|
|
|
|
|
arguments->children[i]->formatImpl(settings, state, nested_dont_need_parens);
|
2015-08-05 21:39:42 +00:00
|
|
|
|
}
|
2015-08-06 03:26:27 +00:00
|
|
|
|
settings.ostr << (settings.hilite ? hilite_operator : "") << ']' << (settings.hilite ? hilite_none : "");
|
|
|
|
|
written = true;
|
|
|
|
|
}
|
2015-08-05 21:39:42 +00:00
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (!written && arguments->children.size() >= 2 && 0 == strcmp(name.c_str(), "tuple"))
|
|
|
|
|
{
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_operator : "") << '(' << (settings.hilite ? hilite_none : "");
|
|
|
|
|
for (size_t i = 0; i < arguments->children.size(); ++i)
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (i != 0)
|
|
|
|
|
settings.ostr << ", ";
|
|
|
|
|
arguments->children[i]->formatImpl(settings, state, nested_dont_need_parens);
|
2015-08-05 21:39:42 +00:00
|
|
|
|
}
|
2015-08-06 03:26:27 +00:00
|
|
|
|
settings.ostr << (settings.hilite ? hilite_operator : "") << ')' << (settings.hilite ? hilite_none : "");
|
|
|
|
|
written = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!written)
|
|
|
|
|
{
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_function : "") << name;
|
2015-08-05 21:39:42 +00:00
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (parameters)
|
|
|
|
|
{
|
|
|
|
|
settings.ostr << '(' << (settings.hilite ? hilite_none : "");
|
|
|
|
|
parameters->formatImpl(settings, state, nested_dont_need_parens);
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
|
2015-08-05 21:39:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-06 03:26:27 +00:00
|
|
|
|
if (arguments)
|
2015-08-05 21:39:42 +00:00
|
|
|
|
{
|
2015-08-06 03:26:27 +00:00
|
|
|
|
settings.ostr << '(' << (settings.hilite ? hilite_none : "");
|
|
|
|
|
arguments->formatImpl(settings, state, nested_dont_need_parens);
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
|
2015-08-05 21:39:42 +00:00
|
|
|
|
}
|
2015-08-06 03:26:27 +00:00
|
|
|
|
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_none : "");
|
2015-08-05 21:39:42 +00:00
|
|
|
|
}
|
2015-08-06 03:26:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-05-03 23:19:14 +00:00
|
|
|
|
void ASTFunction::formatCase(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
|
|
|
|
|
{
|
|
|
|
|
static constexpr auto s_case = "CASE";
|
|
|
|
|
static constexpr auto s_when = "WHEN";
|
|
|
|
|
static constexpr auto s_then = "THEN";
|
|
|
|
|
static constexpr auto s_else = "ELSE";
|
|
|
|
|
static constexpr auto s_end = "END";
|
|
|
|
|
static constexpr auto s_ws = " ";
|
|
|
|
|
|
|
|
|
|
const ASTExpressionList * expr_list = static_cast<const ASTExpressionList *>(&*arguments);
|
|
|
|
|
const ASTs & args = expr_list->children;
|
|
|
|
|
|
|
|
|
|
frame.need_parens = false;
|
|
|
|
|
|
|
|
|
|
std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
|
|
|
|
|
std::string indent_str2 = settings.one_line ? "" : std::string(4 * (frame.indent + 1), ' ');
|
|
|
|
|
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << s_case << s_ws
|
|
|
|
|
<< (settings.hilite ? hilite_none : "");
|
|
|
|
|
|
|
|
|
|
if (genus == Genus::CASE_WITH_EXPR)
|
|
|
|
|
{
|
|
|
|
|
args[0]->formatImpl(settings, state, frame);
|
|
|
|
|
settings.ostr << settings.nl_or_ws;
|
|
|
|
|
|
|
|
|
|
const ASTFunction * src_array_function = static_cast<const ASTFunction *>(&*args[1]);
|
|
|
|
|
const ASTExpressionList * src_expr_list = static_cast<const ASTExpressionList *>(&*src_array_function->arguments);
|
|
|
|
|
|
|
|
|
|
const ASTFunction * dst_array_function = static_cast<const ASTFunction *>(&*args[2]);
|
|
|
|
|
const ASTExpressionList * dst_expr_list = static_cast<const ASTExpressionList *>(&*dst_array_function->arguments);
|
|
|
|
|
|
|
|
|
|
size_t size = src_expr_list->children.size();
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
|
{
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "")
|
|
|
|
|
<< indent_str2 << s_when << s_ws;
|
|
|
|
|
src_expr_list->children[i]->formatImpl(settings, state, frame);
|
|
|
|
|
settings.ostr << s_ws;
|
|
|
|
|
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << s_then << s_ws;
|
|
|
|
|
dst_expr_list->children[i]->formatImpl(settings, state, frame);
|
|
|
|
|
settings.ostr << settings.nl_or_ws;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (genus == Genus::CASE_WITHOUT_EXPR)
|
|
|
|
|
{
|
|
|
|
|
settings.ostr << settings.nl_or_ws;
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < (args.size() - 1); ++i)
|
|
|
|
|
{
|
|
|
|
|
if ((i % 2) == 0)
|
|
|
|
|
{
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "")
|
|
|
|
|
<< indent_str2 << s_when << s_ws;
|
|
|
|
|
args[i]->formatImpl(settings, state, frame);
|
|
|
|
|
settings.ostr << " ";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << s_then << s_ws;
|
|
|
|
|
args[i]->formatImpl(settings, state, frame);
|
|
|
|
|
settings.ostr << settings.nl_or_ws;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw Exception{"Invalid function genus", ErrorCodes::INVALID_FUNCTION_GENUS};
|
|
|
|
|
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str2
|
|
|
|
|
<< s_else << s_ws;
|
|
|
|
|
args.back()->formatImpl(settings, state, frame);
|
|
|
|
|
settings.ostr << settings.nl_or_ws;
|
|
|
|
|
|
|
|
|
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << s_end;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-05 21:39:42 +00:00
|
|
|
|
}
|