diff options
| author | vitalyisaev <[email protected]> | 2023-11-14 09:58:56 +0300 |
|---|---|---|
| committer | vitalyisaev <[email protected]> | 2023-11-14 10:20:20 +0300 |
| commit | c2b2dfd9827a400a8495e172a56343462e3ceb82 (patch) | |
| tree | cd4e4f597d01bede4c82dffeb2d780d0a9046bd0 /contrib/clickhouse/src/Parsers/Access/ParserCreateRowPolicyQuery.cpp | |
| parent | d4ae8f119e67808cb0cf776ba6e0cf95296f2df7 (diff) | |
YQ Connector: move tests from yql to ydb (OSS)
Перенос папки с тестами на Коннектор из папки yql в папку ydb (синхронизируется с github).
Diffstat (limited to 'contrib/clickhouse/src/Parsers/Access/ParserCreateRowPolicyQuery.cpp')
| -rw-r--r-- | contrib/clickhouse/src/Parsers/Access/ParserCreateRowPolicyQuery.cpp | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/contrib/clickhouse/src/Parsers/Access/ParserCreateRowPolicyQuery.cpp b/contrib/clickhouse/src/Parsers/Access/ParserCreateRowPolicyQuery.cpp new file mode 100644 index 00000000000..f9e9466e35d --- /dev/null +++ b/contrib/clickhouse/src/Parsers/Access/ParserCreateRowPolicyQuery.cpp @@ -0,0 +1,306 @@ +#include <Access/IAccessStorage.h> +#include <Parsers/Access/ParserCreateRowPolicyQuery.h> +#include <Parsers/Access/ASTCreateRowPolicyQuery.h> +#include <Parsers/Access/ASTRolesOrUsersSet.h> +#include <Parsers/Access/ASTRowPolicyName.h> +#include <Parsers/Access/ParserRolesOrUsersSet.h> +#include <Parsers/Access/ParserRowPolicyName.h> +#include <Parsers/ExpressionListParsers.h> +#include <Parsers/ExpressionElementParsers.h> +#include <Parsers/parseDatabaseAndTableName.h> +#include <Parsers/parseIdentifierOrStringLiteral.h> +#include <Access/Common/RowPolicyDefs.h> +#include <base/range.h> +#include <boost/container/flat_set.hpp> +#include <base/insertAtEnd.h> + + +namespace DB +{ +namespace +{ + bool parseRenameTo(IParserBase::Pos & pos, Expected & expected, String & new_short_name) + { + return IParserBase::wrapParseImpl(pos, [&] + { + if (!ParserKeyword{"RENAME TO"}.ignore(pos, expected)) + return false; + + return parseIdentifierOrStringLiteral(pos, expected, new_short_name); + }); + } + + bool parseAsRestrictiveOrPermissive(IParserBase::Pos & pos, Expected & expected, bool & is_restrictive) + { + return IParserBase::wrapParseImpl(pos, [&] + { + if (!ParserKeyword{"AS"}.ignore(pos, expected)) + return false; + + if (ParserKeyword{"RESTRICTIVE"}.ignore(pos, expected)) + { + is_restrictive = true; + return true; + } + + if (!ParserKeyword{"PERMISSIVE"}.ignore(pos, expected)) + return false; + + is_restrictive = false; + return true; + }); + } + + bool parseFilterExpression(IParserBase::Pos & pos, Expected & expected, ASTPtr & expr) + { + return IParserBase::wrapParseImpl(pos, [&] + { + if (ParserKeyword("NONE").ignore(pos, expected)) + { + expr = nullptr; + return true; + } + + ParserExpression parser; + ASTPtr x; + if (!parser.parse(pos, x, expected)) + return false; + + expr = x; + return true; + }); + } + + + void addAllCommands(boost::container::flat_set<std::string_view> & commands) + { + for (auto filter_type : collections::range(RowPolicyFilterType::MAX)) + { + std::string_view command = RowPolicyFilterTypeInfo::get(filter_type).command; + commands.emplace(command); + } + } + + + bool parseCommands(IParserBase::Pos & pos, Expected & expected, + boost::container::flat_set<std::string_view> & commands) + { + boost::container::flat_set<std::string_view> res_commands; + + auto parse_command = [&] + { + if (ParserKeyword{"ALL"}.ignore(pos, expected)) + { + addAllCommands(res_commands); + return true; + } + + for (auto filter_type : collections::range(RowPolicyFilterType::MAX)) + { + std::string_view command = RowPolicyFilterTypeInfo::get(filter_type).command; + if (ParserKeyword{command.data()}.ignore(pos, expected)) + { + res_commands.emplace(command); + return true; + } + } + + return false; + }; + + if (!ParserList::parseUtil(pos, expected, parse_command, false)) + return false; + + commands = std::move(res_commands); + return true; + } + + + bool parseForClauses( + IParserBase::Pos & pos, Expected & expected, bool alter, std::vector<std::pair<RowPolicyFilterType, ASTPtr>> & filters) + { + std::vector<std::pair<RowPolicyFilterType, ASTPtr>> res_filters; + + auto parse_for_clause = [&] + { + boost::container::flat_set<std::string_view> commands; + + if (ParserKeyword{"FOR"}.ignore(pos, expected)) + { + if (!parseCommands(pos, expected, commands)) + return false; + } + else + addAllCommands(commands); + + std::optional<ASTPtr> filter; + std::optional<ASTPtr> check; + if (ParserKeyword{"USING"}.ignore(pos, expected)) + { + if (!parseFilterExpression(pos, expected, filter.emplace())) + return false; + } + if (ParserKeyword{"WITH CHECK"}.ignore(pos, expected)) + { + if (!parseFilterExpression(pos, expected, check.emplace())) + return false; + } + + if (!filter && !check) + return false; + + if (!check && !alter) + check = filter; + + for (auto filter_type : collections::range(RowPolicyFilterType::MAX)) + { + const auto & type_info = RowPolicyFilterTypeInfo::get(filter_type); + if (commands.count(type_info.command)) + { + if (type_info.is_check && check) + res_filters.emplace_back(filter_type, *check); + else if (filter) + res_filters.emplace_back(filter_type, *filter); + } + } + + return true; + }; + + if (!ParserList::parseUtil(pos, expected, parse_for_clause, false)) + return false; + + filters = std::move(res_filters); + return true; + } + + bool parseToRoles(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::shared_ptr<ASTRolesOrUsersSet> & roles) + { + return IParserBase::wrapParseImpl(pos, [&] + { + ASTPtr ast; + if (!ParserKeyword{"TO"}.ignore(pos, expected)) + return false; + + ParserRolesOrUsersSet roles_p; + roles_p.allowAll().allowRoles().allowUsers().allowCurrentUser().useIDMode(id_mode); + if (!roles_p.parse(pos, ast, expected)) + return false; + + roles = std::static_pointer_cast<ASTRolesOrUsersSet>(ast); + return true; + }); + } + + bool parseOnCluster(IParserBase::Pos & pos, Expected & expected, String & cluster) + { + return IParserBase::wrapParseImpl(pos, [&] + { + return ParserKeyword{"ON"}.ignore(pos, expected) && ASTQueryWithOnCluster::parse(pos, cluster, expected); + }); + } +} + + +bool ParserCreateRowPolicyQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) +{ + bool alter = false; + if (attach_mode) + { + if (!ParserKeyword{"ATTACH POLICY"}.ignore(pos, expected) && !ParserKeyword{"ATTACH ROW POLICY"}.ignore(pos, expected)) + return false; + } + else + { + if (ParserKeyword{"ALTER POLICY"}.ignore(pos, expected) || ParserKeyword{"ALTER ROW POLICY"}.ignore(pos, expected)) + alter = true; + else if (!ParserKeyword{"CREATE POLICY"}.ignore(pos, expected) && !ParserKeyword{"CREATE ROW POLICY"}.ignore(pos, expected)) + return false; + } + + bool if_exists = false; + bool if_not_exists = false; + bool or_replace = false; + if (alter) + { + if (ParserKeyword{"IF EXISTS"}.ignore(pos, expected)) + if_exists = true; + } + else + { + if (ParserKeyword{"IF NOT EXISTS"}.ignore(pos, expected)) + if_not_exists = true; + else if (ParserKeyword{"OR REPLACE"}.ignore(pos, expected)) + or_replace = true; + } + + ParserRowPolicyNames names_parser; + names_parser.allowOnCluster(); + ASTPtr names_ast; + if (!names_parser.parse(pos, names_ast, expected)) + return false; + + auto names = typeid_cast<std::shared_ptr<ASTRowPolicyNames>>(names_ast); + String cluster = std::exchange(names->cluster, ""); + + String new_short_name; + std::optional<bool> is_restrictive; + std::vector<std::pair<RowPolicyFilterType, ASTPtr>> filters; + String storage_name; + + while (true) + { + if (alter && (names->full_names.size() == 1) && new_short_name.empty() && parseRenameTo(pos, expected, new_short_name)) + continue; + + if (!is_restrictive) + { + bool new_is_restrictive; + if (parseAsRestrictiveOrPermissive(pos, expected, new_is_restrictive)) + { + is_restrictive = new_is_restrictive; + continue; + } + } + + std::vector<std::pair<RowPolicyFilterType, ASTPtr>> new_filters; + if (parseForClauses(pos, expected, alter, new_filters)) + { + insertAtEnd(filters, std::move(new_filters)); + continue; + } + + if (cluster.empty() && parseOnCluster(pos, expected, cluster)) + continue; + + if (storage_name.empty() && ParserKeyword{"IN"}.ignore(pos, expected) && parseAccessStorageName(pos, expected, storage_name)) + continue; + + break; + } + + std::shared_ptr<ASTRolesOrUsersSet> roles; + parseToRoles(pos, expected, attach_mode, roles); + + if (cluster.empty()) + parseOnCluster(pos, expected, cluster); + + auto query = std::make_shared<ASTCreateRowPolicyQuery>(); + node = query; + + query->alter = alter; + query->attach = attach_mode; + query->if_exists = if_exists; + query->if_not_exists = if_not_exists; + query->or_replace = or_replace; + query->cluster = std::move(cluster); + query->names = std::move(names); + query->new_short_name = std::move(new_short_name); + query->is_restrictive = is_restrictive; + query->filters = std::move(filters); + query->roles = std::move(roles); + query->storage_name = std::move(storage_name); + + return true; +} +} |
