sql_parse/
alter.rs

1use alloc::vec::Vec;
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14use crate::{
15    data_type::parse_data_type,
16    expression::parse_expression,
17    keywords::Keyword,
18    lexer::Token,
19    parser::{ParseError, Parser},
20    qualified_name::parse_qualified_name,
21    DataType, Expression, Identifier, QualifiedName, SString, Span, Spanned, Statement,
22};
23
24/// Option on an index
25#[derive(Clone, Debug)]
26pub enum IndexOption<'a> {
27    /// The index should be a BTree
28    IndexTypeBTree(Span),
29    /// The index should be hashed
30    IndexTypeHash(Span),
31    /// The index should be an RTree
32    IndexTypeRTree(Span),
33    /// Attach a comment to the index
34    Comment(SString<'a>),
35}
36
37impl<'a> Spanned for IndexOption<'a> {
38    fn span(&self) -> Span {
39        match &self {
40            IndexOption::IndexTypeBTree(v) => v.span(),
41            IndexOption::IndexTypeHash(v) => v.span(),
42            IndexOption::IndexTypeRTree(v) => v.span(),
43            IndexOption::Comment(v) => v.span(),
44        }
45    }
46}
47
48/// Type of index to add
49#[derive(Clone, Debug)]
50pub enum IndexType {
51    Index(Span),
52    Primary(Span),
53    Unique(Span),
54    FullText(Span),
55    Spatial(Span),
56}
57
58impl Spanned for IndexType {
59    fn span(&self) -> Span {
60        match &self {
61            IndexType::Index(v) => v.span(),
62            IndexType::Primary(v) => v.span(),
63            IndexType::Unique(v) => v.span(),
64            IndexType::FullText(v) => v.span(),
65            IndexType::Spatial(v) => v.span(),
66        }
67    }
68}
69
70/// When to take a foreign key action
71#[derive(Clone, Debug)]
72pub enum ForeignKeyOnType {
73    Update(Span),
74    Delete(Span),
75}
76
77impl Spanned for ForeignKeyOnType {
78    fn span(&self) -> Span {
79        match &self {
80            ForeignKeyOnType::Update(v) => v.span(),
81            ForeignKeyOnType::Delete(v) => v.span(),
82        }
83    }
84}
85
86/// Action to take on event for foreign key
87#[derive(Clone, Debug)]
88pub enum ForeignKeyOnAction {
89    Restrict(Span),
90    Cascade(Span),
91    SetNull(Span),
92    NoAction(Span),
93    SetDefault(Span),
94}
95
96impl Spanned for ForeignKeyOnAction {
97    fn span(&self) -> Span {
98        match &self {
99            ForeignKeyOnAction::Restrict(v) => v.span(),
100            ForeignKeyOnAction::Cascade(v) => v.span(),
101            ForeignKeyOnAction::SetNull(v) => v.span(),
102            ForeignKeyOnAction::NoAction(v) => v.span(),
103            ForeignKeyOnAction::SetDefault(v) => v.span(),
104        }
105    }
106}
107
108/// Action to perform on events on foreign keys
109#[derive(Clone, Debug)]
110pub struct ForeignKeyOn {
111    pub type_: ForeignKeyOnType,
112    pub action: ForeignKeyOnAction,
113}
114
115impl Spanned for ForeignKeyOn {
116    fn span(&self) -> Span {
117        self.type_.join_span(&self.action)
118    }
119}
120
121/// Specify a column for an index, together with a with
122#[derive(Clone, Debug)]
123pub struct IndexCol<'a> {
124    /// The name of the column
125    pub name: Identifier<'a>,
126    /// Optional width of index together with its span
127    pub size: Option<(u32, Span)>,
128}
129
130impl<'a> Spanned for IndexCol<'a> {
131    fn span(&self) -> Span {
132        self.name.join_span(&self.size)
133    }
134}
135
136/// Enum of alterations to perform on a column
137#[derive(Clone, Debug)]
138pub enum AlterColumnAction<'a> {
139    SetDefault {
140        set_default_span: Span,
141        value: Expression<'a>,
142    },
143    DropDefault {
144        drop_default_span: Span,
145    },
146    Type {
147        type_span: Span,
148        type_: DataType<'a>,
149    },
150    SetNotNull {
151        set_not_null_span: Span,
152    },
153    DropNotNull {
154        drop_not_null_span: Span,
155    },
156}
157
158impl<'a> Spanned for AlterColumnAction<'a> {
159    fn span(&self) -> Span {
160        match self {
161            AlterColumnAction::SetDefault {
162                set_default_span,
163                value,
164            } => set_default_span.join_span(value),
165            AlterColumnAction::DropDefault { drop_default_span } => drop_default_span.clone(),
166            AlterColumnAction::Type { type_span, type_ } => type_span.join_span(type_),
167            AlterColumnAction::SetNotNull { set_not_null_span } => set_not_null_span.clone(),
168            AlterColumnAction::DropNotNull { drop_not_null_span } => drop_not_null_span.clone(),
169        }
170    }
171}
172
173/// Enum of alterations to perform on a table
174#[derive(Clone, Debug)]
175pub enum AlterSpecification<'a> {
176    AddColumn {
177        add_span: Span,
178        if_not_exists_span: Option<Span>,
179        identifier: Identifier<'a>,
180        data_type: DataType<'a>,
181    },
182    /// Add an index
183    AddIndex {
184        /// Span of "ADD"
185        add_span: Span,
186        /// The type of index to add
187        index_type: IndexType,
188        /// Span of "IF NOT EXISTS" if specified
189        if_not_exists: Option<Span>,
190        /// Named of index if specified
191        name: Option<Identifier<'a>>,
192        /// Optional "CONSTRAINT" with symbol if specified
193        constraint: Option<(Span, Option<Identifier<'a>>)>,
194        /// Columns to add the index over
195        cols: Vec<IndexCol<'a>>,
196        /// Options on the index
197        index_options: Vec<IndexOption<'a>>,
198    },
199    /// Add a foreign key
200    AddForeignKey {
201        /// Span of "ADD"
202        add_span: Span,
203        /// Optional "CONSTRAINT" with symbol if specified
204        constraint: Option<(Span, Option<Identifier<'a>>)>,
205        /// Span of "FOREIGN KEY"
206        foreign_key_span: Span,
207        /// Span of "IF NOT EXISTS" if specified
208        if_not_exists: Option<Span>,
209        /// Named of index if specified
210        name: Option<Identifier<'a>>,
211        /// Columns to add the index over
212        cols: Vec<IndexCol<'a>>,
213        /// Span of "REFERENCES"
214        references_span: Span,
215        /// Refereed table
216        references_table: Identifier<'a>,
217        /// Columns in referred table
218        references_cols: Vec<Identifier<'a>>,
219        /// List of what should happen at specified events
220        ons: Vec<ForeignKeyOn>,
221    },
222    /// Modify a column
223    Modify {
224        /// Span of "MODIFY"
225        modify_span: Span,
226        /// Span of "IF EXISTS" if specified
227        if_exists: Option<Span>,
228        /// Name of column to modify
229        col: Identifier<'a>,
230        /// New definition of column
231        definition: DataType<'a>,
232    },
233    DropColumn {
234        /// Span of "DROP COLUMN"
235        drop_column_span: Span,
236        /// Name of column to drop
237        column: Identifier<'a>,
238        /// Span of "CASCADE" if specified
239        cascade: Option<Span>,
240    },
241    AlterColumn {
242        /// Span of "ALTER COLUMN"
243        alter_column_span: Span,
244        /// Name of column to drop
245        column: Identifier<'a>,
246        alter_column_action: AlterColumnAction<'a>,
247    },
248    /// Modify a column
249    OwnerTo {
250        // Span of "OWNER TO"
251        span: Span,
252        /// Name of owner
253        owner: Identifier<'a>,
254    },
255}
256
257impl<'a> Spanned for AlterSpecification<'a> {
258    fn span(&self) -> Span {
259        match &self {
260            AlterSpecification::AddColumn {
261                add_span,
262                if_not_exists_span,
263                identifier,
264                data_type,
265            } => add_span
266                .join_span(if_not_exists_span)
267                .join_span(identifier)
268                .join_span(data_type),
269            AlterSpecification::AddIndex {
270                add_span,
271                index_type,
272                if_not_exists,
273                name,
274                constraint,
275                cols,
276                index_options,
277            } => add_span
278                .join_span(index_type)
279                .join_span(if_not_exists)
280                .join_span(name)
281                .join_span(constraint)
282                .join_span(cols)
283                .join_span(index_options),
284            AlterSpecification::AddForeignKey {
285                add_span,
286                constraint,
287                foreign_key_span: foregin_key_span,
288                if_not_exists,
289                name,
290                cols,
291                references_span,
292                references_table,
293                references_cols,
294                ons,
295            } => add_span
296                .join_span(constraint)
297                .join_span(foregin_key_span)
298                .join_span(if_not_exists)
299                .join_span(name)
300                .join_span(cols)
301                .join_span(references_span)
302                .join_span(references_table)
303                .join_span(references_cols)
304                .join_span(ons),
305            AlterSpecification::Modify {
306                modify_span,
307                if_exists,
308                col,
309                definition,
310            } => modify_span
311                .join_span(if_exists)
312                .join_span(col)
313                .join_span(definition),
314            AlterSpecification::OwnerTo { span, owner } => span.join_span(owner),
315            AlterSpecification::DropColumn {
316                drop_column_span,
317                column: col,
318                cascade,
319            } => drop_column_span.join_span(col).join_span(cascade),
320            AlterSpecification::AlterColumn {
321                alter_column_span,
322                column: col,
323                alter_column_action,
324            } => alter_column_span
325                .join_span(col)
326                .join_span(alter_column_action),
327        }
328    }
329}
330
331fn parse_index_type<'a>(
332    parser: &mut Parser<'a, '_>,
333    out: &mut Vec<IndexOption<'a>>,
334) -> Result<(), ParseError> {
335    parser.consume_keyword(Keyword::USING)?;
336    out.push(match &parser.token {
337        Token::Ident(_, Keyword::BTREE) => {
338            IndexOption::IndexTypeBTree(parser.consume_keyword(Keyword::BTREE)?)
339        }
340        Token::Ident(_, Keyword::HASH) => {
341            IndexOption::IndexTypeHash(parser.consume_keyword(Keyword::HASH)?)
342        }
343        Token::Ident(_, Keyword::RTREE) => {
344            IndexOption::IndexTypeRTree(parser.consume_keyword(Keyword::RTREE)?)
345        }
346        _ => parser.expected_failure("'BTREE', 'RTREE' or 'HASH'")?,
347    });
348    Ok(())
349}
350
351fn parse_index_options<'a>(
352    parser: &mut Parser<'a, '_>,
353    out: &mut Vec<IndexOption<'a>>,
354) -> Result<(), ParseError> {
355    loop {
356        match &parser.token {
357            Token::Ident(_, Keyword::USING) => parse_index_type(parser, out)?,
358            Token::Ident(_, Keyword::COMMENT) => {
359                parser.consume_keyword(Keyword::COMMENT)?;
360                out.push(IndexOption::Comment(parser.consume_string()?))
361            }
362            _ => break,
363        }
364    }
365    Ok(())
366}
367
368fn parse_index_cols<'a>(parser: &mut Parser<'a, '_>) -> Result<Vec<IndexCol<'a>>, ParseError> {
369    parser.consume_token(Token::LParen)?;
370    let mut ans = Vec::new();
371    parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
372        loop {
373            let name = parser.consume_plain_identifier()?;
374            let size = if parser.skip_token(Token::LParen).is_some() {
375                let size = parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
376                    parser.consume_int()
377                })?;
378                parser.consume_token(Token::RParen)?;
379                Some(size)
380            } else {
381                None
382            };
383
384            // TODO [ASC | DESC]
385
386            ans.push(IndexCol { name, size });
387            if parser.skip_token(Token::Comma).is_none() {
388                break;
389            }
390        }
391        Ok(())
392    })?;
393    parser.consume_token(Token::RParen)?;
394    Ok(ans)
395}
396
397fn parse_cols<'a>(parser: &mut Parser<'a, '_>) -> Result<Vec<Identifier<'a>>, ParseError> {
398    parser.consume_token(Token::LParen)?;
399    let mut ans = Vec::new();
400    parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
401        loop {
402            ans.push(parser.consume_plain_identifier()?);
403            if parser.skip_token(Token::Comma).is_none() {
404                break;
405            }
406        }
407        Ok(())
408    })?;
409    parser.consume_token(Token::RParen)?;
410    Ok(ans)
411}
412
413fn parse_add_alter_specification<'a>(
414    parser: &mut Parser<'a, '_>,
415) -> Result<AlterSpecification<'a>, ParseError> {
416    let add_span = parser.consume_keyword(Keyword::ADD)?;
417    let constraint = if let Some(span) = parser.skip_keyword(Keyword::CONSTRAINT) {
418        let v = match &parser.token {
419            Token::Ident(_, kw) if !kw.reserved() => Some(parser.consume_plain_identifier()?),
420            _ => None,
421        };
422        Some((span, v))
423    } else {
424        None
425    };
426    match &parser.token {
427        Token::Ident(_, Keyword::FOREIGN) => {
428            let foregin_key_span = parser.consume_keywords(&[Keyword::FOREIGN, Keyword::KEY])?;
429            let if_not_exists = if let Some(s) = parser.skip_keyword(Keyword::IF) {
430                Some(
431                    parser
432                        .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
433                        .join_span(&s),
434                )
435            } else {
436                None
437            };
438            let name = match &parser.token {
439                Token::Ident(_, kw) if !kw.reserved() => Some(parser.consume_plain_identifier()?),
440                _ => None,
441            };
442
443            let cols = parse_index_cols(parser)?;
444            let references_span = parser.consume_keyword(Keyword::REFERENCES)?;
445            let references_table = parser.consume_plain_identifier()?;
446            let references_cols = parse_cols(parser)?;
447            let mut ons = Vec::new();
448            while let Some(on) = parser.skip_keyword(Keyword::ON) {
449                let type_ = match parser.token {
450                    Token::Ident(_, Keyword::UPDATE) => ForeignKeyOnType::Update(
451                        parser.consume_keyword(Keyword::UPDATE)?.join_span(&on),
452                    ),
453                    Token::Ident(_, Keyword::DELETE) => ForeignKeyOnType::Delete(
454                        parser.consume_keyword(Keyword::DELETE)?.join_span(&on),
455                    ),
456                    _ => parser.expected_failure("'UPDATE' or 'DELETE'")?,
457                };
458
459                let action = match parser.token {
460                    Token::Ident(_, Keyword::RESTRICT) => {
461                        ForeignKeyOnAction::Restrict(parser.consume_keyword(Keyword::RESTRICT)?)
462                    }
463                    Token::Ident(_, Keyword::CASCADE) => {
464                        ForeignKeyOnAction::Cascade(parser.consume_keyword(Keyword::CASCADE)?)
465                    }
466                    Token::Ident(_, Keyword::SET) => {
467                        let set = parser.consume_keyword(Keyword::SET)?;
468                        match parser.token {
469                            Token::Ident(_, Keyword::NULL) => ForeignKeyOnAction::SetNull(
470                                parser.consume_keyword(Keyword::NULL)?.join_span(&set),
471                            ),
472                            Token::Ident(_, Keyword::DELETE) => ForeignKeyOnAction::SetDefault(
473                                parser.consume_keyword(Keyword::DEFAULT)?.join_span(&set),
474                            ),
475                            _ => parser.expected_failure("'NULL' or 'DEFAULT'")?,
476                        }
477                    }
478                    Token::Ident(_, Keyword::NO) => ForeignKeyOnAction::SetNull(
479                        parser.consume_keywords(&[Keyword::NO, Keyword::ACTION])?,
480                    ),
481                    _ => parser.expected_failure("'RESTRICT' or 'CASCADE', 'SET' or 'NO")?,
482                };
483                ons.push(ForeignKeyOn { type_, action })
484            }
485            Ok(AlterSpecification::AddForeignKey {
486                add_span,
487                constraint,
488                foreign_key_span: foregin_key_span,
489                if_not_exists,
490                name,
491                cols,
492                references_span,
493                references_table,
494                references_cols,
495                ons,
496            })
497        }
498        Token::Ident(
499            _,
500            Keyword::PRIMARY
501            | Keyword::INDEX
502            | Keyword::KEY
503            | Keyword::FULLTEXT
504            | Keyword::UNIQUE
505            | Keyword::SPATIAL,
506        ) => {
507            let index_type = match &parser.token {
508                Token::Ident(_, Keyword::PRIMARY) => {
509                    IndexType::Primary(parser.consume_keywords(&[Keyword::PRIMARY, Keyword::KEY])?)
510                }
511                Token::Ident(_, Keyword::INDEX | Keyword::KEY) => {
512                    IndexType::Index(parser.consume())
513                }
514                Token::Ident(_, Keyword::FULLTEXT) => {
515                    let s = parser.consume_keyword(Keyword::FULLTEXT)?;
516                    match &parser.token {
517                        Token::Ident(_, kw @ Keyword::INDEX | kw @ Keyword::KEY) => {
518                            let kw = *kw;
519                            IndexType::FullText(parser.consume_keyword(kw)?.join_span(&s))
520                        }
521                        _ => parser.expected_failure("'KEY' or 'INDEX'")?,
522                    }
523                }
524                Token::Ident(_, Keyword::SPATIAL) => {
525                    let s = parser.consume_keyword(Keyword::SPATIAL)?;
526                    match &parser.token {
527                        Token::Ident(_, kw @ Keyword::INDEX | kw @ Keyword::KEY) => {
528                            let kw = *kw;
529                            IndexType::FullText(parser.consume_keyword(kw)?.join_span(&s))
530                        }
531                        _ => parser.expected_failure("'KEY' or 'INDEX'")?,
532                    }
533                }
534                Token::Ident(_, Keyword::UNIQUE) => {
535                    let s = parser.consume_keyword(Keyword::UNIQUE)?;
536                    match &parser.token {
537                        Token::Ident(_, kw @ Keyword::INDEX | kw @ Keyword::KEY) => {
538                            let kw = *kw;
539                            IndexType::FullText(parser.consume_keyword(kw)?.join_span(&s))
540                        }
541                        _ => parser.expected_failure("'KEY' or 'INDEX'")?,
542                    }
543                }
544                _ => parser.ice(file!(), line!())?,
545            };
546
547            let if_not_exists = if let Some(s) = parser.skip_keyword(Keyword::IF) {
548                Some(
549                    parser
550                        .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
551                        .join_span(&s),
552                )
553            } else {
554                None
555            };
556
557            let name = match &parser.token {
558                Token::Ident(_, kw) if !kw.reserved() => Some(parser.consume_plain_identifier()?),
559                _ => None,
560            };
561
562            let mut index_options = Vec::new();
563            if matches!(parser.token, Token::Ident(_, Keyword::USING)) {
564                parse_index_type(parser, &mut index_options)?;
565            }
566            let cols = parse_index_cols(parser)?;
567            parse_index_options(parser, &mut index_options)?;
568
569            Ok(AlterSpecification::AddIndex {
570                add_span,
571                constraint,
572                index_type,
573                if_not_exists,
574                name,
575                cols,
576                index_options,
577            })
578        }
579        Token::Ident(_, Keyword::COLUMN) => {
580            parser.consume_keyword(Keyword::COLUMN)?;
581            let mut if_not_exists_span = None;
582            if matches!(parser.token, Token::Ident(_, Keyword::IF)) {
583                if_not_exists_span =
584                    Some(parser.consume_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS])?);
585            }
586
587            if let Some(s) = &if_not_exists_span {
588                if parser.options.dialect.is_maria() {
589                    parser.err("IF NOT EXIST is not supported", s);
590                }
591            }
592
593            let identifier = parser.consume_plain_identifier()?;
594            let data_type = parse_data_type(parser, false)?;
595            Ok(AlterSpecification::AddColumn {
596                add_span,
597                if_not_exists_span,
598                identifier,
599                data_type,
600            })
601        }
602        _ => parser.expected_failure("addable"),
603    }
604}
605
606/// Represent an alter table statement
607/// ```
608/// # use sql_parse::{SQLDialect, SQLArguments, ParseOptions, parse_statements, AlterTable, Statement, Issues};
609/// let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
610///
611/// let sql = "ALTER TABLE `t1`
612///     MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,
613///     ADD CONSTRAINT `t1_t2` FOREIGN KEY (`two`) REFERENCES `t2` (`id`);";
614///
615/// let mut issues = Issues::new(sql);
616/// let mut stmts = parse_statements(sql, &mut issues, &options);
617///
618/// # assert!(issues.is_ok());
619/// let alter: AlterTable = match stmts.pop() {
620///     Some(Statement::AlterTable(a)) => a,
621///     _ => panic!("We should get an alter table statement")
622/// };
623///
624/// assert!(alter.table.identifier.as_str() == "t1");
625/// println!("{:#?}", alter.alter_specifications);
626///
627/// let options = ParseOptions::new().dialect(SQLDialect::PostgreSQL);
628/// let sql = "ALTER TABLE t1
629///     ALTER COLUMN id DROP NOT NULL,
630///     ALTER COLUMN id SET NOT NULL,
631///     ALTER COLUMN id SET DEFAULT 47,
632///     ALTER COLUMN id DROP DEFAULT,
633///     ALTER COLUMN id TYPE int;";
634///
635/// let mut issues = Issues::new(sql);
636/// let mut stmts = parse_statements(sql, &mut issues, &options);
637///
638/// # assert!(issues.is_ok());
639/// let alter: AlterTable = match stmts.pop() {
640///     Some(Statement::AlterTable(a)) => a,
641///     _ => panic!("We should get an alter table statement")
642/// };
643///
644#[derive(Clone, Debug)]
645pub struct AlterTable<'a> {
646    /// Span of "ALTER"
647    pub alter_span: Span,
648    /// Span of "ONLINE" if specified
649    pub online: Option<Span>,
650    /// Span of "IGNORE" if specified
651    pub ignore: Option<Span>,
652    /// Span of "TABLE"
653    pub table_span: Span,
654    /// Span of "IF EXISTS" if specified
655    pub if_exists: Option<Span>,
656    /// The identifier of the table to alter
657    pub table: QualifiedName<'a>,
658    /// List of alterations to do
659    pub alter_specifications: Vec<AlterSpecification<'a>>,
660}
661
662impl<'a> Spanned for AlterTable<'a> {
663    fn span(&self) -> Span {
664        self.alter_span
665            .join_span(&self.online)
666            .join_span(&self.ignore)
667            .join_span(&self.table_span)
668            .join_span(&self.if_exists)
669            .join_span(&self.table)
670            .join_span(&self.alter_specifications)
671    }
672}
673
674fn parse_alter_table<'a>(
675    parser: &mut Parser<'a, '_>,
676    alter_span: Span,
677    online: Option<Span>,
678    ignore: Option<Span>,
679) -> Result<AlterTable<'a>, ParseError> {
680    let table_span = parser.consume_keyword(Keyword::TABLE)?;
681    let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
682        Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
683    } else {
684        None
685    };
686    let table = parse_qualified_name(parser)?;
687    let d = parser.delimiter.clone();
688    let mut alter_specifications = Vec::new();
689    parser.recovered(d.name(), &|t| (t == &d || t == &Token::Eof), |parser| {
690        loop {
691            alter_specifications.push(match parser.token {
692                Token::Ident(_, Keyword::ADD) => parse_add_alter_specification(parser)?,
693                Token::Ident(_, Keyword::MODIFY) => {
694                    let mut modify_span = parser.consume_keyword(Keyword::MODIFY)?;
695                    if let Some(v) = parser.skip_keyword(Keyword::COLUMN) {
696                        modify_span = modify_span.join_span(&v);
697                    }
698                    let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
699                        Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
700                    } else {
701                        None
702                    };
703                    let col = parser.consume_plain_identifier()?;
704                    let definition = parse_data_type(parser, false)?;
705                    // TODO [FIRST | AFTER col_name]
706                    AlterSpecification::Modify {
707                        modify_span,
708                        if_exists,
709                        col,
710                        definition,
711                    }
712                }
713                Token::Ident(_, Keyword::OWNER) => {
714                    let span = parser.consume_keywords(&[Keyword::OWNER, Keyword::TO])?;
715                    let owner = parser.consume_plain_identifier()?;
716                    AlterSpecification::OwnerTo { span, owner }
717                }
718                Token::Ident(_, Keyword::DROP) => {
719                    let drop_column_span =
720                        parser.consume_keywords(&[Keyword::DROP, Keyword::COLUMN])?;
721                    let column = parser.consume_plain_identifier()?;
722                    let cascade = parser.skip_keyword(Keyword::CASCADE);
723                    AlterSpecification::DropColumn {
724                        drop_column_span,
725                        column,
726                        cascade,
727                    }
728                }
729                Token::Ident(_, Keyword::ALTER) => {
730                    let span = parser.consume_keywords(&[Keyword::ALTER, Keyword::COLUMN])?;
731                    let column = parser.consume_plain_identifier()?;
732
733                    let alter_column_action = match parser.token {
734                        Token::Ident(_, Keyword::SET) => {
735                            let set_span = parser.consume();
736                            match parser.token {
737                                Token::Ident(_, Keyword::DEFAULT) => {
738                                    let set_default_span = parser.consume().join_span(&set_span);
739                                    let value = parse_expression(parser, false)?;
740                                    AlterColumnAction::SetDefault {
741                                        set_default_span,
742                                        value,
743                                    }
744                                }
745                                Token::Ident(_, Keyword::NOT) => {
746                                    let set_not_null_span = set_span.join_span(
747                                        &parser.consume_keywords(&[Keyword::NOT, Keyword::NULL])?,
748                                    );
749                                    AlterColumnAction::SetNotNull { set_not_null_span }
750                                }
751                                _ => parser.expected_failure("'DEFAULT' or 'NOT NULL'")?,
752                            }
753                        }
754                        Token::Ident(_, Keyword::DROP) => {
755                            let set_span = parser.consume();
756                            match parser.token {
757                                Token::Ident(_, Keyword::DEFAULT) => {
758                                    let drop_default_span = parser.consume().join_span(&set_span);
759                                    AlterColumnAction::DropDefault {
760                                        drop_default_span: drop_default_span,
761                                    }
762                                }
763                                Token::Ident(_, Keyword::NOT) => {
764                                    let drop_not_null_span = set_span.join_span(
765                                        &parser.consume_keywords(&[Keyword::NOT, Keyword::NULL])?,
766                                    );
767                                    AlterColumnAction::DropNotNull { drop_not_null_span }
768                                }
769                                _ => parser.expected_failure("'DEFAULT' or 'NOT NULL'")?,
770                            }
771                        }
772                        Token::Ident(_, Keyword::TYPE) => {
773                            let type_span = parser.consume();
774                            let type_ = parse_data_type(parser, false)?;
775                            AlterColumnAction::Type { type_span, type_ }
776                        }
777                        _ => parser.expected_failure("alter column action")?,
778                    };
779                    AlterSpecification::AlterColumn {
780                        alter_column_span: span,
781                        column,
782                        alter_column_action,
783                    }
784                }
785                _ => parser.expected_failure("alter specification")?,
786            });
787            if parser.skip_token(Token::Comma).is_none() {
788                break;
789            }
790        }
791        Ok(())
792    })?;
793    Ok(AlterTable {
794        alter_span,
795        online,
796        ignore,
797        table_span,
798        if_exists,
799        table,
800        alter_specifications,
801    })
802}
803
804pub(crate) fn parse_alter<'a>(parser: &mut Parser<'a, '_>) -> Result<Statement<'a>, ParseError> {
805    let alter_span = parser.consume_keyword(Keyword::ALTER)?;
806
807    let online = parser.skip_keyword(Keyword::ONLINE);
808    let ignore = parser.skip_keyword(Keyword::IGNORE);
809
810    match &parser.token {
811        Token::Ident(_, Keyword::TABLE) => Ok(Statement::AlterTable(parse_alter_table(
812            parser, alter_span, online, ignore,
813        )?)),
814        _ => parser.expected_failure("alterable"),
815    }
816}