提交 e072db7d 编写于 作者: A Alexey Milovidov

dbms: preparation to more compact query formatting [#METR-17606].

上级 4eac0230
......@@ -119,7 +119,7 @@ protected:
}
settings.ostr << indent_str << table;
}
settings.ostr << nl_or_ws;
settings.ostr << settings.nl_or_ws;
for (size_t i = 0; i < parameters.size(); ++i)
{
......
......@@ -40,7 +40,7 @@ protected:
{
std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
s << settings.nl_or_ws << indent_str << backQuoteIfNeed(name) << " ";
settings.ostr << settings.nl_or_ws << indent_str << backQuoteIfNeed(name) << " ";
type->formatImpl(settings, state, frame);
}
};
......
......@@ -24,7 +24,7 @@ public:
/// Объявляет класс-наследник ASTQueryWithOutput с реализованными методами getID и clone.
#define DEFINE_AST_QUERY_WITH_OUTPUT(Name, ID) \
#define DEFINE_AST_QUERY_WITH_OUTPUT(Name, ID, Query) \
class Name : public ASTQueryWithOutput \
{ \
public: \
......@@ -44,6 +44,12 @@ public: \
} \
return ptr; \
} \
\
protected: \
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override \
{ \
settings.ostr << (settings.hilite ? hilite_keyword : "") << Query << (settings.hilite ? hilite_none : ""); \
} \
};
}
......@@ -6,8 +6,8 @@
namespace DB
{
/** Запрос с указанием названия таблицы и, возможно, БД и секцией FORMAT.
*/
class ASTQueryWithTableAndOutput : public ASTQueryWithOutput
......@@ -18,14 +18,28 @@ public:
ASTQueryWithTableAndOutput() = default;
ASTQueryWithTableAndOutput(const StringRange range_) : ASTQueryWithOutput(range_) {}
protected:
void formatHelper(const FormatSettings & settings, FormatState & state, FormatStateStacked frame, const char * name) const
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << name << " " << (settings.hilite ? hilite_none : "")
<< (!database.empty() ? backQuoteIfNeed(database) + "." : "") << backQuoteIfNeed(table);
if (format)
{
std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << indent_str << "FORMAT " << (settings.hilite ? hilite_none : "");
format->formatImpl(settings, state, frame);
}
}
};
/// Объявляет класс-наследник ASTQueryWithTableAndOutput с реализованными методами getID и clone.
#define DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(Name, ID) \
#define DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(Name, ID, Query) \
class Name : public ASTQueryWithTableAndOutput \
{ \
public: \
public: \
Name() = default; \
Name(const StringRange range_) : ASTQueryWithTableAndOutput(range_) {} \
String getID() const override { return ID"_" + database + "_" + table; }; \
......@@ -42,5 +56,11 @@ public: \
} \
return ptr; \
} \
\
protected: \
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override \
{ \
formatHelper(settings, state, frame, Query); \
} \
};
}
......@@ -22,6 +22,17 @@ public:
String getID() const override { return "Set_" + getColumnName(); }
ASTPtr clone() const override { return new ASTSet(*this); }
String getColumnName() const override { return column_name; }
protected:
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
{
/** Подготовленное множество. В пользовательских запросах такого не бывает, но такое бывает после промежуточных преобразований запроса.
* Выведем его не по-настоящему (это не будет корректным запросом, но покажет, что здесь было множество).
*/
settings.ostr << (settings.hilite ? hilite_keyword : "")
<< "(...)"
<< (settings.hilite ? hilite_none : "");
}
};
}
......@@ -26,11 +26,25 @@ public:
ASTSetQuery() = default;
ASTSetQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "Set"; };
ASTPtr clone() const override { return new ASTSetQuery(*this); }
protected:
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << "SET " << (global ? "GLOBAL " : "") << (settings.hilite ? hilite_none : "");
for (ASTSetQuery::Changes::const_iterator it = changes.begin(); it != changes.end(); ++it)
{
if (it != changes.begin())
settings.ostr << ", ";
settings.ostr << it->name << " = " << apply_visitor(FieldVisitorToString(), it->value);
}
}
};
}
......@@ -5,5 +5,7 @@
namespace DB
{
DEFINE_AST_QUERY_WITH_OUTPUT(ASTShowProcesslistQuery, "ShowProcesslistQuery")
DEFINE_AST_QUERY_WITH_OUTPUT(ASTShowProcesslistQuery, "ShowProcesslistQuery", "SHOW PROCESSLIST")
}
#pragma once
#include <mysqlxx/Manip.h>
#include <DB/Parsers/IAST.h>
#include <DB/Parsers/ASTQueryWithOutput.h>
......@@ -20,7 +21,7 @@ public:
ASTShowTablesQuery() = default;
ASTShowTablesQuery(const StringRange range_) : ASTQueryWithOutput(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "ShowTables"; };
......@@ -30,15 +31,43 @@ public:
ASTPtr ptr{res};
res->children.clear();
if (format)
{
res->format = format->clone();
res->children.push_back(res->format);
}
return ptr;
}
protected:
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
{
if (databases)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << "SHOW DATABASES" << (settings.hilite ? hilite_none : "");
}
else
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << "SHOW TABLES" << (settings.hilite ? hilite_none : "");
if (!from.empty())
settings.ostr << (settings.hilite ? hilite_keyword : "") << " FROM " << (settings.hilite ? hilite_none : "")
<< backQuoteIfNeed(from);
if (!like.empty())
settings.ostr << (settings.hilite ? hilite_keyword : "") << " LIKE " << (settings.hilite ? hilite_none : "")
<< mysqlxx::quote << like;
}
if (format)
{
std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << indent_str << "FORMAT " << (settings.hilite ? hilite_none : "");
format->formatImpl(settings, state, frame);
}
}
};
}
......@@ -34,6 +34,30 @@ public:
}
String getColumnName() const override { return getTreeID(); }
protected:
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
{
/// Если есть алиас, то требуются скобки вокруг всего выражения, включая алиас. Потому что запись вида 0 AS x + 0 синтаксически некорректна.
if (frame.need_parens && !alias.empty())
settings.ostr << '(';
std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
std::string nl_or_nothing = settings.one_line ? "" : "\n";
settings.ostr << nl_or_nothing << indent_str << "(" << nl_or_nothing;
FormatStateStacked frame_dont_need_parens = frame;
frame_dont_need_parens.need_parens = false;
children[0]->formatImpl(settings, state, frame_dont_need_parens);
settings.ostr << nl_or_nothing << indent_str << ")";
if (!alias.empty())
{
writeAlias(alias, settings.ostr, settings.hilite);
if (frame.need_parens)
settings.ostr << ')';
}
}
};
}
......@@ -16,11 +16,18 @@ public:
ASTUseQuery() = default;
ASTUseQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "UseQuery_" + database; };
ASTPtr clone() const override { return new ASTUseQuery(*this); }
protected:
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << "USE " << (settings.hilite ? hilite_none : "") << backQuoteIfNeed(database);
return;
}
};
}
......@@ -171,7 +171,7 @@ public:
formatImpl(settings, state, FormatStateStacked());
}
protected:
/// Для подсветки синтаксиса.
static const char * hilite_keyword;
static const char * hilite_identifier;
......@@ -190,7 +190,7 @@ protected:
ErrorCodes::UNKNOWN_ELEMENT_IN_AST);
}
void writeAlias(const String & name, std::ostream & s, bool hilite);
void writeAlias(const String & name, std::ostream & s, bool hilite) const;
private:
size_t checkDepthImpl(size_t max_depth, size_t level) const
......
......@@ -5,17 +5,9 @@
namespace DB
{
/** EXISTS запрос
*/
DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(ASTExistsQuery, "ExistsQuery")
/** SHOW CREATE TABLE запрос
*/
DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(ASTShowCreateQuery, "ShowCreateQuery")
/** DESCRIBE TABLE запрос
*/
DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(ASTDescribeQuery, "DescribeQuery")
DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(ASTExistsQuery, "ExistsQuery", "EXISTS TABLE")
DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(ASTShowCreateQuery, "ShowCreateQuery", "SHOW CREATE TABLE")
DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(ASTDescribeQuery, "DescribeQuery", "DESCRIBE TABLE")
}
......@@ -12,11 +12,14 @@ namespace DB
/** Берёт синтаксическое дерево и превращает его обратно в текст.
* В случае запроса INSERT, данные будут отсутствовать.
*/
void formatAST(const IAST & ast, std::ostream & s, size_t indent = 0, bool hilite = true, bool one_line = false, bool need_parens = false);
inline void formatAST(const IAST & ast, std::ostream & s, size_t indent = 0, bool hilite = true, bool one_line = false)
{
IAST::FormatSettings settings(s, hilite, one_line);
ast.format(settings);
}
String formatColumnsForCreateQuery(NamesAndTypesList & columns);
String backQuoteIfNeed(const String & x);
inline std::ostream & operator<<(std::ostream & os, const IAST & ast) { return formatAST(ast, os, 0, false, true), os; }
inline std::ostream & operator<<(std::ostream & os, const ASTPtr & ast) { return formatAST(*ast, os, 0, false, true), os; }
......
......@@ -4,194 +4,196 @@
namespace DB
{
void ASTFunction::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
void ASTFunction::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
{
/// Если есть алиас, то требуются скобки вокруг всего выражения, включая алиас. Потому что запись вида 0 AS x + 0 синтаксически некорректна.
if (frame.need_parens && !alias.empty())
settings.ostr << '(';
FormatStateStacked nested_need_parens = frame;
FormatStateStacked nested_dont_need_parens = frame;
nested_need_parens.need_parens = true;
nested_dont_need_parens.need_parens = false;
/// Стоит ли записать эту функцию в виде оператора?
bool written = false;
if (arguments && !parameters)
{
/// Если есть алиас, то требуются скобки вокруг всего выражения, включая алиас. Потому что запись вида 0 AS x + 0 синтаксически некорректна.
if (frame.need_parens && !alias.empty())
settings.ostr << '(';
FormatStateStacked nested_need_parens;
FormatStateStacked nested_dont_need_parens;
nested_need_parens.need_parens = true;
nested_dont_need_parens.need_parens = false;
/// Стоит ли записать эту функцию в виде оператора?
bool written = false;
if (arguments && !parameters)
if (arguments->children.size() == 1)
{
if (arguments->children.size() == 1)
const char * operators[] =
{
const char * operators[] =
{
"negate", "-",
"not", "NOT ",
nullptr
};
"negate", "-",
"not", "NOT ",
nullptr
};
for (const char ** func = operators; *func; func += 2)
for (const char ** func = operators; *func; func += 2)
{
if (0 == strcmp(name.c_str(), func[0]))
{
if (0 == strcmp(name.c_str(), func[0]))
{
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 << ' ';
FormatStateStacked nested_frame;
nested_frame.need_parens = true;
arguments->formatImpl(settings, state, nested_need_parens);
written = true;
}
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 << ' ';
FormatStateStacked nested_frame;
nested_frame.need_parens = true;
arguments->formatImpl(settings, state, nested_need_parens);
written = true;
}
}
}
/** need_parens - нужны ли скобки вокруг выражения с оператором.
* Они нужны, только если это выражение входит в другое выражение с оператором.
*/
/** need_parens - нужны ли скобки вокруг выражения с оператором.
* Они нужны, только если это выражение входит в другое выражение с оператором.
*/
if (!written && arguments->children.size() == 2)
if (!written && arguments->children.size() == 2)
{
const char * operators[] =
{
const char * operators[] =
{
"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]))
{
if (frame.need_parens)
settings.ostr << '(';
arguments->children[0]->formatImpl(settings, state, nested_need_parens);
settings.ostr << (settings.hilite ? hilite_operator : "") << func[1] << (settings.hilite ? hilite_none : "");
arguments->children[1]->formatImpl(settings, state, nested_need_parens);
if (frame.need_parens)
settings.ostr << ')';
written = true;
}
}
if (!written && 0 == strcmp(name.c_str(), "arrayElement"))
{
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;
}
if (!written && 0 == strcmp(name.c_str(), "tupleElement"))
"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]))
{
if (frame.need_parens)
settings.ostr << '(';
arguments->children[0]->formatImpl(settings, state, nested_need_parens);
settings.ostr << (settings.hilite ? hilite_operator : "") << "." << (settings.hilite ? hilite_none : "");
settings.ostr << (settings.hilite ? hilite_operator : "") << func[1] << (settings.hilite ? hilite_none : "");
arguments->children[1]->formatImpl(settings, state, nested_need_parens);
if (frame.need_parens)
settings.ostr << ')';
written = true;
}
}
if (!written && arguments->children.size() >= 2)
if (!written && 0 == strcmp(name.c_str(), "arrayElement"))
{
const char * operators[] =
{
"and", " AND ",
"or", " OR ",
nullptr
};
for (const char ** func = operators; *func; func += 2)
{
if (0 == strcmp(name.c_str(), func[0]))
{
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;
}
}
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;
}
if (!written && arguments->children.size() >= 1 && 0 == strcmp(name.c_str(), "array"))
if (!written && 0 == strcmp(name.c_str(), "tupleElement"))
{
settings.ostr << (settings.hilite ? hilite_operator : "") << '[' << (settings.hilite ? hilite_none : "");
for (size_t i = 0; i < arguments->children.size(); ++i)
{
if (i != 0)
settings.ostr << ", ";
arguments->children[i]->formatImpl(settings, state, nested_dont_need_parens);
}
settings.ostr << (settings.hilite ? hilite_operator : "") << ']' << (settings.hilite ? hilite_none : "");
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);
written = true;
}
}
if (!written && arguments->children.size() >= 2 && 0 == strcmp(name.c_str(), "tuple"))
if (!written && arguments->children.size() >= 2)
{
const char * operators[] =
{
"and", " AND ",
"or", " OR ",
nullptr
};
for (const char ** func = operators; *func; func += 2)
{
settings.ostr << (settings.hilite ? hilite_operator : "") << '(' << (settings.hilite ? hilite_none : "");
for (size_t i = 0; i < arguments->children.size(); ++i)
if (0 == strcmp(name.c_str(), func[0]))
{
if (i != 0)
settings.ostr << ", ";
arguments->children[i]->formatImpl(settings, state, nested_dont_need_parens);
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;
}
settings.ostr << (settings.hilite ? hilite_operator : "") << ')' << (settings.hilite ? hilite_none : "");
written = true;
}
}
if (!written)
if (!written && arguments->children.size() >= 1 && 0 == strcmp(name.c_str(), "array"))
{
settings.ostr << (settings.hilite ? hilite_function : "") << name;
if (parameters)
settings.ostr << (settings.hilite ? hilite_operator : "") << '[' << (settings.hilite ? hilite_none : "");
for (size_t i = 0; i < arguments->children.size(); ++i)
{
settings.ostr << '(' << (settings.hilite ? hilite_none : "");
parameters->formatImpl(settings, state, nested_dont_need_parens);
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
if (i != 0)
settings.ostr << ", ";
arguments->children[i]->formatImpl(settings, state, nested_dont_need_parens);
}
settings.ostr << (settings.hilite ? hilite_operator : "") << ']' << (settings.hilite ? hilite_none : "");
written = true;
}
if (arguments)
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)
{
settings.ostr << '(' << (settings.hilite ? hilite_none : "");
arguments->formatImpl(settings, state, nested_dont_need_parens);
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
if (i != 0)
settings.ostr << ", ";
arguments->children[i]->formatImpl(settings, state, nested_dont_need_parens);
}
settings.ostr << (settings.hilite ? hilite_operator : "") << ')' << (settings.hilite ? hilite_none : "");
written = true;
}
}
if (!written)
{
settings.ostr << (settings.hilite ? hilite_function : "") << name;
settings.ostr << (settings.hilite ? hilite_none : "");
if (parameters)
{
settings.ostr << '(' << (settings.hilite ? hilite_none : "");
parameters->formatImpl(settings, state, nested_dont_need_parens);
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
}
if (!alias.empty())
if (arguments)
{
writeAlias(alias, settings.ostr, settings.hilite);
if (frame.need_parens)
settings.ostr << ')';
settings.ostr << '(' << (settings.hilite ? hilite_none : "");
arguments->formatImpl(settings, state, nested_dont_need_parens);
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
}
settings.ostr << (settings.hilite ? hilite_none : "");
}
if (!alias.empty())
{
writeAlias(alias, settings.ostr, settings.hilite);
if (frame.need_parens)
settings.ostr << ')';
}
}
}
......@@ -220,148 +220,148 @@ const IAST * ASTSelectQuery::getFormat() const
}
void ASTSelectQuery::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
void ASTSelectQuery::formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const
{
frame.need_parens = false;
std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
std::string indent_str = s.one_line ? "" : std::string(4 * frame.indent, ' ');
settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << "SELECT " << (distinct ? "DISTINCT " : "") << (settings.hilite ? hilite_none : "");
s.ostr << (s.hilite ? hilite_keyword : "") << indent_str << "SELECT " << (distinct ? "DISTINCT " : "") << (s.hilite ? hilite_none : "");
settings.one_line
? select_expression_list->formatImpl(settings, state, frame)
: typeid_cast<const ASTExpressionList &>(*select_expression_list).formatImplMultiline(settings, state, frame);
s.one_line
? select_expression_list->formatImpl(s, state, frame)
: typeid_cast<const ASTExpressionList &>(*select_expression_list).formatImplMultiline(s, state, frame);
if (table)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "FROM " << (settings.hilite ? hilite_none : "");
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "FROM " << (s.hilite ? hilite_none : "");
if (database)
{
database->formatImpl(settings, state, frame);
settings.ostr << ".";
database->formatImpl(s, state, frame);
s.ostr << ".";
}
if (typeid_cast<const ASTSelectQuery *>(&*table))
{
if (settings.one_line)
settings.ostr << " (";
if (s.one_line)
s.ostr << " (";
else
settings.ostr << "\n" << indent_str << "(\n";
s.ostr << "\n" << indent_str << "(\n";
table->formatImpl(settings, state, frame);
table->formatImpl(s, state, frame);
if (settings.one_line)
settings.ostr << ")";
if (s.one_line)
s.ostr << ")";
else
settings.ostr << "\n" << indent_str << ")";
s.ostr << "\n" << indent_str << ")";
}
else
table->formatImpl(settings, state, frame);
table->formatImpl(s, state, frame);
}
if (final)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "FINAL" << (settings.hilite ? hilite_none : "");
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "FINAL" << (s.hilite ? hilite_none : "");
}
if (sample_size)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "SAMPLE " << (settings.hilite ? hilite_none : "");
sample_size->formatImpl(settings, state, frame);
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "SAMPLE " << (s.hilite ? hilite_none : "");
sample_size->formatImpl(s, state, frame);
}
if (array_join_expression_list)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str
<< (array_join_is_left ? "LEFT " : "") << "ARRAY JOIN " << (settings.hilite ? hilite_none : "");
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str
<< (array_join_is_left ? "LEFT " : "") << "ARRAY JOIN " << (s.hilite ? hilite_none : "");
settings.one_line
? array_join_expression_list->formatImpl(settings, state, frame)
: typeid_cast<const ASTExpressionList &>(*array_join_expression_list).formatImplMultiline(settings, state, frame);
s.one_line
? array_join_expression_list->formatImpl(s, state, frame)
: typeid_cast<const ASTExpressionList &>(*array_join_expression_list).formatImplMultiline(s, state, frame);
}
if (join)
{
settings.ostr << " ";
join->formatImpl(settings, state, frame);
s.ostr << " ";
join->formatImpl(s, state, frame);
}
if (prewhere_expression)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "PREWHERE " << (settings.hilite ? hilite_none : "");
prewhere_expression->formatImpl(settings, state, frame);
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "PREWHERE " << (s.hilite ? hilite_none : "");
prewhere_expression->formatImpl(s, state, frame);
}
if (where_expression)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "WHERE " << (settings.hilite ? hilite_none : "");
where_expression, s, indent, hilite, settings.one_line);
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "WHERE " << (s.hilite ? hilite_none : "");
where_expression->formatImpl(s, state, frame);
}
if (group_expression_list)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "GROUP BY " << (settings.hilite ? hilite_none : "");
settings.one_line
? group_expression_list->formatImpl(settings, state, frame)
: typeid_cast<const ASTExpressionList &>(*group_expression_list).formatImplMultiline(settings, state, frame);
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "GROUP BY " << (s.hilite ? hilite_none : "");
s.one_line
? group_expression_list->formatImpl(s, state, frame)
: typeid_cast<const ASTExpressionList &>(*group_expression_list).formatImplMultiline(s, state, frame);
}
if (group_by_with_totals)
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << (settings.one_line ? "" : " ") << "WITH TOTALS" << (settings.hilite ? hilite_none : "");
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << (s.one_line ? "" : " ") << "WITH TOTALS" << (s.hilite ? hilite_none : "");
if (having_expression)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "HAVING " << (settings.hilite ? hilite_none : "");
having_expression->formatImpl(settings, state, frame);
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "HAVING " << (s.hilite ? hilite_none : "");
having_expression->formatImpl(s, state, frame);
}
if (order_expression_list)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "ORDER BY " << (settings.hilite ? hilite_none : "");
settings.one_line
? order_expression_list->formatImpl(settings, state, frame)
: typeid_cast<const ASTExpressionList &>(*order_expression_list).formatImplMultiline(settings, state, frame);
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "ORDER BY " << (s.hilite ? hilite_none : "");
s.one_line
? order_expression_list->formatImpl(s, state, frame)
: typeid_cast<const ASTExpressionList &>(*order_expression_list).formatImplMultiline(s, state, frame);
}
if (limit_length)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "LIMIT " << (settings.hilite ? hilite_none : "");
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "LIMIT " << (s.hilite ? hilite_none : "");
if (limit_offset)
{
limit_offset->formatImpl(settings, state, frame);
settings.ostr << ", ";
limit_offset->formatImpl(s, state, frame);
s.ostr << ", ";
}
limit_length->formatImpl(settings, state, frame);
limit_length->formatImpl(s, state, frame);
}
if (settings)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "SETTINGS " << (settings.hilite ? hilite_none : "");
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "SETTINGS " << (s.hilite ? hilite_none : "");
const ASTSetQuery & ast_set = typeid_cast<const ASTSetQuery &>(*settings);
for (ASTSetQuery::Changes::const_iterator it = ast_set.changes.begin(); it != ast_set.changes.end(); ++it)
{
if (it != ast_set.changes.begin())
settings.ostr << ", ";
s.ostr << ", ";
settings.ostr << it->name << " = " << apply_visitor(FieldVisitorToString(), it->value);
s.ostr << it->name << " = " << apply_visitor(FieldVisitorToString(), it->value);
}
}
if (format)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "FORMAT " << (settings.hilite ? hilite_none : "");
format->formatImpl(settings, state, frame);
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "FORMAT " << (s.hilite ? hilite_none : "");
format->formatImpl(s, state, frame);
}
if (next_union_all)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << settings.nl_or_ws << settings.ostr << indent_str << "UNION ALL " << settings.nl_or_ws << settings.ostr << (settings.hilite ? hilite_none : "");
s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "UNION ALL " << s.nl_or_ws << (s.hilite ? hilite_none : "");
// NOTE Мы можем безопасно применить static_cast вместо typeid_cast, потому что знаем, что в цепочке UNION ALL
// имеются только деревья типа SELECT.
const ASTSelectQuery & next_ast = static_cast<const ASTSelectQuery &>(*next_union_all);
next_ast->formatImpl(settings, state, frame);
next_ast.formatImpl(s, state, frame);
}
}
......
......@@ -25,7 +25,7 @@ String backQuoteIfNeed(const String & x)
}
void IAST::writeAlias(const String & name, std::ostream & s, bool hilite)
void IAST::writeAlias(const String & name, std::ostream & s, bool hilite) const
{
s << (hilite ? hilite_keyword : "") << " AS " << (hilite ? hilite_alias : "");
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册