mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 08:02:02 +00:00
dbms: better handling of compound identifiers [#METR-18692].
This commit is contained in:
parent
4482871274
commit
0e5bf428d0
@ -21,7 +21,7 @@ public:
|
||||
Format,
|
||||
};
|
||||
|
||||
/// имя
|
||||
/// имя. У составного идентификатора здесь будет конкатенированное имя (вида a.b.c), а отдельные составляюшие будут доступны внутри children.
|
||||
String name;
|
||||
|
||||
/// чего идентифицирует этот идентификатор
|
||||
@ -44,16 +44,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
|
||||
{
|
||||
settings.ostr << (settings.hilite ? hilite_identifier : "");
|
||||
|
||||
WriteBufferFromOStream wb(settings.ostr, 32);
|
||||
writeProbablyBackQuotedString(name, wb);
|
||||
wb.next();
|
||||
|
||||
settings.ostr << (settings.hilite ? hilite_none : "");
|
||||
}
|
||||
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
38
dbms/src/Parsers/ASTIdentifier.cpp
Normal file
38
dbms/src/Parsers/ASTIdentifier.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include <DB/Parsers/ASTIdentifier.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
void ASTIdentifier::formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
|
||||
{
|
||||
auto format_element = [&](const String & name)
|
||||
{
|
||||
settings.ostr << (settings.hilite ? hilite_identifier : "");
|
||||
|
||||
WriteBufferFromOStream wb(settings.ostr, 32);
|
||||
writeProbablyBackQuotedString(name, wb);
|
||||
wb.next();
|
||||
|
||||
settings.ostr << (settings.hilite ? hilite_none : "");
|
||||
};
|
||||
|
||||
/// Простой или составной идентификатор?
|
||||
|
||||
if (children.size() > 1)
|
||||
{
|
||||
for (size_t i = 0, size = children.size(); i < size; ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
settings.ostr << '.';
|
||||
|
||||
format_element(static_cast<const ASTIdentifier &>(*children[i].get()).name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
format_element(name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
#include <DB/Parsers/ParserSelectQuery.h>
|
||||
|
||||
#include <DB/Parsers/ExpressionElementParsers.h>
|
||||
#include <DB/Parsers/formatAST.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -165,44 +166,27 @@ bool ParserCompoundIdentifier::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos
|
||||
{
|
||||
Pos begin = pos;
|
||||
|
||||
/// Идентификатор в обратных кавычках
|
||||
if (pos != end && *pos == '`')
|
||||
{
|
||||
ReadBuffer buf(const_cast<char *>(pos), end - pos, 0);
|
||||
String s;
|
||||
readBackQuotedString(s, buf);
|
||||
pos += buf.count();
|
||||
node = new ASTIdentifier(StringRange(begin, pos), s);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (pos != end)
|
||||
{
|
||||
while (pos != end
|
||||
&& ((*pos >= 'a' && *pos <= 'z')
|
||||
|| (*pos >= 'A' && *pos <= 'Z')
|
||||
|| (*pos == '_')
|
||||
|| (pos != begin && *pos >= '0' && *pos <= '9')))
|
||||
++pos;
|
||||
ASTPtr id_list;
|
||||
if (!ParserList(ParserPtr(new ParserIdentifier), ParserPtr(new ParserString(".")), false)
|
||||
.parse(pos, end, id_list, max_parsed_pos, expected))
|
||||
return false;
|
||||
|
||||
/// Если следующий символ - точка '.' и за ней следует, не цифра,
|
||||
/// то продолжаем парсинг имени идентификатора
|
||||
if (pos != begin && pos + 1 < end && *pos == '.' &&
|
||||
!(*(pos + 1) >= '0' && *(pos + 1) <= '9'))
|
||||
++pos;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (pos != begin)
|
||||
{
|
||||
node = new ASTIdentifier(StringRange(begin, pos), String(begin, pos - begin));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
String name;
|
||||
const ASTExpressionList & list = static_cast<const ASTExpressionList &>(*id_list.get());
|
||||
for (const auto & child : list.children)
|
||||
{
|
||||
if (!name.empty())
|
||||
name += '.';
|
||||
name += static_cast<const ASTIdentifier &>(*child.get()).name;
|
||||
}
|
||||
|
||||
node = new ASTIdentifier(StringRange(begin, pos), name);
|
||||
|
||||
/// В children запомним идентификаторы-составляющие, если их больше одного.
|
||||
if (list.children.size() > 1)
|
||||
node->children.insert(node->children.end(), list.children.begin(), list.children.end());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user