1use crate::storage::query::ast::{
35 AlterUserAttribute, AlterUserStmt, GrantObject, GrantObjectKind, GrantPrincipalRef, GrantStmt,
36 LintPolicySource, PolicyPrincipalRef, PolicyResourceRef, PolicyUserRef, QueryExpr, RevokeStmt,
37};
38use crate::storage::query::lexer::Token;
39use crate::storage::query::parser::{ParseError, Parser};
40
41impl<'a> Parser<'a> {
42 pub fn parse_grant_statement(&mut self) -> Result<GrantStmt, ParseError> {
46 self.advance()?;
48
49 let (actions, all, columns) = self.parse_privilege_list()?;
50 self.expect(Token::On)?;
51 let object_kind = self.parse_grant_object_kind()?;
52 let objects = self.parse_grant_object_list(&object_kind)?;
53 self.expect(Token::To)?;
54 let principals = self.parse_grant_principal_list()?;
55
56 let with_grant_option = self.consume_grant_option_suffix()?;
57
58 Ok(GrantStmt {
59 actions,
60 columns,
61 object_kind,
62 objects,
63 principals,
64 with_grant_option,
65 all,
66 })
67 }
68
69 pub fn parse_revoke_statement(&mut self) -> Result<RevokeStmt, ParseError> {
72 self.advance()?;
74
75 let grant_option_for = self.consume_grant_option_for_prefix()?;
77
78 let (actions, all, columns) = self.parse_privilege_list()?;
79 self.expect(Token::On)?;
80 let object_kind = self.parse_grant_object_kind()?;
81 let objects = self.parse_grant_object_list(&object_kind)?;
82 self.expect(Token::From)?;
83 let principals = self.parse_grant_principal_list()?;
84
85 Ok(RevokeStmt {
86 actions,
87 columns,
88 object_kind,
89 objects,
90 principals,
91 grant_option_for,
92 all,
93 })
94 }
95
96 pub fn parse_alter_user_statement(&mut self) -> Result<AlterUserStmt, ParseError> {
99 if !self.consume_ident_ci("USER")? {
101 return Err(ParseError::expected(
102 vec!["USER"],
103 self.peek(),
104 self.position(),
105 ));
106 }
107 let (tenant, username) = self.parse_user_name()?;
108
109 let mut attributes = Vec::new();
110 loop {
111 if self.consume_ident_ci("VALID")? {
112 if !self.consume_ident_ci("UNTIL")? {
113 return Err(ParseError::expected(
114 vec!["UNTIL"],
115 self.peek(),
116 self.position(),
117 ));
118 }
119 let ts = self.parse_string()?;
120 attributes.push(AlterUserAttribute::ValidUntil(ts));
121 } else if self.consume_ident_ci("CONNECTION")? {
122 if !self.consume(&Token::Limit)? && !self.consume_ident_ci("LIMIT")? {
123 return Err(ParseError::expected(
124 vec!["LIMIT"],
125 self.peek(),
126 self.position(),
127 ));
128 }
129 let n = self.parse_integer()?;
130 attributes.push(AlterUserAttribute::ConnectionLimit(n));
131 } else if self.consume(&Token::Enable)? {
132 attributes.push(AlterUserAttribute::Enable);
133 } else if self.consume(&Token::Disable)? {
134 attributes.push(AlterUserAttribute::Disable);
135 } else if self.consume(&Token::Set)? {
136 if !self.consume_ident_ci("SEARCH_PATH")? {
138 return Err(ParseError::expected(
139 vec!["search_path"],
140 self.peek(),
141 self.position(),
142 ));
143 }
144 if !self.consume(&Token::Eq)? && !self.consume(&Token::To)? {
145 return Err(ParseError::expected(
146 vec!["="],
147 self.peek(),
148 self.position(),
149 ));
150 }
151 let value = self.parse_string()?;
152 attributes.push(AlterUserAttribute::SetSearchPath(value));
153 } else if self.consume(&Token::Add)? || self.consume_ident_ci("ADD")? {
154 if !self.consume(&Token::Group)? && !self.consume_ident_ci("GROUP")? {
155 return Err(ParseError::expected(
156 vec!["GROUP"],
157 self.peek(),
158 self.position(),
159 ));
160 }
161 let group = self.expect_ident()?;
162 attributes.push(AlterUserAttribute::AddGroup(group));
163 } else if self.consume(&Token::Drop)? || self.consume_ident_ci("DROP")? {
164 if !self.consume(&Token::Group)? && !self.consume_ident_ci("GROUP")? {
165 return Err(ParseError::expected(
166 vec!["GROUP"],
167 self.peek(),
168 self.position(),
169 ));
170 }
171 let group = self.expect_ident()?;
172 attributes.push(AlterUserAttribute::DropGroup(group));
173 } else if self.consume_ident_ci("PASSWORD")? {
174 let pw = self.parse_string()?;
175 attributes.push(AlterUserAttribute::Password(pw));
176 } else {
177 break;
178 }
179 }
180
181 if attributes.is_empty() {
182 return Err(ParseError::expected(
183 vec![
184 "VALID",
185 "CONNECTION",
186 "ENABLE",
187 "DISABLE",
188 "SET",
189 "ADD",
190 "DROP",
191 "PASSWORD",
192 ],
193 self.peek(),
194 self.position(),
195 ));
196 }
197
198 Ok(AlterUserStmt {
199 tenant,
200 username,
201 attributes,
202 })
203 }
204
205 pub fn parse_create_iam_policy_after_keywords(&mut self) -> Result<QueryExpr, ParseError> {
214 let id = self.parse_string()?;
215 if !self.consume(&Token::As)? && !self.consume_ident_ci("AS")? {
216 return Err(ParseError::expected(
217 vec!["AS"],
218 self.peek(),
219 self.position(),
220 ));
221 }
222 let json = self.parse_string()?;
223 Ok(QueryExpr::CreateIamPolicy { id, json })
224 }
225
226 pub fn parse_drop_iam_policy_after_keywords(&mut self) -> Result<QueryExpr, ParseError> {
229 let id = self.parse_string()?;
230 Ok(QueryExpr::DropIamPolicy { id })
231 }
232
233 pub fn parse_attach_policy(&mut self) -> Result<QueryExpr, ParseError> {
237 self.advance()?; if !self.consume(&Token::Policy)? && !self.consume_ident_ci("POLICY")? {
239 return Err(ParseError::expected(
240 vec!["POLICY"],
241 self.peek(),
242 self.position(),
243 ));
244 }
245 let policy_id = self.parse_string()?;
246 self.expect(Token::To)?;
247 let principal = self.parse_iam_principal_kind()?;
248 Ok(QueryExpr::AttachPolicy {
249 policy_id,
250 principal,
251 })
252 }
253
254 pub fn parse_detach_policy(&mut self) -> Result<QueryExpr, ParseError> {
256 self.advance()?; if !self.consume(&Token::Policy)? && !self.consume_ident_ci("POLICY")? {
258 return Err(ParseError::expected(
259 vec!["POLICY"],
260 self.peek(),
261 self.position(),
262 ));
263 }
264 let policy_id = self.parse_string()?;
265 self.expect(Token::From)?;
266 let principal = self.parse_iam_principal_kind()?;
267 Ok(QueryExpr::DetachPolicy {
268 policy_id,
269 principal,
270 })
271 }
272
273 pub fn parse_simulate_policy(&mut self) -> Result<QueryExpr, ParseError> {
275 self.advance()?; let user = self.parse_iam_user_ref()?;
277 if !self.consume_ident_ci("ACTION")? {
278 return Err(ParseError::expected(
279 vec!["ACTION"],
280 self.peek(),
281 self.position(),
282 ));
283 }
284 let action = self.parse_iam_action_token()?;
285 self.expect(Token::On)?;
286 let resource = self.parse_iam_resource_ref()?;
287 Ok(QueryExpr::SimulatePolicy {
288 user,
289 action,
290 resource,
291 })
292 }
293
294 pub fn parse_migrate_policy_mode(&mut self) -> Result<QueryExpr, ParseError> {
298 self.advance()?; if !self.consume(&Token::Policy)? && !self.consume_ident_ci("POLICY")? {
300 return Err(ParseError::expected(
301 vec!["POLICY"],
302 self.peek(),
303 self.position(),
304 ));
305 }
306 if !self.consume(&Token::Mode)? && !self.consume_ident_ci("MODE")? {
307 return Err(ParseError::expected(
308 vec!["MODE"],
309 self.peek(),
310 self.position(),
311 ));
312 }
313 if !self.consume(&Token::To)? && !self.consume_ident_ci("TO")? {
314 return Err(ParseError::expected(
315 vec!["TO"],
316 self.peek(),
317 self.position(),
318 ));
319 }
320 let target = self.parse_string()?;
321 let dry_run = if self.consume_ident_ci("DRY")? {
322 if !self.consume_ident_ci("RUN")? {
323 return Err(ParseError::expected(
324 vec!["RUN"],
325 self.peek(),
326 self.position(),
327 ));
328 }
329 true
330 } else {
331 false
332 };
333 Ok(QueryExpr::MigratePolicyMode { target, dry_run })
334 }
335
336 pub fn parse_lint_policy(&mut self) -> Result<QueryExpr, ParseError> {
340 self.advance()?; if !self.consume(&Token::Policy)? && !self.consume_ident_ci("POLICY")? {
342 return Err(ParseError::expected(
343 vec!["POLICY"],
344 self.peek(),
345 self.position(),
346 ));
347 }
348 if self.consume(&Token::Json)? || self.consume_ident_ci("JSON")? {
352 let json = self.parse_string()?;
353 return Ok(QueryExpr::LintPolicy {
354 source: LintPolicySource::Json(json),
355 });
356 }
357 let id = self.parse_string()?;
358 Ok(QueryExpr::LintPolicy {
359 source: LintPolicySource::Id(id),
360 })
361 }
362
363 pub fn parse_show_iam_after_show(&mut self) -> Result<Option<QueryExpr>, ParseError> {
367 if self.consume_ident_ci("POLICIES")? {
369 if self.consume(&Token::For)? || self.consume_ident_ci("FOR")? {
371 let principal = self.parse_iam_principal_kind()?;
372 return Ok(Some(QueryExpr::ShowPolicies {
373 filter: Some(principal),
374 }));
375 }
376 return Ok(Some(QueryExpr::ShowPolicies { filter: None }));
377 }
378 if self.consume_ident_ci("EFFECTIVE")? {
379 if !self.consume_ident_ci("PERMISSIONS")? {
380 return Err(ParseError::expected(
381 vec!["PERMISSIONS"],
382 self.peek(),
383 self.position(),
384 ));
385 }
386 if !self.consume(&Token::For)? && !self.consume_ident_ci("FOR")? {
387 return Err(ParseError::expected(
388 vec!["FOR"],
389 self.peek(),
390 self.position(),
391 ));
392 }
393 let user = self.parse_iam_user_ref()?;
394 let resource = if self.consume(&Token::On)? || self.consume_ident_ci("ON")? {
395 Some(self.parse_iam_resource_ref()?)
396 } else {
397 None
398 };
399 return Ok(Some(QueryExpr::ShowEffectivePermissions { user, resource }));
400 }
401 Ok(None)
402 }
403
404 pub(crate) fn parse_iam_principal_kind(&mut self) -> Result<PolicyPrincipalRef, ParseError> {
407 if self.consume_ident_ci("USER")? {
408 let user = self.parse_iam_user_ref()?;
409 Ok(PolicyPrincipalRef::User(user))
410 } else if self.consume(&Token::Group)? || self.consume_ident_ci("GROUP")? {
411 let g = self.expect_ident()?;
412 Ok(PolicyPrincipalRef::Group(g))
413 } else {
414 Err(ParseError::expected(
415 vec!["USER", "GROUP"],
416 self.peek(),
417 self.position(),
418 ))
419 }
420 }
421
422 fn parse_iam_user_ref(&mut self) -> Result<PolicyUserRef, ParseError> {
423 let (tenant, username) = self.parse_user_name()?;
424 Ok(PolicyUserRef { tenant, username })
425 }
426
427 fn parse_iam_resource_ref(&mut self) -> Result<PolicyResourceRef, ParseError> {
428 if matches!(self.peek(), Token::String(_)) {
432 let raw = self.parse_string()?;
433 let (kind, name) = raw.split_once(':').ok_or_else(|| {
434 ParseError::new(
435 format!("resource must be `kind:name`, got {raw:?}"),
440 self.position(),
441 )
442 })?;
443 return Ok(PolicyResourceRef {
444 kind: kind.to_string(),
445 name: name.to_string(),
446 });
447 }
448 let kind = self.expect_ident_or_keyword()?.to_ascii_lowercase();
452 if !self.consume(&Token::Colon)? {
453 return Err(ParseError::expected(
454 vec![":"],
455 self.peek(),
456 self.position(),
457 ));
458 }
459 let mut name = self.expect_ident_or_keyword()?;
462 while self.consume(&Token::Dot)? {
463 let next = self.expect_ident_or_keyword()?;
464 name.push('.');
465 name.push_str(&next);
466 }
467 Ok(PolicyResourceRef { kind, name })
468 }
469
470 fn parse_iam_action_token(&mut self) -> Result<String, ParseError> {
471 if matches!(self.peek(), Token::String(_)) {
472 return self.parse_string();
473 }
474 match self.peek() {
477 Token::Select => {
478 self.advance()?;
479 Ok("select".into())
480 }
481 Token::Insert => {
482 self.advance()?;
483 Ok("insert".into())
484 }
485 Token::Update => {
486 self.advance()?;
487 Ok("update".into())
488 }
489 Token::Delete => {
490 self.advance()?;
491 Ok("delete".into())
492 }
493 Token::Ident(_) => {
494 let raw = self.expect_ident()?;
495 Ok(raw.to_ascii_lowercase())
496 }
497 other => Err(ParseError::expected(
498 vec!["action keyword"],
499 other,
500 self.position(),
501 )),
502 }
503 }
504
505 fn parse_privilege_list(
514 &mut self,
515 ) -> Result<(Vec<String>, bool, Option<Vec<String>>), ParseError> {
516 if self.consume(&Token::All)? || self.consume_ident_ci("ALL")? {
518 let _ = self.consume_ident_ci("PRIVILEGES")?;
519 let columns = self.parse_optional_column_list()?;
520 return Ok((vec!["ALL".to_string()], true, columns));
521 }
522
523 let mut actions = Vec::new();
525 loop {
526 actions.push(self.parse_privilege_keyword()?);
527 if !self.consume(&Token::Comma)? {
528 break;
529 }
530 }
531 let columns = self.parse_optional_column_list()?;
532 Ok((actions, false, columns))
533 }
534
535 fn parse_privilege_keyword(&mut self) -> Result<String, ParseError> {
539 match self.peek() {
540 Token::Select => {
541 self.advance()?;
542 Ok("SELECT".to_string())
543 }
544 Token::Insert => {
545 self.advance()?;
546 Ok("INSERT".to_string())
547 }
548 Token::Update => {
549 self.advance()?;
550 Ok("UPDATE".to_string())
551 }
552 Token::Delete => {
553 self.advance()?;
554 Ok("DELETE".to_string())
555 }
556 Token::Truncate => {
557 self.advance()?;
558 Ok("TRUNCATE".to_string())
559 }
560 Token::Ident(name)
561 if matches!(
562 name.to_ascii_uppercase().as_str(),
563 "REFERENCES" | "EXECUTE" | "USAGE"
564 ) =>
565 {
566 let upper = name.to_ascii_uppercase();
567 self.advance()?;
568 Ok(upper)
569 }
570 other => Err(ParseError::expected(
571 vec![
572 "SELECT",
573 "INSERT",
574 "UPDATE",
575 "DELETE",
576 "TRUNCATE",
577 "REFERENCES",
578 "EXECUTE",
579 "USAGE",
580 ],
581 other,
582 self.position(),
583 )),
584 }
585 }
586
587 fn parse_optional_column_list(&mut self) -> Result<Option<Vec<String>>, ParseError> {
590 if !self.check(&Token::LParen) {
591 return Ok(None);
592 }
593 self.expect(Token::LParen)?;
594 let mut cols = Vec::new();
595 loop {
596 cols.push(self.expect_ident()?);
597 if !self.consume(&Token::Comma)? {
598 break;
599 }
600 }
601 self.expect(Token::RParen)?;
602 Ok(Some(cols))
603 }
604
605 fn parse_grant_object_kind(&mut self) -> Result<GrantObjectKind, ParseError> {
609 if self.consume(&Token::Table)? {
610 Ok(GrantObjectKind::Table)
611 } else if self.consume(&Token::Schema)? {
612 Ok(GrantObjectKind::Schema)
613 } else if self.consume_ident_ci("DATABASE")? {
614 Ok(GrantObjectKind::Database)
615 } else if self.consume_ident_ci("FUNCTION")? {
616 Ok(GrantObjectKind::Function)
617 } else {
618 Ok(GrantObjectKind::Table)
620 }
621 }
622
623 fn parse_grant_object_list(
625 &mut self,
626 kind: &GrantObjectKind,
627 ) -> Result<Vec<GrantObject>, ParseError> {
628 let mut out = Vec::new();
629 loop {
630 if matches!(kind, GrantObjectKind::Database) {
633 let name = self.expect_ident()?;
634 out.push(GrantObject { schema: None, name });
635 } else {
636 let first = self.expect_ident()?;
637 let (schema, name) = if self.consume(&Token::Dot)? {
638 let second = self.expect_ident_or_keyword()?;
639 (Some(first), second)
640 } else {
641 (None, first)
642 };
643 out.push(GrantObject { schema, name });
644 }
645 if !self.consume(&Token::Comma)? {
646 break;
647 }
648 }
649 Ok(out)
650 }
651
652 fn parse_grant_principal_list(&mut self) -> Result<Vec<GrantPrincipalRef>, ParseError> {
657 let mut out = Vec::new();
658 loop {
659 if self.consume_ident_ci("PUBLIC")? {
660 out.push(GrantPrincipalRef::Public);
661 } else if self.consume(&Token::Group)? || self.consume_ident_ci("GROUP")? {
662 let g = self.expect_ident()?;
663 out.push(GrantPrincipalRef::Group(g));
664 } else {
665 let (tenant, name) = self.parse_user_name()?;
666 out.push(GrantPrincipalRef::User { tenant, name });
667 }
668 if !self.consume(&Token::Comma)? {
669 break;
670 }
671 }
672 Ok(out)
673 }
674
675 fn parse_user_name(&mut self) -> Result<(Option<String>, String), ParseError> {
677 let first = self.expect_ident()?;
678 if self.consume(&Token::Dot)? {
679 let name = self.expect_ident()?;
680 Ok((Some(first), name))
681 } else {
682 Ok((None, first))
683 }
684 }
685
686 fn consume_grant_option_suffix(&mut self) -> Result<bool, ParseError> {
688 if self.consume(&Token::With)? {
689 if !self.consume_ident_ci("GRANT")? {
690 return Err(ParseError::expected(
691 vec!["GRANT"],
692 self.peek(),
693 self.position(),
694 ));
695 }
696 if !self.consume_ident_ci("OPTION")? {
697 return Err(ParseError::expected(
698 vec!["OPTION"],
699 self.peek(),
700 self.position(),
701 ));
702 }
703 Ok(true)
704 } else {
705 Ok(false)
706 }
707 }
708
709 fn consume_grant_option_for_prefix(&mut self) -> Result<bool, ParseError> {
711 let saved_pos = self.position();
714 if !matches!(self.peek(), Token::Ident(s) if s.eq_ignore_ascii_case("GRANT")) {
715 return Ok(false);
716 }
717 self.advance()?;
719 if !self.consume_ident_ci("OPTION")? {
720 return Err(ParseError::expected(vec!["OPTION"], self.peek(), saved_pos));
724 }
725 if !self.consume(&Token::For)? && !self.consume_ident_ci("FOR")? {
726 return Err(ParseError::expected(vec!["FOR"], self.peek(), saved_pos));
727 }
728 Ok(true)
729 }
730}