Skip to main content

qusql_parse/
alter_sequence.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
13use alloc::vec::Vec;
14
15use crate::create::parse_sequence_options;
16use crate::{
17    Identifier, OptSpanned, QualifiedName, SequenceOption, Span, Spanned,
18    alter_table::{AlterTableOwner, parse_alter_owner},
19    keywords::Keyword,
20    lexer::Token,
21    parser::{ParseError, Parser},
22    qualified_name::parse_qualified_name_unreserved,
23};
24
25/// ALTER SEQUENCE action (PostgreSQL)
26#[derive(Clone, Debug)]
27pub enum AlterSequenceAction<'a> {
28    /// One or more sequence option changes:
29    /// AS / INCREMENT / MINVALUE / MAXVALUE / START / RESTART / CACHE / CYCLE / OWNED BY
30    Options(Vec<SequenceOption<'a>>),
31    /// RENAME TO new_name
32    RenameTo {
33        rename_to_span: Span,
34        new_name: Identifier<'a>,
35    },
36    /// SET SCHEMA new_schema
37    SetSchema {
38        set_schema_span: Span,
39        new_schema: Identifier<'a>,
40    },
41    /// OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
42    OwnerTo {
43        owner_to_span: Span,
44        new_owner: AlterTableOwner<'a>,
45    },
46}
47
48impl<'a> Spanned for AlterSequenceAction<'a> {
49    fn span(&self) -> Span {
50        match self {
51            // Options is never empty: parse_alter_sequence rejects an empty option list
52            AlterSequenceAction::Options(options) => options.opt_span().unwrap(),
53            AlterSequenceAction::RenameTo {
54                rename_to_span,
55                new_name,
56            } => rename_to_span.join_span(new_name),
57            AlterSequenceAction::SetSchema {
58                set_schema_span,
59                new_schema,
60            } => set_schema_span.join_span(new_schema),
61            AlterSequenceAction::OwnerTo {
62                owner_to_span,
63                new_owner,
64            } => owner_to_span.join_span(new_owner),
65        }
66    }
67}
68
69/// ALTER SEQUENCE statement (PostgreSQL)
70/// ```
71/// # use qusql_parse::{SQLDialect, SQLArguments, ParseOptions, parse_statements, AlterSequence, AlterSequenceAction, Statement, Issues};
72/// # let options = ParseOptions::new().dialect(SQLDialect::PostgreSQL);
73/// #
74/// let sql = "ALTER SEQUENCE myseq OWNER TO compute;";
75/// let mut issues = Issues::new(sql);
76/// let mut stmts = parse_statements(sql, &mut issues, &options);
77///
78/// # assert!(issues.is_ok());
79/// let s: AlterSequence = match stmts.pop() {
80///     Some(Statement::AlterSequence(s)) => *s,
81///     _ => panic!("We should get an alter sequence statement")
82/// };
83///
84/// assert!(s.name.identifier.as_str() == "myseq");
85/// assert!(matches!(s.action, AlterSequenceAction::OwnerTo { .. }));
86/// ```
87#[derive(Clone, Debug)]
88pub struct AlterSequence<'a> {
89    /// Span of "ALTER SEQUENCE"
90    pub alter_sequence_span: Span,
91    /// Span of "IF EXISTS" if specified
92    pub if_exists: Option<Span>,
93    /// Name of the sequence being altered
94    pub name: QualifiedName<'a>,
95    /// The action applied to the sequence
96    pub action: AlterSequenceAction<'a>,
97}
98
99impl<'a> Spanned for AlterSequence<'a> {
100    fn span(&self) -> Span {
101        self.alter_sequence_span
102            .join_span(&self.if_exists)
103            .join_span(&self.name)
104            .join_span(&self.action)
105    }
106}
107
108/// Parse ALTER SEQUENCE statement (PostgreSQL).
109/// `alter_sequence_span` is the span of the "ALTER SEQUENCE" keywords.
110pub(crate) fn parse_alter_sequence<'a>(
111    parser: &mut Parser<'a, '_>,
112    alter_sequence_span: Span,
113) -> Result<AlterSequence<'a>, ParseError> {
114    parser.postgres_only(&alter_sequence_span);
115    let if_exists = if let Some(if_span) = parser.skip_keyword(Keyword::IF) {
116        Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&if_span))
117    } else {
118        None
119    };
120    let name = parse_qualified_name_unreserved(parser)?;
121    let action = match &parser.token {
122        Token::Ident(_, Keyword::RENAME) => {
123            let rename_to_span = parser.consume_keywords(&[Keyword::RENAME, Keyword::TO])?;
124            let new_name = parser.consume_plain_identifier_unreserved()?;
125            AlterSequenceAction::RenameTo {
126                rename_to_span,
127                new_name,
128            }
129        }
130        Token::Ident(_, Keyword::SET) => {
131            let set_span = parser.consume_keyword(Keyword::SET)?;
132            if let Token::Ident(_, Keyword::SCHEMA) = parser.token {
133                let schema_span = parser.consume_keyword(Keyword::SCHEMA)?;
134                let new_schema = parser.consume_plain_identifier_unreserved()?;
135                AlterSequenceAction::SetSchema {
136                    set_schema_span: set_span.join_span(&schema_span),
137                    new_schema,
138                }
139            } else {
140                parser.expected_failure("'SCHEMA' after 'SET' in ALTER SEQUENCE")?
141            }
142        }
143        Token::Ident(_, Keyword::OWNER) => {
144            let owner_to_span = parser.consume_keywords(&[Keyword::OWNER, Keyword::TO])?;
145            let new_owner = parse_alter_owner(parser)?;
146            AlterSequenceAction::OwnerTo {
147                owner_to_span,
148                new_owner,
149            }
150        }
151        _ => {
152            let options = parse_sequence_options(parser)?;
153            if options.is_empty() {
154                parser.expected_failure("sequence options, 'RENAME TO', 'SET SCHEMA' or 'OWNER TO' after ALTER SEQUENCE")?;
155            }
156            AlterSequenceAction::Options(options)
157        }
158    };
159    Ok(AlterSequence {
160        alter_sequence_span,
161        if_exists,
162        name,
163        action,
164    })
165}