Skip to main content

qusql_parse/
grant.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13//! Parser for the `GRANT` statement.
14//!
15//! Covers both the privilege-grant form and the role-membership form as documented at
16//! <https://www.postgresql.org/docs/current/sql-grant.html>.
17
18use crate::{
19    DataType, Identifier, QualifiedName, Span, Spanned,
20    create_function::FunctionParamDirection,
21    data_type::{DataTypeContext, parse_data_type},
22    expression::{Expression, PRIORITY_MAX, parse_expression_unreserved},
23    keywords::Keyword,
24    lexer::Token,
25    parser::{ParseError, Parser},
26    qualified_name::parse_qualified_name_unreserved,
27    span::OptSpanned,
28};
29use alloc::vec::Vec;
30
31/// A single privilege keyword in a GRANT statement.
32#[derive(Clone, Debug)]
33pub enum GrantPrivilege {
34    Select(Span),
35    Insert(Span),
36    Update(Span),
37    Delete(Span),
38    Truncate(Span),
39    References(Span),
40    Trigger(Span),
41    Maintain(Span),
42    Usage(Span),
43    Create(Span),
44    Connect(Span),
45    /// TEMPORARY or TEMP
46    Temporary(Span),
47    Execute(Span),
48    Set(Span),
49    /// ALTER SYSTEM - span covers both keywords
50    AlterSystem(Span),
51    /// ALL [ PRIVILEGES ] - second span is the optional PRIVILEGES keyword
52    All(Span, Option<Span>),
53}
54
55impl Spanned for GrantPrivilege {
56    fn span(&self) -> Span {
57        match self {
58            GrantPrivilege::Select(s)
59            | GrantPrivilege::Insert(s)
60            | GrantPrivilege::Update(s)
61            | GrantPrivilege::Delete(s)
62            | GrantPrivilege::Truncate(s)
63            | GrantPrivilege::References(s)
64            | GrantPrivilege::Trigger(s)
65            | GrantPrivilege::Maintain(s)
66            | GrantPrivilege::Usage(s)
67            | GrantPrivilege::Create(s)
68            | GrantPrivilege::Connect(s)
69            | GrantPrivilege::Temporary(s)
70            | GrantPrivilege::Execute(s)
71            | GrantPrivilege::Set(s)
72            | GrantPrivilege::AlterSystem(s) => s.clone(),
73            GrantPrivilege::All(s, p) => s.join_span(p),
74        }
75    }
76}
77
78/// One entry in the privilege list: a privilege with an optional column list.
79///
80/// Column lists are valid for SELECT, INSERT, UPDATE, REFERENCES on tables.
81#[derive(Clone, Debug)]
82pub struct PrivilegeItem<'a> {
83    pub privilege: GrantPrivilege,
84    /// Empty unless the privilege was qualified with `( col [, ...] )`.
85    pub columns: Vec<Identifier<'a>>,
86}
87
88impl<'a> Spanned for PrivilegeItem<'a> {
89    fn span(&self) -> Span {
90        self.privilege.join_span(&self.columns)
91    }
92}
93
94/// How a routine was named in the GRANT ON { FUNCTION | PROCEDURE | ROUTINE } clause.
95#[derive(Clone, Debug)]
96pub enum RoutineKind {
97    Function(Span),
98    Procedure(Span),
99    Routine(Span),
100}
101
102impl Spanned for RoutineKind {
103    fn span(&self) -> Span {
104        match self {
105            RoutineKind::Function(s) | RoutineKind::Procedure(s) | RoutineKind::Routine(s) => {
106                s.clone()
107            }
108        }
109    }
110}
111
112/// ALL { FUNCTIONS | PROCEDURES | ROUTINES } - which plural form was used.
113#[derive(Clone, Debug)]
114pub enum AllRoutineKind {
115    Functions(Span),
116    Procedures(Span),
117    Routines(Span),
118}
119
120impl Spanned for AllRoutineKind {
121    fn span(&self) -> Span {
122        match self {
123            AllRoutineKind::Functions(s)
124            | AllRoutineKind::Procedures(s)
125            | AllRoutineKind::Routines(s) => s.clone(),
126        }
127    }
128}
129
130/// An argument type entry inside a routine reference's optional `( args )` list.
131#[derive(Clone, Debug)]
132pub struct RoutineArgType<'a> {
133    /// Optional IN / OUT / INOUT modifier.
134    pub mode: Option<FunctionParamDirection>,
135    /// Optional parameter name (present when followed by a type token).
136    pub name: Option<Identifier<'a>>,
137    /// The argument data type.
138    pub type_: DataType<'a>,
139}
140
141impl<'a> Spanned for RoutineArgType<'a> {
142    fn span(&self) -> Span {
143        self.type_.join_span(&self.mode).join_span(&self.name)
144    }
145}
146
147/// A routine name together with an optional argument-type list.
148///
149/// The argument list is used only for disambiguation when overloaded routines exist.
150#[derive(Clone, Debug)]
151pub struct RoutineName<'a> {
152    pub name: QualifiedName<'a>,
153    /// `None` means no parentheses were written; `Some([])` means `name()`.
154    pub args: Option<Vec<RoutineArgType<'a>>>,
155}
156
157impl<'a> Spanned for RoutineName<'a> {
158    fn span(&self) -> Span {
159        self.name.join_span(&self.args)
160    }
161}
162
163/// The object (or set of objects) to which privileges are being granted.
164#[derive(Clone, Debug)]
165pub enum GrantObject<'a> {
166    /// `[ TABLE ] table_name [, ...]`
167    Tables {
168        table_kw: Option<Span>,
169        names: Vec<QualifiedName<'a>>,
170    },
171    /// `ALL TABLES IN SCHEMA schema_name [, ...]`
172    AllTablesInSchema {
173        /// Span covering `ALL TABLES IN SCHEMA`
174        span: Span,
175        schemas: Vec<QualifiedName<'a>>,
176    },
177    /// `SEQUENCE sequence_name [, ...]`
178    Sequences {
179        sequence_kw: Span,
180        names: Vec<QualifiedName<'a>>,
181    },
182    /// `ALL SEQUENCES IN SCHEMA schema_name [, ...]`
183    AllSequencesInSchema {
184        /// Span covering `ALL SEQUENCES IN SCHEMA`
185        span: Span,
186        schemas: Vec<QualifiedName<'a>>,
187    },
188    /// `DATABASE database_name [, ...]`
189    Databases {
190        database_kw: Span,
191        names: Vec<QualifiedName<'a>>,
192    },
193    /// `DOMAIN domain_name [, ...]`
194    Domains {
195        domain_kw: Span,
196        names: Vec<QualifiedName<'a>>,
197    },
198    /// `FOREIGN DATA WRAPPER fdw_name [, ...]`
199    ForeignDataWrappers {
200        /// Span covering `FOREIGN DATA WRAPPER`
201        span: Span,
202        names: Vec<QualifiedName<'a>>,
203    },
204    /// `FOREIGN SERVER server_name [, ...]`
205    ForeignServers {
206        /// Span covering `FOREIGN SERVER`
207        span: Span,
208        names: Vec<QualifiedName<'a>>,
209    },
210    /// `{ FUNCTION | PROCEDURE | ROUTINE } name[(args)] [, ...]`
211    Routines {
212        kind: RoutineKind,
213        names: Vec<RoutineName<'a>>,
214    },
215    /// `ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name [, ...]`
216    AllRoutinesInSchema {
217        all_span: Span,
218        kind: AllRoutineKind,
219        in_schema_span: Span,
220        schemas: Vec<QualifiedName<'a>>,
221    },
222    /// `LANGUAGE lang_name [, ...]`
223    Languages {
224        language_kw: Span,
225        names: Vec<QualifiedName<'a>>,
226    },
227    /// `LARGE OBJECT loid [, ...]`
228    LargeObjects {
229        /// Span covering `LARGE OBJECT`
230        span: Span,
231        oids: Vec<Expression<'a>>,
232    },
233    /// `PARAMETER configuration_parameter [, ...]`
234    Parameters {
235        parameter_kw: Span,
236        names: Vec<QualifiedName<'a>>,
237    },
238    /// `SCHEMA schema_name [, ...]`
239    Schemas {
240        schema_kw: Span,
241        names: Vec<QualifiedName<'a>>,
242    },
243    /// `TABLESPACE tablespace_name [, ...]`
244    Tablespaces {
245        tablespace_kw: Span,
246        names: Vec<QualifiedName<'a>>,
247    },
248    /// `TYPE type_name [, ...]`
249    Types {
250        type_kw: Span,
251        names: Vec<QualifiedName<'a>>,
252    },
253}
254
255impl<'a> Spanned for GrantObject<'a> {
256    fn span(&self) -> Span {
257        match self {
258            GrantObject::Tables { table_kw, names } => {
259                names.opt_span().unwrap().join_span(table_kw)
260            }
261            GrantObject::AllTablesInSchema { span, schemas } => span.join_span(schemas),
262            GrantObject::Sequences { sequence_kw, names } => sequence_kw.join_span(names),
263            GrantObject::AllSequencesInSchema { span, schemas } => span.join_span(schemas),
264            GrantObject::Databases { database_kw, names } => database_kw.join_span(names),
265            GrantObject::Domains { domain_kw, names } => domain_kw.join_span(names),
266            GrantObject::ForeignDataWrappers { span, names } => span.join_span(names),
267            GrantObject::ForeignServers { span, names } => span.join_span(names),
268            GrantObject::Routines { kind, names } => kind.join_span(names),
269            GrantObject::AllRoutinesInSchema {
270                all_span, schemas, ..
271            } => all_span.join_span(schemas),
272            GrantObject::Languages { language_kw, names } => language_kw.join_span(names),
273            GrantObject::LargeObjects { span, oids } => span.join_span(oids),
274            GrantObject::Parameters {
275                parameter_kw,
276                names,
277            } => parameter_kw.join_span(names),
278            GrantObject::Schemas { schema_kw, names } => schema_kw.join_span(names),
279            GrantObject::Tablespaces {
280                tablespace_kw,
281                names,
282            } => tablespace_kw.join_span(names),
283            GrantObject::Types { type_kw, names } => type_kw.join_span(names),
284        }
285    }
286}
287
288/// A grantee or grantor role specification.
289#[derive(Clone, Debug)]
290pub enum RoleSpec<'a> {
291    /// `[ GROUP ] role_name`
292    Named {
293        group_kw: Option<Span>,
294        name: Identifier<'a>,
295    },
296    /// `PUBLIC`
297    Public(Span),
298    /// `CURRENT_ROLE`
299    CurrentRole(Span),
300    /// `CURRENT_USER`
301    CurrentUser(Span),
302    /// `SESSION_USER`
303    SessionUser(Span),
304}
305
306impl<'a> Spanned for RoleSpec<'a> {
307    fn span(&self) -> Span {
308        match self {
309            RoleSpec::Named { group_kw, name } => name.span().join_span(group_kw),
310            RoleSpec::Public(s)
311            | RoleSpec::CurrentRole(s)
312            | RoleSpec::CurrentUser(s)
313            | RoleSpec::SessionUser(s) => s.clone(),
314        }
315    }
316}
317
318/// Which membership option is being set in `WITH { ADMIN | INHERIT | SET } ...`.
319#[derive(Clone, Debug)]
320pub enum MembershipOptionKind {
321    Admin(Span),
322    Inherit(Span),
323    Set(Span),
324}
325
326impl Spanned for MembershipOptionKind {
327    fn span(&self) -> Span {
328        match self {
329            MembershipOptionKind::Admin(s)
330            | MembershipOptionKind::Inherit(s)
331            | MembershipOptionKind::Set(s) => s.clone(),
332        }
333    }
334}
335
336/// The value part of a membership option: `OPTION` (= TRUE), `TRUE`, or `FALSE`.
337#[derive(Clone, Debug)]
338pub enum MembershipOptionValue {
339    /// The `OPTION` noise word — equivalent to `TRUE`.
340    Option(Span),
341    True(Span),
342    False(Span),
343}
344
345impl Spanned for MembershipOptionValue {
346    fn span(&self) -> Span {
347        match self {
348            MembershipOptionValue::Option(s)
349            | MembershipOptionValue::True(s)
350            | MembershipOptionValue::False(s) => s.clone(),
351        }
352    }
353}
354
355/// A single `WITH { ADMIN | INHERIT | SET } { OPTION | TRUE | FALSE }` clause.
356#[derive(Clone, Debug)]
357pub struct MembershipOption {
358    pub with_span: Span,
359    pub kind: MembershipOptionKind,
360    pub value: MembershipOptionValue,
361}
362
363impl Spanned for MembershipOption {
364    fn span(&self) -> Span {
365        self.with_span.join_span(&self.kind).join_span(&self.value)
366    }
367}
368
369/// The two top-level forms that GRANT can take.
370#[derive(Clone, Debug)]
371pub enum GrantKind<'a> {
372    /// `GRANT privileges ON object TO grantees [WITH GRANT OPTION] [GRANTED BY role]`
373    Privilege {
374        privileges: Vec<PrivilegeItem<'a>>,
375        on_span: Span,
376        object: GrantObject<'a>,
377        to_span: Span,
378        grantees: Vec<RoleSpec<'a>>,
379        /// Span covering `WITH GRANT OPTION` if present.
380        with_grant_option: Option<Span>,
381        /// The `GRANTED BY role_spec` clause if present.
382        granted_by: Option<(Span, RoleSpec<'a>)>,
383    },
384    /// `GRANT role_name [, ...] TO role_spec [, ...] [WITH opt] [GRANTED BY role]`
385    Role {
386        roles: Vec<QualifiedName<'a>>,
387        to_span: Span,
388        grantees: Vec<RoleSpec<'a>>,
389        with_option: Option<MembershipOption>,
390        granted_by: Option<(Span, RoleSpec<'a>)>,
391    },
392}
393
394impl<'a> Spanned for GrantKind<'a> {
395    fn span(&self) -> Span {
396        match self {
397            GrantKind::Privilege {
398                privileges,
399                on_span,
400                object,
401                grantees,
402                granted_by,
403                ..
404            } => on_span
405                .join_span(privileges)
406                .join_span(object)
407                .join_span(grantees)
408                .join_span(granted_by),
409            GrantKind::Role {
410                roles,
411                to_span,
412                grantees,
413                with_option,
414                granted_by,
415                ..
416            } => to_span
417                .join_span(roles)
418                .join_span(grantees)
419                .join_span(with_option)
420                .join_span(granted_by),
421        }
422    }
423}
424
425/// A parsed `GRANT` statement.
426#[derive(Clone, Debug)]
427pub struct Grant<'a> {
428    pub grant_span: Span,
429    pub kind: GrantKind<'a>,
430}
431
432impl<'a> Spanned for Grant<'a> {
433    fn span(&self) -> Span {
434        self.grant_span.join_span(&self.kind)
435    }
436}
437
438fn is_privilege_keyword(token: &Token) -> bool {
439    matches!(
440        token,
441        Token::Ident(
442            _,
443            Keyword::SELECT
444                | Keyword::INSERT
445                | Keyword::UPDATE
446                | Keyword::DELETE
447                | Keyword::TRUNCATE
448                | Keyword::REFERENCES
449                | Keyword::TRIGGER
450                | Keyword::MAINTAIN
451                | Keyword::USAGE
452                | Keyword::CREATE
453                | Keyword::CONNECT
454                | Keyword::TEMPORARY
455                | Keyword::TEMP
456                | Keyword::EXECUTE
457                | Keyword::SET
458                | Keyword::ALTER
459                | Keyword::ALL
460        )
461    )
462}
463
464fn parse_privilege<'a>(parser: &mut Parser<'a, '_>) -> Result<GrantPrivilege, ParseError> {
465    match &parser.token {
466        Token::Ident(_, Keyword::SELECT) => Ok(GrantPrivilege::Select(
467            parser.consume_keyword(Keyword::SELECT)?,
468        )),
469        Token::Ident(_, Keyword::INSERT) => Ok(GrantPrivilege::Insert(
470            parser.consume_keyword(Keyword::INSERT)?,
471        )),
472        Token::Ident(_, Keyword::UPDATE) => Ok(GrantPrivilege::Update(
473            parser.consume_keyword(Keyword::UPDATE)?,
474        )),
475        Token::Ident(_, Keyword::DELETE) => Ok(GrantPrivilege::Delete(
476            parser.consume_keyword(Keyword::DELETE)?,
477        )),
478        Token::Ident(_, Keyword::TRUNCATE) => Ok(GrantPrivilege::Truncate(
479            parser.consume_keyword(Keyword::TRUNCATE)?,
480        )),
481        Token::Ident(_, Keyword::REFERENCES) => Ok(GrantPrivilege::References(
482            parser.consume_keyword(Keyword::REFERENCES)?,
483        )),
484        Token::Ident(_, Keyword::TRIGGER) => Ok(GrantPrivilege::Trigger(
485            parser.consume_keyword(Keyword::TRIGGER)?,
486        )),
487        Token::Ident(_, Keyword::MAINTAIN) => Ok(GrantPrivilege::Maintain(
488            parser.consume_keyword(Keyword::MAINTAIN)?,
489        )),
490        Token::Ident(_, Keyword::USAGE) => Ok(GrantPrivilege::Usage(
491            parser.consume_keyword(Keyword::USAGE)?,
492        )),
493        Token::Ident(_, Keyword::CREATE) => Ok(GrantPrivilege::Create(
494            parser.consume_keyword(Keyword::CREATE)?,
495        )),
496        Token::Ident(_, Keyword::CONNECT) => Ok(GrantPrivilege::Connect(
497            parser.consume_keyword(Keyword::CONNECT)?,
498        )),
499        Token::Ident(_, Keyword::TEMPORARY) => Ok(GrantPrivilege::Temporary(
500            parser.consume_keyword(Keyword::TEMPORARY)?,
501        )),
502        Token::Ident(_, Keyword::TEMP) => Ok(GrantPrivilege::Temporary(
503            parser.consume_keyword(Keyword::TEMP)?,
504        )),
505        Token::Ident(_, Keyword::EXECUTE) => Ok(GrantPrivilege::Execute(
506            parser.consume_keyword(Keyword::EXECUTE)?,
507        )),
508        Token::Ident(_, Keyword::SET) => {
509            Ok(GrantPrivilege::Set(parser.consume_keyword(Keyword::SET)?))
510        }
511        Token::Ident(_, Keyword::ALTER) => {
512            let alter = parser.consume_keyword(Keyword::ALTER)?;
513            let sys = parser.consume_keyword(Keyword::SYSTEM)?;
514            Ok(GrantPrivilege::AlterSystem(alter.join_span(&sys)))
515        }
516        Token::Ident(_, Keyword::ALL) => {
517            let all = parser.consume_keyword(Keyword::ALL)?;
518            let privileges = parser.skip_keyword(Keyword::PRIVILEGES);
519            Ok(GrantPrivilege::All(all, privileges))
520        }
521        _ => parser.expected_failure("privilege keyword"),
522    }
523}
524
525fn parse_privilege_list<'a>(
526    parser: &mut Parser<'a, '_>,
527) -> Result<Vec<PrivilegeItem<'a>>, ParseError> {
528    let mut items = Vec::new();
529    loop {
530        let privilege = parse_privilege(parser)?;
531        let mut columns = Vec::new();
532        if matches!(parser.token, Token::LParen) {
533            parser.consume_token(Token::LParen)?;
534            parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
535                loop {
536                    columns.push(parser.consume_plain_identifier_unreserved()?);
537                    if parser.skip_token(Token::Comma).is_none() {
538                        break;
539                    }
540                }
541                Ok(())
542            })?;
543            parser.consume_token(Token::RParen)?;
544        }
545        items.push(PrivilegeItem { privilege, columns });
546        if parser.skip_token(Token::Comma).is_none() {
547            break;
548        }
549        // If after the comma we don't see a privilege keyword, stop - could be ON
550        if !is_privilege_keyword(&parser.token) {
551            break;
552        }
553    }
554    Ok(items)
555}
556
557fn parse_role_spec<'a>(parser: &mut Parser<'a, '_>) -> Result<RoleSpec<'a>, ParseError> {
558    match &parser.token {
559        Token::Ident(_, Keyword::PUBLIC) => {
560            Ok(RoleSpec::Public(parser.consume_keyword(Keyword::PUBLIC)?))
561        }
562        Token::Ident(_, Keyword::CURRENT_ROLE) => Ok(RoleSpec::CurrentRole(
563            parser.consume_keyword(Keyword::CURRENT_ROLE)?,
564        )),
565        Token::Ident(_, Keyword::CURRENT_USER) => Ok(RoleSpec::CurrentUser(
566            parser.consume_keyword(Keyword::CURRENT_USER)?,
567        )),
568        Token::Ident(_, Keyword::SESSION_USER) => Ok(RoleSpec::SessionUser(
569            parser.consume_keyword(Keyword::SESSION_USER)?,
570        )),
571        Token::Ident(_, Keyword::GROUP) => {
572            let group_kw = Some(parser.consume_keyword(Keyword::GROUP)?);
573            let name = parser.consume_plain_identifier_unreserved()?;
574            Ok(RoleSpec::Named { group_kw, name })
575        }
576        _ => {
577            let name = parser.consume_plain_identifier_unreserved()?;
578            Ok(RoleSpec::Named {
579                group_kw: None,
580                name,
581            })
582        }
583    }
584}
585
586fn parse_role_spec_list<'a>(parser: &mut Parser<'a, '_>) -> Result<Vec<RoleSpec<'a>>, ParseError> {
587    let mut list = Vec::new();
588    loop {
589        list.push(parse_role_spec(parser)?);
590        if parser.skip_token(Token::Comma).is_none() {
591            break;
592        }
593    }
594    Ok(list)
595}
596
597fn parse_granted_by<'a>(
598    parser: &mut Parser<'a, '_>,
599) -> Result<Option<(Span, RoleSpec<'a>)>, ParseError> {
600    if let Some(granted_span) = parser.skip_keyword(Keyword::GRANTED) {
601        let by_span = parser.consume_keyword(Keyword::BY)?;
602        let role = parse_role_spec(parser)?;
603        Ok(Some((granted_span.join_span(&by_span), role)))
604    } else {
605        Ok(None)
606    }
607}
608
609fn parse_routine_arg_list<'a>(
610    parser: &mut Parser<'a, '_>,
611) -> Result<Vec<RoutineArgType<'a>>, ParseError> {
612    let mut args = Vec::new();
613    parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
614        loop {
615            if matches!(parser.token, Token::RParen) {
616                break;
617            }
618            let mode = match &parser.token {
619                Token::Ident(_, Keyword::IN) => {
620                    let in_ = parser.consume_keyword(Keyword::IN)?;
621                    if let Some(out) = parser.skip_keyword(Keyword::OUT) {
622                        Some(FunctionParamDirection::InOut(in_.join_span(&out)))
623                    } else {
624                        Some(FunctionParamDirection::In(in_))
625                    }
626                }
627                Token::Ident(_, Keyword::OUT) => Some(FunctionParamDirection::Out(
628                    parser.consume_keyword(Keyword::OUT)?,
629                )),
630                Token::Ident(_, Keyword::INOUT) => Some(FunctionParamDirection::InOut(
631                    parser.consume_keyword(Keyword::INOUT)?,
632                )),
633                _ => None,
634            };
635            // Peek: if next token after this one looks like a type start, this is a name
636            let name = {
637                let is_unnamed = matches!(
638                    parser.peek(),
639                    Token::Comma | Token::RParen | Token::LBracket
640                );
641                if is_unnamed {
642                    None
643                } else {
644                    Some(parser.consume_plain_identifier_unreserved()?)
645                }
646            };
647            let type_ = parse_data_type(parser, DataTypeContext::FunctionParam)?;
648            args.push(RoutineArgType { mode, name, type_ });
649            if parser.skip_token(Token::Comma).is_none() {
650                break;
651            }
652        }
653        Ok(())
654    })?;
655    Ok(args)
656}
657
658fn parse_routine_name_list<'a>(
659    parser: &mut Parser<'a, '_>,
660) -> Result<Vec<RoutineName<'a>>, ParseError> {
661    let mut names = Vec::new();
662    loop {
663        let name = parse_qualified_name_unreserved(parser)?;
664        let args = if matches!(parser.token, Token::LParen) {
665            parser.consume_token(Token::LParen)?;
666            let args = parse_routine_arg_list(parser)?;
667            parser.consume_token(Token::RParen)?;
668            Some(args)
669        } else {
670            None
671        };
672        names.push(RoutineName { name, args });
673        if parser.skip_token(Token::Comma).is_none() {
674            break;
675        }
676    }
677    Ok(names)
678}
679
680fn parse_qualified_name_list<'a>(
681    parser: &mut Parser<'a, '_>,
682) -> Result<Vec<QualifiedName<'a>>, ParseError> {
683    let mut names = Vec::new();
684    loop {
685        names.push(parse_qualified_name_unreserved(parser)?);
686        if parser.skip_token(Token::Comma).is_none() {
687            break;
688        }
689    }
690    Ok(names)
691}
692
693fn parse_grant_object<'a>(parser: &mut Parser<'a, '_>) -> Result<GrantObject<'a>, ParseError> {
694    match &parser.token {
695        Token::Ident(_, Keyword::TABLE) => {
696            let table_kw = Some(parser.consume_keyword(Keyword::TABLE)?);
697            let names = parse_qualified_name_list(parser)?;
698            Ok(GrantObject::Tables { table_kw, names })
699        }
700        Token::Ident(_, Keyword::ALL) => {
701            let all_span = parser.consume_keyword(Keyword::ALL)?;
702            match &parser.token {
703                Token::Ident(_, Keyword::TABLES) => {
704                    let table_in_schema_span = parser.consume_keywords(&[
705                        Keyword::TABLES,
706                        Keyword::IN,
707                        Keyword::SCHEMA,
708                    ])?;
709                    let schemas = parse_qualified_name_list(parser)?;
710                    Ok(GrantObject::AllTablesInSchema {
711                        span: all_span.join_span(&table_in_schema_span),
712                        schemas,
713                    })
714                }
715                Token::Ident(_, Keyword::SEQUENCES) => {
716                    let in_sequences_schema_span = parser.consume_keywords(&[
717                        Keyword::SEQUENCES,
718                        Keyword::IN,
719                        Keyword::SCHEMA,
720                    ])?;
721                    let schemas = parse_qualified_name_list(parser)?;
722                    Ok(GrantObject::AllSequencesInSchema {
723                        span: all_span.join_span(&in_sequences_schema_span),
724                        schemas,
725                    })
726                }
727                Token::Ident(_, Keyword::FUNCTIONS) => {
728                    let kind_span = parser.consume_keyword(Keyword::FUNCTIONS)?;
729                    let in_schema_span =
730                        parser.consume_keywords(&[Keyword::IN, Keyword::SCHEMA])?;
731                    let schemas = parse_qualified_name_list(parser)?;
732                    Ok(GrantObject::AllRoutinesInSchema {
733                        all_span,
734                        kind: AllRoutineKind::Functions(kind_span),
735                        in_schema_span,
736                        schemas,
737                    })
738                }
739                Token::Ident(_, Keyword::PROCEDURES) => {
740                    let kind_span = parser.consume_keyword(Keyword::PROCEDURES)?;
741                    let in_schema_span =
742                        parser.consume_keywords(&[Keyword::IN, Keyword::SCHEMA])?;
743                    let schemas = parse_qualified_name_list(parser)?;
744                    Ok(GrantObject::AllRoutinesInSchema {
745                        all_span,
746                        kind: AllRoutineKind::Procedures(kind_span),
747                        in_schema_span,
748                        schemas,
749                    })
750                }
751                Token::Ident(_, Keyword::ROUTINES) => {
752                    let kind_span = parser.consume_keyword(Keyword::ROUTINES)?;
753                    let in_schema_span =
754                        parser.consume_keywords(&[Keyword::IN, Keyword::SCHEMA])?;
755                    let schemas = parse_qualified_name_list(parser)?;
756                    Ok(GrantObject::AllRoutinesInSchema {
757                        all_span,
758                        kind: AllRoutineKind::Routines(kind_span),
759                        in_schema_span,
760                        schemas,
761                    })
762                }
763                _ => parser.expected_failure(
764                    "TABLES, SEQUENCES, FUNCTIONS, PROCEDURES, or ROUTINES after ALL",
765                ),
766            }
767        }
768        Token::Ident(_, Keyword::SEQUENCE) => {
769            let sequence_kw = parser.consume_keyword(Keyword::SEQUENCE)?;
770            let names = parse_qualified_name_list(parser)?;
771            Ok(GrantObject::Sequences { sequence_kw, names })
772        }
773        Token::Ident(_, Keyword::DATABASE) => {
774            let database_kw = parser.consume_keyword(Keyword::DATABASE)?;
775            let names = parse_qualified_name_list(parser)?;
776            Ok(GrantObject::Databases { database_kw, names })
777        }
778        Token::Ident(_, Keyword::DOMAIN) => {
779            let domain_kw = parser.consume_keyword(Keyword::DOMAIN)?;
780            let names = parse_qualified_name_list(parser)?;
781            Ok(GrantObject::Domains { domain_kw, names })
782        }
783        Token::Ident(_, Keyword::FOREIGN) => {
784            let foreign_span = parser.consume_keyword(Keyword::FOREIGN)?;
785            match &parser.token {
786                Token::Ident(_, Keyword::DATA) => {
787                    let data_span = parser.consume_keyword(Keyword::DATA)?;
788                    let wrapper_span = parser.consume_keyword(Keyword::WRAPPER)?;
789                    let names = parse_qualified_name_list(parser)?;
790                    Ok(GrantObject::ForeignDataWrappers {
791                        span: foreign_span.join_span(&data_span).join_span(&wrapper_span),
792                        names,
793                    })
794                }
795                Token::Ident(_, Keyword::SERVER) => {
796                    let server_span = parser.consume_keyword(Keyword::SERVER)?;
797                    let names = parse_qualified_name_list(parser)?;
798                    Ok(GrantObject::ForeignServers {
799                        span: foreign_span.join_span(&server_span),
800                        names,
801                    })
802                }
803                _ => parser.expected_failure("DATA WRAPPER or SERVER after FOREIGN"),
804            }
805        }
806        Token::Ident(_, Keyword::FUNCTION) => {
807            let kw = parser.consume_keyword(Keyword::FUNCTION)?;
808            let names = parse_routine_name_list(parser)?;
809            Ok(GrantObject::Routines {
810                kind: RoutineKind::Function(kw),
811                names,
812            })
813        }
814        Token::Ident(_, Keyword::PROCEDURE) => {
815            let kw = parser.consume_keyword(Keyword::PROCEDURE)?;
816            let names = parse_routine_name_list(parser)?;
817            Ok(GrantObject::Routines {
818                kind: RoutineKind::Procedure(kw),
819                names,
820            })
821        }
822        Token::Ident(_, Keyword::ROUTINE) => {
823            let kw = parser.consume_keyword(Keyword::ROUTINE)?;
824            let names = parse_routine_name_list(parser)?;
825            Ok(GrantObject::Routines {
826                kind: RoutineKind::Routine(kw),
827                names,
828            })
829        }
830        Token::Ident(_, Keyword::LANGUAGE) => {
831            let language_kw = parser.consume_keyword(Keyword::LANGUAGE)?;
832            let names = parse_qualified_name_list(parser)?;
833            Ok(GrantObject::Languages { language_kw, names })
834        }
835        Token::Ident(_, Keyword::LARGE) => {
836            let large_span = parser.consume_keyword(Keyword::LARGE)?;
837            let object_span = parser.consume_keyword(Keyword::OBJECT)?;
838            let mut oids = Vec::new();
839            loop {
840                oids.push(parse_expression_unreserved(parser, PRIORITY_MAX)?);
841                if parser.skip_token(Token::Comma).is_none() {
842                    break;
843                }
844            }
845            Ok(GrantObject::LargeObjects {
846                span: large_span.join_span(&object_span),
847                oids,
848            })
849        }
850        Token::Ident(_, Keyword::PARAMETER) => {
851            let parameter_kw = parser.consume_keyword(Keyword::PARAMETER)?;
852            let names = parse_qualified_name_list(parser)?;
853            Ok(GrantObject::Parameters {
854                parameter_kw,
855                names,
856            })
857        }
858        Token::Ident(_, Keyword::SCHEMA) => {
859            let schema_kw = parser.consume_keyword(Keyword::SCHEMA)?;
860            let names = parse_qualified_name_list(parser)?;
861            Ok(GrantObject::Schemas { schema_kw, names })
862        }
863        Token::Ident(_, Keyword::TABLESPACE) => {
864            let tablespace_kw = parser.consume_keyword(Keyword::TABLESPACE)?;
865            let names = parse_qualified_name_list(parser)?;
866            Ok(GrantObject::Tablespaces {
867                tablespace_kw,
868                names,
869            })
870        }
871        Token::Ident(_, Keyword::TYPE) => {
872            let type_kw = parser.consume_keyword(Keyword::TYPE)?;
873            let names = parse_qualified_name_list(parser)?;
874            Ok(GrantObject::Types { type_kw, names })
875        }
876        _ => {
877            // Bare table name without TABLE keyword
878            let names = parse_qualified_name_list(parser)?;
879            Ok(GrantObject::Tables {
880                table_kw: None,
881                names,
882            })
883        }
884    }
885}
886
887pub(crate) fn parse_grant<'a>(parser: &mut Parser<'a, '_>) -> Result<Grant<'a>, ParseError> {
888    let grant_span = parser.consume_keyword(Keyword::GRANT)?;
889
890    // Disambiguate: if the first token is a privilege keyword, this is a privilege grant.
891    // Otherwise it is a role-membership grant.
892    let kind = if is_privilege_keyword(&parser.token) {
893        let privileges = parse_privilege_list(parser)?;
894        let on_span = parser.consume_keyword(Keyword::ON)?;
895        let object = parse_grant_object(parser)?;
896        let to_span = parser.consume_keyword(Keyword::TO)?;
897        let grantees = parse_role_spec_list(parser)?;
898
899        // WITH GRANT OPTION
900        let with_grant_option = if let Some(with_span) = parser.skip_keyword(Keyword::WITH) {
901            let grant_span = parser.consume_keyword(Keyword::GRANT)?;
902            let option_span = parser.consume_keyword(Keyword::OPTION)?;
903            Some(with_span.join_span(&grant_span).join_span(&option_span))
904        } else {
905            None
906        };
907
908        let granted_by = parse_granted_by(parser)?;
909
910        GrantKind::Privilege {
911            privileges,
912            on_span,
913            object,
914            to_span,
915            grantees,
916            with_grant_option,
917            granted_by,
918        }
919    } else {
920        let roles = parse_qualified_name_list(parser)?;
921        let to_span = parser.consume_keyword(Keyword::TO)?;
922        let grantees = parse_role_spec_list(parser)?;
923
924        // WITH { ADMIN | INHERIT | SET } { OPTION | TRUE | FALSE }
925        let with_option = if let Some(with_span) = parser.skip_keyword(Keyword::WITH) {
926            let kind = match &parser.token {
927                Token::Ident(_, Keyword::ADMIN) => {
928                    MembershipOptionKind::Admin(parser.consume_keyword(Keyword::ADMIN)?)
929                }
930                Token::Ident(_, Keyword::INHERIT) => {
931                    MembershipOptionKind::Inherit(parser.consume_keyword(Keyword::INHERIT)?)
932                }
933                Token::Ident(_, Keyword::SET) => {
934                    MembershipOptionKind::Set(parser.consume_keyword(Keyword::SET)?)
935                }
936                _ => parser.expected_failure("ADMIN, INHERIT, or SET after WITH")?,
937            };
938            let value = match &parser.token {
939                Token::Ident(_, Keyword::OPTION) => {
940                    MembershipOptionValue::Option(parser.consume_keyword(Keyword::OPTION)?)
941                }
942                Token::Ident(_, Keyword::TRUE) => {
943                    MembershipOptionValue::True(parser.consume_keyword(Keyword::TRUE)?)
944                }
945                Token::Ident(_, Keyword::FALSE) => {
946                    MembershipOptionValue::False(parser.consume_keyword(Keyword::FALSE)?)
947                }
948                _ => parser.expected_failure("OPTION, TRUE, or FALSE")?,
949            };
950            Some(MembershipOption {
951                with_span,
952                kind,
953                value,
954            })
955        } else {
956            None
957        };
958
959        let granted_by = parse_granted_by(parser)?;
960
961        GrantKind::Role {
962            roles,
963            to_span,
964            grantees,
965            with_option,
966            granted_by,
967        }
968    };
969
970    Ok(Grant { grant_span, kind })
971}