Skip to main content

qusql_parse/
statement.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13use alloc::{boxed::Box, vec::Vec};
14
15use crate::{
16    AlterOperator, AlterOperatorClass, AlterOperatorFamily, AlterRole, AlterTable, AlterType,
17    CreateConstraintTrigger, CreateDomain, CreateExtension, CreateIndex, CreateOperator,
18    CreateOperatorClass, CreateOperatorFamily, CreateRole, CreateTrigger, DropOperatorClass,
19    DropOperatorFamily, QualifiedName, RenameTable, Span, Spanned, WithQuery,
20    alter_role::parse_alter_role,
21    alter_table::parse_alter_table,
22    copy::{CopyFrom, CopyTo, parse_copy_statement},
23    create::{
24        CreateDatabase, CreateSchema, CreateSequence, CreateServer, CreateTypeEnum, parse_create,
25    },
26    create_function::{CreateFunction, CreateProcedure},
27    create_table::{CreateTable, CreateTablePartitionOf},
28    create_view::CreateView,
29    delete::{Delete, parse_delete},
30    drop::{
31        DropDatabase, DropDomain, DropEvent, DropExtension, DropFunction, DropIndex, DropOperator,
32        DropProcedure, DropSequence, DropServer, DropTable, DropTrigger, DropView, parse_drop,
33    },
34    expression::{Expression, PRIORITY_MAX, parse_expression_unreserved},
35    flush::{Flush, parse_flush},
36    insert_replace::{InsertReplace, parse_insert_replace},
37    keywords::Keyword,
38    kill::{Kill, parse_kill},
39    lexer::{StringType, Token},
40    lock::{Lock, Unlock, parse_lock, parse_unlock},
41    parser::{ParseError, Parser},
42    qualified_name::parse_qualified_name_unreserved,
43    rename::parse_rename_table,
44    select::{OrderFlag, Select, parse_select},
45    show::{
46        ShowCharacterSet, ShowCollation, ShowColumns, ShowCreateDatabase, ShowCreateTable,
47        ShowCreateView, ShowDatabases, ShowEngines, ShowProcessList, ShowStatus, ShowTables,
48        ShowVariables, parse_show,
49    },
50    span::OptSpanned,
51    truncate::{TruncateTable, parse_truncate_table},
52    update::{Update, parse_update},
53    values::parse_values,
54    with_query::parse_with_query,
55};
56
57#[derive(Clone, Debug)]
58pub struct Set<'a> {
59    pub set_span: Span,
60    pub values: Vec<(QualifiedName<'a>, Expression<'a>)>,
61}
62
63impl<'a> Spanned for Set<'a> {
64    fn span(&self) -> Span {
65        self.set_span.join_span(&self.values)
66    }
67}
68
69fn parse_set<'a>(parser: &mut Parser<'a, '_>) -> Result<Set<'a>, ParseError> {
70    let set_span = parser.consume_keyword(Keyword::SET)?;
71    let mut values = Vec::new();
72    loop {
73        let name = parse_qualified_name_unreserved(parser)?;
74        parser.consume_token(Token::Eq)?;
75        let val = parse_expression_unreserved(parser, PRIORITY_MAX)?;
76        values.push((name, val));
77        if parser.skip_token(Token::Comma).is_none() {
78            break;
79        }
80    }
81    Ok(Set { set_span, values })
82}
83
84fn parse_statement_list_inner<'a>(
85    parser: &mut Parser<'a, '_>,
86    out: &mut Vec<Statement<'a>>,
87) -> Result<(), ParseError> {
88    loop {
89        while parser.skip_token(Token::Delimiter).is_some() {}
90        // Detect MariaDB statement labels: `label_name:`
91        let label = if parser.permit_compound_statements
92            && matches!(&parser.token, Token::Ident(_, Keyword::NOT_A_KEYWORD))
93            && matches!(parser.peek(), Token::Colon)
94        {
95            let l = parser.consume_plain_identifier_unreserved()?;
96            parser.consume(); // colon
97            Some(l)
98        } else {
99            None
100        };
101        let stmt = if let Some(label) = label {
102            // After a label, only loop constructs are valid; label is stored in AST
103            match &parser.token {
104                Token::Ident(_, Keyword::LOOP) if parser.options.dialect.is_maria() => {
105                    Some(Statement::Loop(Box::new(parse_loop(parser, Some(label))?)))
106                }
107                Token::Ident(_, Keyword::WHILE) if parser.options.dialect.is_maria() => Some(
108                    Statement::While(Box::new(parse_while(parser, Some(label))?)),
109                ),
110                Token::Ident(_, Keyword::REPEAT) if parser.options.dialect.is_maria() => Some(
111                    Statement::Repeat(Box::new(parse_repeat(parser, Some(label))?)),
112                ),
113                _ => parse_statement(parser)?,
114            }
115        } else {
116            parse_statement(parser)?
117        };
118        let stdin = match stmt {
119            Some(v) => {
120                let stdin = v.reads_from_stdin();
121                out.push(v);
122                stdin
123            }
124            None => break,
125        };
126        if !matches!(parser.token, Token::Delimiter) {
127            break;
128        }
129        if stdin {
130            let (s, span) = parser.read_from_stdin_and_next();
131            out.push(Statement::Stdin(Box::new(Stdin { input: s, span })));
132        } else {
133            parser.consume_token(Token::Delimiter)?;
134        }
135    }
136    Ok(())
137}
138
139fn parse_statement_list<'a>(
140    parser: &mut Parser<'a, '_>,
141    out: &mut Vec<Statement<'a>>,
142) -> Result<(), ParseError> {
143    let old = core::mem::replace(&mut parser.lexer.semicolon_as_delimiter, true);
144    let r = parse_statement_list_inner(parser, out);
145    parser.lexer.semicolon_as_delimiter = old;
146    r
147}
148
149fn parse_begin(parser: &mut Parser<'_, '_>) -> Result<Begin, ParseError> {
150    Ok(Begin {
151        span: parser.consume_keyword(Keyword::BEGIN)?,
152    })
153}
154
155fn parse_end(parser: &mut Parser<'_, '_>) -> Result<End, ParseError> {
156    Ok(End {
157        span: parser.consume_keyword(Keyword::END)?,
158    })
159}
160
161fn parse_start_transaction<'a>(
162    parser: &mut Parser<'a, '_>,
163) -> Result<StartTransaction, ParseError> {
164    Ok(StartTransaction {
165        span: parser.consume_keywords(&[Keyword::START, Keyword::TRANSACTION])?,
166    })
167}
168
169fn parse_commit(parser: &mut Parser<'_, '_>) -> Result<Commit, ParseError> {
170    Ok(Commit {
171        span: parser.consume_keyword(Keyword::COMMIT)?,
172    })
173}
174
175fn parse_block<'a>(parser: &mut Parser<'a, '_>) -> Result<Block<'a>, ParseError> {
176    let begin_span = parser.consume_keyword(Keyword::BEGIN)?;
177    let mut statements = Vec::new();
178    parser.recovered(
179        "'END' | 'EXCEPTION'",
180        &|e| matches!(e, Token::Ident(_, Keyword::END | Keyword::EXCEPTION)),
181        |parser| parse_statement_list(parser, &mut statements),
182    )?;
183    if let Some(_exception_span) = parser.skip_keyword(Keyword::EXCEPTION) {
184        while let Some(_when_span) = parser.skip_keyword(Keyword::WHEN) {
185            parser.consume_plain_identifier_unreserved()?;
186            parser.consume_keyword(Keyword::THEN)?;
187            parse_expression_unreserved(parser, PRIORITY_MAX)?;
188            parser.consume_token(Token::SemiColon)?;
189        }
190    }
191    let end_span = parser.consume_keyword(Keyword::END)?;
192    Ok(Block {
193        begin_span,
194        statements,
195        end_span,
196    })
197}
198
199/// Condition in if statement
200#[derive(Clone, Debug)]
201pub struct IfCondition<'a> {
202    /// Span of "ELSEIF" if specified
203    pub elseif_span: Option<Span>,
204    /// Expression that must be true for `then` to be executed
205    pub search_condition: Expression<'a>,
206    /// Span of "THEN"
207    pub then_span: Span,
208    /// List of statement to be executed if `search_condition` is true
209    pub then: Vec<Statement<'a>>,
210}
211
212impl<'a> Spanned for IfCondition<'a> {
213    fn span(&self) -> Span {
214        self.then_span
215            .join_span(&self.elseif_span)
216            .join_span(&self.search_condition)
217            .join_span(&self.then_span)
218            .join_span(&self.then)
219    }
220}
221
222/// If statement
223#[derive(Clone, Debug)]
224pub struct If<'a> {
225    /// Span of "IF"
226    pub if_span: Span,
227    // List of if a then v parts
228    pub conditions: Vec<IfCondition<'a>>,
229    /// Span of "ELSE" and else Statement if specified
230    pub else_: Option<(Span, Vec<Statement<'a>>)>,
231    /// Span of "ENDIF"
232    pub endif_span: Span,
233}
234
235impl<'a> Spanned for If<'a> {
236    fn span(&self) -> Span {
237        self.if_span
238            .join_span(&self.conditions)
239            .join_span(&self.else_)
240            .join_span(&self.endif_span)
241    }
242}
243
244fn parse_if<'a>(parser: &mut Parser<'a, '_>) -> Result<If<'a>, ParseError> {
245    let if_span = parser.consume_keyword(Keyword::IF)?;
246    let mut conditions = Vec::new();
247    let mut else_ = None;
248    parser.recovered(
249        "'END'",
250        &|e| matches!(e, Token::Ident(_, Keyword::END)),
251        |parser| {
252            let search_condition = parse_expression_unreserved(parser, PRIORITY_MAX)?;
253            let then_span = parser.consume_keyword(Keyword::THEN)?;
254            let mut then = Vec::new();
255            parse_statement_list(parser, &mut then)?;
256            conditions.push(IfCondition {
257                elseif_span: None,
258                search_condition,
259                then_span,
260                then,
261            });
262            while let Some(elseif_span) = parser.skip_keyword(Keyword::ELSEIF) {
263                let search_condition = parse_expression_unreserved(parser, PRIORITY_MAX)?;
264                let then_span = parser.consume_keyword(Keyword::THEN)?;
265                let mut then = Vec::new();
266                parse_statement_list(parser, &mut then)?;
267                conditions.push(IfCondition {
268                    elseif_span: Some(elseif_span),
269                    search_condition,
270                    then_span,
271                    then,
272                })
273            }
274            if let Some(else_span) = parser.skip_keyword(Keyword::ELSE) {
275                let mut o = Vec::new();
276                parse_statement_list(parser, &mut o)?;
277                else_ = Some((else_span, o));
278            }
279            Ok(())
280        },
281    )?;
282    let endif_span = parser.consume_keywords(&[Keyword::END, Keyword::IF])?;
283    Ok(If {
284        if_span,
285        conditions,
286        else_,
287        endif_span,
288    })
289}
290
291/// Return statement
292#[derive(Clone, Debug)]
293pub struct Return<'a> {
294    /// Span of "Return"
295    pub return_span: Span,
296    pub expr: Expression<'a>,
297}
298
299impl<'a> Spanned for Return<'a> {
300    fn span(&self) -> Span {
301        self.return_span.join_span(&self.expr)
302    }
303}
304
305fn parse_return<'a>(parser: &mut Parser<'a, '_>) -> Result<Return<'a>, ParseError> {
306    let return_span = parser.consume_keyword(Keyword::RETURN)?;
307    let expr = parse_expression_unreserved(parser, PRIORITY_MAX)?;
308    Ok(Return { return_span, expr })
309}
310
311#[derive(Clone, Debug)]
312pub enum SignalConditionInformationName {
313    ClassOrigin(Span),
314    SubclassOrigin(Span),
315    MessageText(Span),
316    MysqlErrno(Span),
317    ConstraintCatalog(Span),
318    ConstraintSchema(Span),
319    ConstraintName(Span),
320    CatalogName(Span),
321    SchemaName(Span),
322    TableName(Span),
323    ColumnName(Span),
324    CursorName(Span),
325}
326
327impl Spanned for SignalConditionInformationName {
328    fn span(&self) -> Span {
329        match self {
330            SignalConditionInformationName::ClassOrigin(span) => span.clone(),
331            SignalConditionInformationName::SubclassOrigin(span) => span.clone(),
332            SignalConditionInformationName::MessageText(span) => span.clone(),
333            SignalConditionInformationName::MysqlErrno(span) => span.clone(),
334            SignalConditionInformationName::ConstraintCatalog(span) => span.clone(),
335            SignalConditionInformationName::ConstraintSchema(span) => span.clone(),
336            SignalConditionInformationName::ConstraintName(span) => span.clone(),
337            SignalConditionInformationName::CatalogName(span) => span.clone(),
338            SignalConditionInformationName::SchemaName(span) => span.clone(),
339            SignalConditionInformationName::TableName(span) => span.clone(),
340            SignalConditionInformationName::ColumnName(span) => span.clone(),
341            SignalConditionInformationName::CursorName(span) => span.clone(),
342        }
343    }
344}
345
346/// Return statement
347#[derive(Clone, Debug)]
348pub struct Signal<'a> {
349    pub signal_span: Span,
350    pub sqlstate_span: Span,
351    pub value_span: Option<Span>,
352    pub sql_state: Expression<'a>,
353    pub set_span: Option<Span>,
354    pub sets: Vec<(SignalConditionInformationName, Span, Expression<'a>)>,
355}
356
357impl<'a> Spanned for Signal<'a> {
358    fn span(&self) -> Span {
359        self.signal_span
360            .join_span(&self.sqlstate_span)
361            .join_span(&self.value_span)
362            .join_span(&self.sql_state)
363            .join_span(&self.set_span)
364            .join_span(&self.sets)
365    }
366}
367
368fn parse_signal<'a>(parser: &mut Parser<'a, '_>) -> Result<Signal<'a>, ParseError> {
369    let signal_span = parser.consume_keyword(Keyword::SIGNAL)?;
370    let sqlstate_span = parser.consume_keyword(Keyword::SQLSTATE)?;
371    let value_span = parser.skip_keyword(Keyword::VALUE);
372    let sql_state = parse_expression_unreserved(parser, PRIORITY_MAX)?;
373    let mut sets = Vec::new();
374    let set_span = parser.skip_keyword(Keyword::SET);
375    if set_span.is_some() {
376        loop {
377            let v = match &parser.token {
378                Token::Ident(_, Keyword::CLASS_ORIGIN) => {
379                    SignalConditionInformationName::ClassOrigin(parser.consume())
380                }
381                Token::Ident(_, Keyword::SUBCLASS_ORIGIN) => {
382                    SignalConditionInformationName::SubclassOrigin(parser.consume())
383                }
384                Token::Ident(_, Keyword::MESSAGE_TEXT) => {
385                    SignalConditionInformationName::MessageText(parser.consume())
386                }
387                Token::Ident(_, Keyword::MYSQL_ERRNO) => {
388                    SignalConditionInformationName::MysqlErrno(parser.consume())
389                }
390                Token::Ident(_, Keyword::CONSTRAINT_CATALOG) => {
391                    SignalConditionInformationName::ConstraintCatalog(parser.consume())
392                }
393                Token::Ident(_, Keyword::CONSTRAINT_SCHEMA) => {
394                    SignalConditionInformationName::ConstraintSchema(parser.consume())
395                }
396                Token::Ident(_, Keyword::CONSTRAINT_NAME) => {
397                    SignalConditionInformationName::ConstraintName(parser.consume())
398                }
399                Token::Ident(_, Keyword::CATALOG_NAME) => {
400                    SignalConditionInformationName::CatalogName(parser.consume())
401                }
402                Token::Ident(_, Keyword::SCHEMA_NAME) => {
403                    SignalConditionInformationName::SchemaName(parser.consume())
404                }
405                Token::Ident(_, Keyword::TABLE_NAME) => {
406                    SignalConditionInformationName::TableName(parser.consume())
407                }
408                Token::Ident(_, Keyword::COLUMN_NAME) => {
409                    SignalConditionInformationName::ColumnName(parser.consume())
410                }
411                Token::Ident(_, Keyword::CURSOR_NAME) => {
412                    SignalConditionInformationName::CursorName(parser.consume())
413                }
414                _ => parser.expected_failure("Condition information item name")?,
415            };
416            let eq_span = parser.consume_token(Token::Eq)?;
417            let value = parse_expression_unreserved(parser, PRIORITY_MAX)?;
418            sets.push((v, eq_span, value));
419            if parser.skip_token(Token::Comma).is_none() {
420                break;
421            }
422        }
423    }
424    Ok(Signal {
425        signal_span,
426        sqlstate_span,
427        value_span,
428        sql_state,
429        set_span,
430        sets,
431    })
432}
433
434/// Block statement, for example in stored procedures
435#[derive(Clone, Debug)]
436pub struct Block<'a> {
437    /// Span of "BEGIN"
438    pub begin_span: Span,
439    /// Statements in block
440    pub statements: Vec<Statement<'a>>,
441    /// Span of "END"
442    pub end_span: Span,
443}
444
445impl Spanned for Block<'_> {
446    fn span(&self) -> Span {
447        self.begin_span
448            .join_span(&self.statements)
449            .join_span(&self.end_span)
450    }
451}
452
453/// Begin statement
454#[derive(Clone, Debug)]
455pub struct Begin {
456    /// Span of "BEGIN"
457    pub span: Span,
458}
459
460impl Spanned for Begin {
461    fn span(&self) -> Span {
462        self.span.clone()
463    }
464}
465
466/// End statement
467#[derive(Clone, Debug)]
468pub struct End {
469    /// Span of "END"
470    pub span: Span,
471}
472
473impl Spanned for End {
474    fn span(&self) -> Span {
475        self.span.clone()
476    }
477}
478
479/// Commit statement
480#[derive(Clone, Debug)]
481pub struct Commit {
482    /// Span of "COMMIT"
483    pub span: Span,
484}
485
486impl Spanned for Commit {
487    fn span(&self) -> Span {
488        self.span.clone()
489    }
490}
491
492/// Start transaction statement
493#[derive(Clone, Debug)]
494pub struct StartTransaction {
495    /// Span of "START TRANSACTION"
496    pub span: Span,
497}
498
499impl Spanned for StartTransaction {
500    fn span(&self) -> Span {
501        self.span.clone()
502    }
503}
504
505/// Body of a DO statement
506#[derive(Clone, Debug)]
507pub enum DoBody<'a> {
508    /// Parsed statements from `DO $$ BEGIN ... END $$`
509    Statements(Vec<Statement<'a>>),
510    /// Unparsed dollar-quoted string literal, e.g. `DO $$ ... $$`
511    String(&'a str, Span),
512}
513
514impl<'a> OptSpanned for DoBody<'a> {
515    fn opt_span(&self) -> Option<Span> {
516        match self {
517            DoBody::Statements(s) => s.opt_span(),
518            DoBody::String(_, span) => Some(span.clone()),
519        }
520    }
521}
522
523/// Do statement
524#[derive(Clone, Debug)]
525pub struct Do<'a> {
526    /// Span of "DO"
527    pub do_span: Span,
528    /// Body of the DO block
529    pub body: DoBody<'a>,
530}
531
532impl<'a> Spanned for Do<'a> {
533    fn span(&self) -> Span {
534        self.do_span.join_span(&self.body)
535    }
536}
537
538/// Invalid statement produced after recovering from parse error
539#[derive(Clone, Debug)]
540pub struct Invalid {
541    /// Span of invalid statement
542    pub span: Span,
543}
544
545impl Spanned for Invalid {
546    fn span(&self) -> Span {
547        self.span.clone()
548    }
549}
550
551/// Stdin statement, used to represent input from stdin after a COPY statement
552#[derive(Clone, Debug)]
553pub struct Stdin<'a> {
554    /// The input from stdin
555    pub input: &'a str,
556    /// Span of the input
557    pub span: Span,
558}
559
560impl Spanned for Stdin<'_> {
561    fn span(&self) -> Span {
562        self.span.clone()
563    }
564}
565
566/// ALTER SCHEMA statement (PostgreSQL)
567#[derive(Clone, Debug)]
568pub struct AlterSchema<'a> {
569    /// Span of "ALTER SCHEMA"
570    pub alter_schema_span: Span,
571    /// The schema name
572    pub name: QualifiedName<'a>,
573    /// The action (RENAME TO, OWNER TO)
574    pub action: AlterSchemaAction<'a>,
575}
576
577#[derive(Clone, Debug)]
578pub enum AlterSchemaAction<'a> {
579    /// RENAME TO new_name
580    RenameTo {
581        rename_to_span: Span,
582        new_name: QualifiedName<'a>,
583    },
584    /// OWNER TO new_owner
585    OwnerTo {
586        owner_to_span: Span,
587        new_owner: crate::alter_table::AlterTableOwner<'a>,
588    },
589}
590
591impl<'a> Spanned for AlterSchemaAction<'a> {
592    fn span(&self) -> Span {
593        match self {
594            AlterSchemaAction::RenameTo {
595                rename_to_span,
596                new_name,
597            } => rename_to_span.join_span(new_name),
598            AlterSchemaAction::OwnerTo {
599                owner_to_span,
600                new_owner,
601            } => owner_to_span.join_span(new_owner),
602        }
603    }
604}
605
606impl<'a> Spanned for AlterSchema<'a> {
607    fn span(&self) -> Span {
608        self.alter_schema_span
609            .join_span(&self.name)
610            .join_span(&self.action)
611    }
612}
613
614/// Parse ALTER SCHEMA statement (PostgreSQL)
615pub(crate) fn parse_alter_schema<'a>(
616    parser: &mut Parser<'a, '_>,
617    alter_schema_span: Span,
618) -> Result<AlterSchema<'a>, ParseError> {
619    parser.postgres_only(&alter_schema_span);
620    let name = parse_qualified_name_unreserved(parser)?;
621    let action = match &parser.token {
622        Token::Ident(_, Keyword::RENAME) => {
623            let rename_to_span = parser.consume_keywords(&[Keyword::RENAME, Keyword::TO])?;
624            let new_name = parse_qualified_name_unreserved(parser)?;
625            AlterSchemaAction::RenameTo {
626                rename_to_span,
627                new_name,
628            }
629        }
630        Token::Ident(_, Keyword::OWNER) => {
631            let owner_to_span = parser.consume_keywords(&[Keyword::OWNER, Keyword::TO])?;
632            let new_owner = crate::alter_table::parse_alter_owner(parser)?;
633            AlterSchemaAction::OwnerTo {
634                owner_to_span,
635                new_owner,
636            }
637        }
638        _ => parser.expected_failure("'RENAME TO' or 'OWNER TO' after ALTER SCHEMA ...")?,
639    };
640    Ok(AlterSchema {
641        alter_schema_span,
642        name,
643        action,
644    })
645}
646
647pub fn parse_alter<'a>(parser: &mut Parser<'a, '_>) -> Result<Statement<'a>, ParseError> {
648    let alter_span = parser.consume_keyword(Keyword::ALTER)?;
649    let online = parser.skip_keyword(Keyword::ONLINE);
650    let ignore = parser.skip_keyword(Keyword::IGNORE);
651
652    match &parser.token {
653        Token::Ident(_, Keyword::SCHEMA) => {
654            let schema_span = parser.consume_keyword(Keyword::SCHEMA)?;
655            Ok(Statement::AlterSchema(Box::new(parse_alter_schema(
656                parser,
657                alter_span.join_span(&schema_span),
658            )?)))
659        }
660        Token::Ident(_, Keyword::TABLE) => Ok(Statement::AlterTable(Box::new(parse_alter_table(
661            parser, alter_span, online, ignore,
662        )?))),
663        Token::Ident(_, Keyword::ROLE) => Ok(Statement::AlterRole(Box::new(parse_alter_role(
664            parser, alter_span,
665        )?))),
666        Token::Ident(_, Keyword::TYPE) => {
667            let type_span = parser.consume_keyword(Keyword::TYPE)?;
668            Ok(Statement::AlterType(Box::new(
669                crate::alter_type::parse_alter_type(parser, alter_span.join_span(&type_span))?,
670            )))
671        }
672        Token::Ident(_, Keyword::OPERATOR) => {
673            let operator_span = parser.consume_keyword(Keyword::OPERATOR)?;
674            match &parser.token {
675                Token::Ident(_, Keyword::CLASS) => {
676                    let class_span = parser.consume_keyword(Keyword::CLASS)?;
677                    Ok(Statement::AlterOperatorClass(Box::new(
678                        crate::operator::parse_alter_operator_class(
679                            parser,
680                            alter_span.join_span(&operator_span).join_span(&class_span),
681                        )?,
682                    )))
683                }
684                Token::Ident(_, Keyword::FAMILY) => {
685                    let family_span = parser.consume_keyword(Keyword::FAMILY)?;
686                    Ok(Statement::AlterOperatorFamily(Box::new(
687                        crate::operator::parse_alter_operator_family(
688                            parser,
689                            alter_span.join_span(&operator_span).join_span(&family_span),
690                        )?,
691                    )))
692                }
693                _ => Ok(Statement::AlterOperator(Box::new(
694                    crate::operator::parse_alter_operator(
695                        parser,
696                        alter_span.join_span(&operator_span),
697                    )?,
698                ))),
699            }
700        }
701        _ => parser.expected_failure("alterable"),
702    }
703}
704
705/// CALL statement — invokes a stored procedure
706#[derive(Clone, Debug)]
707pub struct Call<'a> {
708    /// Span of "CALL"
709    pub call_span: Span,
710    /// Name of the procedure (possibly qualified)
711    pub name: crate::QualifiedName<'a>,
712    /// Argument expressions
713    pub args: Vec<Expression<'a>>,
714}
715
716impl<'a> Spanned for Call<'a> {
717    fn span(&self) -> Span {
718        self.call_span.join_span(&self.name).join_span(&self.args)
719    }
720}
721
722fn parse_call<'a>(parser: &mut Parser<'a, '_>) -> Result<Call<'a>, ParseError> {
723    let call_span = parser.consume_keyword(Keyword::CALL)?;
724    let name = parse_qualified_name_unreserved(parser)?;
725    let mut args = Vec::new();
726    parser.consume_token(Token::LParen)?;
727    parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
728        loop {
729            if matches!(parser.token, Token::RParen) {
730                break;
731            }
732            args.push(parse_expression_unreserved(parser, PRIORITY_MAX)?);
733            if parser.skip_token(Token::Comma).is_none() {
734                break;
735            }
736        }
737        Ok(())
738    })?;
739    parser.consume_token(Token::RParen)?;
740    Ok(Call {
741        call_span,
742        name,
743        args,
744    })
745}
746
747/// SQL statement
748#[derive(Clone, Debug)]
749pub enum Statement<'a> {
750    AlterSchema(Box<AlterSchema<'a>>),
751    CreateIndex(Box<CreateIndex<'a>>),
752    CreateTable(Box<CreateTable<'a>>),
753    CreateView(Box<CreateView<'a>>),
754    CreateTrigger(Box<CreateTrigger<'a>>),
755    CreateFunction(Box<CreateFunction<'a>>),
756    CreateProcedure(Box<CreateProcedure<'a>>),
757    CreateDatabase(Box<CreateDatabase<'a>>),
758    CreateSchema(Box<CreateSchema<'a>>),
759    CreateSequence(Box<CreateSequence<'a>>),
760    CreateServer(Box<CreateServer<'a>>),
761    CreateRole(Box<CreateRole<'a>>),
762    CreateOperator(Box<CreateOperator<'a>>),
763    CreateTypeEnum(Box<CreateTypeEnum<'a>>),
764    CreateOperatorClass(Box<CreateOperatorClass<'a>>),
765    CreateOperatorFamily(Box<CreateOperatorFamily<'a>>),
766    CreateExtension(Box<CreateExtension<'a>>),
767    CreateDomain(Box<CreateDomain<'a>>),
768    CreateConstraintTrigger(Box<CreateConstraintTrigger<'a>>),
769    CreateTablePartitionOf(Box<CreateTablePartitionOf<'a>>),
770    AlterOperator(Box<AlterOperator<'a>>),
771    AlterOperatorClass(Box<AlterOperatorClass<'a>>),
772    Select(Box<Select<'a>>),
773    Delete(Box<Delete<'a>>),
774    InsertReplace(Box<InsertReplace<'a>>),
775    Update(Box<Update<'a>>),
776    Unlock(Box<Unlock>),
777    DropIndex(Box<DropIndex<'a>>),
778    DropTable(Box<DropTable<'a>>),
779    DropFunction(Box<DropFunction<'a>>),
780    DropProcedure(Box<DropProcedure<'a>>),
781    DropSequence(Box<DropSequence<'a>>),
782    DropEvent(Box<DropEvent<'a>>),
783    DropDatabase(Box<DropDatabase<'a>>),
784    DropServer(Box<DropServer<'a>>),
785    DropTrigger(Box<DropTrigger<'a>>),
786    DropView(Box<DropView<'a>>),
787    DropExtension(Box<DropExtension<'a>>),
788    DropOperator(Box<DropOperator<'a>>),
789    DropOperatorFamily(Box<DropOperatorFamily<'a>>),
790    DropOperatorClass(Box<DropOperatorClass<'a>>),
791    DropDomain(Box<DropDomain<'a>>),
792    Set(Box<Set<'a>>),
793    Signal(Box<Signal<'a>>),
794    Kill(Box<Kill<'a>>),
795    ShowTables(Box<ShowTables<'a>>),
796    ShowDatabases(Box<ShowDatabases>),
797    ShowProcessList(Box<ShowProcessList>),
798    ShowVariables(Box<ShowVariables<'a>>),
799    ShowStatus(Box<ShowStatus<'a>>),
800    ShowColumns(Box<ShowColumns<'a>>),
801    ShowCreateTable(Box<ShowCreateTable<'a>>),
802    ShowCreateDatabase(Box<ShowCreateDatabase<'a>>),
803    ShowCreateView(Box<ShowCreateView<'a>>),
804    ShowCharacterSet(Box<ShowCharacterSet<'a>>),
805    ShowCollation(Box<ShowCollation<'a>>),
806    ShowEngines(Box<ShowEngines>),
807    AlterTable(Box<AlterTable<'a>>),
808    AlterRole(Box<AlterRole<'a>>),
809    AlterType(Box<AlterType<'a>>),
810    AlterOperatorFamily(Box<AlterOperatorFamily<'a>>),
811    Block(Box<Block<'a>>),
812    Begin(Box<Begin>),
813    End(Box<End>),
814    Commit(Box<Commit>),
815    StartTransaction(Box<StartTransaction>),
816    If(Box<If<'a>>),
817    /// Invalid statement produced after recovering from parse error
818    Invalid(Box<Invalid>),
819    Lock(Box<Lock<'a>>),
820    CompoundQuery(Box<CompoundQuery<'a>>),
821    Case(Box<CaseStatement<'a>>),
822    CopyFrom(Box<CopyFrom<'a>>),
823    CopyTo(Box<CopyTo<'a>>),
824    Stdin(Box<Stdin<'a>>),
825    Do(Box<Do<'a>>),
826    TruncateTable(Box<TruncateTable<'a>>),
827    RenameTable(Box<RenameTable<'a>>),
828    WithQuery(Box<WithQuery<'a>>),
829    Return(Box<Return<'a>>),
830    Flush(Box<Flush<'a>>),
831    /// PostgreSQL VALUES statement
832    Values(Box<crate::values::Values<'a>>),
833    /// PostgreSQL EXPLAIN statement
834    Explain(Box<Explain<'a>>),
835    /// PostgreSQL DECLARE cursor statement
836    DeclareCursor(Box<DeclareCursor<'a>>),
837    /// MariaDB/MySQL DECLARE variable inside a stored procedure/function
838    DeclareVariable(Box<DeclareVariable<'a>>),
839    /// MariaDB/MySQL DECLARE cursor inside a stored procedure/function
840    DeclareCursorMariaDb(Box<DeclareCursorMariaDb<'a>>),
841    /// MariaDB/MySQL DECLARE handler inside a stored procedure/function
842    DeclareHandler(Box<DeclareHandler<'a>>),
843    /// MariaDB/MySQL OPEN cursor statement
844    OpenCursor(Box<OpenCursor<'a>>),
845    /// MariaDB/MySQL CLOSE cursor statement
846    CloseCursor(Box<CloseCursor<'a>>),
847    /// MariaDB/MySQL FETCH cursor statement
848    FetchCursor(Box<FetchCursor<'a>>),
849    /// MariaDB/MySQL LEAVE label statement
850    Leave(Box<Leave<'a>>),
851    /// MariaDB/MySQL ITERATE label statement
852    Iterate(Box<Iterate<'a>>),
853    /// MariaDB/MySQL LOOP body END LOOP construct
854    Loop(Box<Loop<'a>>),
855    /// MariaDB/MySQL WHILE condition DO body END WHILE construct
856    While(Box<While<'a>>),
857    /// MariaDB/MySQL REPEAT body UNTIL condition END REPEAT construct
858    Repeat(Box<Repeat<'a>>),
859    /// PostgreSQL REFRESH MATERIALIZED VIEW statement
860    RefreshMaterializedView(Box<RefreshMaterializedView<'a>>),
861    /// PostgreSQL PREPARE statement
862    Prepare(Box<Prepare<'a>>),
863    /// CALL statement for invoking stored procedures
864    Call(Box<Call<'a>>),
865}
866
867impl<'a> Spanned for Statement<'a> {
868    fn span(&self) -> Span {
869        match &self {
870            Statement::AlterOperator(v) => v.span(),
871            Statement::AlterSchema(v) => v.span(),
872            Statement::CreateIndex(v) => v.span(),
873            Statement::CreateTable(v) => v.span(),
874            Statement::CreateView(v) => v.span(),
875            Statement::CreateTrigger(v) => v.span(),
876            Statement::CreateFunction(v) => v.span(),
877            Statement::CreateProcedure(v) => v.span(),
878            Statement::CreateDatabase(v) => v.span(),
879            Statement::CreateSchema(v) => v.span(),
880            Statement::CreateSequence(v) => v.span(),
881            Statement::CreateServer(v) => v.span(),
882            Statement::CreateRole(v) => v.span(),
883            Statement::CreateOperator(v) => v.span(),
884            Statement::Select(v) => v.span(),
885            Statement::Delete(v) => v.span(),
886            Statement::InsertReplace(v) => v.span(),
887            Statement::Update(v) => v.span(),
888            Statement::Unlock(v) => v.span(),
889            Statement::DropDatabase(v) => v.span(),
890            Statement::DropDomain(v) => v.span(),
891            Statement::DropEvent(v) => v.span(),
892            Statement::DropExtension(v) => v.span(),
893            Statement::DropFunction(v) => v.span(),
894            Statement::DropIndex(v) => v.span(),
895            Statement::DropOperator(v) => v.span(),
896            Statement::DropOperatorClass(v) => v.span(),
897            Statement::AlterOperatorClass(v) => v.span(),
898            Statement::DropProcedure(v) => v.span(),
899            Statement::DropSequence(v) => v.span(),
900            Statement::DropServer(v) => v.span(),
901            Statement::DropTable(v) => v.span(),
902            Statement::DropTrigger(v) => v.span(),
903            Statement::DropView(v) => v.span(),
904            Statement::Set(v) => v.span(),
905            Statement::AlterOperatorFamily(v) => v.span(),
906            Statement::DropOperatorFamily(v) => v.span(),
907            Statement::AlterRole(v) => v.span(),
908            Statement::AlterType(v) => v.span(),
909            Statement::AlterTable(v) => v.span(),
910            Statement::Block(v) => v.opt_span().expect("Span of block"),
911            Statement::If(v) => v.span(),
912            Statement::Invalid(v) => v.span(),
913            Statement::Lock(v) => v.span(),
914            Statement::CompoundQuery(v) => v.span(),
915            Statement::Case(v) => v.span(),
916            Statement::CopyFrom(v) => v.span(),
917            Statement::CopyTo(v) => v.span(),
918            Statement::Stdin(v) => v.span(),
919            Statement::Begin(v) => v.span(),
920            Statement::End(v) => v.span(),
921            Statement::Commit(v) => v.span(),
922            Statement::StartTransaction(v) => v.span(),
923            Statement::CreateTypeEnum(v) => v.span(),
924            Statement::CreateOperatorClass(v) => v.span(),
925            Statement::Do(v) => v.opt_span().expect("Span of block"),
926            Statement::TruncateTable(v) => v.span(),
927            Statement::RenameTable(v) => v.span(),
928            Statement::WithQuery(v) => v.span(),
929            Statement::Return(v) => v.span(),
930            Statement::Signal(v) => v.span(),
931            Statement::Kill(v) => v.span(),
932            Statement::ShowTables(v) => v.span(),
933            Statement::ShowDatabases(v) => v.span(),
934            Statement::ShowProcessList(v) => v.span(),
935            Statement::ShowVariables(v) => v.span(),
936            Statement::ShowStatus(v) => v.span(),
937            Statement::ShowColumns(v) => v.span(),
938            Statement::ShowCreateTable(v) => v.span(),
939            Statement::ShowCreateDatabase(v) => v.span(),
940            Statement::ShowCreateView(v) => v.span(),
941            Statement::ShowCharacterSet(v) => v.span(),
942            Statement::ShowCollation(v) => v.span(),
943            Statement::ShowEngines(v) => v.span(),
944            Statement::Flush(v) => v.span(),
945            Statement::CreateOperatorFamily(v) => v.span(),
946            Statement::Values(v) => v.span(),
947            Statement::CreateExtension(v) => v.span(),
948            Statement::CreateDomain(v) => v.span(),
949            Statement::CreateConstraintTrigger(v) => v.span(),
950            Statement::CreateTablePartitionOf(v) => v.span(),
951            Statement::Explain(v) => v.span(),
952            Statement::DeclareCursor(v) => v.span(),
953            Statement::DeclareVariable(v) => v.span(),
954            Statement::DeclareCursorMariaDb(v) => v.span(),
955            Statement::DeclareHandler(v) => v.span(),
956            Statement::OpenCursor(v) => v.span(),
957            Statement::CloseCursor(v) => v.span(),
958            Statement::FetchCursor(v) => v.span(),
959            Statement::Leave(v) => v.span(),
960            Statement::Iterate(v) => v.span(),
961            Statement::Loop(v) => v.span(),
962            Statement::While(v) => v.span(),
963            Statement::Repeat(v) => v.span(),
964            Statement::RefreshMaterializedView(v) => v.span(),
965            Statement::Prepare(v) => v.span(),
966            Statement::Call(v) => v.span(),
967        }
968    }
969}
970
971impl Statement<'_> {
972    fn reads_from_stdin(&self) -> bool {
973        match self {
974            Statement::CopyFrom(v) => v.reads_from_stdin(),
975            _ => false,
976        }
977    }
978}
979
980pub(crate) fn parse_statement<'a>(
981    parser: &mut Parser<'a, '_>,
982) -> Result<Option<Statement<'a>>, ParseError> {
983    Ok(match &parser.token {
984        Token::Ident(_, Keyword::CREATE) => Some(parse_create(parser)?),
985        Token::Ident(_, Keyword::DROP) => Some(parse_drop(parser)?),
986        Token::Ident(_, Keyword::SELECT) | Token::LParen => Some(parse_compound_query(parser)?),
987        Token::Ident(_, Keyword::VALUES) => {
988            Some(Statement::Values(Box::new(parse_values(parser)?)))
989        }
990        Token::Ident(_, Keyword::DELETE) => {
991            Some(Statement::Delete(Box::new(parse_delete(parser)?)))
992        }
993        Token::Ident(_, Keyword::INSERT | Keyword::REPLACE) => Some(Statement::InsertReplace(
994            Box::new(parse_insert_replace(parser)?),
995        )),
996        Token::Ident(_, Keyword::UPDATE) => {
997            Some(Statement::Update(Box::new(parse_update(parser)?)))
998        }
999        Token::Ident(_, Keyword::SET) => Some(Statement::Set(Box::new(parse_set(parser)?))),
1000        Token::Ident(_, Keyword::SIGNAL) => {
1001            Some(Statement::Signal(Box::new(parse_signal(parser)?)))
1002        }
1003        Token::Ident(_, Keyword::KILL) => Some(Statement::Kill(Box::new(parse_kill(parser)?))),
1004        Token::Ident(_, Keyword::SHOW) => Some(parse_show(parser)?),
1005        Token::Ident(_, Keyword::BEGIN) => Some(if parser.permit_compound_statements {
1006            Statement::Block(Box::new(parse_block(parser)?))
1007        } else {
1008            Statement::Begin(Box::new(parse_begin(parser)?))
1009        }),
1010        Token::Ident(_, Keyword::END) if !parser.permit_compound_statements => {
1011            Some(Statement::End(Box::new(parse_end(parser)?)))
1012        }
1013        Token::Ident(_, Keyword::START) => Some(Statement::StartTransaction(Box::new(
1014            parse_start_transaction(parser)?,
1015        ))),
1016        Token::Ident(_, Keyword::COMMIT) => {
1017            Some(Statement::Commit(Box::new(parse_commit(parser)?)))
1018        }
1019        Token::Ident(_, Keyword::IF) => Some(Statement::If(Box::new(parse_if(parser)?))),
1020        Token::Ident(_, Keyword::RETURN) => {
1021            Some(Statement::Return(Box::new(parse_return(parser)?)))
1022        }
1023        Token::Ident(_, Keyword::ALTER) => Some(parse_alter(parser)?),
1024        Token::Ident(_, Keyword::CASE) => {
1025            Some(Statement::Case(Box::new(parse_case_statement(parser)?)))
1026        }
1027        Token::Ident(_, Keyword::COPY) => Some(parse_copy_statement(parser)?),
1028        Token::Ident(_, Keyword::DO) => Some(parse_do(parser)?),
1029        Token::Ident(_, Keyword::LOCK) => Some(Statement::Lock(Box::new(parse_lock(parser)?))),
1030        Token::Ident(_, Keyword::UNLOCK) => {
1031            Some(Statement::Unlock(Box::new(parse_unlock(parser)?)))
1032        }
1033        Token::Ident(_, Keyword::TRUNCATE) => Some(Statement::TruncateTable(Box::new(
1034            parse_truncate_table(parser)?,
1035        ))),
1036        Token::Ident(_, Keyword::RENAME) => Some(Statement::RenameTable(Box::new(
1037            parse_rename_table(parser)?,
1038        ))),
1039        Token::Ident(_, Keyword::WITH) => {
1040            Some(Statement::WithQuery(Box::new(parse_with_query(parser)?)))
1041        }
1042        Token::Ident(_, Keyword::FLUSH) => Some(Statement::Flush(Box::new(parse_flush(parser)?))),
1043        Token::Ident(_, Keyword::EXPLAIN) => {
1044            Some(Statement::Explain(Box::new(parse_explain(parser)?)))
1045        }
1046        Token::Ident(_, Keyword::DECLARE) => Some(
1047            if parser.permit_compound_statements && parser.options.dialect.is_maria() {
1048                parse_declare_maria(parser)?
1049            } else {
1050                Statement::DeclareCursor(Box::new(parse_declare_cursor(parser)?))
1051            },
1052        ),
1053        Token::Ident(_, Keyword::PREPARE) => {
1054            Some(Statement::Prepare(Box::new(parse_prepare(parser)?)))
1055        }
1056        Token::Ident(_, Keyword::REFRESH) => Some(Statement::RefreshMaterializedView(Box::new(
1057            parse_refresh_materialized_view(parser)?,
1058        ))),
1059        Token::Ident(_, Keyword::CALL) => Some(Statement::Call(Box::new(parse_call(parser)?))),
1060        // MariaDB compound-block control statements
1061        Token::Ident(_, Keyword::OPEN)
1062            if parser.permit_compound_statements && parser.options.dialect.is_maria() =>
1063        {
1064            Some(Statement::OpenCursor(Box::new(parse_open_cursor(parser)?)))
1065        }
1066        Token::Ident(_, Keyword::CLOSE)
1067            if parser.permit_compound_statements && parser.options.dialect.is_maria() =>
1068        {
1069            Some(Statement::CloseCursor(Box::new(parse_close_cursor(
1070                parser,
1071            )?)))
1072        }
1073        Token::Ident(_, Keyword::FETCH)
1074            if parser.permit_compound_statements && parser.options.dialect.is_maria() =>
1075        {
1076            Some(Statement::FetchCursor(Box::new(parse_fetch_cursor(
1077                parser,
1078            )?)))
1079        }
1080        Token::Ident(_, Keyword::LEAVE)
1081            if parser.permit_compound_statements && parser.options.dialect.is_maria() =>
1082        {
1083            Some(Statement::Leave(Box::new(parse_leave(parser)?)))
1084        }
1085        Token::Ident(_, Keyword::ITERATE)
1086            if parser.permit_compound_statements && parser.options.dialect.is_maria() =>
1087        {
1088            Some(Statement::Iterate(Box::new(parse_iterate(parser)?)))
1089        }
1090        Token::Ident(_, Keyword::LOOP)
1091            if parser.permit_compound_statements && parser.options.dialect.is_maria() =>
1092        {
1093            Some(Statement::Loop(Box::new(parse_loop(parser, None)?)))
1094        }
1095        Token::Ident(_, Keyword::WHILE)
1096            if parser.permit_compound_statements && parser.options.dialect.is_maria() =>
1097        {
1098            Some(Statement::While(Box::new(parse_while(parser, None)?)))
1099        }
1100        Token::Ident(_, Keyword::REPEAT)
1101            if parser.permit_compound_statements && parser.options.dialect.is_maria() =>
1102        {
1103            Some(Statement::Repeat(Box::new(parse_repeat(parser, None)?)))
1104        }
1105        _ => None,
1106    })
1107}
1108
1109pub(crate) fn parse_do<'a>(parser: &mut Parser<'a, '_>) -> Result<Statement<'a>, ParseError> {
1110    let do_span = parser.consume_keyword(Keyword::DO)?;
1111    if let Token::String(s, StringType::DollarQuoted) = parser.token {
1112        // PostgreSQL: DO $$...$$ — the body is a dollar-quoted string literal
1113        let body_str = s;
1114        let body_span = parser.consume();
1115        return Ok(Statement::Do(Box::new(Do {
1116            do_span,
1117            body: DoBody::String(body_str, body_span),
1118        })));
1119    }
1120    parser.consume_token(Token::DoubleDollar)?;
1121    let block = parse_block(parser)?;
1122    parser.consume_token(Token::DoubleDollar)?;
1123    Ok(Statement::Do(Box::new(Do {
1124        do_span,
1125        body: DoBody::Statements(block.statements),
1126    })))
1127}
1128
1129/// PostgreSQL EXPLAIN output format
1130#[derive(Clone, Debug)]
1131pub enum ExplainFormat {
1132    Text(Span),
1133    Xml(Span),
1134    Json(Span),
1135    Yaml(Span),
1136}
1137
1138impl Spanned for ExplainFormat {
1139    fn span(&self) -> Span {
1140        match self {
1141            ExplainFormat::Text(s)
1142            | ExplainFormat::Xml(s)
1143            | ExplainFormat::Json(s)
1144            | ExplainFormat::Yaml(s) => s.clone(),
1145        }
1146    }
1147}
1148
1149/// A single option in a parenthesized EXPLAIN (...) list
1150#[derive(Clone, Debug)]
1151pub enum ExplainOption {
1152    Analyze(Span, Option<(bool, Span)>),
1153    Verbose(Span, Option<(bool, Span)>),
1154    Costs(Span, Option<(bool, Span)>),
1155    Settings(Span, Option<(bool, Span)>),
1156    GenericPlan(Span, Option<(bool, Span)>),
1157    Buffers(Span, Option<(bool, Span)>),
1158    Wal(Span, Option<(bool, Span)>),
1159    Timing(Span, Option<(bool, Span)>),
1160    Summary(Span, Option<(bool, Span)>),
1161    Memory(Span, Option<(bool, Span)>),
1162    Format(Span, ExplainFormat),
1163}
1164
1165impl Spanned for ExplainOption {
1166    fn span(&self) -> Span {
1167        match self {
1168            ExplainOption::Analyze(s, b)
1169            | ExplainOption::Verbose(s, b)
1170            | ExplainOption::Costs(s, b)
1171            | ExplainOption::Settings(s, b)
1172            | ExplainOption::GenericPlan(s, b)
1173            | ExplainOption::Buffers(s, b)
1174            | ExplainOption::Wal(s, b)
1175            | ExplainOption::Timing(s, b)
1176            | ExplainOption::Summary(s, b)
1177            | ExplainOption::Memory(s, b) => s.join_span(&b.as_ref().map(|(_, vs)| vs.clone())),
1178            ExplainOption::Format(s, fmt) => s.join_span(fmt),
1179        }
1180    }
1181}
1182
1183/// PostgreSQL EXPLAIN statement
1184#[derive(Clone, Debug)]
1185pub struct Explain<'a> {
1186    pub explain_span: Span,
1187    pub options: Vec<ExplainOption>,
1188    pub statement: Box<Statement<'a>>,
1189}
1190
1191impl<'a> Spanned for Explain<'a> {
1192    fn span(&self) -> Span {
1193        self.explain_span.join_span(&self.statement)
1194    }
1195}
1196
1197fn parse_explain<'a>(parser: &mut Parser<'a, '_>) -> Result<Explain<'a>, ParseError> {
1198    let explain_span = parser.consume_keyword(Keyword::EXPLAIN)?;
1199    parser.postgres_only(&explain_span);
1200    let mut options = Vec::new();
1201    if matches!(parser.token, Token::LParen) {
1202        // Parenthesized option list: EXPLAIN (ANALYZE, BUFFERS, ...)
1203        parser.consume_token(Token::LParen)?;
1204        loop {
1205            let opt = match &parser.token {
1206                Token::Ident(_, Keyword::ANALYZE) => {
1207                    let s = parser.consume_keyword(Keyword::ANALYZE)?;
1208                    ExplainOption::Analyze(s, parser.try_parse_bool())
1209                }
1210                Token::Ident(_, Keyword::VERBOSE) => {
1211                    let s = parser.consume_keyword(Keyword::VERBOSE)?;
1212                    ExplainOption::Verbose(s, parser.try_parse_bool())
1213                }
1214                Token::Ident(_, Keyword::COSTS) => {
1215                    let s = parser.consume_keyword(Keyword::COSTS)?;
1216                    ExplainOption::Costs(s, parser.try_parse_bool())
1217                }
1218                Token::Ident(_, Keyword::SETTINGS) => {
1219                    let s = parser.consume_keyword(Keyword::SETTINGS)?;
1220                    ExplainOption::Settings(s, parser.try_parse_bool())
1221                }
1222                Token::Ident(_, Keyword::GENERIC_PLAN) => {
1223                    let s = parser.consume_keyword(Keyword::GENERIC_PLAN)?;
1224                    ExplainOption::GenericPlan(s, parser.try_parse_bool())
1225                }
1226                Token::Ident(_, Keyword::BUFFERS) => {
1227                    let s = parser.consume_keyword(Keyword::BUFFERS)?;
1228                    ExplainOption::Buffers(s, parser.try_parse_bool())
1229                }
1230                Token::Ident(_, Keyword::WAL) => {
1231                    let s = parser.consume_keyword(Keyword::WAL)?;
1232                    ExplainOption::Wal(s, parser.try_parse_bool())
1233                }
1234                Token::Ident(_, Keyword::TIMING) => {
1235                    let s = parser.consume_keyword(Keyword::TIMING)?;
1236                    ExplainOption::Timing(s, parser.try_parse_bool())
1237                }
1238                Token::Ident(_, Keyword::SUMMARY) => {
1239                    let s = parser.consume_keyword(Keyword::SUMMARY)?;
1240                    ExplainOption::Summary(s, parser.try_parse_bool())
1241                }
1242                Token::Ident(_, Keyword::MEMORY) => {
1243                    let s = parser.consume_keyword(Keyword::MEMORY)?;
1244                    ExplainOption::Memory(s, parser.try_parse_bool())
1245                }
1246                Token::Ident(_, Keyword::FORMAT) => {
1247                    let fmt_kw = parser.consume_keyword(Keyword::FORMAT)?;
1248                    let fmt = match &parser.token {
1249                        Token::Ident(_, Keyword::TEXT) => ExplainFormat::Text(parser.consume()),
1250                        Token::Ident(_, Keyword::XML) => ExplainFormat::Xml(parser.consume()),
1251                        Token::Ident(_, Keyword::JSON) => ExplainFormat::Json(parser.consume()),
1252                        Token::Ident(_, Keyword::YAML) => ExplainFormat::Yaml(parser.consume()),
1253                        _ => parser.expected_failure("TEXT, XML, JSON, or YAML")?,
1254                    };
1255                    ExplainOption::Format(fmt_kw, fmt)
1256                }
1257                _ => parser.expected_failure("EXPLAIN option")?,
1258            };
1259            options.push(opt);
1260            if parser.skip_token(Token::Comma).is_none() {
1261                break;
1262            }
1263        }
1264        parser.consume_token(Token::RParen)?;
1265    } else {
1266        // Legacy: EXPLAIN [ANALYZE] [VERBOSE]
1267        if let Some(s) = parser.skip_keyword(Keyword::ANALYZE) {
1268            options.push(ExplainOption::Analyze(s.clone(), Some((true, s))));
1269        }
1270        if let Some(s) = parser.skip_keyword(Keyword::VERBOSE) {
1271            options.push(ExplainOption::Verbose(s.clone(), Some((true, s))));
1272        }
1273    }
1274    let inner = match parse_statement(parser)? {
1275        Some(s) => s,
1276        None => parser.expected_failure("Statement after EXPLAIN")?,
1277    };
1278    Ok(Explain {
1279        explain_span,
1280        options,
1281        statement: Box::new(inner),
1282    })
1283}
1284
1285/// Sensitivity of a declared cursor
1286#[derive(Clone, Debug)]
1287pub enum CursorSensitivity {
1288    Asensitive(Span),
1289    Insensitive(Span),
1290}
1291
1292impl Spanned for CursorSensitivity {
1293    fn span(&self) -> Span {
1294        match self {
1295            CursorSensitivity::Asensitive(s) | CursorSensitivity::Insensitive(s) => s.clone(),
1296        }
1297    }
1298}
1299
1300/// Scroll behaviour of a declared cursor
1301#[derive(Clone, Debug)]
1302pub enum CursorScroll {
1303    Scroll(Span),
1304    NoScroll(Span),
1305}
1306
1307impl Spanned for CursorScroll {
1308    fn span(&self) -> Span {
1309        match self {
1310            CursorScroll::Scroll(s) | CursorScroll::NoScroll(s) => s.clone(),
1311        }
1312    }
1313}
1314
1315/// Hold behaviour of a declared cursor
1316#[derive(Clone, Debug)]
1317pub enum CursorHold {
1318    WithHold(Span),
1319    WithoutHold(Span),
1320}
1321
1322impl Spanned for CursorHold {
1323    fn span(&self) -> Span {
1324        match self {
1325            CursorHold::WithHold(s) | CursorHold::WithoutHold(s) => s.clone(),
1326        }
1327    }
1328}
1329
1330/// MariaDB/MySQL DECLARE variable statement inside a stored procedure/function.
1331/// `DECLARE name data_type [DEFAULT expr]`
1332#[derive(Clone, Debug)]
1333pub struct DeclareVariable<'a> {
1334    pub declare_span: Span,
1335    pub name: crate::Identifier<'a>,
1336    pub data_type: crate::DataType<'a>,
1337    pub default: Option<(Span, Expression<'a>)>,
1338}
1339
1340impl<'a> Spanned for DeclareVariable<'a> {
1341    fn span(&self) -> Span {
1342        self.declare_span
1343            .join_span(&self.name)
1344            .join_span(&self.data_type)
1345            .join_span(&self.default)
1346    }
1347}
1348
1349/// MariaDB/MySQL DECLARE cursor statement inside a stored procedure/function.
1350/// `DECLARE name CURSOR FOR select`
1351#[derive(Clone, Debug)]
1352pub struct DeclareCursorMariaDb<'a> {
1353    pub declare_span: Span,
1354    pub name: crate::Identifier<'a>,
1355    pub cursor_span: Span,
1356    pub for_span: Span,
1357    pub query: Box<Select<'a>>,
1358}
1359
1360impl<'a> Spanned for DeclareCursorMariaDb<'a> {
1361    fn span(&self) -> Span {
1362        self.declare_span.join_span(&self.query)
1363    }
1364}
1365
1366/// Action part of a MariaDB/MySQL handler declaration.
1367#[derive(Clone, Debug)]
1368pub enum HandlerAction {
1369    Continue(Span),
1370    Exit(Span),
1371}
1372
1373impl Spanned for HandlerAction {
1374    fn span(&self) -> Span {
1375        match self {
1376            HandlerAction::Continue(s) | HandlerAction::Exit(s) => s.clone(),
1377        }
1378    }
1379}
1380
1381/// Condition part of a MariaDB/MySQL handler declaration.
1382#[derive(Clone, Debug)]
1383pub enum HandlerCondition<'a> {
1384    /// `NOT FOUND`
1385    NotFound(Span, Span),
1386    /// `SQLEXCEPTION`
1387    SqlException(Span),
1388    /// `SQLWARNING`
1389    SqlWarning(Span),
1390    /// `SQLSTATE [VALUE] 'code'`
1391    SqlState(Span, crate::SString<'a>),
1392}
1393
1394impl<'a> Spanned for HandlerCondition<'a> {
1395    fn span(&self) -> Span {
1396        match self {
1397            HandlerCondition::NotFound(a, b) => a.join_span(b),
1398            HandlerCondition::SqlException(s) => s.clone(),
1399            HandlerCondition::SqlWarning(s) => s.clone(),
1400            HandlerCondition::SqlState(s, v) => s.join_span(v),
1401        }
1402    }
1403}
1404
1405/// MariaDB/MySQL DECLARE handler statement inside a stored procedure/function.
1406/// `DECLARE CONTINUE|EXIT HANDLER FOR condition statement`
1407#[derive(Clone, Debug)]
1408pub struct DeclareHandler<'a> {
1409    pub declare_span: Span,
1410    pub action: HandlerAction,
1411    pub handler_span: Span,
1412    pub for_span: Span,
1413    pub condition: HandlerCondition<'a>,
1414    pub statement: Box<Statement<'a>>,
1415}
1416
1417impl<'a> Spanned for DeclareHandler<'a> {
1418    fn span(&self) -> Span {
1419        self.declare_span.join_span(&self.statement)
1420    }
1421}
1422
1423/// MariaDB/MySQL OPEN cursor statement.
1424/// `OPEN cursor_name`
1425#[derive(Clone, Debug)]
1426pub struct OpenCursor<'a> {
1427    pub open_span: Span,
1428    pub name: crate::Identifier<'a>,
1429}
1430
1431impl<'a> Spanned for OpenCursor<'a> {
1432    fn span(&self) -> Span {
1433        self.open_span.join_span(&self.name)
1434    }
1435}
1436
1437/// MariaDB/MySQL CLOSE cursor statement.
1438/// `CLOSE cursor_name`
1439#[derive(Clone, Debug)]
1440pub struct CloseCursor<'a> {
1441    pub close_span: Span,
1442    pub name: crate::Identifier<'a>,
1443}
1444
1445impl<'a> Spanned for CloseCursor<'a> {
1446    fn span(&self) -> Span {
1447        self.close_span.join_span(&self.name)
1448    }
1449}
1450
1451/// MariaDB/MySQL FETCH cursor statement.
1452/// `FETCH [NEXT] [FROM] cursor INTO var, ...`
1453#[derive(Clone, Debug)]
1454pub struct FetchCursor<'a> {
1455    pub fetch_span: Span,
1456    pub next_span: Option<Span>,
1457    pub from_span: Option<Span>,
1458    pub cursor: crate::Identifier<'a>,
1459    pub into_span: Span,
1460    pub variables: Vec<crate::Identifier<'a>>,
1461}
1462
1463impl<'a> Spanned for FetchCursor<'a> {
1464    fn span(&self) -> Span {
1465        self.fetch_span.join_span(&self.variables)
1466    }
1467}
1468
1469/// MariaDB/MySQL LEAVE label statement.
1470/// `LEAVE label`
1471#[derive(Clone, Debug)]
1472pub struct Leave<'a> {
1473    pub leave_span: Span,
1474    pub label: crate::Identifier<'a>,
1475}
1476
1477impl<'a> Spanned for Leave<'a> {
1478    fn span(&self) -> Span {
1479        self.leave_span.join_span(&self.label)
1480    }
1481}
1482
1483/// MariaDB/MySQL ITERATE label statement.
1484/// `ITERATE label`
1485#[derive(Clone, Debug)]
1486pub struct Iterate<'a> {
1487    pub iterate_span: Span,
1488    pub label: crate::Identifier<'a>,
1489}
1490
1491impl<'a> Spanned for Iterate<'a> {
1492    fn span(&self) -> Span {
1493        self.iterate_span.join_span(&self.label)
1494    }
1495}
1496
1497/// MariaDB/MySQL LOOP body END LOOP construct.
1498/// `[label:] LOOP body END LOOP [label]`
1499#[derive(Clone, Debug)]
1500pub struct Loop<'a> {
1501    pub label: Option<crate::Identifier<'a>>,
1502    pub loop_span: Span,
1503    pub body: Vec<Statement<'a>>,
1504    pub end_loop_span: Span,
1505    pub end_label: Option<crate::Identifier<'a>>,
1506}
1507
1508impl<'a> Spanned for Loop<'a> {
1509    fn span(&self) -> Span {
1510        self.loop_span
1511            .join_span(&self.label)
1512            .join_span(&self.body)
1513            .join_span(&self.end_loop_span)
1514            .join_span(&self.end_label)
1515    }
1516}
1517
1518/// MariaDB/MySQL WHILE condition DO body END WHILE construct.
1519/// `[label:] WHILE condition DO body END WHILE [label]`
1520#[derive(Clone, Debug)]
1521pub struct While<'a> {
1522    pub label: Option<crate::Identifier<'a>>,
1523    pub while_span: Span,
1524    pub condition: Expression<'a>,
1525    pub do_span: Span,
1526    pub body: Vec<Statement<'a>>,
1527    pub end_while_span: Span,
1528    pub end_label: Option<crate::Identifier<'a>>,
1529}
1530
1531impl<'a> Spanned for While<'a> {
1532    fn span(&self) -> Span {
1533        self.while_span
1534            .join_span(&self.label)
1535            .join_span(&self.condition)
1536            .join_span(&self.do_span)
1537            .join_span(&self.body)
1538            .join_span(&self.end_while_span)
1539            .join_span(&self.end_label)
1540    }
1541}
1542
1543/// MariaDB/MySQL REPEAT body UNTIL condition END REPEAT construct.
1544/// `[label:] REPEAT body UNTIL condition END REPEAT [label]`
1545#[derive(Clone, Debug)]
1546pub struct Repeat<'a> {
1547    pub label: Option<crate::Identifier<'a>>,
1548    pub repeat_span: Span,
1549    pub body: Vec<Statement<'a>>,
1550    pub until_span: Span,
1551    pub condition: Expression<'a>,
1552    pub end_repeat_span: Span,
1553    pub end_label: Option<crate::Identifier<'a>>,
1554}
1555
1556impl<'a> Spanned for Repeat<'a> {
1557    fn span(&self) -> Span {
1558        self.repeat_span
1559            .join_span(&self.label)
1560            .join_span(&self.body)
1561            .join_span(&self.until_span)
1562            .join_span(&self.condition)
1563            .join_span(&self.end_repeat_span)
1564            .join_span(&self.end_label)
1565    }
1566}
1567
1568/// Dispatcher: parse a MariaDB DECLARE and return the appropriate Statement variant.
1569fn parse_declare_maria<'a>(parser: &mut Parser<'a, '_>) -> Result<Statement<'a>, ParseError> {
1570    let declare_span = parser.consume_keyword(Keyword::DECLARE)?;
1571    match &parser.token {
1572        Token::Ident(_, Keyword::CONTINUE | Keyword::EXIT) => Ok(Statement::DeclareHandler(
1573            Box::new(parse_handler_body(parser, declare_span)?),
1574        )),
1575        _ => {
1576            let name = parser.consume_plain_identifier_unreserved()?;
1577            if matches!(&parser.token, Token::Ident(_, Keyword::CURSOR)) {
1578                Ok(Statement::DeclareCursorMariaDb(Box::new(
1579                    parse_cursor_mariadb_body(parser, declare_span, name)?,
1580                )))
1581            } else {
1582                Ok(Statement::DeclareVariable(Box::new(parse_variable_body(
1583                    parser,
1584                    declare_span,
1585                    name,
1586                )?)))
1587            }
1588        }
1589    }
1590}
1591
1592fn parse_variable_body<'a>(
1593    parser: &mut Parser<'a, '_>,
1594    declare_span: Span,
1595    name: crate::Identifier<'a>,
1596) -> Result<DeclareVariable<'a>, ParseError> {
1597    use crate::data_type::{DataTypeContext, parse_data_type};
1598    let data_type = parse_data_type(parser, DataTypeContext::TypeRef)?;
1599    let default = if let Some(default_span) = parser.skip_keyword(Keyword::DEFAULT) {
1600        let expr = parse_expression_unreserved(parser, PRIORITY_MAX)?;
1601        Some((default_span, expr))
1602    } else {
1603        None
1604    };
1605    Ok(DeclareVariable {
1606        declare_span,
1607        name,
1608        data_type,
1609        default,
1610    })
1611}
1612
1613fn parse_cursor_mariadb_body<'a>(
1614    parser: &mut Parser<'a, '_>,
1615    declare_span: Span,
1616    name: crate::Identifier<'a>,
1617) -> Result<DeclareCursorMariaDb<'a>, ParseError> {
1618    let cursor_span = parser.consume_keyword(Keyword::CURSOR)?;
1619    let for_span = parser.consume_keyword(Keyword::FOR)?;
1620    let query = Box::new(parse_select(parser)?);
1621    Ok(DeclareCursorMariaDb {
1622        declare_span,
1623        name,
1624        cursor_span,
1625        for_span,
1626        query,
1627    })
1628}
1629
1630fn parse_handler_body<'a>(
1631    parser: &mut Parser<'a, '_>,
1632    declare_span: Span,
1633) -> Result<DeclareHandler<'a>, ParseError> {
1634    let action = match &parser.token {
1635        Token::Ident(_, Keyword::CONTINUE) => {
1636            HandlerAction::Continue(parser.consume_keyword(Keyword::CONTINUE)?)
1637        }
1638        _ => HandlerAction::Exit(parser.consume_keyword(Keyword::EXIT)?),
1639    };
1640    let handler_span = parser.consume_keyword(Keyword::HANDLER)?;
1641    let for_span = parser.consume_keyword(Keyword::FOR)?;
1642    let condition = match &parser.token {
1643        Token::Ident(_, Keyword::NOT) => {
1644            let not_span = parser.consume_keyword(Keyword::NOT)?;
1645            let found_span = parser.consume_keyword(Keyword::FOUND)?;
1646            HandlerCondition::NotFound(not_span, found_span)
1647        }
1648        Token::Ident(_, Keyword::SQLEXCEPTION) => {
1649            HandlerCondition::SqlException(parser.consume_keyword(Keyword::SQLEXCEPTION)?)
1650        }
1651        Token::Ident(_, Keyword::SQLWARNING) => {
1652            HandlerCondition::SqlWarning(parser.consume_keyword(Keyword::SQLWARNING)?)
1653        }
1654        Token::Ident(_, Keyword::SQLSTATE) => {
1655            let sqlstate_span = parser.consume_keyword(Keyword::SQLSTATE)?;
1656            parser.skip_keyword(Keyword::VALUE);
1657            let code = parser.consume_string()?;
1658            HandlerCondition::SqlState(sqlstate_span, code)
1659        }
1660        _ => parser.expected_failure("NOT FOUND, SQLEXCEPTION, SQLWARNING, or SQLSTATE")?,
1661    };
1662    let statement = match parse_statement(parser)? {
1663        Some(s) => Box::new(s),
1664        None => parser.expected_failure("statement after handler condition")?,
1665    };
1666    Ok(DeclareHandler {
1667        declare_span,
1668        action,
1669        handler_span,
1670        for_span,
1671        condition,
1672        statement,
1673    })
1674}
1675
1676fn parse_open_cursor<'a>(parser: &mut Parser<'a, '_>) -> Result<OpenCursor<'a>, ParseError> {
1677    let open_span = parser.consume_keyword(Keyword::OPEN)?;
1678    let name = parser.consume_plain_identifier_unreserved()?;
1679    Ok(OpenCursor { open_span, name })
1680}
1681
1682fn parse_close_cursor<'a>(parser: &mut Parser<'a, '_>) -> Result<CloseCursor<'a>, ParseError> {
1683    let close_span = parser.consume_keyword(Keyword::CLOSE)?;
1684    let name = parser.consume_plain_identifier_unreserved()?;
1685    Ok(CloseCursor { close_span, name })
1686}
1687
1688fn parse_fetch_cursor<'a>(parser: &mut Parser<'a, '_>) -> Result<FetchCursor<'a>, ParseError> {
1689    let fetch_span = parser.consume_keyword(Keyword::FETCH)?;
1690    let next_span = parser.skip_keyword(Keyword::NEXT);
1691    let from_span = parser.skip_keyword(Keyword::FROM);
1692    let cursor = parser.consume_plain_identifier_unreserved()?;
1693    let into_span = parser.consume_keyword(Keyword::INTO)?;
1694    let mut variables = Vec::new();
1695    loop {
1696        variables.push(parser.consume_plain_identifier_unreserved()?);
1697        if parser.skip_token(Token::Comma).is_none() {
1698            break;
1699        }
1700    }
1701    Ok(FetchCursor {
1702        fetch_span,
1703        next_span,
1704        from_span,
1705        cursor,
1706        into_span,
1707        variables,
1708    })
1709}
1710
1711fn parse_leave<'a>(parser: &mut Parser<'a, '_>) -> Result<Leave<'a>, ParseError> {
1712    let leave_span = parser.consume_keyword(Keyword::LEAVE)?;
1713    let label = parser.consume_plain_identifier_unreserved()?;
1714    Ok(Leave { leave_span, label })
1715}
1716
1717fn parse_iterate<'a>(parser: &mut Parser<'a, '_>) -> Result<Iterate<'a>, ParseError> {
1718    let iterate_span = parser.consume_keyword(Keyword::ITERATE)?;
1719    let label = parser.consume_plain_identifier_unreserved()?;
1720    Ok(Iterate {
1721        iterate_span,
1722        label,
1723    })
1724}
1725
1726fn parse_loop<'a>(
1727    parser: &mut Parser<'a, '_>,
1728    label: Option<crate::Identifier<'a>>,
1729) -> Result<Loop<'a>, ParseError> {
1730    let loop_span = parser.consume_keyword(Keyword::LOOP)?;
1731    let mut body = Vec::new();
1732    parser.recovered(
1733        "'END'",
1734        &|t| matches!(t, Token::Ident(_, Keyword::END)),
1735        |parser| parse_statement_list(parser, &mut body),
1736    )?;
1737    let end_loop_span = parser.consume_keywords(&[Keyword::END, Keyword::LOOP])?;
1738    let end_label = if matches!(&parser.token, Token::Ident(_, Keyword::NOT_A_KEYWORD)) {
1739        Some(parser.consume_plain_identifier_unreserved()?)
1740    } else {
1741        None
1742    };
1743    Ok(Loop {
1744        label,
1745        loop_span,
1746        body,
1747        end_loop_span,
1748        end_label,
1749    })
1750}
1751
1752fn parse_while<'a>(
1753    parser: &mut Parser<'a, '_>,
1754    label: Option<crate::Identifier<'a>>,
1755) -> Result<While<'a>, ParseError> {
1756    let while_span = parser.consume_keyword(Keyword::WHILE)?;
1757    let condition = parse_expression_unreserved(parser, PRIORITY_MAX)?;
1758    let do_span = parser.consume_keyword(Keyword::DO)?;
1759    let mut body = Vec::new();
1760    parser.recovered(
1761        "'END'",
1762        &|t| matches!(t, Token::Ident(_, Keyword::END)),
1763        |parser| parse_statement_list(parser, &mut body),
1764    )?;
1765    let end_while_span = parser.consume_keywords(&[Keyword::END, Keyword::WHILE])?;
1766    let end_label = if matches!(&parser.token, Token::Ident(_, Keyword::NOT_A_KEYWORD)) {
1767        Some(parser.consume_plain_identifier_unreserved()?)
1768    } else {
1769        None
1770    };
1771    Ok(While {
1772        label,
1773        while_span,
1774        condition,
1775        do_span,
1776        body,
1777        end_while_span,
1778        end_label,
1779    })
1780}
1781
1782fn parse_repeat<'a>(
1783    parser: &mut Parser<'a, '_>,
1784    label: Option<crate::Identifier<'a>>,
1785) -> Result<Repeat<'a>, ParseError> {
1786    let repeat_span = parser.consume_keyword(Keyword::REPEAT)?;
1787    let mut body = Vec::new();
1788    parser.recovered(
1789        "'UNTIL'",
1790        &|t| matches!(t, Token::Ident(_, Keyword::UNTIL)),
1791        |parser| parse_statement_list(parser, &mut body),
1792    )?;
1793    let until_span = parser.consume_keyword(Keyword::UNTIL)?;
1794    let condition = parse_expression_unreserved(parser, PRIORITY_MAX)?;
1795    let end_repeat_span = parser.consume_keywords(&[Keyword::END, Keyword::REPEAT])?;
1796    let end_label = if matches!(&parser.token, Token::Ident(_, Keyword::NOT_A_KEYWORD)) {
1797        Some(parser.consume_plain_identifier_unreserved()?)
1798    } else {
1799        None
1800    };
1801    Ok(Repeat {
1802        label,
1803        repeat_span,
1804        body,
1805        until_span,
1806        condition,
1807        end_repeat_span,
1808        end_label,
1809    })
1810}
1811
1812/// PostgreSQL DECLARE cursor statement
1813#[derive(Clone, Debug)]
1814pub struct DeclareCursor<'a> {
1815    pub declare_span: Span,
1816    pub name: crate::Identifier<'a>,
1817    pub binary: Option<Span>,
1818    pub sensitivity: Option<CursorSensitivity>,
1819    pub scroll: Option<CursorScroll>,
1820    pub cursor_span: Span,
1821    pub hold: Option<CursorHold>,
1822    pub for_span: Span,
1823    pub query: Box<Statement<'a>>,
1824}
1825
1826impl<'a> Spanned for DeclareCursor<'a> {
1827    fn span(&self) -> Span {
1828        self.declare_span.join_span(&self.query)
1829    }
1830}
1831
1832fn parse_declare_cursor<'a>(parser: &mut Parser<'a, '_>) -> Result<DeclareCursor<'a>, ParseError> {
1833    let declare_span = parser.consume_keyword(Keyword::DECLARE)?;
1834    parser.postgres_only(&declare_span);
1835    let name = parser.consume_plain_identifier_unreserved()?;
1836    // Optional BINARY
1837    let binary = parser.skip_keyword(Keyword::BINARY);
1838    // Optional ASENSITIVE | INSENSITIVE
1839    let sensitivity = match &parser.token {
1840        Token::Ident(_, Keyword::ASENSITIVE) => {
1841            Some(CursorSensitivity::Asensitive(parser.consume()))
1842        }
1843        Token::Ident(_, Keyword::INSENSITIVE) => {
1844            Some(CursorSensitivity::Insensitive(parser.consume()))
1845        }
1846        _ => None,
1847    };
1848    // Optional [NO] SCROLL
1849    let scroll = if let Some(no_span) = parser.skip_keyword(Keyword::NO) {
1850        let scroll_span = parser.consume_keyword(Keyword::SCROLL)?;
1851        Some(CursorScroll::NoScroll(no_span.join_span(&scroll_span)))
1852    } else {
1853        parser
1854            .skip_keyword(Keyword::SCROLL)
1855            .map(CursorScroll::Scroll)
1856    };
1857    let cursor_span = parser.consume_keyword(Keyword::CURSOR)?;
1858    // Optional WITH HOLD | WITHOUT HOLD
1859    let hold = if let Some(without_span) = parser.skip_keyword(Keyword::WITHOUT) {
1860        let hold_span = parser.consume_keyword(Keyword::HOLD)?;
1861        Some(CursorHold::WithoutHold(without_span.join_span(&hold_span)))
1862    } else if let Some(with_span) = parser.skip_keyword(Keyword::WITH) {
1863        let hold_span = parser.consume_keyword(Keyword::HOLD)?;
1864        Some(CursorHold::WithHold(with_span.join_span(&hold_span)))
1865    } else {
1866        None
1867    };
1868    let for_span = parser.consume_keyword(Keyword::FOR)?;
1869    let query = match parse_statement(parser)? {
1870        Some(s) => s,
1871        None => parser.expected_failure("Query after FOR")?,
1872    };
1873    Ok(DeclareCursor {
1874        declare_span,
1875        name,
1876        binary,
1877        sensitivity,
1878        scroll,
1879        cursor_span,
1880        hold,
1881        for_span,
1882        query: Box::new(query),
1883    })
1884}
1885
1886/// PostgreSQL REFRESH MATERIALIZED VIEW statement
1887#[derive(Clone, Debug)]
1888pub struct RefreshMaterializedView<'a> {
1889    pub refresh_span: Span,
1890    pub concurrently: Option<Span>,
1891    pub view_name: crate::QualifiedName<'a>,
1892    /// WITH [ NO ] DATA: Some(true) = WITH DATA, Some(false) = WITH NO DATA, None = not specified
1893    pub with_data: Option<(Span, bool)>,
1894}
1895
1896impl<'a> Spanned for RefreshMaterializedView<'a> {
1897    fn span(&self) -> Span {
1898        self.refresh_span
1899            .join_span(&self.view_name)
1900            .join_span(&self.with_data.as_ref().map(|(s, _)| s.clone()))
1901    }
1902}
1903
1904fn parse_refresh_materialized_view<'a>(
1905    parser: &mut Parser<'a, '_>,
1906) -> Result<RefreshMaterializedView<'a>, ParseError> {
1907    let refresh_span = parser.consume_keyword(Keyword::REFRESH)?;
1908    parser.postgres_only(&refresh_span);
1909    parser.consume_keyword(Keyword::MATERIALIZED)?;
1910    parser.consume_keyword(Keyword::VIEW)?;
1911    let concurrently = parser.skip_keyword(Keyword::CONCURRENTLY);
1912    let view_name = parse_qualified_name_unreserved(parser)?;
1913    // Optional WITH [ NO ] DATA
1914    let with_data = if let Some(with_span) = parser.skip_keyword(Keyword::WITH) {
1915        if let Some(no_span) = parser.skip_keyword(Keyword::NO) {
1916            let data_span = parser.consume_keyword(Keyword::DATA)?;
1917            Some((with_span.join_span(&no_span).join_span(&data_span), false))
1918        } else {
1919            let data_span = parser.consume_keyword(Keyword::DATA)?;
1920            Some((with_span.join_span(&data_span), true))
1921        }
1922    } else {
1923        None
1924    };
1925    Ok(RefreshMaterializedView {
1926        refresh_span,
1927        concurrently,
1928        view_name,
1929        with_data,
1930    })
1931}
1932
1933/// PostgreSQL PREPARE statement
1934#[derive(Clone, Debug)]
1935pub struct Prepare<'a> {
1936    pub prepare_span: Span,
1937    pub name: crate::Identifier<'a>,
1938    pub param_types: Vec<crate::DataType<'a>>,
1939    pub as_span: Span,
1940    pub statement: Box<Statement<'a>>,
1941}
1942
1943impl<'a> Spanned for Prepare<'a> {
1944    fn span(&self) -> Span {
1945        self.prepare_span.join_span(&self.statement)
1946    }
1947}
1948
1949fn parse_prepare<'a>(parser: &mut Parser<'a, '_>) -> Result<Prepare<'a>, ParseError> {
1950    use crate::data_type::{DataTypeContext, parse_data_type};
1951    let prepare_span = parser.consume_keyword(Keyword::PREPARE)?;
1952    parser.postgres_only(&prepare_span);
1953    let name = parser.consume_plain_identifier_unreserved()?;
1954    // Optional (type, ...) parameter type list
1955    let mut param_types = Vec::new();
1956    if matches!(parser.token, Token::LParen) {
1957        parser.consume_token(Token::LParen)?;
1958        loop {
1959            parser.recovered(
1960                "')' or ','",
1961                &|t| matches!(t, Token::RParen | Token::Comma),
1962                |parser| {
1963                    param_types.push(parse_data_type(parser, DataTypeContext::TypeRef)?);
1964                    Ok(())
1965                },
1966            )?;
1967            if parser.skip_token(Token::Comma).is_none() {
1968                break;
1969            }
1970        }
1971        parser.consume_token(Token::RParen)?;
1972    }
1973    let as_span = parser.consume_keyword(Keyword::AS)?;
1974    let statement = match parse_statement(parser)? {
1975        Some(s) => s,
1976        None => parser.expected_failure("Statement after AS")?,
1977    };
1978    Ok(Prepare {
1979        prepare_span,
1980        name,
1981        param_types,
1982        as_span,
1983        statement: Box::new(statement),
1984    })
1985}
1986
1987/// When part of case statement
1988#[derive(Clone, Debug)]
1989pub struct WhenStatement<'a> {
1990    /// Span of "WHEN"
1991    pub when_span: Span,
1992    /// Expression who's match yields execution `then`
1993    pub when: Expression<'a>,
1994    /// Span of "THEN"
1995    pub then_span: Span,
1996    /// Statements to execute if `when` matches
1997    pub then: Vec<Statement<'a>>,
1998}
1999
2000impl<'a> Spanned for WhenStatement<'a> {
2001    fn span(&self) -> Span {
2002        self.when_span
2003            .join_span(&self.when)
2004            .join_span(&self.then_span)
2005            .join_span(&self.then)
2006    }
2007}
2008
2009/// Case statement
2010#[derive(Clone, Debug)]
2011pub struct CaseStatement<'a> {
2012    /// Span of "CASE"
2013    pub case_span: Span,
2014    /// Value to match against
2015    pub value: Option<Expression<'a>>,
2016    /// List of whens
2017    pub whens: Vec<WhenStatement<'a>>,
2018    /// Span of "ELSE" and statement to execute if specified
2019    pub else_: Option<(Span, Vec<Statement<'a>>)>,
2020    /// Span of "END"
2021    pub end_span: Span,
2022}
2023
2024impl<'a> Spanned for CaseStatement<'a> {
2025    fn span(&self) -> Span {
2026        self.case_span
2027            .join_span(&self.value)
2028            .join_span(&self.whens)
2029            .join_span(&self.else_)
2030            .join_span(&self.end_span)
2031    }
2032}
2033
2034pub(crate) fn parse_case_statement<'a>(
2035    parser: &mut Parser<'a, '_>,
2036) -> Result<CaseStatement<'a>, ParseError> {
2037    let case_span = parser.consume_keyword(Keyword::CASE)?;
2038    let value = if !matches!(parser.token, Token::Ident(_, Keyword::WHEN)) {
2039        Some(parse_expression_unreserved(parser, PRIORITY_MAX)?)
2040    } else {
2041        None
2042    };
2043
2044    let mut whens = Vec::new();
2045    let mut else_ = None;
2046    parser.recovered(
2047        "'END'",
2048        &|t| matches!(t, Token::Ident(_, Keyword::END)),
2049        |parser| {
2050            loop {
2051                let when_span = parser.consume_keyword(Keyword::WHEN)?;
2052                let when = parse_expression_unreserved(parser, PRIORITY_MAX)?;
2053                let then_span = parser.consume_keyword(Keyword::THEN)?;
2054                let mut then = Vec::new();
2055                parse_statement_list(parser, &mut then)?;
2056                whens.push(WhenStatement {
2057                    when_span,
2058                    when,
2059                    then_span,
2060                    then,
2061                });
2062                if !matches!(parser.token, Token::Ident(_, Keyword::WHEN)) {
2063                    break;
2064                }
2065            }
2066            if let Some(span) = parser.skip_keyword(Keyword::ELSE) {
2067                let mut e = Vec::new();
2068                parse_statement_list(parser, &mut e)?;
2069                else_ = Some((span, e))
2070            };
2071            Ok(())
2072        },
2073    )?;
2074    let end_span = parser.consume_keyword(Keyword::END)?;
2075    Ok(CaseStatement {
2076        case_span,
2077        value,
2078        whens,
2079        else_,
2080        end_span,
2081    })
2082}
2083
2084pub(crate) fn parse_compound_query_bottom<'a>(
2085    parser: &mut Parser<'a, '_>,
2086) -> Result<Statement<'a>, ParseError> {
2087    match &parser.token {
2088        Token::LParen => {
2089            let lp = parser.consume_token(Token::LParen)?;
2090            let s = parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
2091                Ok(Some(parse_compound_query(parser)?))
2092            })?;
2093            parser.consume_token(Token::RParen)?;
2094            Ok(s.unwrap_or(Statement::Invalid(Box::new(Invalid { span: lp }))))
2095        }
2096        Token::Ident(_, Keyword::SELECT) => Ok(Statement::Select(Box::new(parse_select(parser)?))),
2097        Token::Ident(_, Keyword::VALUES) => Ok(Statement::Values(Box::new(parse_values(parser)?))),
2098        _ => parser.expected_failure("'SELECET' or '('")?,
2099    }
2100}
2101
2102/// Quantifier for a compound-query operator
2103#[derive(Clone, Debug)]
2104pub enum CompoundQuantifier {
2105    All(Span),
2106    Distinct(Span),
2107    Default,
2108}
2109
2110impl OptSpanned for CompoundQuantifier {
2111    fn opt_span(&self) -> Option<Span> {
2112        match &self {
2113            CompoundQuantifier::All(v) => v.opt_span(),
2114            CompoundQuantifier::Distinct(v) => v.opt_span(),
2115            CompoundQuantifier::Default => None,
2116        }
2117    }
2118}
2119
2120/// Set operator used between compound query branches
2121#[derive(Clone, Debug, Copy, PartialEq, Eq)]
2122pub enum CompoundOperator {
2123    Union,
2124    Intersect,
2125    Except,
2126}
2127
2128/// Right hand side branch of a compound query
2129#[derive(Clone, Debug)]
2130pub struct CompoundQueryBranch<'a> {
2131    /// Operator used to combine this branch with the left side
2132    pub operator: CompoundOperator,
2133    /// Span of operator keyword (UNION/INTERSECT/EXCEPT)
2134    pub operator_span: Span,
2135    /// Optional quantifier (ALL / DISTINCT)
2136    pub quantifier: CompoundQuantifier,
2137    /// Statement for this branch
2138    pub statement: Box<Statement<'a>>,
2139}
2140
2141impl<'a> Spanned for CompoundQueryBranch<'a> {
2142    fn span(&self) -> Span {
2143        self.operator_span
2144            .join_span(&self.quantifier)
2145            .join_span(&self.statement)
2146    }
2147}
2148
2149/// Compound query statement
2150#[derive(Clone, Debug)]
2151pub struct CompoundQuery<'a> {
2152    /// Left side of compound query
2153    pub left: Box<Statement<'a>>,
2154    /// Branches combined with the left side
2155    pub with: Vec<CompoundQueryBranch<'a>>,
2156    /// Span of "ORDER BY", and list of ordering expressions and directions if specified
2157    pub order_by: Option<(Span, Vec<(Expression<'a>, OrderFlag)>)>,
2158    /// Span of "LIMIT", offset and count expressions if specified
2159    pub limit: Option<(Span, Option<Expression<'a>>, Expression<'a>)>,
2160}
2161
2162impl<'a> Spanned for CompoundQuery<'a> {
2163    fn span(&self) -> Span {
2164        self.left
2165            .join_span(&self.with)
2166            .join_span(&self.order_by)
2167            .join_span(&self.limit)
2168    }
2169}
2170
2171pub(crate) fn parse_compound_query<'a>(
2172    parser: &mut Parser<'a, '_>,
2173) -> Result<Statement<'a>, ParseError> {
2174    let q = parse_compound_query_bottom(parser)?;
2175    if !matches!(
2176        parser.token,
2177        Token::Ident(_, Keyword::UNION | Keyword::INTERSECT | Keyword::EXCEPT)
2178    ) {
2179        return Ok(q);
2180    };
2181    let mut with = Vec::new();
2182    loop {
2183        let (operator, operator_span) = match &parser.token {
2184            Token::Ident(_, Keyword::UNION) => (
2185                CompoundOperator::Union,
2186                parser.consume_keyword(Keyword::UNION)?,
2187            ),
2188            Token::Ident(_, Keyword::INTERSECT) => (
2189                CompoundOperator::Intersect,
2190                parser.consume_keyword(Keyword::INTERSECT)?,
2191            ),
2192            Token::Ident(_, Keyword::EXCEPT) => (
2193                CompoundOperator::Except,
2194                parser.consume_keyword(Keyword::EXCEPT)?,
2195            ),
2196            _ => parser.expected_failure("'UNION' | 'INTERSECT' | 'EXCEPT'")?,
2197        };
2198        let quantifier = match &parser.token {
2199            Token::Ident(_, Keyword::ALL) => {
2200                CompoundQuantifier::All(parser.consume_keyword(Keyword::ALL)?)
2201            }
2202            Token::Ident(_, Keyword::DISTINCT) => {
2203                CompoundQuantifier::Distinct(parser.consume_keyword(Keyword::DISTINCT)?)
2204            }
2205            _ => CompoundQuantifier::Default,
2206        };
2207        let statement = Box::new(parse_compound_query_bottom(parser)?);
2208        with.push(CompoundQueryBranch {
2209            operator,
2210            operator_span,
2211            quantifier,
2212            statement,
2213        });
2214        if !matches!(
2215            parser.token,
2216            Token::Ident(_, Keyword::UNION | Keyword::INTERSECT | Keyword::EXCEPT)
2217        ) {
2218            break;
2219        }
2220    }
2221
2222    let order_by = if let Some(span) = parser.skip_keyword(Keyword::ORDER) {
2223        let span = parser.consume_keyword(Keyword::BY)?.join_span(&span);
2224        let mut order = Vec::new();
2225        loop {
2226            let e = parse_expression_unreserved(parser, PRIORITY_MAX)?;
2227            let f = match &parser.token {
2228                Token::Ident(_, Keyword::ASC) => OrderFlag::Asc(parser.consume()),
2229                Token::Ident(_, Keyword::DESC) => OrderFlag::Desc(parser.consume()),
2230                _ => OrderFlag::None,
2231            };
2232            order.push((e, f));
2233            if parser.skip_token(Token::Comma).is_none() {
2234                break;
2235            }
2236        }
2237        Some((span, order))
2238    } else {
2239        None
2240    };
2241
2242    let limit = if let Some(span) = parser.skip_keyword(Keyword::LIMIT) {
2243        let n = parse_expression_unreserved(parser, PRIORITY_MAX)?;
2244        match parser.token {
2245            Token::Comma => {
2246                parser.consume();
2247                Some((
2248                    span,
2249                    Some(n),
2250                    parse_expression_unreserved(parser, PRIORITY_MAX)?,
2251                ))
2252            }
2253            Token::Ident(_, Keyword::OFFSET) => {
2254                parser.consume();
2255                Some((
2256                    span,
2257                    Some(parse_expression_unreserved(parser, PRIORITY_MAX)?),
2258                    n,
2259                ))
2260            }
2261            _ => Some((span, None, n)),
2262        }
2263    } else {
2264        None
2265    };
2266
2267    Ok(Statement::CompoundQuery(Box::new(CompoundQuery {
2268        left: Box::new(q),
2269        with,
2270        order_by,
2271        limit,
2272    })))
2273}
2274
2275pub(crate) fn parse_statements<'a>(parser: &mut Parser<'a, '_>) -> Vec<Statement<'a>> {
2276    let mut ans = Vec::new();
2277    loop {
2278        match &parser.token {
2279            Token::Delimiter => {
2280                parser.consume();
2281                continue;
2282            }
2283            Token::Eof => return ans,
2284            _ => (),
2285        }
2286
2287        if matches!(parser.token, Token::Ident(_, Keyword::DELIMITER)) {
2288            if let Err(e) = parser.lexer.update_mysql_delimitor() {
2289                parser.err("Invalid delimiter", &e);
2290            }
2291            parser.consume();
2292            continue;
2293        }
2294
2295        let stmt = match parse_statement(parser) {
2296            Ok(Some(v)) => Ok(v),
2297            Ok(None) => parser.expected_failure("Statement"),
2298            Err(e) => Err(e),
2299        };
2300        let err = stmt.is_err();
2301        let mut from_stdin = false;
2302        if let Ok(stmt) = stmt {
2303            from_stdin = stmt.reads_from_stdin();
2304            ans.push(stmt);
2305        }
2306
2307        if !matches!(parser.token, Token::Delimiter) {
2308            if !err {
2309                parser.expected_error(parser.lexer.delimiter_name());
2310            }
2311            // We use a custom recovery here as ; is not allowed in sub expressions, it always terminates outer most statements
2312            loop {
2313                parser.next();
2314                match &parser.token {
2315                    Token::Delimiter => break,
2316                    Token::Eof => return ans,
2317                    _ => (),
2318                }
2319            }
2320        }
2321        if from_stdin {
2322            let (s, span) = parser.read_from_stdin_and_next();
2323            ans.push(Statement::Stdin(Box::new(Stdin { span, input: s })));
2324        } else {
2325            parser
2326                .consume_token(Token::Delimiter)
2327                .unwrap_or_else(|_| panic!("{}", parser.lexer.delimiter_name()));
2328        }
2329    }
2330}