Skip to main content

qusql_parse/
alter_table.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 crate::create::parse_sequence_options;
14use crate::qualified_name::parse_qualified_name_unreserved;
15use crate::{
16    DataType, Expression, Identifier, QualifiedName, SString, SequenceOption, Span, Spanned,
17    data_type::{DataTypeContext, parse_data_type},
18    expression::{PRIORITY_MAX, parse_expression_unreserved},
19    keywords::{Keyword, Restrict},
20    lexer::{StringType, Token},
21    parser::{ParseError, Parser},
22};
23use alloc::vec::Vec;
24
25/// Parse OWNER TO ... for ALTER TABLE/ALTER OPERATOR CLASS (PostgreSQL)
26pub(crate) fn parse_alter_owner<'a>(
27    parser: &mut Parser<'a, '_>,
28) -> Result<AlterTableOwner<'a>, ParseError> {
29    // In PostgreSQL, CURRENT_ROLE, CURRENT_USER, and SESSION_USER are valid without quotes
30    match &parser.token {
31        Token::Ident(_, Keyword::CURRENT_ROLE) => {
32            Ok(AlterTableOwner::CurrentRole(parser.consume()))
33        }
34        Token::Ident(_, Keyword::CURRENT_USER) => {
35            Ok(AlterTableOwner::CurrentUser(parser.consume()))
36        }
37        Token::Ident(_, Keyword::SESSION_USER) => {
38            Ok(AlterTableOwner::SessionUser(parser.consume()))
39        }
40        _ => Ok(AlterTableOwner::Identifier(
41            parser.consume_plain_identifier_unreserved()?,
42        )),
43    }
44}
45
46/// Option on an index
47#[derive(Clone, Debug)]
48pub enum IndexOption<'a> {
49    /// The index should be a BTree
50    IndexTypeBTree(Span),
51    /// The index should be hashed
52    IndexTypeHash(Span),
53    /// The index should be an RTree
54    IndexTypeRTree(Span),
55    /// Attach a comment to the index
56    Comment(SString<'a>),
57}
58
59impl<'a> Spanned for IndexOption<'a> {
60    fn span(&self) -> Span {
61        match &self {
62            IndexOption::IndexTypeBTree(v) => v.span(),
63            IndexOption::IndexTypeHash(v) => v.span(),
64            IndexOption::IndexTypeRTree(v) => v.span(),
65            IndexOption::Comment(v) => v.span(),
66        }
67    }
68}
69
70/// Type of index to add
71#[derive(Clone, Debug)]
72pub enum IndexType {
73    Index(Span),
74    Primary(Span),
75    Unique(Span),
76    FullText(Span),
77    Spatial(Span),
78}
79
80impl Spanned for IndexType {
81    fn span(&self) -> Span {
82        match &self {
83            IndexType::Index(v) => v.span(),
84            IndexType::Primary(v) => v.span(),
85            IndexType::Unique(v) => v.span(),
86            IndexType::FullText(v) => v.span(),
87            IndexType::Spatial(v) => v.span(),
88        }
89    }
90}
91
92/// When to take a foreign key action
93#[derive(Clone, Debug)]
94pub enum ForeignKeyOnType {
95    Update(Span),
96    Delete(Span),
97}
98
99impl Spanned for ForeignKeyOnType {
100    fn span(&self) -> Span {
101        match &self {
102            ForeignKeyOnType::Update(v) => v.span(),
103            ForeignKeyOnType::Delete(v) => v.span(),
104        }
105    }
106}
107
108/// Action to take on event for foreign key
109#[derive(Clone, Debug)]
110pub enum ForeignKeyOnAction {
111    Restrict(Span),
112    Cascade(Span),
113    SetNull(Span),
114    NoAction(Span),
115    SetDefault(Span),
116}
117
118impl Spanned for ForeignKeyOnAction {
119    fn span(&self) -> Span {
120        match &self {
121            ForeignKeyOnAction::Restrict(v) => v.span(),
122            ForeignKeyOnAction::Cascade(v) => v.span(),
123            ForeignKeyOnAction::SetNull(v) => v.span(),
124            ForeignKeyOnAction::NoAction(v) => v.span(),
125            ForeignKeyOnAction::SetDefault(v) => v.span(),
126        }
127    }
128}
129
130/// MATCH type for a foreign key reference
131#[derive(Clone, Debug)]
132pub enum ForeignKeyMatch {
133    Full(Span),
134    Simple(Span),
135    Partial(Span),
136}
137
138impl Spanned for ForeignKeyMatch {
139    fn span(&self) -> Span {
140        match self {
141            ForeignKeyMatch::Full(v) => v.span(),
142            ForeignKeyMatch::Simple(v) => v.span(),
143            ForeignKeyMatch::Partial(v) => v.span(),
144        }
145    }
146}
147
148/// Action to perform on events on foreign keys
149#[derive(Clone, Debug)]
150pub struct ForeignKeyOn {
151    pub type_: ForeignKeyOnType,
152    pub action: ForeignKeyOnAction,
153}
154
155impl Spanned for ForeignKeyOn {
156    fn span(&self) -> Span {
157        self.type_.join_span(&self.action)
158    }
159}
160
161/// Column or expression specification for an index
162#[derive(Clone, Debug)]
163pub enum IndexColExpr<'a> {
164    /// Regular column name
165    Column(Identifier<'a>),
166    /// Functional index expression (wrapped in parentheses)
167    Expression(Expression<'a>),
168}
169
170impl<'a> Spanned for IndexColExpr<'a> {
171    fn span(&self) -> Span {
172        match self {
173            IndexColExpr::Column(id) => id.span(),
174            IndexColExpr::Expression(expr) => expr.span(),
175        }
176    }
177}
178
179/// Specify a column for an index, together with a with
180#[derive(Clone, Debug)]
181pub struct IndexCol<'a> {
182    /// The column name or expression
183    pub expr: IndexColExpr<'a>,
184    /// Optional width of index together with its span
185    pub size: Option<(u32, Span)>,
186    /// Optional operator class (PostgreSQL)
187    pub opclass: Option<QualifiedName<'a>>,
188    /// Optional ASC ordering
189    pub asc: Option<Span>,
190    /// Optional DESC ordering
191    pub desc: Option<Span>,
192}
193
194impl<'a> Spanned for IndexCol<'a> {
195    fn span(&self) -> Span {
196        self.expr
197            .join_span(&self.size)
198            .join_span(&self.opclass)
199            .join_span(&self.asc)
200            .join_span(&self.desc)
201    }
202}
203
204/// Enum of alterations to perform on a column
205#[derive(Clone, Debug)]
206pub enum AlterColumnAction<'a> {
207    SetDefault {
208        set_default_span: Span,
209        value: Expression<'a>,
210    },
211    DropDefault {
212        drop_default_span: Span,
213    },
214    Type {
215        type_span: Span,
216        type_: DataType<'a>,
217        using: Option<(Span, Expression<'a>)>,
218    },
219    SetNotNull {
220        set_not_null_span: Span,
221    },
222    DropNotNull {
223        drop_not_null_span: Span,
224    },
225    AddGenerated {
226        add_span: Span,
227        generated_span: Span,
228        always_or_default: Option<(Span, Span)>, // (ALWAYS|BY, DEFAULT)
229        as_span: Span,
230        identity_span: Span,
231        sequence_options: Vec<SequenceOption<'a>>,
232    },
233}
234
235impl<'a> Spanned for AlterColumnAction<'a> {
236    fn span(&self) -> Span {
237        match self {
238            AlterColumnAction::SetDefault {
239                set_default_span,
240                value,
241            } => set_default_span.join_span(value),
242            AlterColumnAction::DropDefault { drop_default_span } => drop_default_span.clone(),
243            AlterColumnAction::Type {
244                type_span,
245                type_,
246                using,
247            } => type_span.join_span(type_).join_span(using),
248            AlterColumnAction::SetNotNull { set_not_null_span } => set_not_null_span.clone(),
249            AlterColumnAction::DropNotNull { drop_not_null_span } => drop_not_null_span.clone(),
250            AlterColumnAction::AddGenerated {
251                add_span,
252                generated_span,
253                always_or_default,
254                as_span,
255                identity_span,
256                sequence_options,
257            } => add_span
258                .join_span(generated_span)
259                .join_span(always_or_default)
260                .join_span(as_span)
261                .join_span(identity_span)
262                .join_span(sequence_options),
263        }
264    }
265}
266
267#[derive(Clone, Debug)]
268pub enum AlterLock {
269    Default(Span),
270    None(Span),
271    Shared(Span),
272    Exclusive(Span),
273}
274
275impl Spanned for AlterLock {
276    fn span(&self) -> Span {
277        match self {
278            AlterLock::Default(v) => v.span(),
279            AlterLock::None(v) => v.span(),
280            AlterLock::Shared(v) => v.span(),
281            AlterLock::Exclusive(v) => v.span(),
282        }
283    }
284}
285
286#[derive(Clone, Debug)]
287pub enum AlterAlgorithm {
288    Default(Span),
289    Instant(Span),
290    Inplace(Span),
291    Copy(Span),
292}
293
294impl Spanned for AlterAlgorithm {
295    fn span(&self) -> Span {
296        match self {
297            AlterAlgorithm::Default(v) => v.span(),
298            AlterAlgorithm::Instant(v) => v.span(),
299            AlterAlgorithm::Inplace(v) => v.span(),
300            AlterAlgorithm::Copy(v) => v.span(),
301        }
302    }
303}
304
305/// Owner value for ALTER TABLE OWNER TO
306#[derive(Clone, Debug)]
307pub enum AlterTableOwner<'a> {
308    /// Regular identifier (role name)
309    Identifier(Identifier<'a>),
310    /// CURRENT_ROLE keyword
311    CurrentRole(Span),
312    /// CURRENT_USER keyword
313    CurrentUser(Span),
314    /// SESSION_USER keyword
315    SessionUser(Span),
316}
317
318impl<'a> Spanned for AlterTableOwner<'a> {
319    fn span(&self) -> Span {
320        match self {
321            AlterTableOwner::Identifier(i) => i.span(),
322            AlterTableOwner::CurrentRole(s) => s.span(),
323            AlterTableOwner::CurrentUser(s) => s.span(),
324            AlterTableOwner::SessionUser(s) => s.span(),
325        }
326    }
327}
328
329/// ADD COLUMN specification
330#[derive(Clone, Debug)]
331pub struct AddColumn<'a> {
332    pub add_span: Span,
333    pub if_not_exists_span: Option<Span>,
334    pub identifier: Identifier<'a>,
335    pub data_type: DataType<'a>,
336    /// Optional "FIRST"
337    pub first: Option<Span>,
338    /// Optional "AFTER col_name"
339    pub after: Option<(Span, Identifier<'a>)>,
340}
341
342impl<'a> Spanned for AddColumn<'a> {
343    fn span(&self) -> Span {
344        self.add_span
345            .join_span(&self.if_not_exists_span)
346            .join_span(&self.identifier)
347            .join_span(&self.data_type)
348            .join_span(&self.first)
349            .join_span(&self.after)
350    }
351}
352
353fn parse_add_column<'a>(
354    parser: &mut Parser<'a, '_>,
355    add_span: Span,
356) -> Result<AddColumn<'a>, ParseError> {
357    parser.consume_keyword(Keyword::COLUMN)?;
358    let mut if_not_exists_span = None;
359    if matches!(parser.token, Token::Ident(_, Keyword::IF)) {
360        if_not_exists_span =
361            Some(parser.consume_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS])?);
362    }
363
364    parser.postgres_only(&if_not_exists_span);
365
366    let identifier = parser.consume_plain_identifier_unreserved()?;
367    let data_type = parse_data_type(parser, DataTypeContext::Column)?;
368
369    let mut first = None;
370    let mut after = None;
371    match &parser.token {
372        Token::Ident(_, Keyword::FIRST) => {
373            first = Some(parser.consume_keyword(Keyword::FIRST)?);
374        }
375        Token::Ident(_, Keyword::AFTER) => {
376            let after_span = parser.consume_keyword(Keyword::AFTER)?;
377            let after_col = parser.consume_plain_identifier_unreserved()?;
378            after = Some((after_span, after_col));
379        }
380        _ => {}
381    }
382
383    Ok(AddColumn {
384        add_span,
385        if_not_exists_span,
386        identifier,
387        data_type,
388        first,
389        after,
390    })
391}
392
393/// Add an index
394#[derive(Clone, Debug)]
395pub struct AddIndex<'a> {
396    /// Span of "ADD"
397    pub add_span: Span,
398    /// The type of index to add
399    pub index_type: IndexType,
400    /// Span of "IF NOT EXISTS" if specified
401    pub if_not_exists: Option<Span>,
402    /// Named of index if specified
403    pub name: Option<Identifier<'a>>,
404    /// Optional "CONSTRAINT" with symbol if specified
405    pub constraint: Option<(Span, Option<Identifier<'a>>)>,
406    /// Columns to add the index over
407    pub cols: Vec<IndexCol<'a>>,
408    /// Options on the index
409    pub index_options: Vec<IndexOption<'a>>,
410}
411
412impl<'a> Spanned for AddIndex<'a> {
413    fn span(&self) -> Span {
414        self.add_span
415            .join_span(&self.index_type)
416            .join_span(&self.if_not_exists)
417            .join_span(&self.name)
418            .join_span(&self.constraint)
419            .join_span(&self.cols)
420            .join_span(&self.index_options)
421    }
422}
423
424fn parse_add_index<'a>(
425    parser: &mut Parser<'a, '_>,
426    add_span: Span,
427    constraint: Option<(Span, Option<Identifier<'a>>)>,
428) -> Result<AddIndex<'a>, ParseError> {
429    let index_type = match &parser.token {
430        Token::Ident(_, Keyword::PRIMARY) => {
431            IndexType::Primary(parser.consume_keywords(&[Keyword::PRIMARY, Keyword::KEY])?)
432        }
433        Token::Ident(_, Keyword::INDEX | Keyword::KEY) => IndexType::Index(parser.consume()),
434        Token::Ident(_, Keyword::FULLTEXT) => {
435            let s = parser.consume_keyword(Keyword::FULLTEXT)?;
436            match &parser.token {
437                Token::Ident(_, kw @ Keyword::INDEX | kw @ Keyword::KEY) => {
438                    let kw = *kw;
439                    IndexType::FullText(parser.consume_keyword(kw)?.join_span(&s))
440                }
441                _ => parser.expected_failure("'KEY' or 'INDEX'")?,
442            }
443        }
444        Token::Ident(_, Keyword::SPATIAL) => {
445            let s = parser.consume_keyword(Keyword::SPATIAL)?;
446            match &parser.token {
447                Token::Ident(_, kw @ Keyword::INDEX | kw @ Keyword::KEY) => {
448                    let kw = *kw;
449                    IndexType::Spatial(parser.consume_keyword(kw)?.join_span(&s))
450                }
451                _ => parser.expected_failure("'KEY' or 'INDEX'")?,
452            }
453        }
454        Token::Ident(_, Keyword::UNIQUE) => {
455            let s = parser.consume_keyword(Keyword::UNIQUE)?;
456            match &parser.token {
457                Token::Ident(_, kw @ Keyword::INDEX | kw @ Keyword::KEY) => {
458                    let kw = *kw;
459                    IndexType::Unique(parser.consume_keyword(kw)?.join_span(&s))
460                }
461                _ => parser.expected_failure("'KEY' or 'INDEX'")?,
462            }
463        }
464        _ => parser.ice(file!(), line!())?,
465    };
466
467    let if_not_exists = if let Some(s) = parser.skip_keyword(Keyword::IF) {
468        Some(
469            parser
470                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
471                .join_span(&s),
472        )
473    } else {
474        None
475    };
476
477    let name = match &parser.token {
478        Token::Ident(_, kw) if !kw.restricted(parser.reserved()) => {
479            Some(parser.consume_plain_identifier_unreserved()?)
480        }
481        _ => None,
482    };
483
484    let mut index_options = Vec::new();
485    if matches!(parser.token, Token::Ident(_, Keyword::USING)) {
486        parse_index_type(parser, &mut index_options)?;
487    }
488    let cols = parse_index_cols(parser)?;
489    parse_index_options(parser, &mut index_options)?;
490
491    Ok(AddIndex {
492        add_span,
493        index_type,
494        if_not_exists,
495        name,
496        constraint,
497        cols,
498        index_options,
499    })
500}
501
502/// Add a foreign key
503#[derive(Clone, Debug)]
504pub struct AddForeignKey<'a> {
505    /// Span of "ADD"
506    pub add_span: Span,
507    /// Optional "CONSTRAINT" with symbol if specified
508    pub constraint: Option<(Span, Option<Identifier<'a>>)>,
509    /// Span of "FOREIGN KEY"
510    pub foreign_key_span: Span,
511    /// Span of "IF NOT EXISTS" if specified
512    pub if_not_exists: Option<Span>,
513    /// Named of index if specified
514    pub name: Option<Identifier<'a>>,
515    /// Columns to add the index over
516    pub cols: Vec<IndexCol<'a>>,
517    /// Span of "REFERENCES"
518    pub references_span: Span,
519    /// Refereed table
520    pub references_table: Identifier<'a>,
521    /// Columns in referred table
522    pub references_cols: Vec<Identifier<'a>>,
523    /// List of what should happen at specified events
524    pub ons: Vec<ForeignKeyOn>,
525    /// Span of "NOT VALID" if specified
526    pub not_valid: Option<Span>,
527}
528
529impl<'a> Spanned for AddForeignKey<'a> {
530    fn span(&self) -> Span {
531        self.add_span
532            .join_span(&self.constraint)
533            .join_span(&self.foreign_key_span)
534            .join_span(&self.if_not_exists)
535            .join_span(&self.name)
536            .join_span(&self.cols)
537            .join_span(&self.references_span)
538            .join_span(&self.references_table)
539            .join_span(&self.references_cols)
540            .join_span(&self.not_valid)
541            .join_span(&self.ons)
542    }
543}
544
545fn parse_add_foreign_key<'a>(
546    parser: &mut Parser<'a, '_>,
547    add_span: Span,
548    constraint: Option<(Span, Option<Identifier<'a>>)>,
549) -> Result<AddForeignKey<'a>, ParseError> {
550    let foregin_key_span = parser.consume_keywords(&[Keyword::FOREIGN, Keyword::KEY])?;
551    let if_not_exists = if let Some(s) = parser.skip_keyword(Keyword::IF) {
552        Some(
553            parser
554                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
555                .join_span(&s),
556        )
557    } else {
558        None
559    };
560    let name = match &parser.token {
561        Token::Ident(_, kw) if !kw.restricted(parser.reserved()) => {
562            Some(parser.consume_plain_identifier_unreserved()?)
563        }
564        _ => None,
565    };
566
567    let cols = parse_index_cols(parser)?;
568    let references_span = parser.consume_keyword(Keyword::REFERENCES)?;
569    let references_table = parser.consume_plain_identifier_unreserved()?;
570    let references_cols = parse_cols(parser)?;
571    let mut ons = Vec::new();
572    while let Some(on) = parser.skip_keyword(Keyword::ON) {
573        let type_ = match parser.token {
574            Token::Ident(_, Keyword::UPDATE) => {
575                ForeignKeyOnType::Update(parser.consume_keyword(Keyword::UPDATE)?.join_span(&on))
576            }
577            Token::Ident(_, Keyword::DELETE) => {
578                ForeignKeyOnType::Delete(parser.consume_keyword(Keyword::DELETE)?.join_span(&on))
579            }
580            _ => parser.expected_failure("'UPDATE' or 'DELETE'")?,
581        };
582
583        let action = match parser.token {
584            Token::Ident(_, Keyword::RESTRICT) => {
585                ForeignKeyOnAction::Restrict(parser.consume_keyword(Keyword::RESTRICT)?)
586            }
587            Token::Ident(_, Keyword::CASCADE) => {
588                ForeignKeyOnAction::Cascade(parser.consume_keyword(Keyword::CASCADE)?)
589            }
590            Token::Ident(_, Keyword::SET) => {
591                let set = parser.consume_keyword(Keyword::SET)?;
592                match parser.token {
593                    Token::Ident(_, Keyword::NULL) => ForeignKeyOnAction::SetNull(
594                        parser.consume_keyword(Keyword::NULL)?.join_span(&set),
595                    ),
596                    Token::Ident(_, Keyword::DELETE) => ForeignKeyOnAction::SetDefault(
597                        parser.consume_keyword(Keyword::DEFAULT)?.join_span(&set),
598                    ),
599                    _ => parser.expected_failure("'NULL' or 'DEFAULT'")?,
600                }
601            }
602            Token::Ident(_, Keyword::NO) => ForeignKeyOnAction::SetNull(
603                parser.consume_keywords(&[Keyword::NO, Keyword::ACTION])?,
604            ),
605            _ => parser.expected_failure("'RESTRICT' or 'CASCADE', 'SET' or 'NO")?,
606        };
607        ons.push(ForeignKeyOn { type_, action })
608    }
609    // Parse optional NOT VALID
610    let not_valid = if let Some(span) = parser.skip_keyword(Keyword::NOT) {
611        Some(span.join_span(&parser.consume_keyword(Keyword::VALID)?))
612    } else {
613        None
614    };
615    Ok(AddForeignKey {
616        add_span,
617        constraint,
618        foreign_key_span: foregin_key_span,
619        if_not_exists,
620        name,
621        cols,
622        references_span,
623        references_table,
624        references_cols,
625        ons,
626        not_valid,
627    })
628}
629
630/// Modify a column
631#[derive(Clone, Debug)]
632pub struct ModifyColumn<'a> {
633    /// Span of "MODIFY"
634    pub modify_span: Span,
635    /// Span of "IF EXISTS" if specified
636    pub if_exists: Option<Span>,
637    /// Name of column to modify
638    pub col: Identifier<'a>,
639    /// New definition of column
640    pub definition: DataType<'a>,
641    /// Optional "FIRST"
642    pub first: Option<Span>,
643    /// Optional "AFTER col_name"
644    pub after: Option<(Span, Identifier<'a>)>,
645}
646
647impl<'a> Spanned for ModifyColumn<'a> {
648    fn span(&self) -> Span {
649        self.modify_span
650            .join_span(&self.if_exists)
651            .join_span(&self.col)
652            .join_span(&self.definition)
653            .join_span(&self.first)
654            .join_span(&self.after)
655    }
656}
657
658fn parse_modify_column<'a>(
659    parser: &mut Parser<'a, '_>,
660    mut modify_span: Span,
661) -> Result<ModifyColumn<'a>, ParseError> {
662    parser.maria_only(&modify_span);
663    if let Some(v) = parser.skip_keyword(Keyword::COLUMN) {
664        modify_span = modify_span.join_span(&v);
665    }
666    let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
667        Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
668    } else {
669        None
670    };
671    let col = parser.consume_plain_identifier_unreserved()?;
672    let definition = parse_data_type(parser, DataTypeContext::Column)?;
673
674    let mut first = None;
675    let mut after = None;
676    match parser.token {
677        Token::Ident(_, Keyword::FIRST) => {
678            let first_span = parser.consume_keyword(Keyword::FIRST)?;
679            parser.maria_only(&first_span);
680            first = Some(first_span);
681        }
682        Token::Ident(_, Keyword::AFTER) => {
683            let after_span = parser.consume_keyword(Keyword::AFTER)?;
684            parser.maria_only(&after_span);
685            let col = parser.consume_plain_identifier_unreserved()?;
686            after = Some((after_span, col));
687        }
688        _ => {}
689    }
690
691    Ok(ModifyColumn {
692        modify_span,
693        if_exists,
694        col,
695        definition,
696        first,
697        after,
698    })
699}
700
701/// DROP COLUMN specification
702#[derive(Clone, Debug)]
703pub struct DropColumn<'a> {
704    /// Span of "DROP COLUMN"
705    pub drop_column_span: Span,
706    /// Name of column to drop
707    pub column: Identifier<'a>,
708    /// Span of "CASCADE" if specified
709    pub cascade: Option<Span>,
710}
711
712impl<'a> Spanned for DropColumn<'a> {
713    fn span(&self) -> Span {
714        self.drop_column_span
715            .join_span(&self.column)
716            .join_span(&self.cascade)
717    }
718}
719
720fn parse_drop_column<'a>(
721    parser: &mut Parser<'a, '_>,
722    drop_span: Span,
723) -> Result<DropColumn<'a>, ParseError> {
724    let drop_column_span = drop_span.join_span(&parser.consume_keyword(Keyword::COLUMN)?);
725    let column = parser.consume_plain_identifier_unreserved()?;
726    let cascade = parser.skip_keyword(Keyword::CASCADE);
727    if let Some(span) = &cascade {
728        parser.postgres_only(span);
729    }
730    Ok(DropColumn {
731        drop_column_span,
732        column,
733        cascade,
734    })
735}
736
737/// DROP INDEX specification
738#[derive(Clone, Debug)]
739pub struct DropIndex<'a> {
740    /// Span of "DROP INDEX"
741    pub drop_index_span: Span,
742    /// Name of index to drop
743    pub name: Identifier<'a>,
744}
745
746impl<'a> Spanned for DropIndex<'a> {
747    fn span(&self) -> Span {
748        self.drop_index_span.join_span(&self.name)
749    }
750}
751
752fn parse_drop_index<'a>(
753    parser: &mut Parser<'a, '_>,
754    drop_span: Span,
755) -> Result<DropIndex<'a>, ParseError> {
756    let index_span = parser.consume();
757    let name = parser.consume_plain_identifier_unreserved()?;
758    Ok(DropIndex {
759        drop_index_span: drop_span.join_span(&index_span).join_span(&name),
760        name,
761    })
762}
763
764/// DROP FOREIGN KEY specification
765#[derive(Clone, Debug)]
766pub struct DropForeignKey<'a> {
767    /// Span of "DROP FOREIGN KEY"
768    pub drop_foreign_key_span: Span,
769    /// Name of foreign key to drop
770    pub name: Identifier<'a>,
771}
772
773impl<'a> Spanned for DropForeignKey<'a> {
774    fn span(&self) -> Span {
775        self.drop_foreign_key_span.join_span(&self.name)
776    }
777}
778
779fn parse_drop_foreign_key<'a>(
780    parser: &mut Parser<'a, '_>,
781    drop_span: Span,
782) -> Result<DropForeignKey<'a>, ParseError> {
783    let foreign_span = parser.consume_keywords(&[Keyword::FOREIGN, Keyword::KEY])?;
784    let name = parser.consume_plain_identifier_unreserved()?;
785    Ok(DropForeignKey {
786        drop_foreign_key_span: drop_span.join_span(&foreign_span).join_span(&name),
787        name,
788    })
789}
790
791/// DROP PRIMARY KEY specification
792#[derive(Clone, Debug)]
793pub struct DropPrimaryKey {
794    /// Span of "DROP PRIMARY KEY"
795    pub drop_primary_key_span: Span,
796}
797
798impl Spanned for DropPrimaryKey {
799    fn span(&self) -> Span {
800        self.drop_primary_key_span.clone()
801    }
802}
803
804fn parse_drop_primary_key(
805    parser: &mut Parser<'_, '_>,
806    drop_span: Span,
807) -> Result<DropPrimaryKey, ParseError> {
808    let primary_key_span = parser.consume_keywords(&[Keyword::PRIMARY, Keyword::KEY])?;
809    Ok(DropPrimaryKey {
810        drop_primary_key_span: drop_span.join_span(&primary_key_span),
811    })
812}
813
814/// ALTER COLUMN specification
815#[derive(Clone, Debug)]
816pub struct AlterColumn<'a> {
817    /// Span of "ALTER COLUMN"
818    pub alter_column_span: Span,
819    /// Name of column to alter
820    pub column: Identifier<'a>,
821    pub alter_column_action: AlterColumnAction<'a>,
822}
823
824impl<'a> Spanned for AlterColumn<'a> {
825    fn span(&self) -> Span {
826        self.alter_column_span
827            .join_span(&self.column)
828            .join_span(&self.alter_column_action)
829    }
830}
831
832// Note: parse_alter_column is complex and stays in parse_alter_table
833
834/// OWNER TO specification
835#[derive(Clone, Debug)]
836pub struct OwnerTo<'a> {
837    /// Span of "OWNER TO"
838    pub span: Span,
839    /// Name of owner
840    pub owner: AlterTableOwner<'a>,
841}
842
843impl<'a> Spanned for OwnerTo<'a> {
844    fn span(&self) -> Span {
845        self.span.join_span(&self.owner)
846    }
847}
848
849fn parse_owner_to<'a>(parser: &mut Parser<'a, '_>, span: Span) -> Result<OwnerTo<'a>, ParseError> {
850    let owner = parse_alter_owner(parser)?;
851    Ok(OwnerTo { span, owner })
852}
853
854/// LOCK specification
855#[derive(Clone, Debug)]
856pub struct Lock {
857    /// Span of "LOCK"
858    pub lock_span: Span,
859    pub lock: AlterLock,
860}
861
862impl Spanned for Lock {
863    fn span(&self) -> Span {
864        self.lock_span.join_span(&self.lock)
865    }
866}
867
868fn parse_lock(parser: &mut Parser<'_, '_>, lock_span: Span) -> Result<Lock, ParseError> {
869    parser.skip_token(Token::Eq);
870    let lock = match &parser.token {
871        Token::Ident(_, Keyword::DEFAULT) => {
872            AlterLock::Default(parser.consume_keyword(Keyword::DEFAULT)?)
873        }
874        Token::Ident(_, Keyword::NONE) => AlterLock::None(parser.consume_keyword(Keyword::NONE)?),
875        Token::Ident(_, Keyword::SHARED) => {
876            AlterLock::Shared(parser.consume_keyword(Keyword::SHARED)?)
877        }
878        Token::Ident(_, Keyword::EXCLUSIVE) => {
879            AlterLock::Exclusive(parser.consume_keyword(Keyword::EXCLUSIVE)?)
880        }
881        _ => parser.expected_failure("'DEFAULT', 'NONE', 'SHARED' or 'EXCLUSIVE'")?,
882    };
883    Ok(Lock { lock_span, lock })
884}
885
886/// RENAME COLUMN specification
887#[derive(Clone, Debug)]
888pub struct RenameColumn<'a> {
889    /// Span of "RENAME COLUMN"
890    pub rename_column_span: Span,
891    /// Old name of column
892    pub old_col_name: Identifier<'a>,
893    /// Span of "TO"
894    pub to_span: Span,
895    /// New name of column
896    pub new_col_name: Identifier<'a>,
897}
898
899impl<'a> Spanned for RenameColumn<'a> {
900    fn span(&self) -> Span {
901        self.rename_column_span
902            .join_span(&self.old_col_name)
903            .join_span(&self.to_span)
904            .join_span(&self.new_col_name)
905    }
906}
907
908fn parse_rename_column<'a>(
909    parser: &mut Parser<'a, '_>,
910    rename_span: Span,
911) -> Result<RenameColumn<'a>, ParseError> {
912    let column_span = parser.consume_keyword(Keyword::COLUMN)?;
913    let old_col_name = parser.consume_plain_identifier_unreserved()?;
914    let to_span = parser.consume_keyword(Keyword::TO)?;
915    let new_col_name = parser.consume_plain_identifier_unreserved()?;
916    Ok(RenameColumn {
917        rename_column_span: rename_span.join_span(&column_span),
918        old_col_name,
919        to_span,
920        new_col_name,
921    })
922}
923
924/// RENAME INDEX specification
925#[derive(Clone, Debug)]
926pub struct RenameIndex<'a> {
927    /// Span of "RENAME INDEX" or "RENAME KEY"
928    pub rename_index_span: Span,
929    /// Old name of index
930    pub old_index_name: Identifier<'a>,
931    /// Span of "TO"
932    pub to_span: Span,
933    /// New name of index
934    pub new_index_name: Identifier<'a>,
935}
936
937impl<'a> Spanned for RenameIndex<'a> {
938    fn span(&self) -> Span {
939        self.rename_index_span
940            .join_span(&self.old_index_name)
941            .join_span(&self.to_span)
942            .join_span(&self.new_index_name)
943    }
944}
945
946fn parse_rename_index<'a>(
947    parser: &mut Parser<'a, '_>,
948    rename_span: Span,
949) -> Result<RenameIndex<'a>, ParseError> {
950    let index_span = parser.consume();
951    let old_index_name = parser.consume_plain_identifier_unreserved()?;
952    let to_span = parser.consume_keyword(Keyword::TO)?;
953    let new_index_name = parser.consume_plain_identifier_unreserved()?;
954    Ok(RenameIndex {
955        rename_index_span: rename_span.join_span(&index_span),
956        old_index_name,
957        to_span,
958        new_index_name,
959    })
960}
961
962/// RENAME CONSTRAINT specification
963#[derive(Clone, Debug)]
964pub struct RenameConstraint<'a> {
965    /// Span of "RENAME CONSTRAINT"
966    pub rename_constraint_span: Span,
967    /// Old name of constraint
968    pub old_constraint_name: Identifier<'a>,
969    /// Span of "TO"
970    pub to_span: Span,
971    /// New name of constraint
972    pub new_constraint_name: Identifier<'a>,
973}
974
975impl<'a> Spanned for RenameConstraint<'a> {
976    fn span(&self) -> Span {
977        self.rename_constraint_span
978            .join_span(&self.old_constraint_name)
979            .join_span(&self.to_span)
980            .join_span(&self.new_constraint_name)
981    }
982}
983
984fn parse_rename_constraint<'a>(
985    parser: &mut Parser<'a, '_>,
986    rename_span: Span,
987) -> Result<RenameConstraint<'a>, ParseError> {
988    let constraint_span = parser.consume_keyword(Keyword::CONSTRAINT)?;
989    parser.postgres_only(&constraint_span);
990    let old_constraint_name = parser.consume_plain_identifier_unreserved()?;
991    let to_span = parser.consume_keyword(Keyword::TO)?;
992    let new_constraint_name = parser.consume_plain_identifier_unreserved()?;
993    Ok(RenameConstraint {
994        rename_constraint_span: rename_span.join_span(&constraint_span),
995        old_constraint_name,
996        to_span,
997        new_constraint_name,
998    })
999}
1000
1001/// RENAME TO specification
1002#[derive(Clone, Debug)]
1003pub struct RenameTo<'a> {
1004    /// Span of "RENAME"
1005    pub rename_span: Span,
1006    /// Span of "TO" or "AS"
1007    pub to_span: Span,
1008    /// New name of table
1009    pub new_table_name: Identifier<'a>,
1010}
1011
1012impl<'a> Spanned for RenameTo<'a> {
1013    fn span(&self) -> Span {
1014        self.rename_span
1015            .join_span(&self.to_span)
1016            .join_span(&self.new_table_name)
1017    }
1018}
1019
1020fn parse_rename_to<'a>(
1021    parser: &mut Parser<'a, '_>,
1022    rename_span: Span,
1023) -> Result<RenameTo<'a>, ParseError> {
1024    let to_span = parser.consume();
1025    let new_table_name = parser.consume_plain_identifier_unreserved()?;
1026    Ok(RenameTo {
1027        rename_span,
1028        to_span,
1029        new_table_name,
1030    })
1031}
1032
1033/// ALGORITHM specification
1034#[derive(Clone, Debug)]
1035pub struct Algorithm {
1036    /// Span of "ALGORITHM"
1037    pub algorithm_span: Span,
1038    pub algorithm: AlterAlgorithm,
1039}
1040
1041impl Spanned for Algorithm {
1042    fn span(&self) -> Span {
1043        self.algorithm_span.join_span(&self.algorithm)
1044    }
1045}
1046
1047fn parse_algorithm(
1048    parser: &mut Parser<'_, '_>,
1049    algorithm_span: Span,
1050) -> Result<Algorithm, ParseError> {
1051    parser.skip_token(Token::Eq);
1052    let algorithm = match &parser.token {
1053        Token::Ident(_, Keyword::DEFAULT) => {
1054            AlterAlgorithm::Default(parser.consume_keyword(Keyword::DEFAULT)?)
1055        }
1056        Token::Ident(_, Keyword::INSTANT) => {
1057            AlterAlgorithm::Instant(parser.consume_keyword(Keyword::INSTANT)?)
1058        }
1059        Token::Ident(_, Keyword::INPLACE) => {
1060            AlterAlgorithm::Inplace(parser.consume_keyword(Keyword::INPLACE)?)
1061        }
1062        Token::Ident(_, Keyword::COPY) => {
1063            AlterAlgorithm::Copy(parser.consume_keyword(Keyword::COPY)?)
1064        }
1065        _ => parser.expected_failure("'DEFAULT', 'INSTANT', 'INPLACE' or 'COPY'")?,
1066    };
1067    Ok(Algorithm {
1068        algorithm_span,
1069        algorithm,
1070    })
1071}
1072
1073/// AUTO_INCREMENT specification
1074#[derive(Clone, Debug)]
1075pub struct AutoIncrement {
1076    /// Span of "AUTO_INCREMENT"
1077    pub auto_increment_span: Span,
1078    pub value_span: Span,
1079    /// New value for auto_increment
1080    pub value: u64,
1081}
1082
1083impl Spanned for AutoIncrement {
1084    fn span(&self) -> Span {
1085        self.auto_increment_span.join_span(&self.value_span)
1086    }
1087}
1088
1089fn parse_auto_increment(
1090    parser: &mut Parser<'_, '_>,
1091    auto_increment_span: Span,
1092) -> Result<AutoIncrement, ParseError> {
1093    parser.skip_token(Token::Eq);
1094    let (value, value_span) = parser.consume_int()?;
1095    Ok(AutoIncrement {
1096        auto_increment_span,
1097        value_span,
1098        value,
1099    })
1100}
1101
1102/// CHANGE specification
1103#[derive(Clone, Debug)]
1104pub struct Change<'a> {
1105    /// Span of "CHANGE"
1106    pub change_span: Span,
1107    /// Optional span of "COLUMN"
1108    pub column_span: Option<Span>,
1109    /// Old name of column
1110    pub column: Identifier<'a>,
1111    /// New name of column
1112    pub new_column: Identifier<'a>,
1113    /// New definition of column
1114    pub definition: DataType<'a>,
1115    /// Optional "FIRST"
1116    pub first: Option<Span>,
1117    /// Optional "AFTER col_name"
1118    pub after: Option<(Span, Identifier<'a>)>,
1119}
1120
1121impl<'a> Spanned for Change<'a> {
1122    fn span(&self) -> Span {
1123        self.change_span
1124            .join_span(&self.column_span)
1125            .join_span(&self.column)
1126            .join_span(&self.new_column)
1127            .join_span(&self.definition)
1128            .join_span(&self.first)
1129            .join_span(&self.after)
1130    }
1131}
1132
1133fn parse_change<'a>(
1134    parser: &mut Parser<'a, '_>,
1135    change_span: Span,
1136) -> Result<Change<'a>, ParseError> {
1137    let column_span = parser.skip_keyword(Keyword::COLUMN);
1138
1139    let column = parser.consume_plain_identifier_unreserved()?;
1140    let new_column = parser.consume_plain_identifier_unreserved()?;
1141    let definition = parse_data_type(parser, DataTypeContext::Column)?;
1142
1143    let mut first = None;
1144    let mut after = None;
1145    match parser.token {
1146        Token::Ident(_, Keyword::FIRST) => {
1147            let first_span = parser.consume_keyword(Keyword::FIRST)?;
1148            parser.maria_only(&first_span);
1149            first = Some(first_span);
1150        }
1151        Token::Ident(_, Keyword::AFTER) => {
1152            let after_span = parser.consume_keyword(Keyword::AFTER)?;
1153            parser.maria_only(&after_span);
1154            let col = parser.consume_plain_identifier_unreserved()?;
1155            after = Some((after_span, col));
1156        }
1157        _ => {}
1158    }
1159
1160    Ok(Change {
1161        change_span,
1162        column_span,
1163        column,
1164        new_column,
1165        definition,
1166        first,
1167        after,
1168    })
1169}
1170
1171/// PostgreSQL: REPLICA IDENTITY { DEFAULT | USING INDEX <name> | FULL | NOTHING }
1172#[derive(Clone, Debug)]
1173pub struct ReplicaIdentity<'a> {
1174    pub replica_span: Span,
1175    pub identity_span: Span,
1176    pub option: ReplicaIdentityOption<'a>,
1177}
1178
1179impl<'a> Spanned for ReplicaIdentity<'a> {
1180    fn span(&self) -> Span {
1181        self.replica_span
1182            .join_span(&self.identity_span)
1183            .join_span(&match &self.option {
1184                ReplicaIdentityOption::Default(s) => s.clone(),
1185                ReplicaIdentityOption::Full(s) => s.clone(),
1186                ReplicaIdentityOption::Nothing(s) => s.clone(),
1187                ReplicaIdentityOption::UsingIndex {
1188                    using_span,
1189                    index_span,
1190                    name,
1191                } => using_span.join_span(index_span).join_span(name),
1192            })
1193    }
1194}
1195
1196// Note: parse_replica_identity stays inline in parse_alter_table due to complexity
1197
1198/// PostgreSQL: VALIDATE CONSTRAINT constraint_name
1199#[derive(Clone, Debug)]
1200pub struct ValidateConstraint<'a> {
1201    pub validate_span: Span,
1202    pub constraint_span: Span,
1203    pub constraint_name: Identifier<'a>,
1204}
1205
1206impl<'a> Spanned for ValidateConstraint<'a> {
1207    fn span(&self) -> Span {
1208        self.validate_span
1209            .join_span(&self.constraint_span)
1210            .join_span(&self.constraint_name)
1211    }
1212}
1213
1214fn parse_validate_constraint<'a>(
1215    parser: &mut Parser<'a, '_>,
1216    validate_span: Span,
1217) -> Result<ValidateConstraint<'a>, ParseError> {
1218    let constraint_span = parser.consume_keyword(Keyword::CONSTRAINT)?;
1219    let constraint_name = parser.consume_plain_identifier_unreserved()?;
1220    Ok(ValidateConstraint {
1221        validate_span,
1222        constraint_span,
1223        constraint_name,
1224    })
1225}
1226
1227/// PostgreSQL: ADD CONSTRAINT ... UNIQUE/PRIMARY KEY/CHECK
1228#[derive(Clone, Debug)]
1229pub struct AddTableConstraint<'a> {
1230    pub add_span: Span,
1231    pub constraint: Option<(Span, Option<Identifier<'a>>)>,
1232    pub constraint_type: TableConstraintType<'a>,
1233    pub not_valid: Option<Span>,
1234}
1235
1236impl<'a> Spanned for AddTableConstraint<'a> {
1237    fn span(&self) -> Span {
1238        let type_span = match &self.constraint_type {
1239            TableConstraintType::Unique {
1240                unique_span,
1241                nulls_clause,
1242                cols,
1243            } => unique_span.join_span(nulls_clause).join_span(cols),
1244            TableConstraintType::PrimaryKey {
1245                primary_span,
1246                key_span,
1247                cols,
1248            } => primary_span.join_span(key_span).join_span(cols),
1249            TableConstraintType::Check { check_span, expr } => check_span.join_span(expr),
1250        };
1251        self.add_span
1252            .join_span(&self.constraint)
1253            .join_span(&type_span)
1254            .join_span(&self.not_valid)
1255    }
1256}
1257
1258// Note: parse_add_table_constraint variants stay inline in parse_add_alter_specification
1259
1260/// PostgreSQL: DISABLE TRIGGER { trigger_name | ALL | USER }
1261#[derive(Clone, Debug)]
1262pub struct DisableTrigger<'a> {
1263    pub disable_span: Span,
1264    pub trigger_span: Span,
1265    pub trigger_name: TriggerName<'a>,
1266}
1267
1268impl<'a> Spanned for DisableTrigger<'a> {
1269    fn span(&self) -> Span {
1270        let name_span = match &self.trigger_name {
1271            TriggerName::Named(n) => n.span(),
1272            TriggerName::All(s) => s.clone(),
1273            TriggerName::User(s) => s.clone(),
1274        };
1275        self.disable_span
1276            .join_span(&self.trigger_span)
1277            .join_span(&name_span)
1278    }
1279}
1280
1281// Note: parse_disable_trigger stays inline due to DISABLE/ENABLE branching logic
1282
1283/// PostgreSQL: ENABLE [ REPLICA | ALWAYS ] TRIGGER { trigger_name | ALL | USER }
1284#[derive(Clone, Debug)]
1285pub struct EnableTrigger<'a> {
1286    pub enable_span: Span,
1287    pub modifier: Option<Span>, // REPLICA or ALWAYS
1288    pub trigger_span: Span,
1289    pub trigger_name: TriggerName<'a>,
1290}
1291
1292impl<'a> Spanned for EnableTrigger<'a> {
1293    fn span(&self) -> Span {
1294        let name_span = match &self.trigger_name {
1295            TriggerName::Named(n) => n.span(),
1296            TriggerName::All(s) => s.clone(),
1297            TriggerName::User(s) => s.clone(),
1298        };
1299        self.enable_span
1300            .join_span(&self.modifier)
1301            .join_span(&self.trigger_span)
1302            .join_span(&name_span)
1303    }
1304}
1305
1306// Note: parse_enable_trigger stays inline due to DISABLE/ENABLE branching logic
1307
1308/// PostgreSQL: DISABLE RULE rule_name
1309#[derive(Clone, Debug)]
1310pub struct DisableRule<'a> {
1311    pub disable_span: Span,
1312    pub rule_span: Span,
1313    pub rule_name: Identifier<'a>,
1314}
1315
1316impl<'a> Spanned for DisableRule<'a> {
1317    fn span(&self) -> Span {
1318        self.disable_span
1319            .join_span(&self.rule_span)
1320            .join_span(&self.rule_name)
1321    }
1322}
1323
1324// Note: parse_disable_rule stays inline due to DISABLE/ENABLE branching logic
1325
1326/// PostgreSQL: ENABLE [ REPLICA | ALWAYS ] RULE rule_name
1327#[derive(Clone, Debug)]
1328pub struct EnableRule<'a> {
1329    pub enable_span: Span,
1330    pub modifier: Option<Span>, // REPLICA or ALWAYS
1331    pub rule_span: Span,
1332    pub rule_name: Identifier<'a>,
1333}
1334
1335impl<'a> Spanned for EnableRule<'a> {
1336    fn span(&self) -> Span {
1337        self.enable_span
1338            .join_span(&self.modifier)
1339            .join_span(&self.rule_span)
1340            .join_span(&self.rule_name)
1341    }
1342}
1343
1344// Note: parse_enable_rule stays inline due to DISABLE/ENABLE branching logic
1345
1346/// PostgreSQL: DISABLE ROW LEVEL SECURITY
1347#[derive(Clone, Debug)]
1348pub struct DisableRowLevelSecurity {
1349    pub disable_span: Span,
1350    pub row_span: Span,
1351    pub level_span: Span,
1352    pub security_span: Span,
1353}
1354
1355impl Spanned for DisableRowLevelSecurity {
1356    fn span(&self) -> Span {
1357        self.disable_span
1358            .join_span(&self.row_span)
1359            .join_span(&self.level_span)
1360            .join_span(&self.security_span)
1361    }
1362}
1363
1364// Note: parse_disable_row_level_security stays inline due to DISABLE/ENABLE branching logic
1365
1366/// PostgreSQL: ENABLE ROW LEVEL SECURITY
1367#[derive(Clone, Debug)]
1368pub struct EnableRowLevelSecurity {
1369    pub enable_span: Span,
1370    pub row_span: Span,
1371    pub level_span: Span,
1372    pub security_span: Span,
1373}
1374
1375impl Spanned for EnableRowLevelSecurity {
1376    fn span(&self) -> Span {
1377        self.enable_span
1378            .join_span(&self.row_span)
1379            .join_span(&self.level_span)
1380            .join_span(&self.security_span)
1381    }
1382}
1383
1384// Note: parse_enable_row_level_security stays inline due to DISABLE/ENABLE branching logic
1385
1386/// PostgreSQL: FORCE ROW LEVEL SECURITY
1387#[derive(Clone, Debug)]
1388pub struct ForceRowLevelSecurity {
1389    pub force_span: Span,
1390    pub row_span: Span,
1391    pub level_span: Span,
1392    pub security_span: Span,
1393}
1394
1395impl Spanned for ForceRowLevelSecurity {
1396    fn span(&self) -> Span {
1397        self.force_span
1398            .join_span(&self.row_span)
1399            .join_span(&self.level_span)
1400            .join_span(&self.security_span)
1401    }
1402}
1403
1404// Note: parse_force_row_level_security stays inline due to FORCE/NO FORCE branching
1405
1406/// PostgreSQL: NO FORCE ROW LEVEL SECURITY
1407#[derive(Clone, Debug)]
1408pub struct NoForceRowLevelSecurity {
1409    pub no_span: Span,
1410    pub force_span: Span,
1411    pub row_span: Span,
1412    pub level_span: Span,
1413    pub security_span: Span,
1414}
1415
1416impl Spanned for NoForceRowLevelSecurity {
1417    fn span(&self) -> Span {
1418        self.no_span
1419            .join_span(&self.force_span)
1420            .join_span(&self.row_span)
1421            .join_span(&self.level_span)
1422            .join_span(&self.security_span)
1423    }
1424}
1425
1426// Note: parse_no_force_row_level_security stays inline due to FORCE/NO FORCE branching
1427
1428/// Enum of alterations to perform on a table
1429#[derive(Clone, Debug)]
1430pub enum AlterSpecification<'a> {
1431    AddColumn(AddColumn<'a>),
1432    AddIndex(AddIndex<'a>),
1433    AddForeignKey(AddForeignKey<'a>),
1434    Modify(ModifyColumn<'a>),
1435    DropColumn(DropColumn<'a>),
1436    DropIndex(DropIndex<'a>),
1437    DropForeignKey(DropForeignKey<'a>),
1438    DropPrimaryKey(DropPrimaryKey),
1439    AlterColumn(AlterColumn<'a>),
1440    OwnerTo(OwnerTo<'a>),
1441    Lock(Lock),
1442    RenameColumn(RenameColumn<'a>),
1443    RenameIndex(RenameIndex<'a>),
1444    RenameConstraint(RenameConstraint<'a>),
1445    RenameTo(RenameTo<'a>),
1446    Algorithm(Algorithm),
1447    AutoIncrement(AutoIncrement),
1448    Change(Change<'a>),
1449    ReplicaIdentity(ReplicaIdentity<'a>),
1450    ValidateConstraint(ValidateConstraint<'a>),
1451    AddTableConstraint(AddTableConstraint<'a>),
1452    DisableTrigger(DisableTrigger<'a>),
1453    EnableTrigger(EnableTrigger<'a>),
1454    DisableRule(DisableRule<'a>),
1455    EnableRule(EnableRule<'a>),
1456    DisableRowLevelSecurity(DisableRowLevelSecurity),
1457    EnableRowLevelSecurity(EnableRowLevelSecurity),
1458    ForceRowLevelSecurity(ForceRowLevelSecurity),
1459    NoForceRowLevelSecurity(NoForceRowLevelSecurity),
1460}
1461
1462/// Options for REPLICA IDENTITY
1463#[derive(Clone, Debug)]
1464pub enum ReplicaIdentityOption<'a> {
1465    Default(Span),
1466    Full(Span),
1467    Nothing(Span),
1468    UsingIndex {
1469        using_span: Span,
1470        index_span: Span,
1471        name: Identifier<'a>,
1472    },
1473}
1474
1475/// Table constraint types for ADD CONSTRAINT
1476#[derive(Clone, Debug)]
1477pub enum TableConstraintType<'a> {
1478    Unique {
1479        unique_span: Span,
1480        nulls_clause: Option<(Span, Option<Span>)>, // (NULLS, NOT?)
1481        cols: Vec<Identifier<'a>>,
1482    },
1483    PrimaryKey {
1484        primary_span: Span,
1485        key_span: Span,
1486        cols: Vec<Identifier<'a>>,
1487    },
1488    Check {
1489        check_span: Span,
1490        expr: Expression<'a>,
1491    },
1492}
1493
1494/// Trigger name variants for ENABLE/DISABLE TRIGGER
1495#[derive(Clone, Debug)]
1496pub enum TriggerName<'a> {
1497    Named(Identifier<'a>),
1498    All(Span),
1499    User(Span),
1500}
1501
1502impl<'a> Spanned for AlterSpecification<'a> {
1503    fn span(&self) -> Span {
1504        match self {
1505            AlterSpecification::AddColumn(v) => v.span(),
1506            AlterSpecification::AddIndex(v) => v.span(),
1507            AlterSpecification::AddForeignKey(v) => v.span(),
1508            AlterSpecification::Modify(v) => v.span(),
1509            AlterSpecification::DropColumn(v) => v.span(),
1510            AlterSpecification::DropIndex(v) => v.span(),
1511            AlterSpecification::DropForeignKey(v) => v.span(),
1512            AlterSpecification::DropPrimaryKey(v) => v.span(),
1513            AlterSpecification::AlterColumn(v) => v.span(),
1514            AlterSpecification::OwnerTo(v) => v.span(),
1515            AlterSpecification::Lock(v) => v.span(),
1516            AlterSpecification::RenameColumn(v) => v.span(),
1517            AlterSpecification::RenameIndex(v) => v.span(),
1518            AlterSpecification::RenameConstraint(v) => v.span(),
1519            AlterSpecification::RenameTo(v) => v.span(),
1520            AlterSpecification::Algorithm(v) => v.span(),
1521            AlterSpecification::AutoIncrement(v) => v.span(),
1522            AlterSpecification::Change(v) => v.span(),
1523            AlterSpecification::ReplicaIdentity(v) => v.span(),
1524            AlterSpecification::ValidateConstraint(v) => v.span(),
1525            AlterSpecification::AddTableConstraint(v) => v.span(),
1526            AlterSpecification::DisableTrigger(v) => v.span(),
1527            AlterSpecification::EnableTrigger(v) => v.span(),
1528            AlterSpecification::DisableRule(v) => v.span(),
1529            AlterSpecification::EnableRule(v) => v.span(),
1530            AlterSpecification::DisableRowLevelSecurity(v) => v.span(),
1531            AlterSpecification::EnableRowLevelSecurity(v) => v.span(),
1532            AlterSpecification::ForceRowLevelSecurity(v) => v.span(),
1533            AlterSpecification::NoForceRowLevelSecurity(v) => v.span(),
1534        }
1535    }
1536}
1537
1538pub(crate) fn parse_index_type<'a>(
1539    parser: &mut Parser<'a, '_>,
1540    out: &mut Vec<IndexOption<'a>>,
1541) -> Result<(), ParseError> {
1542    parser.consume_keyword(Keyword::USING)?;
1543    out.push(match &parser.token {
1544        Token::Ident(_, Keyword::BTREE) => {
1545            IndexOption::IndexTypeBTree(parser.consume_keyword(Keyword::BTREE)?)
1546        }
1547        Token::Ident(_, Keyword::HASH) => {
1548            IndexOption::IndexTypeHash(parser.consume_keyword(Keyword::HASH)?)
1549        }
1550        Token::Ident(_, Keyword::RTREE) => {
1551            IndexOption::IndexTypeRTree(parser.consume_keyword(Keyword::RTREE)?)
1552        }
1553        _ => parser.expected_failure("'BTREE', 'RTREE' or 'HASH'")?,
1554    });
1555    Ok(())
1556}
1557
1558pub(crate) fn parse_index_options<'a>(
1559    parser: &mut Parser<'a, '_>,
1560    out: &mut Vec<IndexOption<'a>>,
1561) -> Result<(), ParseError> {
1562    loop {
1563        match &parser.token {
1564            Token::Ident(_, Keyword::USING) => parse_index_type(parser, out)?,
1565            Token::Ident(_, Keyword::COMMENT) => {
1566                parser.consume_keyword(Keyword::COMMENT)?;
1567                out.push(IndexOption::Comment(parser.consume_string()?))
1568            }
1569            _ => break,
1570        }
1571    }
1572    Ok(())
1573}
1574
1575/// Parse optional operator class (PostgreSQL)
1576/// This can be a qualified name like public.vector_cosine_ops or a known pattern_ops keyword
1577pub(crate) fn parse_operator_class<'a>(
1578    parser: &mut Parser<'a, '_>,
1579) -> Result<Option<QualifiedName<'a>>, ParseError> {
1580    if matches!(
1581        parser.token,
1582        Token::Ident(
1583            _,
1584            Keyword::TEXT_PATTERN_OPS
1585                | Keyword::VARCHAR_PATTERN_OPS
1586                | Keyword::BPCHAR_PATTERN_OPS
1587                | Keyword::INT8_OPS
1588                | Keyword::INT4_OPS
1589                | Keyword::INT2_OPS
1590        )
1591    ) {
1592        // Known pattern_ops keywords
1593        match parser.token {
1594            Token::Ident(v, _) => {
1595                let value = v;
1596                let span = parser.consume();
1597                parser.postgres_only(&span);
1598                Ok(Some(QualifiedName {
1599                    prefix: Vec::new(),
1600                    identifier: Identifier { value, span },
1601                }))
1602            }
1603            _ => Ok(None),
1604        }
1605    } else if matches!(parser.token, Token::Ident(_, _))
1606        && !matches!(
1607            parser.token,
1608            Token::Ident(_, Keyword::ASC | Keyword::DESC | Keyword::NULLS)
1609        )
1610        && *parser.peek() != Token::Comma
1611        && *parser.peek() != Token::RParen
1612    {
1613        // Try to parse as qualified name (for things like public.vector_cosine_ops)
1614        let qname = parse_qualified_name_unreserved(parser)?;
1615        parser.postgres_only(&qname);
1616        Ok(Some(qname))
1617    } else {
1618        Ok(None)
1619    }
1620}
1621
1622pub(crate) fn parse_index_cols<'a>(
1623    parser: &mut Parser<'a, '_>,
1624) -> Result<Vec<IndexCol<'a>>, ParseError> {
1625    parser.consume_token(Token::LParen)?;
1626    let mut ans = Vec::new();
1627    parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
1628        loop {
1629            // Check if this is a functional index expression (starts with '(')
1630            let expr = if parser.token == Token::LParen {
1631                // Functional index: parse expression
1632                parser.consume_token(Token::LParen)?;
1633                let expression = parse_expression_unreserved(parser, PRIORITY_MAX)?;
1634                parser.consume_token(Token::RParen)?;
1635                IndexColExpr::Expression(expression)
1636            } else {
1637                // Regular column name
1638                let name = parser.consume_plain_identifier_unreserved()?;
1639                IndexColExpr::Column(name)
1640            };
1641
1642            let size = if parser.skip_token(Token::LParen).is_some() {
1643                let size = parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
1644                    parser.consume_int()
1645                })?;
1646                parser.consume_token(Token::RParen)?;
1647                Some(size)
1648            } else {
1649                None
1650            };
1651
1652            // Parse optional operator class (PostgreSQL)
1653            let opclass = parse_operator_class(parser)?;
1654
1655            // Parse optional ASC | DESC
1656            let asc = parser.skip_keyword(Keyword::ASC);
1657            let desc = if asc.is_none() {
1658                parser.skip_keyword(Keyword::DESC)
1659            } else {
1660                None
1661            };
1662
1663            ans.push(IndexCol {
1664                expr,
1665                size,
1666                opclass,
1667                asc,
1668                desc,
1669            });
1670            if parser.skip_token(Token::Comma).is_none() {
1671                break;
1672            }
1673        }
1674        Ok(())
1675    })?;
1676    parser.consume_token(Token::RParen)?;
1677    Ok(ans)
1678}
1679
1680fn parse_cols<'a>(parser: &mut Parser<'a, '_>) -> Result<Vec<Identifier<'a>>, ParseError> {
1681    parser.consume_token(Token::LParen)?;
1682    let mut ans = Vec::new();
1683    parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
1684        loop {
1685            ans.push(parser.consume_plain_identifier_unreserved()?);
1686            if parser.skip_token(Token::Comma).is_none() {
1687                break;
1688            }
1689        }
1690        Ok(())
1691    })?;
1692    parser.consume_token(Token::RParen)?;
1693    Ok(ans)
1694}
1695
1696fn parse_add_alter_specification<'a>(
1697    parser: &mut Parser<'a, '_>,
1698) -> Result<AlterSpecification<'a>, ParseError> {
1699    let add_span = parser.consume_keyword(Keyword::ADD)?;
1700    let constraint = if let Some(span) = parser.skip_keyword(Keyword::CONSTRAINT) {
1701        let v = match &parser.token {
1702            Token::Ident(_, kw)
1703                if !kw.restricted(parser.reserved()) || kw == &Keyword::QUOTED_IDENTIFIER =>
1704            {
1705                Some(parser.consume_plain_identifier_restrict(Restrict::EMPTY)?)
1706            }
1707            Token::String(_, StringType::DoubleQuoted)
1708                if parser.options.dialect.is_postgresql() =>
1709            {
1710                Some(parser.consume_plain_identifier_restrict(Restrict::EMPTY)?)
1711            }
1712            _ => None,
1713        };
1714        Some((span, v))
1715    } else {
1716        None
1717    };
1718    // Peek ahead to check if PRIMARY is followed by KEY (for distinguishing table constraints)
1719    let primary_followed_by_key = matches!(&parser.token, Token::Ident(_, Keyword::PRIMARY))
1720        && matches!(parser.peek(), Token::Ident(_, Keyword::KEY));
1721
1722    match &parser.token {
1723        // Check for table constraints (UNIQUE/PRIMARY KEY without explicit INDEX/KEY keyword)
1724        Token::Ident(_, Keyword::UNIQUE) if constraint.is_some() => {
1725            // This is ADD CONSTRAINT ... UNIQUE (...) - a table constraint, not an index
1726            let unique_span = parser.consume_keyword(Keyword::UNIQUE)?;
1727            parser.postgres_only(&unique_span);
1728            // Parse optional NULLS [NOT] DISTINCT
1729            let nulls_clause = if let Some(nulls_span) = parser.skip_keyword(Keyword::NULLS) {
1730                let not_span = parser.skip_keyword(Keyword::NOT);
1731                parser.consume_keyword(Keyword::DISTINCT)?;
1732                Some((nulls_span, not_span))
1733            } else {
1734                None
1735            };
1736            let cols = parse_cols(parser)?;
1737            let not_valid = if let Some(span) = parser.skip_keyword(Keyword::NOT) {
1738                Some(span.join_span(&parser.consume_keyword(Keyword::VALID)?))
1739            } else {
1740                None
1741            };
1742            Ok(AlterSpecification::AddTableConstraint(AddTableConstraint {
1743                add_span,
1744                constraint,
1745                constraint_type: TableConstraintType::Unique {
1746                    unique_span,
1747                    nulls_clause,
1748                    cols,
1749                },
1750                not_valid,
1751            }))
1752        }
1753        Token::Ident(_, Keyword::PRIMARY) if constraint.is_some() && primary_followed_by_key => {
1754            // This is ADD CONSTRAINT ... PRIMARY KEY (...) - a table constraint
1755            let primary_span = parser.consume_keyword(Keyword::PRIMARY)?;
1756            parser.postgres_only(&primary_span);
1757            let key_span = parser.consume_keyword(Keyword::KEY)?;
1758            let cols = parse_cols(parser)?;
1759            let not_valid = if let Some(span) = parser.skip_keyword(Keyword::NOT) {
1760                Some(span.join_span(&parser.consume_keyword(Keyword::VALID)?))
1761            } else {
1762                None
1763            };
1764            Ok(AlterSpecification::AddTableConstraint(AddTableConstraint {
1765                add_span,
1766                constraint,
1767                constraint_type: TableConstraintType::PrimaryKey {
1768                    primary_span,
1769                    key_span,
1770                    cols,
1771                },
1772                not_valid,
1773            }))
1774        }
1775        Token::Ident(_, Keyword::CHECK) if constraint.is_some() => {
1776            // This is ADD CONSTRAINT ... CHECK (...)
1777            let check_span = parser.consume_keyword(Keyword::CHECK)?;
1778            parser.postgres_only(&check_span);
1779            parser.consume_token(Token::LParen)?;
1780            let expr = parse_expression_unreserved(parser, PRIORITY_MAX)?;
1781            parser.consume_token(Token::RParen)?;
1782            let not_valid = if let Some(span) = parser.skip_keyword(Keyword::NOT) {
1783                Some(span.join_span(&parser.consume_keyword(Keyword::VALID)?))
1784            } else {
1785                None
1786            };
1787            Ok(AlterSpecification::AddTableConstraint(AddTableConstraint {
1788                add_span,
1789                constraint,
1790                constraint_type: TableConstraintType::Check { check_span, expr },
1791                not_valid,
1792            }))
1793        }
1794        Token::Ident(_, Keyword::FOREIGN) => Ok(AlterSpecification::AddForeignKey(
1795            parse_add_foreign_key(parser, add_span, constraint)?,
1796        )),
1797        Token::Ident(
1798            _,
1799            Keyword::PRIMARY
1800            | Keyword::INDEX
1801            | Keyword::KEY
1802            | Keyword::FULLTEXT
1803            | Keyword::UNIQUE
1804            | Keyword::SPATIAL,
1805        ) => Ok(AlterSpecification::AddIndex(parse_add_index(
1806            parser, add_span, constraint,
1807        )?)),
1808        Token::Ident(_, Keyword::COLUMN) => Ok(AlterSpecification::AddColumn(parse_add_column(
1809            parser, add_span,
1810        )?)),
1811        _ => parser.expected_failure("addable"),
1812    }
1813}
1814
1815fn parse_rename_alter_specification<'a>(
1816    parser: &mut Parser<'a, '_>,
1817) -> Result<AlterSpecification<'a>, ParseError> {
1818    let rename_span = parser.consume_keyword(Keyword::RENAME)?;
1819
1820    match parser.token {
1821        Token::Ident(_, Keyword::COLUMN) => Ok(AlterSpecification::RenameColumn(
1822            parse_rename_column(parser, rename_span)?,
1823        )),
1824        Token::Ident(_, Keyword::INDEX | Keyword::KEY) => Ok(AlterSpecification::RenameIndex(
1825            parse_rename_index(parser, rename_span)?,
1826        )),
1827        Token::Ident(_, Keyword::CONSTRAINT) => Ok(AlterSpecification::RenameConstraint(
1828            parse_rename_constraint(parser, rename_span)?,
1829        )),
1830        Token::Ident(_, Keyword::TO | Keyword::AS) => Ok(AlterSpecification::RenameTo(
1831            parse_rename_to(parser, rename_span)?,
1832        )),
1833        _ => parser.expected_failure("'COLUMN', 'INDEX', 'CONSTRAINT' or 'TO'")?,
1834    }
1835}
1836
1837fn parse_drop<'a>(parser: &mut Parser<'a, '_>) -> Result<AlterSpecification<'a>, ParseError> {
1838    let drop_span = parser.consume_keyword(Keyword::DROP)?;
1839    match parser.token {
1840        Token::Ident(_, Keyword::INDEX | Keyword::KEY) => Ok(AlterSpecification::DropIndex(
1841            parse_drop_index(parser, drop_span)?,
1842        )),
1843        Token::Ident(_, Keyword::FOREIGN) => Ok(AlterSpecification::DropForeignKey(
1844            parse_drop_foreign_key(parser, drop_span)?,
1845        )),
1846        Token::Ident(_, Keyword::PRIMARY) => Ok(AlterSpecification::DropPrimaryKey(
1847            parse_drop_primary_key(parser, drop_span)?,
1848        )),
1849        Token::Ident(_, Keyword::COLUMN) => Ok(AlterSpecification::DropColumn(parse_drop_column(
1850            parser, drop_span,
1851        )?)),
1852        _ => parser.expected_failure("'COLUMN' or 'INDEX'")?,
1853    }
1854}
1855
1856/// Represent an alter table statement
1857/// ```
1858/// # use qusql_parse::{SQLDialect, SQLArguments, ParseOptions, parse_statements, AlterTable, Statement, Issues};
1859/// let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
1860///
1861/// let sql = "ALTER TABLE `t1`
1862///     MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,
1863///     ADD CONSTRAINT `t1_t2` FOREIGN KEY (`two`) REFERENCES `t2` (`id`);";
1864///
1865/// let mut issues = Issues::new(sql);
1866/// let mut stmts = parse_statements(sql, &mut issues, &options);
1867///
1868/// # assert!(issues.is_ok());
1869/// let alter: AlterTable = match stmts.pop() {
1870///     Some(Statement::AlterTable(a)) => *a,
1871///     _ => panic!("We should get an alter table statement")
1872/// };
1873///
1874/// assert!(alter.table.identifier.as_str() == "t1");
1875/// println!("{:#?}", alter.alter_specifications);
1876///
1877/// let options = ParseOptions::new().dialect(SQLDialect::PostgreSQL);
1878/// let sql = "ALTER TABLE t1
1879///     ALTER COLUMN id DROP NOT NULL,
1880///     ALTER COLUMN id SET NOT NULL,
1881///     ALTER COLUMN id SET DEFAULT 47,
1882///     ALTER COLUMN id DROP DEFAULT,
1883///     ALTER COLUMN id TYPE int;";
1884///
1885/// let mut issues = Issues::new(sql);
1886/// let mut stmts = parse_statements(sql, &mut issues, &options);
1887///
1888/// # assert!(issues.is_ok());
1889/// let alter: AlterTable = match stmts.pop() {
1890///     Some(Statement::AlterTable(a)) => *a,
1891///     _ => panic!("We should get an alter table statement")
1892/// };
1893///
1894#[derive(Clone, Debug)]
1895pub struct AlterTable<'a> {
1896    /// Span of "ALTER"
1897    pub alter_span: Span,
1898    /// Span of "ONLINE" if specified
1899    pub online: Option<Span>,
1900    /// Span of "IGNORE" if specified
1901    pub ignore: Option<Span>,
1902    /// Span of "TABLE"
1903    pub table_span: Span,
1904    /// Span of "IF EXISTS" if specified
1905    pub if_exists: Option<Span>,
1906    /// Span of "ONLY" if specified after IF EXISTS
1907    pub only: Option<Span>,
1908    /// The identifier of the table to alter
1909    pub table: QualifiedName<'a>,
1910    /// List of alterations to do
1911    pub alter_specifications: Vec<AlterSpecification<'a>>,
1912}
1913
1914impl<'a> Spanned for AlterTable<'a> {
1915    fn span(&self) -> Span {
1916        self.alter_span
1917            .join_span(&self.online)
1918            .join_span(&self.ignore)
1919            .join_span(&self.table_span)
1920            .join_span(&self.if_exists)
1921            .join_span(&self.only)
1922            .join_span(&self.table)
1923            .join_span(&self.alter_specifications)
1924    }
1925}
1926
1927pub(crate) fn parse_alter_table<'a>(
1928    parser: &mut Parser<'a, '_>,
1929    alter_span: Span,
1930    online: Option<Span>,
1931    ignore: Option<Span>,
1932) -> Result<AlterTable<'a>, ParseError> {
1933    // ONLINE and IGNORE are MariaDB/MySQL-specific
1934    if let Some(span) = &online {
1935        parser.maria_only(span);
1936    }
1937    if let Some(span) = &ignore {
1938        parser.maria_only(span);
1939    }
1940
1941    let table_span = parser.consume_keyword(Keyword::TABLE)?;
1942    let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
1943        Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
1944    } else {
1945        None
1946    };
1947    let only = if if_exists.is_some() {
1948        parser.skip_keyword(Keyword::ONLY)
1949    } else {
1950        None
1951    };
1952    let table = parse_qualified_name_unreserved(parser)?;
1953    let delimeter_name = parser.lexer.delimiter_name();
1954    let mut alter_specifications = Vec::new();
1955    parser.recovered(
1956        delimeter_name,
1957        &|t| matches!(t, Token::Delimiter | Token::Eof),
1958        |parser| {
1959            loop {
1960                alter_specifications.push(match parser.token {
1961                    Token::Ident(_, Keyword::ADD) => parse_add_alter_specification(parser)?,
1962                    Token::Ident(_, Keyword::MODIFY) => {
1963                        let modify_span = parser.consume_keyword(Keyword::MODIFY)?;
1964                        parser.maria_only(&modify_span);
1965                        AlterSpecification::Modify(parse_modify_column(parser, modify_span)?)
1966                    }
1967                    Token::Ident(_, Keyword::OWNER) => {
1968                        let span = parser.consume_keywords(&[Keyword::OWNER, Keyword::TO])?;
1969                        parser.postgres_only(&span);
1970                        AlterSpecification::OwnerTo(parse_owner_to(parser, span)?)
1971                    }
1972                    Token::Ident(_, Keyword::DROP) => parse_drop(parser)?,
1973                    Token::Ident(_, Keyword::ALTER) => {
1974                        let span = parser.consume_keywords(&[Keyword::ALTER, Keyword::COLUMN])?;
1975                        parser.postgres_only(&span);
1976                        let column = parser.consume_plain_identifier_unreserved()?;
1977
1978                        let alter_column_action = match parser.token {
1979                            Token::Ident(_, Keyword::SET) => {
1980                                let set_span = parser.consume();
1981                                match parser.token {
1982                                    Token::Ident(_, Keyword::DEFAULT) => {
1983                                        let set_default_span =
1984                                            parser.consume().join_span(&set_span);
1985                                        let value =
1986                                            parse_expression_unreserved(parser, PRIORITY_MAX)?;
1987                                        AlterColumnAction::SetDefault {
1988                                            set_default_span,
1989                                            value,
1990                                        }
1991                                    }
1992                                    Token::Ident(_, Keyword::NOT) => {
1993                                        let set_not_null_span =
1994                                            set_span.join_span(&parser.consume_keywords(&[
1995                                                Keyword::NOT,
1996                                                Keyword::NULL,
1997                                            ])?);
1998                                        AlterColumnAction::SetNotNull { set_not_null_span }
1999                                    }
2000                                    Token::Ident(_, Keyword::DATA) => {
2001                                        // SET DATA TYPE
2002                                        parser.consume_keyword(Keyword::DATA)?;
2003                                        let type_span = parser.consume_keyword(Keyword::TYPE)?;
2004                                        let type_span = set_span.join_span(&type_span);
2005                                        let type_ =
2006                                            parse_data_type(parser, DataTypeContext::Column)?;
2007                                        let using = if let Some(using_span) =
2008                                            parser.skip_keyword(Keyword::USING)
2009                                        {
2010                                            let expr =
2011                                                parse_expression_unreserved(parser, PRIORITY_MAX)?;
2012                                            Some((using_span, expr))
2013                                        } else {
2014                                            None
2015                                        };
2016                                        AlterColumnAction::Type {
2017                                            type_span,
2018                                            type_,
2019                                            using,
2020                                        }
2021                                    }
2022                                    _ => parser
2023                                        .expected_failure("'DEFAULT', 'NOT NULL', or 'DATA'")?,
2024                                }
2025                            }
2026                            Token::Ident(_, Keyword::DROP) => {
2027                                let set_span = parser.consume();
2028                                match parser.token {
2029                                    Token::Ident(_, Keyword::DEFAULT) => {
2030                                        let drop_default_span =
2031                                            parser.consume().join_span(&set_span);
2032                                        AlterColumnAction::DropDefault { drop_default_span }
2033                                    }
2034                                    Token::Ident(_, Keyword::NOT) => {
2035                                        let drop_not_null_span =
2036                                            set_span.join_span(&parser.consume_keywords(&[
2037                                                Keyword::NOT,
2038                                                Keyword::NULL,
2039                                            ])?);
2040                                        AlterColumnAction::DropNotNull { drop_not_null_span }
2041                                    }
2042                                    _ => parser.expected_failure("'DEFAULT' or 'NOT NULL'")?,
2043                                }
2044                            }
2045                            Token::Ident(_, Keyword::TYPE) => {
2046                                let type_span = parser.consume();
2047                                let type_ = parse_data_type(parser, DataTypeContext::Column)?;
2048                                let using = if let Some(using_span) =
2049                                    parser.skip_keyword(Keyword::USING)
2050                                {
2051                                    let expr = parse_expression_unreserved(parser, PRIORITY_MAX)?;
2052                                    Some((using_span, expr))
2053                                } else {
2054                                    None
2055                                };
2056                                AlterColumnAction::Type {
2057                                    type_span,
2058                                    type_,
2059                                    using,
2060                                }
2061                            }
2062                            Token::Ident(_, Keyword::ADD) => {
2063                                let add_span = parser.consume_keyword(Keyword::ADD)?;
2064                                let generated_span = parser.consume_keyword(Keyword::GENERATED)?;
2065                                // Parse optional ALWAYS or BY DEFAULT
2066                                let always_or_default = if let Some(always_span) =
2067                                    parser.skip_keyword(Keyword::ALWAYS)
2068                                {
2069                                    Some((always_span.clone(), always_span))
2070                                } else if let Some(by_span) = parser.skip_keyword(Keyword::BY) {
2071                                    let default_span = parser.consume_keyword(Keyword::DEFAULT)?;
2072                                    Some((by_span, default_span))
2073                                } else {
2074                                    None
2075                                };
2076                                let as_span = parser.consume_keyword(Keyword::AS)?;
2077                                let identity_span = parser.consume_keyword(Keyword::IDENTITY)?;
2078                                // Parse optional sequence options in parentheses
2079                                let sequence_options = if parser.skip_token(Token::LParen).is_some()
2080                                {
2081                                    let options = parse_sequence_options(parser)?;
2082                                    if options.is_empty() {
2083                                        parser.expected_failure("sequence option")?;
2084                                    }
2085                                    parser.consume_token(Token::RParen)?;
2086                                    options
2087                                } else {
2088                                    Vec::new()
2089                                };
2090                                AlterColumnAction::AddGenerated {
2091                                    add_span,
2092                                    generated_span,
2093                                    always_or_default,
2094                                    as_span,
2095                                    identity_span,
2096                                    sequence_options,
2097                                }
2098                            }
2099                            _ => parser.expected_failure("alter column action")?,
2100                        };
2101                        AlterSpecification::AlterColumn(AlterColumn {
2102                            alter_column_span: span,
2103                            column,
2104                            alter_column_action,
2105                        })
2106                    }
2107                    Token::Ident(_, Keyword::LOCK) => {
2108                        let lock_span = parser.consume_keyword(Keyword::LOCK)?;
2109                        parser.maria_only(&lock_span);
2110                        AlterSpecification::Lock(parse_lock(parser, lock_span)?)
2111                    }
2112                    Token::Ident(_, Keyword::ALGORITHM) => {
2113                        let algorithm_span = parser.consume_keyword(Keyword::ALGORITHM)?;
2114                        parser.maria_only(&algorithm_span);
2115                        AlterSpecification::Algorithm(parse_algorithm(parser, algorithm_span)?)
2116                    }
2117                    Token::Ident(_, Keyword::AUTO_INCREMENT) => {
2118                        let auto_increment_span =
2119                            parser.consume_keyword(Keyword::AUTO_INCREMENT)?;
2120                        parser.maria_only(&auto_increment_span);
2121                        AlterSpecification::AutoIncrement(parse_auto_increment(
2122                            parser,
2123                            auto_increment_span,
2124                        )?)
2125                    }
2126                    Token::Ident(_, Keyword::RENAME) => parse_rename_alter_specification(parser)?,
2127                    Token::Ident(_, Keyword::CHANGE) => {
2128                        let change_span = parser.consume_keyword(Keyword::CHANGE)?;
2129                        parser.maria_only(&change_span);
2130                        AlterSpecification::Change(parse_change(parser, change_span)?)
2131                    }
2132                    Token::Ident(_, Keyword::REPLICA) => {
2133                        let replica_span = parser.consume_keyword(Keyword::REPLICA)?;
2134                        parser.postgres_only(&replica_span);
2135                        let identity_span = parser.consume_keyword(Keyword::IDENTITY)?;
2136                        let option = match &parser.token {
2137                            Token::Ident(_, Keyword::DEFAULT) => ReplicaIdentityOption::Default(
2138                                parser.consume_keyword(Keyword::DEFAULT)?,
2139                            ),
2140                            Token::Ident(_, Keyword::FULL) => {
2141                                ReplicaIdentityOption::Full(parser.consume_keyword(Keyword::FULL)?)
2142                            }
2143                            Token::Ident(_, Keyword::NOTHING) => ReplicaIdentityOption::Nothing(
2144                                parser.consume_keyword(Keyword::NOTHING)?,
2145                            ),
2146                            Token::Ident(_, Keyword::USING) => {
2147                                let using_span = parser.consume_keyword(Keyword::USING)?;
2148                                let index_span = parser.consume_keyword(Keyword::INDEX)?;
2149                                let name = parser.consume_plain_identifier_unreserved()?;
2150                                ReplicaIdentityOption::UsingIndex {
2151                                    using_span,
2152                                    index_span,
2153                                    name,
2154                                }
2155                            }
2156                            _ => parser.expected_failure("REPLICA IDENTITY option")?,
2157                        };
2158                        AlterSpecification::ReplicaIdentity(ReplicaIdentity {
2159                            replica_span,
2160                            identity_span,
2161                            option,
2162                        })
2163                    }
2164                    Token::Ident(_, Keyword::VALIDATE) => {
2165                        let validate_span = parser.consume_keyword(Keyword::VALIDATE)?;
2166                        parser.postgres_only(&validate_span);
2167                        AlterSpecification::ValidateConstraint(parse_validate_constraint(
2168                            parser,
2169                            validate_span,
2170                        )?)
2171                    }
2172                    Token::Ident(_, Keyword::DISABLE) => {
2173                        let disable_span = parser.consume_keyword(Keyword::DISABLE)?;
2174                        parser.postgres_only(&disable_span);
2175                        match &parser.token {
2176                            Token::Ident(_, Keyword::TRIGGER) => {
2177                                let trigger_span = parser.consume_keyword(Keyword::TRIGGER)?;
2178                                let trigger_name = match &parser.token {
2179                                    Token::Ident(_, Keyword::ALL) => {
2180                                        TriggerName::All(parser.consume_keyword(Keyword::ALL)?)
2181                                    }
2182                                    Token::Ident(_, Keyword::USER) => {
2183                                        TriggerName::User(parser.consume_keyword(Keyword::USER)?)
2184                                    }
2185                                    _ => TriggerName::Named(
2186                                        parser.consume_plain_identifier_unreserved()?,
2187                                    ),
2188                                };
2189                                AlterSpecification::DisableTrigger(DisableTrigger {
2190                                    disable_span,
2191                                    trigger_span,
2192                                    trigger_name,
2193                                })
2194                            }
2195                            Token::Ident(_, Keyword::RULE) => {
2196                                let rule_span = parser.consume_keyword(Keyword::RULE)?;
2197                                let rule_name = parser.consume_plain_identifier_unreserved()?;
2198                                AlterSpecification::DisableRule(DisableRule {
2199                                    disable_span,
2200                                    rule_span,
2201                                    rule_name,
2202                                })
2203                            }
2204                            Token::Ident(_, Keyword::ROW) => {
2205                                let row_span = parser.consume_keyword(Keyword::ROW)?;
2206                                let level_span = parser.consume_keyword(Keyword::LEVEL)?;
2207                                let security_span = parser.consume_keyword(Keyword::SECURITY)?;
2208                                AlterSpecification::DisableRowLevelSecurity(
2209                                    DisableRowLevelSecurity {
2210                                        disable_span,
2211                                        row_span,
2212                                        level_span,
2213                                        security_span,
2214                                    },
2215                                )
2216                            }
2217                            _ => parser.expected_failure("'TRIGGER', 'RULE', or 'ROW'")?,
2218                        }
2219                    }
2220                    Token::Ident(_, Keyword::ENABLE) => {
2221                        let enable_span = parser.consume_keyword(Keyword::ENABLE)?;
2222                        parser.postgres_only(&enable_span);
2223                        let modifier = if let Some(span) = parser.skip_keyword(Keyword::REPLICA) {
2224                            Some(span)
2225                        } else {
2226                            parser.skip_keyword(Keyword::ALWAYS)
2227                        };
2228                        match &parser.token {
2229                            Token::Ident(_, Keyword::TRIGGER) => {
2230                                let trigger_span = parser.consume_keyword(Keyword::TRIGGER)?;
2231                                let trigger_name = match &parser.token {
2232                                    Token::Ident(_, Keyword::ALL) => {
2233                                        TriggerName::All(parser.consume_keyword(Keyword::ALL)?)
2234                                    }
2235                                    Token::Ident(_, Keyword::USER) => {
2236                                        TriggerName::User(parser.consume_keyword(Keyword::USER)?)
2237                                    }
2238                                    _ => TriggerName::Named(
2239                                        parser.consume_plain_identifier_unreserved()?,
2240                                    ),
2241                                };
2242                                AlterSpecification::EnableTrigger(EnableTrigger {
2243                                    enable_span,
2244                                    modifier,
2245                                    trigger_span,
2246                                    trigger_name,
2247                                })
2248                            }
2249                            Token::Ident(_, Keyword::RULE) => {
2250                                let rule_span = parser.consume_keyword(Keyword::RULE)?;
2251                                let rule_name = parser.consume_plain_identifier_unreserved()?;
2252                                AlterSpecification::EnableRule(EnableRule {
2253                                    enable_span,
2254                                    modifier,
2255                                    rule_span,
2256                                    rule_name,
2257                                })
2258                            }
2259                            Token::Ident(_, Keyword::ROW) => {
2260                                let row_span = parser.consume_keyword(Keyword::ROW)?;
2261                                let level_span = parser.consume_keyword(Keyword::LEVEL)?;
2262                                let security_span = parser.consume_keyword(Keyword::SECURITY)?;
2263                                AlterSpecification::EnableRowLevelSecurity(EnableRowLevelSecurity {
2264                                    enable_span,
2265                                    row_span,
2266                                    level_span,
2267                                    security_span,
2268                                })
2269                            }
2270                            _ => parser.expected_failure("'TRIGGER', 'RULE', or 'ROW'")?,
2271                        }
2272                    }
2273                    Token::Ident(_, Keyword::FORCE) => {
2274                        let force_span = parser.consume_keyword(Keyword::FORCE)?;
2275                        parser.postgres_only(&force_span);
2276                        let row_span = parser.consume_keyword(Keyword::ROW)?;
2277                        let level_span = parser.consume_keyword(Keyword::LEVEL)?;
2278                        let security_span = parser.consume_keyword(Keyword::SECURITY)?;
2279                        AlterSpecification::ForceRowLevelSecurity(ForceRowLevelSecurity {
2280                            force_span,
2281                            row_span,
2282                            level_span,
2283                            security_span,
2284                        })
2285                    }
2286                    Token::Ident(_, Keyword::NO) => {
2287                        let no_span = parser.consume_keyword(Keyword::NO)?;
2288                        parser.postgres_only(&no_span);
2289                        let force_span = parser.consume_keyword(Keyword::FORCE)?;
2290                        let row_span = parser.consume_keyword(Keyword::ROW)?;
2291                        let level_span = parser.consume_keyword(Keyword::LEVEL)?;
2292                        let security_span = parser.consume_keyword(Keyword::SECURITY)?;
2293                        AlterSpecification::NoForceRowLevelSecurity(NoForceRowLevelSecurity {
2294                            no_span,
2295                            force_span,
2296                            row_span,
2297                            level_span,
2298                            security_span,
2299                        })
2300                    }
2301                    _ => parser.expected_failure("alter specification")?,
2302                });
2303                if parser.skip_token(Token::Comma).is_none() {
2304                    break;
2305                }
2306            }
2307            Ok(())
2308        },
2309    )?;
2310    Ok(AlterTable {
2311        alter_span,
2312        online,
2313        ignore,
2314        table_span,
2315        if_exists,
2316        only,
2317        table,
2318        alter_specifications,
2319    })
2320}