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 | |
12 | namespace DB |
13 | { |
14 | namespace ErrorCodes |
15 | { |
16 | extern const int SYNTAX_ERROR; |
17 | } |
18 | |
19 | |
20 | namespace |
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 | |
203 | bool 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 | |