Merge pull request #13496 from vitlibar/compound-identifiers-for-custom-settings

Support compound identifiers for custom settings.
This commit is contained in:
Vitaly Baranov 2020-08-10 01:03:02 +03:00 committed by GitHub
commit 2e6ba2a05d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 101 additions and 33 deletions

View File

@ -308,7 +308,7 @@ inline void splitInto(To & to, const std::string & what, bool token_compress = f
const char * delimiter_or_end = find_first_symbols<symbols...>(pos, end);
if (!token_compress || pos < delimiter_or_end)
to.emplace_back(pos, delimiter_or_end);
to.emplace_back(pos, delimiter_or_end - pos);
if (delimiter_or_end < end)
pos = delimiter_or_end + 1;

View File

@ -122,6 +122,11 @@ inline bool isPrintableASCII(char c)
return uc >= 32 && uc <= 126; /// 127 is ASCII DEL.
}
inline bool isValidIdentifier(const std::string_view & str)
{
return !str.empty() && isValidIdentifierBegin(str[0]) && std::all_of(str.begin() + 1, str.end(), isWordCharASCII);
}
/// Works assuming isAlphaASCII.
inline char toLowerIfAlphaASCII(char c)
{

View File

@ -68,22 +68,10 @@ void writeException(const Exception & e, WriteBuffer & buf, bool with_stack_trac
template <typename F>
static inline void writeProbablyQuotedStringImpl(const StringRef & s, WriteBuffer & buf, F && write_quoted_string)
{
if (!s.size || !isValidIdentifierBegin(s.data[0]))
{
write_quoted_string(s, buf);
}
else
{
const char * pos = s.data + 1;
const char * end = s.data + s.size;
for (; pos < end; ++pos)
if (!isWordCharASCII(*pos))
break;
if (pos != end)
write_quoted_string(s, buf);
else
if (isValidIdentifier(std::string_view{s}))
writeString(s, buf);
}
else
write_quoted_string(s, buf);
}
void writeProbablyBackQuotedString(const StringRef & s, WriteBuffer & buf)

View File

@ -0,0 +1,22 @@
#include <Parsers/ASTSetQuery.h>
#include <Parsers/formatSettingName.h>
namespace DB
{
void ASTSetQuery::formatImpl(const FormatSettings & format, FormatState &, FormatStateStacked) const
{
if (is_standalone)
format.ostr << (format.hilite ? hilite_keyword : "") << "SET " << (format.hilite ? hilite_none : "");
for (auto it = changes.begin(); it != changes.end(); ++it)
{
if (it != changes.begin())
format.ostr << ", ";
formatSettingName(it->name, format.ostr);
format.ostr << " = " << applyVisitor(FieldVisitorToString(), it->value);
}
}
}

View File

@ -8,7 +8,6 @@
namespace DB
{
/** SET query
*/
class ASTSetQuery : public IAST
@ -23,19 +22,7 @@ public:
ASTPtr clone() const override { return std::make_shared<ASTSetQuery>(*this); }
void formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override
{
if (is_standalone)
settings.ostr << (settings.hilite ? hilite_keyword : "") << "SET " << (settings.hilite ? hilite_none : "");
for (auto it = changes.begin(); it != changes.end(); ++it)
{
if (it != changes.begin())
settings.ostr << ", ";
settings.ostr << it->name << " = " << applyVisitor(FieldVisitorToString(), it->value);
}
}
void formatImpl(const FormatSettings & format, FormatState &, FormatStateStacked) const override;
};
}

View File

@ -1,4 +1,5 @@
#include <Parsers/ASTSettingsProfileElement.h>
#include <Parsers/formatSettingName.h>
#include <Common/FieldVisitors.h>
#include <Common/quoteString.h>
@ -31,7 +32,7 @@ void ASTSettingsProfileElement::formatImpl(const FormatSettings & settings, Form
return;
}
settings.ostr << setting_name;
formatSettingName(setting_name, settings.ostr);
if (!value.isNull())
{

View File

@ -15,7 +15,7 @@ namespace DB
/// Parse `name = value`.
bool ParserSetQuery::parseNameValuePair(SettingChange & change, IParser::Pos & pos, Expected & expected)
{
ParserIdentifier name_p;
ParserCompoundIdentifier name_p;
ParserLiteral value_p;
ParserToken s_eq(TokenType::Equals);

View File

@ -118,7 +118,7 @@ namespace
return IParserBase::wrapParseImpl(pos, [&]
{
ASTPtr name_ast;
if (!ParserIdentifier{}.parse(pos, name_ast, expected))
if (!ParserCompoundIdentifier{}.parse(pos, name_ast, expected))
return false;
String res_setting_name = getIdentifierName(name_ast);

View File

@ -0,0 +1,36 @@
#include <Parsers/formatSettingName.h>
#include <Common/StringUtils/StringUtils.h>
#include <Common/quoteString.h>
#include <common/find_symbols.h>
namespace DB
{
void formatSettingName(const String & setting_name, std::ostream & out)
{
if (isValidIdentifier(setting_name))
{
out << setting_name;
return;
}
std::vector<std::string_view> parts;
splitInto<'.'>(parts, setting_name);
bool all_parts_are_identifiers = std::all_of(parts.begin(), parts.end(), isValidIdentifier);
if (all_parts_are_identifiers && !parts.empty())
{
bool need_dot = false;
for (const auto & part : parts)
{
if (std::exchange(need_dot, true))
out << ".";
out << part;
}
return;
}
out << backQuote(setting_name);
}
}

View File

@ -0,0 +1,14 @@
#pragma once
#include <Core/Types.h>
namespace DB
{
/// Outputs built-in or custom setting's name.
/// The function is like backQuoteIfNeed() but didn't quote with backticks
/// if the name consists of identifiers joined with dots.
void formatSettingName(const String & setting_name, std::ostream & out);
}

View File

@ -44,6 +44,7 @@ SRCS(
ASTSampleRatio.cpp
ASTSelectQuery.cpp
ASTSelectWithUnionQuery.cpp
ASTSetQuery.cpp
ASTSetRoleQuery.cpp
ASTSettingsProfileElement.cpp
ASTShowAccessEntitiesQuery.cpp
@ -61,6 +62,7 @@ SRCS(
ExpressionElementParsers.cpp
ExpressionListParsers.cpp
formatAST.cpp
formatSettingName.cpp
IAST.cpp
iostream_debug_helpers.cpp
IParserBase.cpp

View File

@ -15,3 +15,7 @@ custom_b NULL
custom_c UInt64_50000
custom_d Float64_1.11
0 UInt8
test String
custom_compound.identifier.v1 \'test\'
CREATE SETTINGS PROFILE s1_01418 SETTINGS custom_compound.identifier.v2 = 100

View File

@ -23,3 +23,12 @@ SET custom_e = 0;
SELECT getSetting('custom_e') as v, toTypeName(v);
SET invalid_custom = 8; -- { serverError 115 } -- Setting is neither a builtin nor started with one of the registered prefixes for user-defined settings.
SELECT '';
SET custom_compound.identifier.v1 = 'test';
SELECT getSetting('custom_compound.identifier.v1') as v, toTypeName(v);
SELECT name, value FROM system.settings WHERE name = 'custom_compound.identifier.v1';
CREATE SETTINGS PROFILE s1_01418 SETTINGS custom_compound.identifier.v2 = 100;
SHOW CREATE SETTINGS PROFILE s1_01418;
DROP SETTINGS PROFILE s1_01418;