dbms: improved query formatting for distributed queries [#METR-17606].

This commit is contained in:
Alexey Milovidov 2015-08-07 00:32:51 +03:00
parent 5ed70eeb27
commit 32da2a7d8c
6 changed files with 59 additions and 39 deletions

View File

@ -21,32 +21,8 @@ public:
String tryGetAlias() const override { return alias; }
void setAlias(const String & to) override { alias = to; }
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override final
{
if (!alias.empty())
{
/// Если мы уже ранее вывели этот узел в другом месте запроса, то теперь достаточно вывести лишь алиас.
if (!state.printed_asts_with_alias.insert(this).second)
{
WriteBufferFromOStream wb(settings.ostr, 32);
writeProbablyBackQuotedString(alias, wb);
return;
}
}
/// Если есть алиас, то требуются скобки вокруг всего выражения, включая алиас. Потому что запись вида 0 AS x + 0 синтаксически некорректна.
if (frame.need_parens && !alias.empty())
settings.ostr <<'(';
formatImplWithAlias(settings, state, frame);
if (!alias.empty())
{
writeAlias(alias, settings.ostr, settings.hilite);
if (frame.need_parens)
settings.ostr <<')';
}
}
/// Вызывает formatImplWithAlias, а также выводит алиас. Если надо - заключает всё выражение в скобки.
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override final;
virtual void formatImplWithAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const = 0;
};

View File

@ -4,7 +4,7 @@
#include <set>
#include <sstream>
#include <iostream>
#include <unordered_set>
#include <set>
#include <Poco/SharedPtr.h>
@ -152,10 +152,13 @@ public:
}
};
/// Состояние. Например, множество узлов DAG, которых мы уже обошли.
/// Состояние. Например, может запоминаться множество узлов, которых мы уже обошли.
struct FormatState
{
std::unordered_set<const IAST *> printed_asts_with_alias;
/** Запрос SELECT, в котором найден алиас; идентификатор узла с таким алиасом.
* Нужно, чтобы когда узел встретился повторно, выводить только алиас.
*/
std::set<std::pair<const IAST *, std::string>> printed_asts_with_alias;
};
/// Состояние, которое копируется при форматировании каждого узла. Например, уровень вложенности.
@ -163,6 +166,7 @@ public:
{
bool indent = 0;
bool need_parens = false;
const IAST * current_select = nullptr;
};
void format(const FormatSettings & settings) const
@ -171,16 +175,6 @@ public:
formatImpl(settings, state, FormatStateStacked());
}
/// Для подсветки синтаксиса.
static const char * hilite_keyword;
static const char * hilite_identifier;
static const char * hilite_function;
static const char * hilite_operator;
static const char * hilite_alias;
static const char * hilite_none;
virtual void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
{
throw Exception("Unknown element in AST: " + getID()
@ -192,6 +186,15 @@ public:
void writeAlias(const String & name, std::ostream & s, bool hilite) const;
protected:
/// Для подсветки синтаксиса.
static const char * hilite_keyword;
static const char * hilite_identifier;
static const char * hilite_function;
static const char * hilite_operator;
static const char * hilite_alias;
static const char * hilite_none;
private:
size_t checkDepthImpl(size_t max_depth, size_t level) const
{

View File

@ -222,6 +222,7 @@ const IAST * ASTSelectQuery::getFormat() const
void ASTSelectQuery::formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const
{
frame.current_select = this;
frame.need_parens = false;
std::string indent_str = s.one_line ? "" : std::string(4 * frame.indent, ' ');

View File

@ -0,0 +1,33 @@
#include <DB/Parsers/ASTWithAlias.h>
namespace DB
{
void ASTWithAlias::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
{
if (!alias.empty())
{
/// Если мы уже ранее вывели этот узел в другом месте запроса, то теперь достаточно вывести лишь алиас.
if (!state.printed_asts_with_alias.emplace(frame.current_select, getID()).second)
{
WriteBufferFromOStream wb(settings.ostr, 32);
writeProbablyBackQuotedString(alias, wb);
return;
}
}
/// Если есть алиас, то требуются скобки вокруг всего выражения, включая алиас. Потому что запись вида 0 AS x + 0 синтаксически некорректна.
if (frame.need_parens && !alias.empty())
settings.ostr <<'(';
formatImplWithAlias(settings, state, frame);
if (!alias.empty())
{
writeAlias(alias, settings.ostr, settings.hilite);
if (frame.need_parens)
settings.ostr <<')';
}
}
}

View File

@ -0,0 +1 @@
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

View File

@ -0,0 +1,6 @@
SELECT toUInt64(1) IN (1234567890, 2345678901, 3456789012, 4567890123, 5678901234, 6789012345, 7890123456, 8901234567, 9012345678, 123456789) AS x,
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x
FROM remote('127.0.0.1', system, one) SETTINGS max_query_size = 10000;