Skip to main content

qusql_parse/
create.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.
12use crate::{
13    DataType, Identifier, QualifiedName, SString, Span, Spanned, Statement,
14    create_constraint_trigger::parse_create_constraint_trigger,
15    create_function::{parse_create_function, parse_create_procedure},
16    create_index::parse_create_index,
17    create_option::{CreateAlgorithm, CreateOption},
18    create_role::parse_create_role,
19    create_table::parse_create_table_or_partition_of,
20    create_trigger::parse_create_trigger,
21    create_view::parse_create_view,
22    data_type::{DataTypeContext, parse_data_type},
23    expression::{Expression, PRIORITY_MAX, parse_expression_unreserved},
24    keywords::Keyword,
25    lexer::Token,
26    operator::{parse_create_operator, parse_create_operator_class, parse_create_operator_family},
27    parser::{ParseError, Parser},
28    qualified_name::parse_qualified_name_unreserved,
29};
30use alloc::{boxed::Box, vec::Vec};
31
32#[derive(Clone, Debug)]
33pub struct CreateTypeEnum<'a> {
34    /// Span of "CREATE"
35    pub create_span: Span,
36    /// Options after "CREATE"
37    pub create_options: Vec<CreateOption<'a>>,
38    /// Span of "TYPE"
39    pub type_span: Span,
40    /// Name of the created type
41    pub name: QualifiedName<'a>,
42    /// Span of "AS ENUM"
43    pub as_enum_span: Span,
44    /// Enum values
45    pub values: Vec<SString<'a>>,
46}
47
48impl<'a> Spanned for CreateTypeEnum<'a> {
49    fn span(&self) -> Span {
50        self.create_span
51            .join_span(&self.create_options)
52            .join_span(&self.type_span)
53            .join_span(&self.name)
54            .join_span(&self.as_enum_span)
55            .join_span(&self.values)
56    }
57}
58
59fn parse_create_type<'a>(
60    parser: &mut Parser<'a, '_>,
61    create_span: Span,
62    create_options: Vec<CreateOption<'a>>,
63) -> Result<CreateTypeEnum<'a>, ParseError> {
64    let type_span = parser.consume_keyword(Keyword::TYPE)?;
65    parser.postgres_only(&type_span);
66    let name = parse_qualified_name_unreserved(parser)?;
67    let as_enum_span = parser.consume_keywords(&[Keyword::AS, Keyword::ENUM])?;
68    parser.consume_token(Token::LParen)?;
69    let mut values = Vec::new();
70    loop {
71        parser.recovered(
72            "')' or ','",
73            &|t| matches!(t, Token::RParen | Token::Comma),
74            |parser| {
75                values.push(parser.consume_string()?);
76                Ok(())
77            },
78        )?;
79        if matches!(parser.token, Token::RParen) {
80            break;
81        }
82        parser.consume_token(Token::Comma)?;
83    }
84    parser.consume_token(Token::RParen)?;
85    Ok(CreateTypeEnum {
86        create_span,
87        create_options,
88        type_span,
89        name,
90        as_enum_span,
91        values,
92    })
93}
94
95#[derive(Clone, Debug)]
96pub enum CreateDatabaseOption<'a> {
97    CharSet {
98        identifier: Span,
99        default_span: Option<Span>,
100        value: Identifier<'a>,
101    },
102    Collate {
103        identifier: Span,
104        default_span: Option<Span>,
105        value: Identifier<'a>,
106    },
107    Encryption {
108        identifier: Span,
109        default_span: Option<Span>,
110        value: SString<'a>,
111    },
112}
113
114impl Spanned for CreateDatabaseOption<'_> {
115    fn span(&self) -> Span {
116        match self {
117            CreateDatabaseOption::CharSet {
118                identifier,
119                default_span,
120                value,
121            } => identifier.join_span(default_span).join_span(value),
122            CreateDatabaseOption::Collate {
123                identifier,
124                default_span,
125                value,
126            } => identifier.join_span(default_span).join_span(value),
127            CreateDatabaseOption::Encryption {
128                identifier,
129                default_span,
130                value,
131            } => identifier.join_span(default_span).join_span(value),
132        }
133    }
134}
135
136#[derive(Clone, Debug)]
137pub struct CreateDatabase<'a> {
138    /// Span of "CREATE"
139    pub create_span: Span,
140    /// Span of "DATABASE"
141    pub database_span: Span,
142    /// Span of "IF NOT EXISTS" if specified
143    pub if_not_exists: Option<Span>,
144    /// Name of the created database
145    pub name: Identifier<'a>,
146    /// Options specified for database creation
147    pub create_options: Vec<CreateDatabaseOption<'a>>,
148}
149
150impl Spanned for CreateDatabase<'_> {
151    fn span(&self) -> Span {
152        self.create_span
153            .join_span(&self.create_options)
154            .join_span(&self.database_span)
155            .join_span(&self.if_not_exists)
156            .join_span(&self.name)
157    }
158}
159
160/// CREATE EXTENSION statement (PostgreSQL)
161#[derive(Clone, Debug)]
162pub struct CreateExtension<'a> {
163    /// Span of "CREATE"
164    pub create_span: Span,
165    /// Span of "EXTENSION"
166    pub extension_span: Span,
167    /// Span of "IF NOT EXISTS" if specified
168    pub if_not_exists: Option<Span>,
169    /// Name of the extension
170    pub name: Identifier<'a>,
171    /// Optional SCHEMA clause
172    pub schema: Option<(Span, Identifier<'a>)>,
173    /// Optional VERSION clause
174    pub version: Option<(Span, SString<'a>)>,
175    /// CASCADE option
176    pub cascade: Option<Span>,
177}
178
179impl Spanned for CreateExtension<'_> {
180    fn span(&self) -> Span {
181        self.create_span
182            .join_span(&self.extension_span)
183            .join_span(&self.if_not_exists)
184            .join_span(&self.name)
185            .join_span(&self.schema)
186            .join_span(&self.version)
187            .join_span(&self.cascade)
188    }
189}
190
191fn parse_create_extension<'a>(
192    parser: &mut Parser<'a, '_>,
193    create_span: Span,
194    create_options: Vec<CreateOption<'a>>,
195) -> Result<CreateExtension<'a>, ParseError> {
196    let extension_span = parser.consume_keyword(Keyword::EXTENSION)?;
197    parser.postgres_only(&extension_span);
198
199    for option in create_options {
200        parser.err("Not supported for CREATE EXTENSION", &option.span());
201    }
202
203    let if_not_exists = if let Some(if_span) = parser.skip_keyword(Keyword::IF) {
204        Some(
205            parser
206                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
207                .join_span(&if_span),
208        )
209    } else {
210        None
211    };
212
213    let name = parser.consume_plain_identifier_unreserved()?;
214
215    // Optional WITH
216    parser.skip_keyword(Keyword::WITH);
217
218    // Parse optional SCHEMA, VERSION, CASCADE (any order)
219    let mut schema = None;
220    let mut version = None;
221    let mut cascade = None;
222    loop {
223        match &parser.token {
224            Token::Ident(_, Keyword::SCHEMA) => {
225                let schema_span = parser.consume_keyword(Keyword::SCHEMA)?;
226                let schema_name = parser.consume_plain_identifier_unreserved()?;
227                schema = Some((schema_span, schema_name));
228            }
229            Token::Ident(_, Keyword::VERSION) => {
230                let version_span = parser.consume_keyword(Keyword::VERSION)?;
231                // Version can be identifier or string
232                let version_value = match &parser.token {
233                    Token::String(v, _) => SString::new((*v).into(), parser.consume()),
234                    _ => {
235                        let ident = parser.consume_plain_identifier_unreserved()?;
236                        SString::new(ident.value.into(), ident.span)
237                    }
238                };
239                version = Some((version_span, version_value));
240            }
241            Token::Ident(_, Keyword::CASCADE) => {
242                cascade = Some(parser.consume_keyword(Keyword::CASCADE)?);
243            }
244            _ => break,
245        }
246    }
247
248    Ok(CreateExtension {
249        create_span,
250        extension_span,
251        if_not_exists,
252        name,
253        schema,
254        version,
255        cascade,
256    })
257}
258
259/// CREATE DOMAIN statement (PostgreSQL)
260#[derive(Clone, Debug)]
261pub struct CreateDomain<'a> {
262    /// Span of "CREATE"
263    pub create_span: Span,
264    /// Span of "DOMAIN"
265    pub domain_span: Span,
266    /// Span of "IF NOT EXISTS" if specified
267    pub if_not_exists: Option<Span>,
268    /// Name of the domain (optionally schema-qualified)
269    pub name: QualifiedName<'a>,
270    /// Underlying data type
271    pub data_type: DataType<'a>,
272    /// Optional COLLATE clause
273    pub collate: Option<(Span, Identifier<'a>)>,
274    /// Optional DEFAULT clause
275    pub default: Option<(Span, Expression<'a>)>,
276    /// List of domain constraints (CONSTRAINT name, NOT NULL, NULL, CHECK)
277    pub constraints: Vec<DomainConstraint<'a>>,
278}
279
280impl<'a> Spanned for CreateDomain<'a> {
281    fn span(&self) -> Span {
282        self.create_span
283            .join_span(&self.domain_span)
284            .join_span(&self.if_not_exists)
285            .join_span(&self.name)
286            .join_span(&self.data_type)
287            .join_span(&self.collate)
288            .join_span(&self.default)
289            .join_span(&self.constraints)
290    }
291}
292
293/// Domain constraint for CREATE DOMAIN
294#[derive(Clone, Debug)]
295pub enum DomainConstraint<'a> {
296    ConstraintName(Span, Identifier<'a>),
297    NotNull(Span),
298    Null(Span),
299    Check(Span, Expression<'a>),
300}
301
302impl<'a> Spanned for DomainConstraint<'a> {
303    fn span(&self) -> Span {
304        match self {
305            DomainConstraint::ConstraintName(span, name) => span.join_span(name),
306            DomainConstraint::NotNull(span) => span.clone(),
307            DomainConstraint::Null(span) => span.clone(),
308            DomainConstraint::Check(span, expr) => span.join_span(expr),
309        }
310    }
311}
312
313/// Parse CREATE DOMAIN statement (PostgreSQL)
314pub fn parse_create_domain<'a>(
315    parser: &mut Parser<'a, '_>,
316    create_span: Span,
317    create_options: Vec<CreateOption<'a>>,
318) -> Result<CreateDomain<'a>, ParseError> {
319    let domain_span = parser.consume_keyword(Keyword::DOMAIN)?;
320    parser.postgres_only(&domain_span);
321
322    for option in create_options {
323        parser.err("Not supported for CREATE DOMAIN", &option.span());
324    }
325
326    let if_not_exists = if let Some(if_span) = parser.skip_keyword(Keyword::IF) {
327        Some(
328            parser
329                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
330                .join_span(&if_span),
331        )
332    } else {
333        None
334    };
335
336    let name = parse_qualified_name_unreserved(parser)?;
337
338    // Optional AS
339    parser.skip_keyword(Keyword::AS);
340
341    let data_type = parse_data_type(parser, DataTypeContext::Column)?;
342
343    // Optional COLLATE
344    let collate = if let Some(collate_span) = parser.skip_keyword(Keyword::COLLATE) {
345        let collate_name = parser.consume_plain_identifier_unreserved()?;
346        Some((collate_span, collate_name))
347    } else {
348        None
349    };
350
351    // Optional DEFAULT
352    let default = if let Some(default_span) = parser.skip_keyword(Keyword::DEFAULT) {
353        let expr = parse_expression_unreserved(parser, PRIORITY_MAX)?;
354        Some((default_span, expr))
355    } else {
356        None
357    };
358
359    // Parse domain constraints
360    let mut constraints = Vec::new();
361    loop {
362        match &parser.token {
363            Token::Ident(_, Keyword::CONSTRAINT) => {
364                let constraint_span = parser.consume_keyword(Keyword::CONSTRAINT)?;
365                let name = parser.consume_plain_identifier_unreserved()?;
366                constraints.push(DomainConstraint::ConstraintName(constraint_span, name));
367            }
368            Token::Ident(_, Keyword::NOT) => {
369                let not_span = parser.consume_keyword(Keyword::NOT)?;
370                let null_span = parser.consume_keyword(Keyword::NULL)?;
371                constraints.push(DomainConstraint::NotNull(not_span.join_span(&null_span)));
372            }
373            Token::Ident(_, Keyword::NULL) => {
374                let null_span = parser.consume_keyword(Keyword::NULL)?;
375                constraints.push(DomainConstraint::Null(null_span));
376            }
377            Token::Ident(_, Keyword::CHECK) => {
378                let check_span = parser.consume_keyword(Keyword::CHECK)?;
379                parser.consume_token(Token::LParen)?;
380                let expr = parse_expression_unreserved(parser, PRIORITY_MAX)?;
381                parser.consume_token(Token::RParen)?;
382                constraints.push(DomainConstraint::Check(check_span, expr));
383            }
384            _ => break,
385        }
386    }
387
388    Ok(CreateDomain {
389        create_span,
390        domain_span,
391        if_not_exists,
392        name,
393        data_type,
394        collate,
395        default,
396        constraints,
397    })
398}
399
400/// CREATE SCHEMA statement (PostgreSQL)
401#[derive(Clone, Debug)]
402pub struct CreateSchema<'a> {
403    /// Span of "CREATE"
404    pub create_span: Span,
405    /// Span of "SCHEMA"
406    pub schema_span: Span,
407    /// Span of "IF NOT EXISTS" if specified
408    pub if_not_exists: Option<Span>,
409    /// Name of the created schema (optional if AUTHORIZATION is present)
410    pub name: Option<Identifier<'a>>,
411    /// AUTHORIZATION clause with role name
412    pub authorization: Option<(Span, Identifier<'a>)>,
413}
414
415impl Spanned for CreateSchema<'_> {
416    fn span(&self) -> Span {
417        self.create_span
418            .join_span(&self.schema_span)
419            .join_span(&self.if_not_exists)
420            .join_span(&self.name)
421            .join_span(&self.authorization)
422    }
423}
424
425/// Sequence option for CREATE SEQUENCE / ALTER SEQUENCE
426#[derive(Clone, Debug)]
427pub enum SequenceOption<'a> {
428    /// AS data_type
429    As {
430        as_span: Span,
431        data_type: DataType<'a>,
432    },
433    /// INCREMENT [BY] value
434    IncrementBy {
435        increment_span: Span,
436        by_span: Option<Span>,
437        value: i64,
438        value_span: Span,
439    },
440    /// MINVALUE value
441    MinValue {
442        minvalue_span: Span,
443        value: i64,
444        value_span: Span,
445    },
446    /// NO MINVALUE
447    NoMinValue(Span),
448    /// MAXVALUE value
449    MaxValue {
450        maxvalue_span: Span,
451        value: i64,
452        value_span: Span,
453    },
454    /// NO MAXVALUE
455    NoMaxValue(Span),
456    /// START [WITH] value
457    StartWith {
458        start_span: Span,
459        with_span: Option<Span>,
460        value: i64,
461        value_span: Span,
462    },
463    /// CACHE value
464    Cache {
465        cache_span: Span,
466        value: i64,
467        value_span: Span,
468    },
469    /// CYCLE
470    Cycle(Span),
471    /// NO CYCLE
472    NoCycle(Span),
473    /// OWNED BY table.column
474    OwnedBy {
475        owned_span: Span,
476        by_span: Span,
477        table_column: QualifiedName<'a>,
478    },
479    /// OWNED BY NONE
480    OwnedByNone {
481        owned_span: Span,
482        by_span: Span,
483        none_span: Span,
484    },
485}
486
487impl<'a> Spanned for SequenceOption<'a> {
488    fn span(&self) -> Span {
489        match self {
490            SequenceOption::As { as_span, data_type } => as_span.join_span(data_type),
491            SequenceOption::IncrementBy {
492                increment_span,
493                value_span,
494                ..
495            } => increment_span.join_span(value_span),
496            SequenceOption::MinValue {
497                minvalue_span,
498                value_span,
499                ..
500            } => minvalue_span.join_span(value_span),
501            SequenceOption::NoMinValue(s) => s.span(),
502            SequenceOption::MaxValue {
503                maxvalue_span,
504                value_span,
505                ..
506            } => maxvalue_span.join_span(value_span),
507            SequenceOption::NoMaxValue(s) => s.span(),
508            SequenceOption::StartWith {
509                start_span,
510                value_span,
511                ..
512            } => start_span.join_span(value_span),
513            SequenceOption::Cache {
514                cache_span,
515                value_span,
516                ..
517            } => cache_span.join_span(value_span),
518            SequenceOption::Cycle(s) => s.span(),
519            SequenceOption::NoCycle(s) => s.span(),
520            SequenceOption::OwnedBy {
521                owned_span,
522                table_column,
523                ..
524            } => owned_span.join_span(table_column),
525            SequenceOption::OwnedByNone {
526                owned_span,
527                none_span,
528                ..
529            } => owned_span.join_span(none_span),
530        }
531    }
532}
533
534/// Parse sequence options (used by CREATE SEQUENCE and ALTER TABLE ADD GENERATED AS IDENTITY)
535pub(crate) fn parse_sequence_options<'a>(
536    parser: &mut Parser<'a, '_>,
537) -> Result<Vec<SequenceOption<'a>>, ParseError> {
538    let mut options = Vec::new();
539    loop {
540        match &parser.token {
541            Token::Ident(_, Keyword::AS) => {
542                let as_span = parser.consume_keyword(Keyword::AS)?;
543                let data_type = parse_data_type(parser, DataTypeContext::TypeRef)?;
544                options.push(SequenceOption::As { as_span, data_type });
545            }
546            Token::Ident(_, Keyword::INCREMENT) => {
547                let increment_span = parser.consume_keyword(Keyword::INCREMENT)?;
548                let by_span = parser.skip_keyword(Keyword::BY); // BY is optional
549                let (value, value_span) = parser.consume_signed_int::<i64>()?;
550                options.push(SequenceOption::IncrementBy {
551                    increment_span,
552                    by_span,
553                    value,
554                    value_span,
555                });
556            }
557            Token::Ident(_, Keyword::MINVALUE) => {
558                let minvalue_span = parser.consume_keyword(Keyword::MINVALUE)?;
559                let (value, value_span) = parser.consume_signed_int::<i64>()?;
560                options.push(SequenceOption::MinValue {
561                    minvalue_span,
562                    value,
563                    value_span,
564                });
565            }
566            Token::Ident(_, Keyword::MAXVALUE) => {
567                let maxvalue_span = parser.consume_keyword(Keyword::MAXVALUE)?;
568                let (value, value_span) = parser.consume_signed_int::<i64>()?;
569                options.push(SequenceOption::MaxValue {
570                    maxvalue_span,
571                    value,
572                    value_span,
573                });
574            }
575            Token::Ident(_, Keyword::START) => {
576                let start_span = parser.consume_keyword(Keyword::START)?;
577                let with_span = parser.skip_keyword(Keyword::WITH); // WITH is optional
578                let (value, value_span) = parser.consume_signed_int::<i64>()?;
579                options.push(SequenceOption::StartWith {
580                    start_span,
581                    with_span,
582                    value,
583                    value_span,
584                });
585            }
586            Token::Ident(_, Keyword::CACHE) => {
587                let cache_span = parser.consume_keyword(Keyword::CACHE)?;
588                let (value, value_span) = parser.consume_signed_int::<i64>()?;
589                options.push(SequenceOption::Cache {
590                    cache_span,
591                    value,
592                    value_span,
593                });
594            }
595            Token::Ident(_, Keyword::CYCLE) => {
596                let cycle_span = parser.consume_keyword(Keyword::CYCLE)?;
597                options.push(SequenceOption::Cycle(cycle_span));
598            }
599            Token::Ident(_, Keyword::NO) => {
600                // Could be NO MINVALUE, NO MAXVALUE, or NO CYCLE
601                let no_span = parser.consume_keyword(Keyword::NO)?;
602                match &parser.token {
603                    Token::Ident(_, Keyword::MINVALUE) => {
604                        let minvalue_span = parser.consume_keyword(Keyword::MINVALUE)?;
605                        let span = no_span.join_span(&minvalue_span);
606                        options.push(SequenceOption::NoMinValue(span));
607                    }
608                    Token::Ident(_, Keyword::MAXVALUE) => {
609                        let maxvalue_span = parser.consume_keyword(Keyword::MAXVALUE)?;
610                        let span = no_span.join_span(&maxvalue_span);
611                        options.push(SequenceOption::NoMaxValue(span));
612                    }
613                    Token::Ident(_, Keyword::CYCLE) => {
614                        let cycle_span = parser.consume_keyword(Keyword::CYCLE)?;
615                        let span = no_span.join_span(&cycle_span);
616                        options.push(SequenceOption::NoCycle(span));
617                    }
618                    _ => parser.expected_failure("'MINVALUE', 'MAXVALUE' or 'CYCLE' after 'NO'")?,
619                }
620            }
621            Token::Ident(_, Keyword::OWNED) => {
622                let owned_span = parser.consume_keyword(Keyword::OWNED)?;
623                let by_span = parser.consume_keyword(Keyword::BY)?;
624                if let Token::Ident(_, Keyword::NONE) = parser.token {
625                    let none_span = parser.consume_keyword(Keyword::NONE)?;
626                    options.push(SequenceOption::OwnedByNone {
627                        owned_span,
628                        by_span,
629                        none_span,
630                    });
631                } else {
632                    let table_column = parse_qualified_name_unreserved(parser)?;
633                    options.push(SequenceOption::OwnedBy {
634                        owned_span,
635                        by_span,
636                        table_column,
637                    });
638                }
639            }
640            _ => break,
641        }
642    }
643    Ok(options)
644}
645
646/// CREATE SEQUENCE statement (PostgreSQL)
647#[derive(Clone, Debug)]
648pub struct CreateSequence<'a> {
649    /// Span of "CREATE"
650    pub create_span: Span,
651    /// Span of optional TEMPORARY/TEMP keyword
652    pub temporary: Option<Span>,
653    /// Span of "SEQUENCE"
654    pub sequence_span: Span,
655    /// Span of "IF NOT EXISTS" if specified
656    pub if_not_exists: Option<Span>,
657    /// Name of the created sequence
658    pub name: QualifiedName<'a>,
659    /// Sequence options
660    pub options: Vec<SequenceOption<'a>>,
661}
662
663impl Spanned for CreateSequence<'_> {
664    fn span(&self) -> Span {
665        self.create_span
666            .join_span(&self.temporary)
667            .join_span(&self.sequence_span)
668            .join_span(&self.if_not_exists)
669            .join_span(&self.name)
670            .join_span(&self.options)
671    }
672}
673
674fn parse_create_database<'a>(
675    parser: &mut Parser<'a, '_>,
676    create_span: Span,
677    create_options: Vec<CreateOption<'a>>,
678) -> Result<CreateDatabase<'a>, ParseError> {
679    for option in create_options {
680        parser.err("Not supported fo CREATE DATABASE", &option.span());
681    }
682
683    let database_span = parser.consume();
684
685    let if_not_exists = if let Some(if_) = parser.skip_keyword(Keyword::IF) {
686        Some(
687            parser
688                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
689                .join_span(&if_),
690        )
691    } else {
692        None
693    };
694
695    let mut create_options = Vec::new();
696    let name = parser.consume_plain_identifier_unreserved()?;
697    loop {
698        let default_span = parser.skip_keyword(Keyword::DEFAULT);
699        match &parser.token {
700            Token::Ident(_, Keyword::CHARSET) => {
701                let identifier = parser.consume_keyword(Keyword::CHARSET)?;
702                parser.skip_token(Token::Eq);
703                create_options.push(CreateDatabaseOption::CharSet {
704                    default_span,
705                    identifier,
706                    value: parser.consume_plain_identifier_unreserved()?,
707                });
708            }
709            Token::Ident(_, Keyword::CHARACTER) => {
710                let identifier = parser.consume_keywords(&[Keyword::CHARACTER, Keyword::SET])?;
711                parser.skip_token(Token::Eq);
712                create_options.push(CreateDatabaseOption::CharSet {
713                    default_span,
714                    identifier,
715                    value: parser.consume_plain_identifier_unreserved()?,
716                });
717            }
718            Token::Ident(_, Keyword::COLLATE) => {
719                let identifier = parser.consume_keyword(Keyword::COLLATE)?;
720                parser.skip_token(Token::Eq);
721                create_options.push(CreateDatabaseOption::Collate {
722                    default_span,
723                    identifier,
724                    value: parser.consume_plain_identifier_unreserved()?,
725                });
726            }
727            Token::Ident(_, Keyword::ENCRYPTION) => {
728                let identifier = parser.consume_keyword(Keyword::ENCRYPTION)?;
729                parser.skip_token(Token::Eq);
730                let value = parser.consume_string()?;
731
732                create_options.push(CreateDatabaseOption::Encryption {
733                    default_span,
734                    identifier,
735                    value,
736                });
737            }
738            _ => {
739                if default_span.is_some() {
740                    parser.expected_failure("'CHARSET', 'COLLATE' or 'ENCRYPTION'")?;
741                }
742                break;
743            }
744        }
745    }
746
747    Ok(CreateDatabase {
748        create_span,
749        create_options,
750        database_span,
751        if_not_exists,
752        name,
753    })
754}
755
756fn parse_create_schema<'a>(
757    parser: &mut Parser<'a, '_>,
758    create_span: Span,
759    create_options: Vec<CreateOption<'a>>,
760) -> Result<CreateSchema<'a>, ParseError> {
761    let schema_span = parser.consume_keyword(Keyword::SCHEMA)?;
762    parser.postgres_only(&schema_span);
763
764    for option in create_options {
765        parser.err("Not supported for CREATE SCHEMA", &option.span());
766    }
767
768    let if_not_exists = if let Some(if_span) = parser.skip_keyword(Keyword::IF) {
769        Some(
770            parser
771                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
772                .join_span(&if_span),
773        )
774    } else {
775        None
776    };
777
778    // Parse schema name or AUTHORIZATION
779    let name = if matches!(parser.token, Token::Ident(_, Keyword::AUTHORIZATION)) {
780        None
781    } else {
782        Some(parser.consume_plain_identifier_unreserved()?)
783    };
784
785    let authorization = if let Token::Ident(_, Keyword::AUTHORIZATION) = parser.token {
786        let auth_span = parser.consume_keyword(Keyword::AUTHORIZATION)?;
787        let role_name = parser.consume_plain_identifier_unreserved()?;
788        Some((auth_span, role_name))
789    } else {
790        None
791    };
792
793    // TODO: Parse schema elements (CREATE TABLE, CREATE VIEW, GRANT, etc.)
794
795    Ok(CreateSchema {
796        create_span,
797        schema_span,
798        if_not_exists,
799        name,
800        authorization,
801    })
802}
803
804fn parse_create_sequence<'a>(
805    parser: &mut Parser<'a, '_>,
806    create_span: Span,
807    create_options: Vec<CreateOption<'a>>,
808) -> Result<CreateSequence<'a>, ParseError> {
809    let sequence_span = parser.consume_keyword(Keyword::SEQUENCE)?;
810    parser.postgres_only(&sequence_span);
811
812    // Extract TEMPORARY option if present, reject others
813    let mut temporary = None;
814    for option in create_options {
815        match option {
816            CreateOption::Temporary {
817                local_span,
818                temporary_span,
819            } => {
820                temporary = Some(temporary_span.join_span(&local_span));
821            }
822            _ => {
823                parser.err("Not supported for CREATE SEQUENCE", &option.span());
824            }
825        }
826    }
827
828    let if_not_exists = if let Some(if_span) = parser.skip_keyword(Keyword::IF) {
829        Some(
830            parser
831                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
832                .join_span(&if_span),
833        )
834    } else {
835        None
836    };
837
838    // Parse sequence name
839    let name = parse_qualified_name_unreserved(parser)?;
840
841    // Parse sequence options
842    let options = parse_sequence_options(parser)?;
843
844    Ok(CreateSequence {
845        create_span,
846        temporary,
847        sequence_span,
848        if_not_exists,
849        name,
850        options,
851    })
852}
853
854/// CREATE SERVER statement (PostgreSQL)
855#[derive(Clone, Debug)]
856pub struct CreateServer<'a> {
857    /// Span of "CREATE"
858    pub create_span: Span,
859    /// Span of "SERVER"
860    pub server_span: Span,
861    /// Span of "IF NOT EXISTS" if specified
862    pub if_not_exists: Option<Span>,
863    /// Name of the server
864    pub server_name: Identifier<'a>,
865    /// Optional TYPE 'server_type'
866    pub type_: Option<(Span, SString<'a>)>,
867    /// Optional VERSION 'server_version'
868    pub version: Option<(Span, SString<'a>)>,
869    /// FOREIGN DATA WRAPPER fdw_name
870    pub foreign_data_wrapper: (Span, Identifier<'a>),
871    /// OPTIONS (option 'value', ...)
872    pub options: Vec<(Identifier<'a>, SString<'a>)>,
873}
874
875impl Spanned for CreateServer<'_> {
876    fn span(&self) -> Span {
877        self.create_span
878            .join_span(&self.server_span)
879            .join_span(&self.if_not_exists)
880            .join_span(&self.server_name)
881            .join_span(&self.type_)
882            .join_span(&self.version)
883            .join_span(&self.foreign_data_wrapper)
884            .join_span(&self.options)
885    }
886}
887
888fn parse_create_server<'a>(
889    parser: &mut Parser<'a, '_>,
890    create_span: Span,
891    create_options: Vec<CreateOption<'a>>,
892) -> Result<CreateServer<'a>, ParseError> {
893    let server_span = parser.consume_keyword(Keyword::SERVER)?;
894    parser.postgres_only(&server_span);
895
896    for option in create_options {
897        parser.err("Not supported for CREATE SERVER", &option.span());
898    }
899
900    let if_not_exists = if let Some(if_span) = parser.skip_keyword(Keyword::IF) {
901        Some(
902            parser
903                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
904                .join_span(&if_span),
905        )
906    } else {
907        None
908    };
909
910    // Parse server name
911    let server_name = parser.consume_plain_identifier_unreserved()?;
912
913    // Parse optional TYPE 'server_type'
914    let type_ = if let Some(type_span) = parser.skip_keyword(Keyword::TYPE) {
915        let type_value = parser.consume_string()?;
916        Some((type_span, type_value))
917    } else {
918        None
919    };
920
921    // Parse optional VERSION 'server_version'
922    let version = if let Some(version_span) = parser.skip_keyword(Keyword::VERSION) {
923        let version_value = parser.consume_string()?;
924        Some((version_span, version_value))
925    } else {
926        None
927    };
928
929    // Parse FOREIGN DATA WRAPPER fdw_name
930    let fdw_span = parser.consume_keywords(&[Keyword::FOREIGN, Keyword::DATA, Keyword::WRAPPER])?;
931    let fdw_name = parser.consume_plain_identifier_unreserved()?;
932    let foreign_data_wrapper = (fdw_span, fdw_name);
933
934    // Parse optional OPTIONS (option 'value', ...)
935    let mut options = Vec::new();
936    if parser.skip_keyword(Keyword::OPTIONS).is_some() {
937        parser.consume_token(Token::LParen)?;
938        loop {
939            let option_name = parser.consume_plain_identifier_unreserved()?;
940            let option_value = parser.consume_string()?;
941            options.push((option_name, option_value));
942
943            if parser.skip_token(Token::Comma).is_none() {
944                break;
945            }
946        }
947        parser.consume_token(Token::RParen)?;
948    }
949
950    Ok(CreateServer {
951        create_span,
952        server_span,
953        if_not_exists,
954        server_name,
955        type_,
956        version,
957        foreign_data_wrapper,
958        options,
959    })
960}
961
962pub(crate) fn parse_create<'a>(parser: &mut Parser<'a, '_>) -> Result<Statement<'a>, ParseError> {
963    let create_span = parser.span.clone();
964    parser.consume_keyword(Keyword::CREATE)?;
965
966    let mut create_options = Vec::new();
967    const CREATABLE: &str = "'TABLE' | 'VIEW' | 'TRIGGER' | 'FUNCTION' | 'PROCEDURE' | 'INDEX' | 'TYPE' | 'DATABASE' | 'DOMAIN' |'EXTENSION' | 'SCHEMA' | 'SEQUENCE' | 'ROLE' | 'SERVER' | 'OPERATOR' | 'CONSTRAINT'";
968
969    parser.recovered(
970        CREATABLE,
971        &|t| {
972            matches!(
973                t,
974                Token::Ident(
975                    _,
976                    Keyword::TABLE
977                        | Keyword::MATERIALIZED
978                        | Keyword::VIEW
979                        | Keyword::TRIGGER
980                        | Keyword::FUNCTION
981                        | Keyword::PROCEDURE
982                        | Keyword::INDEX
983                        | Keyword::TYPE
984                        | Keyword::DATABASE
985                        | Keyword::SCHEMA
986                        | Keyword::SEQUENCE
987                        | Keyword::ROLE
988                        | Keyword::SERVER
989                        | Keyword::OPERATOR
990                        | Keyword::EXTENSION
991                        | Keyword::DOMAIN
992                        | Keyword::CONSTRAINT
993                )
994            )
995        },
996        |parser| {
997            loop {
998                let v = match &parser.token {
999                    Token::Ident(_, Keyword::OR) => CreateOption::OrReplace(
1000                        parser.consume_keywords(&[Keyword::OR, Keyword::REPLACE])?,
1001                    ),
1002                    Token::Ident(_, Keyword::LOCAL) => {
1003                        // LOCAL TEMPORARY
1004                        let local_span = parser.consume_keyword(Keyword::LOCAL)?;
1005                        parser.postgres_only(&local_span);
1006                        let temporary_span = parser.consume_keyword(Keyword::TEMPORARY)?;
1007                        CreateOption::Temporary {
1008                            local_span: Some(local_span),
1009                            temporary_span,
1010                        }
1011                    }
1012                    Token::Ident(_, Keyword::TEMPORARY) => {
1013                        let temporary_span = parser.consume_keyword(Keyword::TEMPORARY)?;
1014                        CreateOption::Temporary {
1015                            local_span: None,
1016                            temporary_span,
1017                        }
1018                    }
1019                    Token::Ident(_, Keyword::UNIQUE) => {
1020                        CreateOption::Unique(parser.consume_keyword(Keyword::UNIQUE)?)
1021                    }
1022                    Token::Ident(_, Keyword::ALGORITHM) => {
1023                        let algorithm_span = parser.consume_keyword(Keyword::ALGORITHM)?;
1024                        parser.consume_token(Token::Eq)?;
1025                        let algorithm = match &parser.token {
1026                            Token::Ident(_, Keyword::UNDEFINED) => CreateAlgorithm::Undefined(
1027                                parser.consume_keyword(Keyword::UNDEFINED)?,
1028                            ),
1029                            Token::Ident(_, Keyword::MERGE) => {
1030                                CreateAlgorithm::Merge(parser.consume_keyword(Keyword::MERGE)?)
1031                            }
1032                            Token::Ident(_, Keyword::TEMPTABLE) => CreateAlgorithm::TempTable(
1033                                parser.consume_keyword(Keyword::TEMPTABLE)?,
1034                            ),
1035                            _ => parser.expected_failure("'UNDEFINED', 'MERGE' or 'TEMPTABLE'")?,
1036                        };
1037                        CreateOption::Algorithm(algorithm_span, algorithm)
1038                    }
1039                    Token::Ident(_, Keyword::DEFINER) => {
1040                        let definer_span = parser.consume_keyword(Keyword::DEFINER)?;
1041                        parser.consume_token(Token::Eq)?;
1042                        // TODO user | CURRENT_USER | role | CURRENT_ROLE
1043                        // Accept both plain identifiers and string literals
1044                        let user = match &parser.token {
1045                            Token::String(v, _) => {
1046                                let v = *v;
1047                                Identifier::new(v, parser.consume())
1048                            }
1049                            _ => parser.consume_plain_identifier_unreserved()?,
1050                        };
1051                        parser.consume_token(Token::At)?;
1052                        let host = match &parser.token {
1053                            Token::String(v, _) => {
1054                                let v = *v;
1055                                Identifier::new(v, parser.consume())
1056                            }
1057                            _ => parser.consume_plain_identifier_unreserved()?,
1058                        };
1059                        CreateOption::Definer {
1060                            definer_span,
1061                            user,
1062                            host,
1063                        }
1064                    }
1065                    Token::Ident(_, Keyword::SQL) => {
1066                        let sql_security =
1067                            parser.consume_keywords(&[Keyword::SQL, Keyword::SECURITY])?;
1068                        match &parser.token {
1069                            Token::Ident(_, Keyword::DEFINER) => CreateOption::SqlSecurityDefiner(
1070                                sql_security,
1071                                parser.consume_keyword(Keyword::DEFINER)?,
1072                            ),
1073                            Token::Ident(_, Keyword::INVOKER) => CreateOption::SqlSecurityInvoker(
1074                                sql_security,
1075                                parser.consume_keyword(Keyword::INVOKER)?,
1076                            ),
1077                            Token::Ident(_, Keyword::USER) => CreateOption::SqlSecurityUser(
1078                                sql_security,
1079                                parser.consume_keyword(Keyword::USER)?,
1080                            ),
1081                            _ => parser.expected_failure("'DEFINER', 'INVOKER', 'USER'")?,
1082                        }
1083                    }
1084                    _ => break,
1085                };
1086                create_options.push(v);
1087            }
1088            Ok(())
1089        },
1090    )?;
1091
1092    let r =
1093        match &parser.token {
1094            Token::Ident(_, Keyword::INDEX) => Statement::CreateIndex(Box::new(
1095                parse_create_index(parser, create_span, create_options)?,
1096            )),
1097            Token::Ident(_, Keyword::TABLE) => {
1098                parse_create_table_or_partition_of(parser, create_span, create_options)?
1099            }
1100            Token::Ident(_, Keyword::MATERIALIZED) => {
1101                // MATERIALIZED VIEW
1102                let materialized_span = parser.consume_keyword(Keyword::MATERIALIZED)?;
1103                parser.postgres_only(&materialized_span);
1104                // Don't consume VIEW here, parse_create_view will do it
1105                create_options.push(CreateOption::Materialized(materialized_span));
1106                Statement::CreateView(Box::new(parse_create_view(
1107                    parser,
1108                    create_span,
1109                    create_options,
1110                )?))
1111            }
1112            Token::Ident(_, Keyword::VIEW) => Statement::CreateView(Box::new(parse_create_view(
1113                parser,
1114                create_span,
1115                create_options,
1116            )?)),
1117            Token::Ident(_, Keyword::CONSTRAINT) => Statement::CreateConstraintTrigger(Box::new(
1118                parse_create_constraint_trigger(parser, create_span, create_options)?,
1119            )),
1120            Token::Ident(_, Keyword::DATABASE) => Statement::CreateDatabase(Box::new(
1121                parse_create_database(parser, create_span, create_options)?,
1122            )),
1123            Token::Ident(_, Keyword::DOMAIN) => Statement::CreateDomain(Box::new(
1124                parse_create_domain(parser, create_span, create_options)?,
1125            )),
1126            Token::Ident(_, Keyword::EXTENSION) => Statement::CreateExtension(Box::new(
1127                parse_create_extension(parser, create_span, create_options)?,
1128            )),
1129            Token::Ident(_, Keyword::SCHEMA) => Statement::CreateSchema(Box::new(
1130                parse_create_schema(parser, create_span, create_options)?,
1131            )),
1132            Token::Ident(_, Keyword::SEQUENCE) => Statement::CreateSequence(Box::new(
1133                parse_create_sequence(parser, create_span, create_options)?,
1134            )),
1135            Token::Ident(_, Keyword::FUNCTION) => Statement::CreateFunction(Box::new(
1136                parse_create_function(parser, create_span, create_options)?,
1137            )),
1138            Token::Ident(_, Keyword::PROCEDURE) => Statement::CreateProcedure(Box::new(
1139                parse_create_procedure(parser, create_span, create_options)?,
1140            )),
1141            Token::Ident(_, Keyword::TRIGGER) => Statement::CreateTrigger(Box::new(
1142                parse_create_trigger(parser, create_span, create_options)?,
1143            )),
1144            Token::Ident(_, Keyword::TYPE) => Statement::CreateTypeEnum(Box::new(
1145                parse_create_type(parser, create_span, create_options)?,
1146            )),
1147            Token::Ident(_, Keyword::ROLE) => Statement::CreateRole(Box::new(parse_create_role(
1148                parser,
1149                create_span,
1150                create_options,
1151            )?)),
1152            Token::Ident(_, Keyword::SERVER) => Statement::CreateServer(Box::new(
1153                parse_create_server(parser, create_span, create_options)?,
1154            )),
1155            Token::Ident(_, Keyword::OPERATOR) => {
1156                let operator_span = parser.consume_keyword(Keyword::OPERATOR)?;
1157                match parser.token {
1158                    Token::Ident(_, Keyword::FAMILY) => {
1159                        // CREATE OPERATOR FAMILY
1160                        let family_span = parser.consume_keyword(Keyword::FAMILY)?;
1161                        parser.postgres_only(&family_span);
1162                        Statement::CreateOperatorFamily(Box::new(parse_create_operator_family(
1163                            parser,
1164                            create_span
1165                                .join_span(&operator_span)
1166                                .join_span(&family_span),
1167                            create_options,
1168                        )?))
1169                    }
1170                    Token::Ident(_, Keyword::CLASS) => {
1171                        // CREATE OPERATOR CLASS
1172                        let class_span = parser.consume_keyword(Keyword::CLASS)?;
1173                        Statement::CreateOperatorClass(Box::new(parse_create_operator_class(
1174                            parser,
1175                            create_span.join_span(&operator_span).join_span(&class_span),
1176                            create_options,
1177                        )?))
1178                    }
1179                    _ => {
1180                        // CREATE OPERATOR
1181                        Statement::CreateOperator(Box::new(parse_create_operator(
1182                            parser,
1183                            create_span.join_span(&operator_span),
1184                            create_options,
1185                        )?))
1186                    }
1187                }
1188            }
1189            _ => return parser.expected_failure(CREATABLE),
1190        };
1191    Ok(r)
1192}