1#include <Parsers/ParserCreateRowPolicyQuery.h>
2#include <Parsers/ASTCreateRowPolicyQuery.h>
3#include <Access/RowPolicy.h>
4#include <Parsers/ParserRoleList.h>
5#include <Parsers/ASTRoleList.h>
6#include <Parsers/parseIdentifierOrStringLiteral.h>
7#include <Parsers/parseDatabaseAndTableName.h>
8#include <Parsers/ExpressionListParsers.h>
9#include <Parsers/ASTLiteral.h>
10
11
12namespace DB
13{
14namespace ErrorCodes
15{
16 extern const int SYNTAX_ERROR;
17}
18
19
20namespace
21{
22 using ConditionIndex = RowPolicy::ConditionIndex;
23
24 bool parseRenameTo(IParserBase::Pos & pos, Expected & expected, String & new_policy_name, bool alter)
25 {
26 return IParserBase::wrapParseImpl(pos, [&]
27 {
28 if (!new_policy_name.empty() || !alter)
29 return false;
30
31 if (!ParserKeyword{"RENAME TO"}.ignore(pos, expected))
32 return false;
33
34 return parseIdentifierOrStringLiteral(pos, expected, new_policy_name);
35 });
36 }
37
38 bool parseIsRestrictive(IParserBase::Pos & pos, Expected & expected, std::optional<bool> & is_restrictive)
39 {
40 return IParserBase::wrapParseImpl(pos, [&]
41 {
42 if (is_restrictive)
43 return false;
44
45 if (!ParserKeyword{"AS"}.ignore(pos, expected))
46 return false;
47
48 if (ParserKeyword{"RESTRICTIVE"}.ignore(pos, expected))
49 is_restrictive = true;
50 else if (ParserKeyword{"PERMISSIVE"}.ignore(pos, expected))
51 is_restrictive = false;
52 else
53 return false;
54
55 return true;
56 });
57 }
58
59 bool parseConditionalExpression(IParserBase::Pos & pos, Expected & expected, std::optional<ASTPtr> & expr)
60 {
61 if (ParserKeyword("NONE").ignore(pos, expected))
62 {
63 expr = nullptr;
64 return true;
65 }
66 ParserExpression parser;
67 ASTPtr x;
68 if (parser.parse(pos, x, expected))
69 {
70 expr = x;
71 return true;
72 }
73 expr.reset();
74 return false;
75 }
76
77 bool parseConditions(IParserBase::Pos & pos, Expected & expected, std::vector<std::pair<ConditionIndex, ASTPtr>> & conditions, bool alter)
78 {
79 return IParserBase::wrapParseImpl(pos, [&]
80 {
81 static constexpr char select_op[] = "SELECT";
82 static constexpr char insert_op[] = "INSERT";
83 static constexpr char update_op[] = "UPDATE";
84 static constexpr char delete_op[] = "DELETE";
85 std::vector<const char *> ops;
86
87 bool keyword_for = false;
88 if (ParserKeyword{"FOR"}.ignore(pos, expected))
89 {
90 keyword_for = true;
91 do
92 {
93 if (ParserKeyword{"SELECT"}.ignore(pos, expected))
94 ops.push_back(select_op);
95 else if (ParserKeyword{"INSERT"}.ignore(pos, expected))
96 ops.push_back(insert_op);
97 else if (ParserKeyword{"UPDATE"}.ignore(pos, expected))
98 ops.push_back(update_op);
99 else if (ParserKeyword{"DELETE"}.ignore(pos, expected))
100 ops.push_back(delete_op);
101 else if (ParserKeyword{"ALL"}.ignore(pos, expected))
102 {
103 }
104 else
105 return false;
106 }
107 while (ParserToken{TokenType::Comma}.ignore(pos, expected));
108 }
109
110 if (ops.empty())
111 {
112 ops.push_back(select_op);
113 ops.push_back(insert_op);
114 ops.push_back(update_op);
115 ops.push_back(delete_op);
116 }
117
118 std::optional<ASTPtr> filter;
119 std::optional<ASTPtr> check;
120 bool keyword_using = false, keyword_with_check = false;
121 if (ParserKeyword{"USING"}.ignore(pos, expected))
122 {
123 keyword_using = true;
124 if (!parseConditionalExpression(pos, expected, filter))
125 return false;
126 }
127 if (ParserKeyword{"WITH CHECK"}.ignore(pos, expected))
128 {
129 keyword_with_check = true;
130 if (!parseConditionalExpression(pos, expected, check))
131 return false;
132 }
133
134 if (!keyword_for && !keyword_using && !keyword_with_check)
135 return false;
136
137 if (filter && !check && !alter)
138 check = filter;
139
140 auto set_condition = [&](ConditionIndex index, const ASTPtr & condition)
141 {
142 auto it = std::find_if(conditions.begin(), conditions.end(), [index](const std::pair<ConditionIndex, ASTPtr> & element)
143 {
144 return element.first == index;
145 });
146 if (it == conditions.end())
147 it = conditions.insert(conditions.end(), std::pair<ConditionIndex, ASTPtr>{index, nullptr});
148 it->second = condition;
149 };
150
151 for (const auto & op : ops)
152 {
153 if ((op == select_op) && filter)
154 set_condition(RowPolicy::SELECT_FILTER, *filter);
155 else if ((op == insert_op) && check)
156 set_condition(RowPolicy::INSERT_CHECK, *check);
157 else if (op == update_op)
158 {
159 if (filter)
160 set_condition(RowPolicy::UPDATE_FILTER, *filter);
161 if (check)
162 set_condition(RowPolicy::UPDATE_CHECK, *check);
163 }
164 else if ((op == delete_op) && filter)
165 set_condition(RowPolicy::DELETE_FILTER, *filter);
166 else
167 __builtin_unreachable();
168 }
169
170 return true;
171 });
172 }
173
174 bool parseMultipleConditions(IParserBase::Pos & pos, Expected & expected, std::vector<std::pair<ConditionIndex, ASTPtr>> & conditions, bool alter)
175 {
176 return IParserBase::wrapParseImpl(pos, [&]
177 {
178 do
179 {
180 if (!parseConditions(pos, expected, conditions, alter))
181 return false;
182 }
183 while (ParserToken{TokenType::Comma}.ignore(pos, expected));
184 return true;
185 });
186 }
187
188 bool parseRoles(IParserBase::Pos & pos, Expected & expected, std::shared_ptr<ASTRoleList> & roles)
189 {
190 return IParserBase::wrapParseImpl(pos, [&]
191 {
192 ASTPtr node;
193 if (roles || !ParserKeyword{"TO"}.ignore(pos, expected) || !ParserRoleList{}.parse(pos, node, expected))
194 return false;
195
196 roles = std::static_pointer_cast<ASTRoleList>(node);
197 return true;
198 });
199 }
200}
201
202
203bool ParserCreateRowPolicyQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
204{
205 bool alter;
206 if (ParserKeyword{"CREATE POLICY"}.ignore(pos, expected) || ParserKeyword{"CREATE ROW POLICY"}.ignore(pos, expected))
207 alter = false;
208 else if (ParserKeyword{"ALTER POLICY"}.ignore(pos, expected) || ParserKeyword{"ALTER ROW POLICY"}.ignore(pos, expected))
209 alter = true;
210 else
211 return false;
212
213 bool if_exists = false;
214 bool if_not_exists = false;
215 bool or_replace = false;
216 if (alter)
217 {
218 if (ParserKeyword{"IF EXISTS"}.ignore(pos, expected))
219 if_exists = true;
220 }
221 else
222 {
223 if (ParserKeyword{"IF NOT EXISTS"}.ignore(pos, expected))
224 if_not_exists = true;
225 else if (ParserKeyword{"OR REPLACE"}.ignore(pos, expected))
226 or_replace = true;
227 }
228
229 RowPolicy::FullNameParts name_parts;
230 String & database = name_parts.database;
231 String & table_name = name_parts.table_name;
232 String & policy_name = name_parts.policy_name;
233 if (!parseIdentifierOrStringLiteral(pos, expected, policy_name) || !ParserKeyword{"ON"}.ignore(pos, expected)
234 || !parseDatabaseAndTableName(pos, expected, database, table_name))
235 return false;
236
237 String new_policy_name;
238 std::optional<bool> is_restrictive;
239 std::vector<std::pair<ConditionIndex, ASTPtr>> conditions;
240 std::shared_ptr<ASTRoleList> roles;
241
242 while (parseRenameTo(pos, expected, new_policy_name, alter) || parseIsRestrictive(pos, expected, is_restrictive)
243 || parseMultipleConditions(pos, expected, conditions, alter) || parseRoles(pos, expected, roles))
244 ;
245
246 auto query = std::make_shared<ASTCreateRowPolicyQuery>();
247 node = query;
248
249 query->alter = alter;
250 query->if_exists = if_exists;
251 query->if_not_exists = if_not_exists;
252 query->or_replace = or_replace;
253 query->name_parts = std::move(name_parts);
254 query->new_policy_name = std::move(new_policy_name);
255 query->is_restrictive = is_restrictive;
256 query->conditions = std::move(conditions);
257 query->roles = std::move(roles);
258
259 return true;
260}
261}
262