mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Use function ParserList::parseUtil() to parse lists more accurately.
This commit is contained in:
parent
a5b70fbdda
commit
6146766465
@ -76,41 +76,25 @@ const char * ParserTupleElementExpression::operators[] =
|
||||
|
||||
bool ParserList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
bool first = true;
|
||||
ASTs elements;
|
||||
|
||||
auto parse_element = [&]
|
||||
{
|
||||
ASTPtr element;
|
||||
if (!elem_parser->parse(pos, element, expected))
|
||||
return false;
|
||||
|
||||
elements.push_back(element);
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!parseUtil(pos, expected, parse_element, *separator_parser, allow_empty))
|
||||
return false;
|
||||
|
||||
auto list = std::make_shared<ASTExpressionList>(result_separator);
|
||||
list->children = std::move(elements);
|
||||
node = list;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
ASTPtr elem;
|
||||
if (!elem_parser->parse(pos, elem, expected))
|
||||
break;
|
||||
|
||||
list->children.push_back(elem);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto prev_pos = pos;
|
||||
|
||||
if (!separator_parser->ignore(pos, expected))
|
||||
break;
|
||||
|
||||
ASTPtr elem;
|
||||
if (!elem_parser->parse(pos, elem, expected))
|
||||
{
|
||||
pos = prev_pos;
|
||||
break;
|
||||
}
|
||||
|
||||
list->children.push_back(elem);
|
||||
}
|
||||
}
|
||||
|
||||
return allow_empty || !first;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,6 +26,43 @@ public:
|
||||
, result_separator(result_separator_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static bool parseUtil(Pos & pos, Expected & expected, const F & parse_element, IParser & separator_parser_, bool allow_empty_ = true)
|
||||
{
|
||||
Pos begin = pos;
|
||||
if (!parse_element())
|
||||
{
|
||||
pos = begin;
|
||||
return allow_empty_;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
begin = pos;
|
||||
if (!separator_parser_.ignore(pos, expected) || !parse_element())
|
||||
{
|
||||
pos = begin;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static bool parseUtil(Pos & pos, Expected & expected, const F & parse_element, TokenType separator, bool allow_empty_ = true)
|
||||
{
|
||||
ParserToken sep_parser{separator};
|
||||
return parseUtil(pos, expected, parse_element, sep_parser, allow_empty_);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static bool parseUtil(Pos & pos, Expected & expected, const F & parse_element, bool allow_empty_ = true)
|
||||
{
|
||||
return parseUtil(pos, expected, parse_element, TokenType::Comma, allow_empty_);
|
||||
}
|
||||
|
||||
protected:
|
||||
const char * getName() const override { return "list of elements"; }
|
||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <Parsers/ASTLiteral.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/ASTRolesOrUsersSet.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <ext/range.h>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
@ -126,17 +127,17 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
bool parseLimit(IParserBase::Pos & pos, Expected & expected, bool first, bool & max_prefix_encountered, ResourceType & resource_type, ResourceAmount & max)
|
||||
bool parseLimits(IParserBase::Pos & pos, Expected & expected, std::vector<std::pair<ResourceType, ResourceAmount>> & limits)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
if (!first && !ParserToken{TokenType::Comma}.ignore(pos, expected))
|
||||
return false;
|
||||
std::vector<std::pair<ResourceType, ResourceAmount>> res_limits;
|
||||
bool max_prefix_encountered = false;
|
||||
|
||||
auto parse_limit = [&]
|
||||
{
|
||||
max_prefix_encountered |= ParserKeyword{"MAX"}.ignore(pos, expected);
|
||||
|
||||
ResourceType res_resource_type;
|
||||
if (!parseResourceType(pos, expected, res_resource_type))
|
||||
ResourceType resource_type;
|
||||
if (!parseResourceType(pos, expected, resource_type))
|
||||
return false;
|
||||
|
||||
if (max_prefix_encountered)
|
||||
@ -149,25 +150,32 @@ namespace
|
||||
return false;
|
||||
}
|
||||
|
||||
ResourceAmount res_max;
|
||||
if (!parseMaxAmount(pos, expected, res_resource_type, res_max))
|
||||
ResourceAmount max;
|
||||
if (!parseMaxAmount(pos, expected, resource_type, max))
|
||||
return false;
|
||||
|
||||
resource_type = res_resource_type;
|
||||
max = res_max;
|
||||
res_limits.emplace_back(resource_type, max);
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_limit, false))
|
||||
return false;
|
||||
|
||||
limits = std::move(res_limits);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseIntervalWithLimits(IParserBase::Pos & pos, Expected & expected, ASTCreateQuotaQuery::Limits & limits)
|
||||
bool parseIntervalsWithLimits(IParserBase::Pos & pos, Expected & expected, std::vector<ASTCreateQuotaQuery::Limits> & all_limits)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
std::vector<ASTCreateQuotaQuery::Limits> res_all_limits;
|
||||
|
||||
auto parse_interval_with_limits = [&]
|
||||
{
|
||||
ASTCreateQuotaQuery::Limits new_limits;
|
||||
if (!ParserKeyword{"FOR"}.ignore(pos, expected))
|
||||
return false;
|
||||
|
||||
new_limits.randomize_interval = ParserKeyword{"RANDOMIZED"}.ignore(pos, expected);
|
||||
ASTCreateQuotaQuery::Limits limits;
|
||||
limits.randomize_interval = ParserKeyword{"RANDOMIZED"}.ignore(pos, expected);
|
||||
|
||||
ParserKeyword{"INTERVAL"}.ignore(pos, expected);
|
||||
|
||||
@ -181,53 +189,34 @@ namespace
|
||||
if (!parseIntervalKind(pos, expected, interval_kind))
|
||||
return false;
|
||||
|
||||
new_limits.duration = std::chrono::seconds(static_cast<UInt64>(num_intervals * interval_kind.toAvgSeconds()));
|
||||
limits.duration = std::chrono::seconds(static_cast<UInt64>(num_intervals * interval_kind.toAvgSeconds()));
|
||||
std::vector<std::pair<ResourceType, ResourceAmount>> maxs;
|
||||
|
||||
if (ParserKeyword{"NO LIMITS"}.ignore(pos, expected))
|
||||
{
|
||||
new_limits.drop = true;
|
||||
limits.drop = true;
|
||||
}
|
||||
else if (ParserKeyword{"TRACKING ONLY"}.ignore(pos, expected))
|
||||
{
|
||||
}
|
||||
else if (parseLimits(pos, expected, maxs))
|
||||
{
|
||||
for (const auto & [resource_type, max] : maxs)
|
||||
limits.max[resource_type] = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResourceType resource_type;
|
||||
ResourceAmount max;
|
||||
bool max_prefix_encountered = false;
|
||||
if (!parseLimit(pos, expected, true, max_prefix_encountered, resource_type, max))
|
||||
return false;
|
||||
return false;
|
||||
|
||||
new_limits.max[resource_type] = max;
|
||||
while (parseLimit(pos, expected, false, max_prefix_encountered, resource_type, max))
|
||||
new_limits.max[resource_type] = max;
|
||||
}
|
||||
|
||||
limits = new_limits;
|
||||
res_all_limits.emplace_back(std::move(limits));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
bool parseIntervalsWithLimits(IParserBase::Pos & pos, Expected & expected, std::vector<ASTCreateQuotaQuery::Limits> & all_limits)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
size_t old_size = all_limits.size();
|
||||
do
|
||||
{
|
||||
ASTCreateQuotaQuery::Limits limits;
|
||||
if (!parseIntervalWithLimits(pos, expected, limits))
|
||||
{
|
||||
all_limits.resize(old_size);
|
||||
return false;
|
||||
}
|
||||
all_limits.push_back(limits);
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
if (!ParserList::parseUtil(pos, expected, parse_interval_with_limits, false))
|
||||
return false;
|
||||
|
||||
all_limits = std::move(res_all_limits);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseToRoles(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::shared_ptr<ASTRolesOrUsersSet> & roles)
|
||||
{
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <Parsers/ASTSettingsProfileElement.h>
|
||||
#include <Parsers/ParserSettingsProfileElement.h>
|
||||
#include <Parsers/parseUserName.h>
|
||||
#include <boost/range/algorithm_ext/push_back.hpp>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -23,7 +24,7 @@ namespace
|
||||
});
|
||||
}
|
||||
|
||||
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::shared_ptr<ASTSettingsProfileElements> & settings)
|
||||
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::vector<std::shared_ptr<ASTSettingsProfileElement>> & settings)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
@ -36,10 +37,7 @@ namespace
|
||||
if (!elements_p.parse(pos, new_settings_ast, expected))
|
||||
return false;
|
||||
|
||||
if (!settings)
|
||||
settings = std::make_shared<ASTSettingsProfileElements>();
|
||||
const auto & new_settings = new_settings_ast->as<const ASTSettingsProfileElements &>();
|
||||
settings->elements.insert(settings->elements.end(), new_settings.elements.begin(), new_settings.elements.end());
|
||||
settings = std::move(new_settings_ast->as<const ASTSettingsProfileElements &>().elements);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@ -99,8 +97,14 @@ bool ParserCreateRoleQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
|
||||
if (alter && new_name.empty() && (names.size() == 1) && parseRenameTo(pos, expected, new_name))
|
||||
continue;
|
||||
|
||||
if (parseSettings(pos, expected, attach_mode, settings))
|
||||
std::vector<std::shared_ptr<ASTSettingsProfileElement>> new_settings;
|
||||
if (parseSettings(pos, expected, attach_mode, new_settings))
|
||||
{
|
||||
if (!settings)
|
||||
settings = std::make_shared<ASTSettingsProfileElements>();
|
||||
boost::range::push_back(settings->elements, std::move(new_settings));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cluster.empty() && parseOnCluster(pos, expected, cluster))
|
||||
continue;
|
||||
|
@ -75,6 +75,7 @@ namespace
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void addAllCommands(boost::container::flat_set<std::string_view> & commands)
|
||||
{
|
||||
for (auto condition_type : ext::range(MAX_CONDITION_TYPE))
|
||||
@ -84,44 +85,47 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
bool parseCommands(IParserBase::Pos & pos, Expected & expected, boost::container::flat_set<std::string_view> & commands)
|
||||
|
||||
bool parseCommands(IParserBase::Pos & pos, Expected & expected,
|
||||
boost::container::flat_set<std::string_view> & commands)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
boost::container::flat_set<std::string_view> res_commands;
|
||||
|
||||
auto parse_command = [&]
|
||||
{
|
||||
if (ParserKeyword{"ALL"}.ignore(pos, expected))
|
||||
{
|
||||
addAllCommands(commands);
|
||||
addAllCommands(res_commands);
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::container::flat_set<std::string_view> res_commands;
|
||||
do
|
||||
for (auto condition_type : ext::range(MAX_CONDITION_TYPE))
|
||||
{
|
||||
bool found_keyword = false;
|
||||
for (auto condition_type : ext::range(MAX_CONDITION_TYPE))
|
||||
const std::string_view & command = ConditionTypeInfo::get(condition_type).command;
|
||||
if (ParserKeyword{command.data()}.ignore(pos, expected))
|
||||
{
|
||||
const std::string_view & command = ConditionTypeInfo::get(condition_type).command;
|
||||
if (ParserKeyword{command.data()}.ignore(pos, expected))
|
||||
{
|
||||
res_commands.emplace(command);
|
||||
found_keyword = true;
|
||||
break;
|
||||
}
|
||||
res_commands.emplace(command);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!found_keyword)
|
||||
return false;
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
|
||||
commands = std::move(res_commands);
|
||||
return true;
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_command, false))
|
||||
return false;
|
||||
|
||||
commands = std::move(res_commands);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseForClause(IParserBase::Pos & pos, Expected & expected, bool alter, std::vector<std::pair<ConditionType, ASTPtr>> & conditions)
|
||||
|
||||
bool
|
||||
parseForClauses(IParserBase::Pos & pos, Expected & expected, bool alter, std::vector<std::pair<ConditionType, ASTPtr>> & conditions)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
std::vector<std::pair<ConditionType, ASTPtr>> res_conditions;
|
||||
|
||||
auto parse_for_clause = [&]
|
||||
{
|
||||
boost::container::flat_set<std::string_view> commands;
|
||||
|
||||
@ -158,32 +162,20 @@ namespace
|
||||
if (commands.count(type_info.command))
|
||||
{
|
||||
if (type_info.is_check && check)
|
||||
conditions.emplace_back(condition_type, *check);
|
||||
res_conditions.emplace_back(condition_type, *check);
|
||||
else if (filter)
|
||||
conditions.emplace_back(condition_type, *filter);
|
||||
res_conditions.emplace_back(condition_type, *filter);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
bool parseForClauses(
|
||||
IParserBase::Pos & pos, Expected & expected, bool alter, std::vector<std::pair<ConditionType, ASTPtr>> & conditions)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
std::vector<std::pair<ConditionType, ASTPtr>> res_conditions;
|
||||
do
|
||||
{
|
||||
if (!parseForClause(pos, expected, alter, res_conditions))
|
||||
return false;
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
if (!ParserList::parseUtil(pos, expected, parse_for_clause, false))
|
||||
return false;
|
||||
|
||||
conditions = std::move(res_conditions);
|
||||
return true;
|
||||
});
|
||||
conditions = std::move(res_conditions);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseToRoles(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::shared_ptr<ASTRolesOrUsersSet> & roles)
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <Parsers/ParserRolesOrUsersSet.h>
|
||||
#include <Parsers/ASTRolesOrUsersSet.h>
|
||||
#include <Parsers/parseIdentifierOrStringLiteral.h>
|
||||
#include <boost/range/algorithm_ext/push_back.hpp>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -25,7 +26,7 @@ namespace
|
||||
});
|
||||
}
|
||||
|
||||
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::shared_ptr<ASTSettingsProfileElements> & settings)
|
||||
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::vector<std::shared_ptr<ASTSettingsProfileElement>> & settings)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
@ -38,10 +39,7 @@ namespace
|
||||
if (!elements_p.parse(pos, new_settings_ast, expected))
|
||||
return false;
|
||||
|
||||
if (!settings)
|
||||
settings = std::make_shared<ASTSettingsProfileElements>();
|
||||
const auto & new_settings = new_settings_ast->as<const ASTSettingsProfileElements &>();
|
||||
settings->elements.insert(settings->elements.end(), new_settings.elements.begin(), new_settings.elements.end());
|
||||
settings = std::move(new_settings_ast->as<const ASTSettingsProfileElements &>().elements);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@ -51,7 +49,7 @@ namespace
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (roles || !ParserKeyword{"TO"}.ignore(pos, expected))
|
||||
if (!ParserKeyword{"TO"}.ignore(pos, expected))
|
||||
return false;
|
||||
|
||||
ParserRolesOrUsersSet roles_p;
|
||||
@ -119,8 +117,14 @@ bool ParserCreateSettingsProfileQuery::parseImpl(Pos & pos, ASTPtr & node, Expec
|
||||
if (alter && new_name.empty() && (names.size() == 1) && parseRenameTo(pos, expected, new_name))
|
||||
continue;
|
||||
|
||||
if (parseSettings(pos, expected, attach_mode, settings))
|
||||
std::vector<std::shared_ptr<ASTSettingsProfileElement>> new_settings;
|
||||
if (parseSettings(pos, expected, attach_mode, new_settings))
|
||||
{
|
||||
if (!settings)
|
||||
settings = std::make_shared<ASTSettingsProfileElements>();
|
||||
boost::range::push_back(settings->elements, std::move(new_settings));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cluster.empty() && parseOnCluster(pos, expected, cluster))
|
||||
continue;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <Parsers/ParserSettingsProfileElement.h>
|
||||
#include <ext/range.h>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/range/algorithm_ext/push_back.hpp>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -32,7 +33,7 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
bool parseAuthentication(IParserBase::Pos & pos, Expected & expected, std::optional<Authentication> & authentication)
|
||||
bool parseAuthentication(IParserBase::Pos & pos, Expected & expected, Authentication & authentication)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
@ -96,91 +97,109 @@ namespace
|
||||
|
||||
authentication = Authentication{*type};
|
||||
if (expect_password)
|
||||
authentication->setPassword(password);
|
||||
authentication.setPassword(password);
|
||||
else if (expect_hash)
|
||||
authentication->setPasswordHashHex(password);
|
||||
authentication.setPasswordHashHex(password);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
bool parseHosts(IParserBase::Pos & pos, Expected & expected, const char * prefix, std::optional<AllowedClientHosts> & hosts)
|
||||
bool parseHostsWithoutPrefix(IParserBase::Pos & pos, Expected & expected, AllowedClientHosts & hosts)
|
||||
{
|
||||
AllowedClientHosts res_hosts;
|
||||
|
||||
auto parse_host = [&]
|
||||
{
|
||||
if (ParserKeyword{"NONE"}.ignore(pos, expected))
|
||||
return true;
|
||||
|
||||
if (ParserKeyword{"ANY"}.ignore(pos, expected))
|
||||
{
|
||||
res_hosts.addAnyHost();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ParserKeyword{"LOCAL"}.ignore(pos, expected))
|
||||
{
|
||||
res_hosts.addLocalHost();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ParserKeyword{"REGEXP"}.ignore(pos, expected))
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!ParserList{std::make_unique<ParserStringLiteral>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ast, expected))
|
||||
return false;
|
||||
|
||||
for (const auto & name_regexp_ast : ast->children)
|
||||
res_hosts.addNameRegexp(name_regexp_ast->as<const ASTLiteral &>().value.safeGet<String>());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ParserKeyword{"NAME"}.ignore(pos, expected))
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!ParserList{std::make_unique<ParserStringLiteral>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ast, expected))
|
||||
return false;
|
||||
|
||||
for (const auto & name_ast : ast->children)
|
||||
res_hosts.addName(name_ast->as<const ASTLiteral &>().value.safeGet<String>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ParserKeyword{"IP"}.ignore(pos, expected))
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!ParserList{std::make_unique<ParserStringLiteral>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ast, expected))
|
||||
return false;
|
||||
|
||||
for (const auto & subnet_ast : ast->children)
|
||||
res_hosts.addSubnet(subnet_ast->as<const ASTLiteral &>().value.safeGet<String>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ParserKeyword{"LIKE"}.ignore(pos, expected))
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!ParserList{std::make_unique<ParserStringLiteral>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ast, expected))
|
||||
return false;
|
||||
|
||||
for (const auto & pattern_ast : ast->children)
|
||||
res_hosts.addLikePattern(pattern_ast->as<const ASTLiteral &>().value.safeGet<String>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_host, false))
|
||||
return false;
|
||||
|
||||
hosts = std::move(res_hosts);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool parseHosts(IParserBase::Pos & pos, Expected & expected, const String & prefix, AllowedClientHosts & hosts)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
if (prefix && !ParserKeyword{prefix}.ignore(pos, expected))
|
||||
if (!prefix.empty() && !ParserKeyword{prefix.c_str()}.ignore(pos, expected))
|
||||
return false;
|
||||
|
||||
if (!ParserKeyword{"HOST"}.ignore(pos, expected))
|
||||
return false;
|
||||
|
||||
if (ParserKeyword{"ANY"}.ignore(pos, expected))
|
||||
{
|
||||
if (!hosts)
|
||||
hosts.emplace();
|
||||
hosts->addAnyHost();
|
||||
return true;
|
||||
}
|
||||
AllowedClientHosts res_hosts;
|
||||
if (!parseHostsWithoutPrefix(pos, expected, res_hosts))
|
||||
return false;
|
||||
|
||||
if (ParserKeyword{"NONE"}.ignore(pos, expected))
|
||||
{
|
||||
if (!hosts)
|
||||
hosts.emplace();
|
||||
return true;
|
||||
}
|
||||
|
||||
AllowedClientHosts new_hosts;
|
||||
do
|
||||
{
|
||||
if (ParserKeyword{"LOCAL"}.ignore(pos, expected))
|
||||
{
|
||||
new_hosts.addLocalHost();
|
||||
}
|
||||
else if (ParserKeyword{"REGEXP"}.ignore(pos, expected))
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!ParserList{std::make_unique<ParserStringLiteral>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ast, expected))
|
||||
return false;
|
||||
|
||||
for (const auto & name_regexp_ast : ast->children)
|
||||
new_hosts.addNameRegexp(name_regexp_ast->as<const ASTLiteral &>().value.safeGet<String>());
|
||||
}
|
||||
else if (ParserKeyword{"NAME"}.ignore(pos, expected))
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!ParserList{std::make_unique<ParserStringLiteral>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ast, expected))
|
||||
return false;
|
||||
|
||||
for (const auto & name_ast : ast->children)
|
||||
new_hosts.addName(name_ast->as<const ASTLiteral &>().value.safeGet<String>());
|
||||
}
|
||||
else if (ParserKeyword{"IP"}.ignore(pos, expected))
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!ParserList{std::make_unique<ParserStringLiteral>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ast, expected))
|
||||
return false;
|
||||
|
||||
for (const auto & subnet_ast : ast->children)
|
||||
new_hosts.addSubnet(subnet_ast->as<const ASTLiteral &>().value.safeGet<String>());
|
||||
}
|
||||
else if (ParserKeyword{"LIKE"}.ignore(pos, expected))
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!ParserList{std::make_unique<ParserStringLiteral>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ast, expected))
|
||||
return false;
|
||||
|
||||
for (const auto & pattern_ast : ast->children)
|
||||
new_hosts.addLikePattern(pattern_ast->as<const ASTLiteral &>().value.safeGet<String>());
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
|
||||
if (!hosts)
|
||||
hosts.emplace();
|
||||
hosts->add(new_hosts);
|
||||
hosts.add(std::move(res_hosts));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@ -206,7 +225,7 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::shared_ptr<ASTSettingsProfileElements> & settings)
|
||||
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::vector<std::shared_ptr<ASTSettingsProfileElement>> & settings)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
@ -215,14 +234,11 @@ namespace
|
||||
|
||||
ASTPtr new_settings_ast;
|
||||
ParserSettingsProfileElements elements_p;
|
||||
elements_p.useInheritKeyword(true).useIDMode(id_mode);
|
||||
elements_p.useIDMode(id_mode);
|
||||
if (!elements_p.parse(pos, new_settings_ast, expected))
|
||||
return false;
|
||||
|
||||
if (!settings)
|
||||
settings = std::make_shared<ASTSettingsProfileElements>();
|
||||
const auto & new_settings = new_settings_ast->as<const ASTSettingsProfileElements &>();
|
||||
settings->elements.insert(settings->elements.end(), new_settings.elements.begin(), new_settings.elements.end());
|
||||
settings = std::move(new_settings_ast->as<const ASTSettingsProfileElements &>().elements);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@ -286,14 +302,33 @@ bool ParserCreateUserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!authentication && parseAuthentication(pos, expected, authentication))
|
||||
continue;
|
||||
if (!authentication)
|
||||
{
|
||||
Authentication new_authentication;
|
||||
if (parseAuthentication(pos, expected, new_authentication))
|
||||
{
|
||||
authentication = std::move(new_authentication);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (parseHosts(pos, expected, nullptr, hosts))
|
||||
AllowedClientHosts new_hosts;
|
||||
if (parseHosts(pos, expected, "", new_hosts))
|
||||
{
|
||||
if (!hosts)
|
||||
hosts.emplace();
|
||||
hosts->add(new_hosts);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parseSettings(pos, expected, attach_mode, settings))
|
||||
std::vector<std::shared_ptr<ASTSettingsProfileElement>> new_settings;
|
||||
if (parseSettings(pos, expected, attach_mode, new_settings))
|
||||
{
|
||||
if (!settings)
|
||||
settings = std::make_shared<ASTSettingsProfileElements>();
|
||||
boost::range::push_back(settings->elements, std::move(new_settings));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!default_roles && parseDefaultRoles(pos, expected, attach_mode, default_roles))
|
||||
continue;
|
||||
@ -306,8 +341,21 @@ bool ParserCreateUserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
|
||||
if (new_name.empty() && (names->size() == 1) && parseRenameTo(pos, expected, new_name))
|
||||
continue;
|
||||
|
||||
if (parseHosts(pos, expected, "ADD", add_hosts) || parseHosts(pos, expected, "DROP", remove_hosts))
|
||||
if (parseHosts(pos, expected, "ADD", new_hosts))
|
||||
{
|
||||
if (!add_hosts)
|
||||
add_hosts.emplace();
|
||||
add_hosts->add(new_hosts);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parseHosts(pos, expected, "DROP", new_hosts))
|
||||
{
|
||||
if (!remove_hosts)
|
||||
remove_hosts.emplace();
|
||||
remove_hosts->add(new_hosts);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2,8 +2,11 @@
|
||||
#include <Parsers/ASTGrantQuery.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/ASTRolesOrUsersSet.h>
|
||||
#include <Parsers/ASTLiteral.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/CommonParsers.h>
|
||||
#include <Parsers/ExpressionElementParsers.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <Parsers/ParserRolesOrUsersSet.h>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
@ -66,15 +69,13 @@ namespace
|
||||
if (!ParserToken{TokenType::OpeningRoundBracket}.ignore(pos, expected))
|
||||
return false;
|
||||
|
||||
ASTPtr ast;
|
||||
if (!ParserList{std::make_unique<ParserIdentifier>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ast, expected))
|
||||
return false;
|
||||
|
||||
Strings res_columns;
|
||||
do
|
||||
{
|
||||
ASTPtr column_ast;
|
||||
if (!ParserIdentifier().parse(pos, column_ast, expected))
|
||||
return false;
|
||||
res_columns.emplace_back(getIdentifierName(column_ast));
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
for (const auto & child : ast->children)
|
||||
res_columns.emplace_back(getIdentifierName(child));
|
||||
|
||||
if (!ParserToken{TokenType::ClosingRoundBracket}.ignore(pos, expected))
|
||||
return false;
|
||||
@ -150,25 +151,42 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
bool parseAccessTypesWithColumns(IParser::Pos & pos, Expected & expected,
|
||||
std::vector<std::pair<AccessFlags, Strings>> & access_and_columns)
|
||||
{
|
||||
std::vector<std::pair<AccessFlags, Strings>> res;
|
||||
|
||||
auto parse_access_and_columns = [&]
|
||||
{
|
||||
AccessFlags access_flags;
|
||||
if (!parseAccessFlags(pos, expected, access_flags))
|
||||
return false;
|
||||
|
||||
Strings columns;
|
||||
parseColumnNames(pos, expected, columns);
|
||||
res.emplace_back(access_flags, std::move(columns));
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_access_and_columns, false))
|
||||
return false;
|
||||
|
||||
access_and_columns = std::move(res);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool parseAccessRightsElements(IParser::Pos & pos, Expected & expected, AccessRightsElements & elements)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
AccessRightsElements res_elements;
|
||||
do
|
||||
|
||||
auto parse_around_on = [&]
|
||||
{
|
||||
std::vector<std::pair<AccessFlags, Strings>> access_and_columns;
|
||||
do
|
||||
{
|
||||
AccessFlags access_flags;
|
||||
if (!parseAccessFlags(pos, expected, access_flags))
|
||||
return false;
|
||||
|
||||
Strings columns;
|
||||
parseColumnNames(pos, expected, columns);
|
||||
access_and_columns.emplace_back(access_flags, std::move(columns));
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
if (!parseAccessTypesWithColumns(pos, expected, access_and_columns))
|
||||
return false;
|
||||
|
||||
if (!ParserKeyword{"ON"}.ignore(pos, expected))
|
||||
return false;
|
||||
@ -190,8 +208,12 @@ namespace
|
||||
element.table = table_name;
|
||||
res_elements.emplace_back(std::move(element));
|
||||
}
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_around_on, false))
|
||||
return false;
|
||||
|
||||
elements = std::move(res_elements);
|
||||
return true;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <Parsers/ASTLiteral.h>
|
||||
#include <Parsers/ASTRolesOrUsersSet.h>
|
||||
#include <Parsers/parseUserName.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <boost/range/algorithm/find.hpp>
|
||||
|
||||
|
||||
@ -11,11 +12,15 @@ namespace DB
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool parseRoleNameOrID(IParserBase::Pos & pos, Expected & expected, bool parse_id, String & res)
|
||||
bool parseRoleNameOrID(
|
||||
IParserBase::Pos & pos,
|
||||
Expected & expected,
|
||||
bool id_mode,
|
||||
String & res)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
if (!parse_id)
|
||||
if (!id_mode)
|
||||
return parseRoleName(pos, expected, res);
|
||||
|
||||
if (!ParserKeyword{"ID"}.ignore(pos, expected))
|
||||
@ -40,60 +45,56 @@ namespace
|
||||
Expected & expected,
|
||||
bool id_mode,
|
||||
bool allow_all,
|
||||
bool allow_current_user_tag,
|
||||
bool allow_current_user,
|
||||
Strings & names,
|
||||
bool & all,
|
||||
bool & current_user)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
bool res_all = false;
|
||||
bool res_current_user = false;
|
||||
Strings res_names;
|
||||
while (true)
|
||||
{
|
||||
if (ParserKeyword{"NONE"}.ignore(pos, expected))
|
||||
{
|
||||
}
|
||||
else if (
|
||||
allow_current_user_tag
|
||||
&& (ParserKeyword{"CURRENT_USER"}.ignore(pos, expected) || ParserKeyword{"currentUser"}.ignore(pos, expected)))
|
||||
{
|
||||
if (ParserToken{TokenType::OpeningRoundBracket}.ignore(pos, expected))
|
||||
{
|
||||
if (!ParserToken{TokenType::ClosingRoundBracket}.ignore(pos, expected))
|
||||
return false;
|
||||
}
|
||||
res_current_user = true;
|
||||
}
|
||||
else if (allow_all && ParserKeyword{"ALL"}.ignore(pos, expected))
|
||||
{
|
||||
res_all = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
String name;
|
||||
if (!parseRoleNameOrID(pos, expected, id_mode, name))
|
||||
return false;
|
||||
res_names.push_back(name);
|
||||
}
|
||||
bool res_all = false;
|
||||
bool res_current_user = false;
|
||||
Strings res_names;
|
||||
|
||||
if (!ParserToken{TokenType::Comma}.ignore(pos, expected))
|
||||
break;
|
||||
auto parse_element = [&]
|
||||
{
|
||||
if (ParserKeyword{"NONE"}.ignore(pos, expected))
|
||||
return true;
|
||||
|
||||
if (allow_all && ParserKeyword{"ALL"}.ignore(pos, expected))
|
||||
{
|
||||
res_all = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
all = res_all;
|
||||
current_user = res_current_user;
|
||||
names = std::move(res_names);
|
||||
return true;
|
||||
});
|
||||
if (allow_current_user && parseCurrentUserTag(pos, expected))
|
||||
{
|
||||
res_current_user = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
String name;
|
||||
if (parseRoleNameOrID(pos, expected, id_mode, name))
|
||||
{
|
||||
res_names.emplace_back(std::move(name));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_element, false))
|
||||
return false;
|
||||
|
||||
names = std::move(res_names);
|
||||
all = res_all;
|
||||
current_user = res_current_user;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseExceptAndAfterExcept(
|
||||
IParserBase::Pos & pos,
|
||||
Expected & expected,
|
||||
bool id_mode,
|
||||
bool allow_current_user_tag,
|
||||
bool allow_current_user,
|
||||
Strings & except_names,
|
||||
bool & except_current_user)
|
||||
{
|
||||
@ -102,8 +103,8 @@ namespace
|
||||
if (!ParserKeyword{"EXCEPT"}.ignore(pos, expected))
|
||||
return false;
|
||||
|
||||
bool dummy;
|
||||
return parseBeforeExcept(pos, expected, id_mode, false, allow_current_user_tag, except_names, dummy, except_current_user);
|
||||
bool unused;
|
||||
return parseBeforeExcept(pos, expected, id_mode, false, allow_current_user, except_names, unused, except_current_user);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <Parsers/parseDatabaseAndTableName.h>
|
||||
#include <Parsers/ASTQueryWithOnCluster.h>
|
||||
#include <Parsers/CommonParsers.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <boost/range/algorithm_ext/push_back.hpp>
|
||||
|
||||
|
||||
@ -67,21 +68,18 @@ namespace
|
||||
return false;
|
||||
|
||||
std::vector<std::pair<String, String>> res;
|
||||
std::optional<IParser::Pos> pos_before_comma;
|
||||
do
|
||||
|
||||
auto parse_db_and_table_name = [&]
|
||||
{
|
||||
String database, table_name;
|
||||
if (!parseDBAndTableName(pos, expected, database, table_name))
|
||||
{
|
||||
if (!pos_before_comma)
|
||||
return false;
|
||||
pos = *pos_before_comma;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
res.emplace_back(std::move(database), std::move(table_name));
|
||||
pos_before_comma = pos;
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_db_and_table_name, false))
|
||||
return false;
|
||||
|
||||
database_and_table_names = std::move(res);
|
||||
return true;
|
||||
@ -165,21 +163,28 @@ bool ParserRowPolicyName::parseImpl(Pos & pos, ASTPtr & node, Expected & expecte
|
||||
bool ParserRowPolicyNames::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
std::vector<RowPolicy::NameParts> name_parts;
|
||||
size_t num_added_names_last_time = 0;
|
||||
String cluster;
|
||||
|
||||
do
|
||||
auto parse_around_on = [&]
|
||||
{
|
||||
std::vector<RowPolicy::NameParts> new_name_parts;
|
||||
if (!parseRowPolicyNamesAroundON(pos, expected, name_parts.empty(), name_parts.empty(), allow_on_cluster, new_name_parts, cluster))
|
||||
return false;
|
||||
if (!name_parts.empty())
|
||||
{
|
||||
if ((num_added_names_last_time != 1) || !cluster.empty())
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t num_new_name_parts = new_name_parts.size();
|
||||
assert(num_new_name_parts >= 1);
|
||||
boost::range::push_back(name_parts, std::move(new_name_parts));
|
||||
if ((num_new_name_parts != 1) || !cluster.empty())
|
||||
break;
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
std::vector<RowPolicy::NameParts> new_name_parts;
|
||||
if (!parseRowPolicyNamesAroundON(pos, expected, name_parts.empty(), name_parts.empty(), allow_on_cluster, new_name_parts, cluster))
|
||||
return false;
|
||||
|
||||
num_added_names_last_time = new_name_parts.size();
|
||||
boost::range::push_back(name_parts, std::move(new_name_parts));
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_around_on, false))
|
||||
return false;
|
||||
|
||||
auto result = std::make_shared<ASTRowPolicyNames>();
|
||||
result->name_parts = std::move(name_parts);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <Parsers/ParserSettingsProfileElement.h>
|
||||
#include <Parsers/CommonParsers.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <Parsers/ExpressionElementParsers.h>
|
||||
#include <Parsers/ASTSettingsProfileElement.h>
|
||||
#include <Parsers/ASTLiteral.h>
|
||||
@ -11,12 +12,19 @@ namespace DB
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool parseProfileNameOrID(IParserBase::Pos & pos, Expected & expected, bool parse_id, String & res)
|
||||
bool parseProfileKeyword(IParserBase::Pos & pos, Expected & expected, bool use_inherit_keyword)
|
||||
{
|
||||
return ParserKeyword{"PROFILE"}.ignore(pos, expected) ||
|
||||
(use_inherit_keyword && ParserKeyword{"INHERIT"}.ignore(pos, expected));
|
||||
}
|
||||
|
||||
|
||||
bool parseProfileNameOrID(IParserBase::Pos & pos, Expected & expected, bool id_mode, String & res)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!parse_id)
|
||||
if (!id_mode)
|
||||
return parseIdentifierOrStringLiteral(pos, expected, res);
|
||||
|
||||
if (!ParserKeyword{"ID"}.ignore(pos, expected))
|
||||
@ -96,52 +104,98 @@ namespace
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
bool parseSettingNameWithValueOrConstraints(
|
||||
IParserBase::Pos & pos,
|
||||
Expected & expected,
|
||||
String & setting_name,
|
||||
Field & value,
|
||||
Field & min_value,
|
||||
Field & max_value,
|
||||
std::optional<bool> & readonly)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
ASTPtr name_ast;
|
||||
if (!ParserIdentifier{}.parse(pos, name_ast, expected))
|
||||
return false;
|
||||
|
||||
String res_setting_name = getIdentifierName(name_ast);
|
||||
Field res_value;
|
||||
Field res_min_value;
|
||||
Field res_max_value;
|
||||
std::optional<bool> res_readonly;
|
||||
|
||||
bool has_value_or_constraint = false;
|
||||
while (parseValue(pos, expected, res_value) || parseMinMaxValue(pos, expected, res_min_value, res_max_value)
|
||||
|| parseReadonlyOrWritableKeyword(pos, expected, res_readonly))
|
||||
{
|
||||
has_value_or_constraint = true;
|
||||
}
|
||||
|
||||
if (!has_value_or_constraint)
|
||||
return false;
|
||||
|
||||
setting_name = std::move(res_setting_name);
|
||||
value = std::move(res_value);
|
||||
min_value = std::move(res_min_value);
|
||||
max_value = std::move(res_max_value);
|
||||
readonly = res_readonly;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
bool parseSettingsProfileElement(IParserBase::Pos & pos,
|
||||
Expected & expected,
|
||||
bool id_mode,
|
||||
bool use_inherit_keyword,
|
||||
bool previous_element_was_parent_profile,
|
||||
std::shared_ptr<ASTSettingsProfileElement> & result)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
String parent_profile;
|
||||
String setting_name;
|
||||
Field value;
|
||||
Field min_value;
|
||||
Field max_value;
|
||||
std::optional<bool> readonly;
|
||||
|
||||
if (parseSettingNameWithValueOrConstraints(pos, expected, setting_name, value, min_value, max_value, readonly))
|
||||
{
|
||||
}
|
||||
else if (parseProfileKeyword(pos, expected, use_inherit_keyword) || previous_element_was_parent_profile)
|
||||
{
|
||||
if (!parseProfileNameOrID(pos, expected, id_mode, parent_profile))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
result = std::make_shared<ASTSettingsProfileElement>();
|
||||
result->parent_profile = std::move(parent_profile);
|
||||
result->setting_name = std::move(setting_name);
|
||||
result->value = std::move(value);
|
||||
result->min_value = std::move(min_value);
|
||||
result->max_value = std::move(max_value);
|
||||
result->readonly = readonly;
|
||||
result->id_mode = id_mode;
|
||||
result->use_inherit_keyword = use_inherit_keyword;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ParserSettingsProfileElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
String parent_profile;
|
||||
String setting_name;
|
||||
Field value;
|
||||
Field min_value;
|
||||
Field max_value;
|
||||
std::optional<bool> readonly;
|
||||
std::shared_ptr<ASTSettingsProfileElement> res;
|
||||
if (!parseSettingsProfileElement(pos, expected, id_mode, use_inherit_keyword, false, res))
|
||||
return false;
|
||||
|
||||
if (ParserKeyword{"PROFILE"}.ignore(pos, expected) ||
|
||||
(use_inherit_keyword && ParserKeyword{"INHERIT"}.ignore(pos, expected)))
|
||||
{
|
||||
if (!parseProfileNameOrID(pos, expected, id_mode, parent_profile))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASTPtr name_ast;
|
||||
if (!ParserIdentifier{}.parse(pos, name_ast, expected))
|
||||
return false;
|
||||
setting_name = getIdentifierName(name_ast);
|
||||
|
||||
bool has_value_or_constraint = false;
|
||||
while (parseValue(pos, expected, value) || parseMinMaxValue(pos, expected, min_value, max_value)
|
||||
|| parseReadonlyOrWritableKeyword(pos, expected, readonly))
|
||||
{
|
||||
has_value_or_constraint = true;
|
||||
}
|
||||
|
||||
if (!has_value_or_constraint)
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result = std::make_shared<ASTSettingsProfileElement>();
|
||||
result->parent_profile = std::move(parent_profile);
|
||||
result->setting_name = std::move(setting_name);
|
||||
result->value = std::move(value);
|
||||
result->min_value = std::move(min_value);
|
||||
result->max_value = std::move(max_value);
|
||||
result->readonly = readonly;
|
||||
result->id_mode = id_mode;
|
||||
result->use_inherit_keyword = use_inherit_keyword;
|
||||
node = result;
|
||||
node = res;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -155,17 +209,21 @@ bool ParserSettingsProfileElements::parseImpl(Pos & pos, ASTPtr & node, Expected
|
||||
}
|
||||
else
|
||||
{
|
||||
ParserSettingsProfileElement element_p;
|
||||
element_p.useIDMode(id_mode).useInheritKeyword(use_inherit_keyword);
|
||||
do
|
||||
bool previous_element_was_parent_profile = false;
|
||||
|
||||
auto parse_element = [&]
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!element_p.parse(pos, ast, expected))
|
||||
std::shared_ptr<ASTSettingsProfileElement> element;
|
||||
if (!parseSettingsProfileElement(pos, expected, id_mode, use_inherit_keyword, previous_element_was_parent_profile, element))
|
||||
return false;
|
||||
auto element = typeid_cast<std::shared_ptr<ASTSettingsProfileElement>>(ast);
|
||||
elements.push_back(std::move(element));
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
|
||||
elements.push_back(element);
|
||||
previous_element_was_parent_profile = !element->parent_profile.empty();
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_element, false))
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result = std::make_shared<ASTSettingsProfileElements>();
|
||||
|
@ -1,35 +1,52 @@
|
||||
#include <Parsers/ParserUserNameWithHost.h>
|
||||
#include <Parsers/ASTUserNameWithHost.h>
|
||||
#include <Parsers/CommonParsers.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <Parsers/parseIdentifierOrStringLiteral.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool parseUserNameWithHost(IParserBase::Pos & pos, Expected & expected, std::shared_ptr<ASTUserNameWithHost> & ast)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
String base_name;
|
||||
if (!parseIdentifierOrStringLiteral(pos, expected, base_name))
|
||||
return false;
|
||||
|
||||
boost::algorithm::trim(base_name);
|
||||
|
||||
String host_pattern;
|
||||
if (ParserToken{TokenType::At}.ignore(pos, expected))
|
||||
{
|
||||
if (!parseIdentifierOrStringLiteral(pos, expected, host_pattern))
|
||||
return false;
|
||||
|
||||
boost::algorithm::trim(host_pattern);
|
||||
if (host_pattern == "%")
|
||||
host_pattern.clear();
|
||||
}
|
||||
|
||||
ast = std::make_shared<ASTUserNameWithHost>();
|
||||
ast->base_name = std::move(base_name);
|
||||
ast->host_pattern = std::move(host_pattern);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ParserUserNameWithHost::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
String base_name;
|
||||
if (!parseIdentifierOrStringLiteral(pos, expected, base_name))
|
||||
std::shared_ptr<ASTUserNameWithHost> res;
|
||||
if (!parseUserNameWithHost(pos, expected, res))
|
||||
return false;
|
||||
|
||||
boost::algorithm::trim(base_name);
|
||||
|
||||
String host_pattern;
|
||||
if (ParserToken{TokenType::At}.ignore(pos, expected))
|
||||
{
|
||||
if (!parseIdentifierOrStringLiteral(pos, expected, host_pattern))
|
||||
return false;
|
||||
|
||||
boost::algorithm::trim(host_pattern);
|
||||
if (host_pattern == "%")
|
||||
host_pattern.clear();
|
||||
}
|
||||
|
||||
auto result = std::make_shared<ASTUserNameWithHost>();
|
||||
result->base_name = std::move(base_name);
|
||||
result->host_pattern = std::move(host_pattern);
|
||||
node = result;
|
||||
node = res;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -37,15 +54,19 @@ bool ParserUserNameWithHost::parseImpl(Pos & pos, ASTPtr & node, Expected & expe
|
||||
bool ParserUserNamesWithHost::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
std::vector<std::shared_ptr<ASTUserNameWithHost>> names;
|
||||
do
|
||||
|
||||
auto parse_single_name = [&]
|
||||
{
|
||||
ASTPtr ast;
|
||||
if (!ParserUserNameWithHost{}.parse(pos, ast, expected))
|
||||
std::shared_ptr<ASTUserNameWithHost> ast;
|
||||
if (!parseUserNameWithHost(pos, expected, ast))
|
||||
return false;
|
||||
|
||||
names.emplace_back(typeid_cast<std::shared_ptr<ASTUserNameWithHost>>(ast));
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
names.emplace_back(std::move(ast));
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_single_name, false))
|
||||
return false;
|
||||
|
||||
auto result = std::make_shared<ASTUserNamesWithHost>();
|
||||
result->names = std::move(names);
|
||||
|
@ -4,47 +4,52 @@
|
||||
#include "ASTLiteral.h"
|
||||
#include "ASTIdentifier.h"
|
||||
#include <Parsers/CommonParsers.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <Common/typeid_cast.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
bool parseIdentifierOrStringLiteral(IParser::Pos & pos, Expected & expected, String & result)
|
||||
{
|
||||
ASTPtr res;
|
||||
|
||||
if (!ParserIdentifier().parse(pos, res, expected))
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
{
|
||||
if (!ParserStringLiteral().parse(pos, res, expected))
|
||||
return false;
|
||||
ASTPtr ast;
|
||||
if (ParserIdentifier().parse(pos, ast, expected))
|
||||
{
|
||||
result = getIdentifierName(ast);
|
||||
return true;
|
||||
}
|
||||
|
||||
result = res->as<ASTLiteral &>().value.safeGet<String>();
|
||||
}
|
||||
else
|
||||
result = getIdentifierName(res);
|
||||
if (ParserStringLiteral().parse(pos, ast, expected))
|
||||
{
|
||||
result = ast->as<ASTLiteral &>().value.safeGet<String>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
bool parseIdentifiersOrStringLiterals(IParser::Pos & pos, Expected & expected, Strings & result)
|
||||
{
|
||||
return IParserBase::wrapParseImpl(pos, [&]
|
||||
Strings res;
|
||||
|
||||
auto parse_single_id_or_literal = [&]
|
||||
{
|
||||
Strings strs;
|
||||
do
|
||||
{
|
||||
String str;
|
||||
if (!parseIdentifierOrStringLiteral(pos, expected, str))
|
||||
return false;
|
||||
String str;
|
||||
if (!parseIdentifierOrStringLiteral(pos, expected, str))
|
||||
return false;
|
||||
|
||||
strs.push_back(std::move(str));
|
||||
}
|
||||
while (ParserToken{TokenType::Comma}.ignore(pos, expected));
|
||||
|
||||
result = std::move(strs);
|
||||
res.emplace_back(std::move(str));
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
if (!ParserList::parseUtil(pos, expected, parse_single_id_or_literal, false))
|
||||
return false;
|
||||
|
||||
result = std::move(res);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user