summaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Parsers/Access/ParserCreateRowPolicyQuery.cpp
diff options
context:
space:
mode:
authorvitalyisaev <[email protected]>2023-11-14 09:58:56 +0300
committervitalyisaev <[email protected]>2023-11-14 10:20:20 +0300
commitc2b2dfd9827a400a8495e172a56343462e3ceb82 (patch)
treecd4e4f597d01bede4c82dffeb2d780d0a9046bd0 /contrib/clickhouse/src/Parsers/Access/ParserCreateRowPolicyQuery.cpp
parentd4ae8f119e67808cb0cf776ba6e0cf95296f2df7 (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.cpp306
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;
+}
+}