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    /// RESTART [[WITH] value]
464    Restart {
465        restart_span: Span,
466        with_span: Option<Span>,
467        value: Option<i64>,
468        value_span: Option<Span>,
469    },
470    /// CACHE value
471    Cache {
472        cache_span: Span,
473        value: i64,
474        value_span: Span,
475    },
476    /// CYCLE
477    Cycle(Span),
478    /// NO CYCLE
479    NoCycle(Span),
480    /// OWNED BY table.column
481    OwnedBy {
482        owned_span: Span,
483        by_span: Span,
484        table_column: QualifiedName<'a>,
485    },
486    /// OWNED BY NONE
487    OwnedByNone {
488        owned_span: Span,
489        by_span: Span,
490        none_span: Span,
491    },
492}
493
494impl<'a> Spanned for SequenceOption<'a> {
495    fn span(&self) -> Span {
496        match self {
497            SequenceOption::As { as_span, data_type } => as_span.join_span(data_type),
498            SequenceOption::IncrementBy {
499                increment_span,
500                value_span,
501                ..
502            } => increment_span.join_span(value_span),
503            SequenceOption::MinValue {
504                minvalue_span,
505                value_span,
506                ..
507            } => minvalue_span.join_span(value_span),
508            SequenceOption::NoMinValue(s) => s.span(),
509            SequenceOption::MaxValue {
510                maxvalue_span,
511                value_span,
512                ..
513            } => maxvalue_span.join_span(value_span),
514            SequenceOption::NoMaxValue(s) => s.span(),
515            SequenceOption::StartWith {
516                start_span,
517                value_span,
518                ..
519            } => start_span.join_span(value_span),
520            SequenceOption::Restart {
521                restart_span,
522                value_span,
523                ..
524            } => restart_span.join_span(value_span),
525            SequenceOption::Cache {
526                cache_span,
527                value_span,
528                ..
529            } => cache_span.join_span(value_span),
530            SequenceOption::Cycle(s) => s.span(),
531            SequenceOption::NoCycle(s) => s.span(),
532            SequenceOption::OwnedBy {
533                owned_span,
534                table_column,
535                ..
536            } => owned_span.join_span(table_column),
537            SequenceOption::OwnedByNone {
538                owned_span,
539                none_span,
540                ..
541            } => owned_span.join_span(none_span),
542        }
543    }
544}
545
546/// Parse sequence options (used by CREATE SEQUENCE and ALTER TABLE ADD GENERATED AS IDENTITY)
547pub(crate) fn parse_sequence_options<'a>(
548    parser: &mut Parser<'a, '_>,
549) -> Result<Vec<SequenceOption<'a>>, ParseError> {
550    let mut options = Vec::new();
551    loop {
552        match &parser.token {
553            Token::Ident(_, Keyword::AS) => {
554                let as_span = parser.consume_keyword(Keyword::AS)?;
555                let data_type = parse_data_type(parser, DataTypeContext::TypeRef)?;
556                options.push(SequenceOption::As { as_span, data_type });
557            }
558            Token::Ident(_, Keyword::INCREMENT) => {
559                let increment_span = parser.consume_keyword(Keyword::INCREMENT)?;
560                let by_span = parser.skip_keyword(Keyword::BY); // BY is optional
561                let (value, value_span) = parser.consume_signed_int::<i64>()?;
562                options.push(SequenceOption::IncrementBy {
563                    increment_span,
564                    by_span,
565                    value,
566                    value_span,
567                });
568            }
569            Token::Ident(_, Keyword::MINVALUE) => {
570                let minvalue_span = parser.consume_keyword(Keyword::MINVALUE)?;
571                let (value, value_span) = parser.consume_signed_int::<i64>()?;
572                options.push(SequenceOption::MinValue {
573                    minvalue_span,
574                    value,
575                    value_span,
576                });
577            }
578            Token::Ident(_, Keyword::MAXVALUE) => {
579                let maxvalue_span = parser.consume_keyword(Keyword::MAXVALUE)?;
580                let (value, value_span) = parser.consume_signed_int::<i64>()?;
581                options.push(SequenceOption::MaxValue {
582                    maxvalue_span,
583                    value,
584                    value_span,
585                });
586            }
587            Token::Ident(_, Keyword::START) => {
588                let start_span = parser.consume_keyword(Keyword::START)?;
589                let with_span = parser.skip_keyword(Keyword::WITH); // WITH is optional
590                let (value, value_span) = parser.consume_signed_int::<i64>()?;
591                options.push(SequenceOption::StartWith {
592                    start_span,
593                    with_span,
594                    value,
595                    value_span,
596                });
597            }
598            Token::Ident(_, Keyword::RESTART) => {
599                let restart_span = parser.consume_keyword(Keyword::RESTART)?;
600                let with_span = parser.skip_keyword(Keyword::WITH); // WITH is optional
601                // The value is only optional for bare RESTART, which resets to the
602                // sequence's start value. RESTART WITH requires a value.
603                let has_value = match &parser.token {
604                    Token::Integer(_) | Token::Minus | Token::Plus => true,
605                    _ => with_span.is_some(),
606                };
607                if has_value {
608                    // Errors via consume_signed_int if RESTART WITH is not followed by a value
609                    let (value, value_span) = parser.consume_signed_int::<i64>()?;
610                    options.push(SequenceOption::Restart {
611                        restart_span,
612                        with_span,
613                        value: Some(value),
614                        value_span: Some(value_span),
615                    });
616                } else {
617                    options.push(SequenceOption::Restart {
618                        restart_span,
619                        with_span,
620                        value: None,
621                        value_span: None,
622                    });
623                }
624            }
625            Token::Ident(_, Keyword::CACHE) => {
626                let cache_span = parser.consume_keyword(Keyword::CACHE)?;
627                let (value, value_span) = parser.consume_signed_int::<i64>()?;
628                options.push(SequenceOption::Cache {
629                    cache_span,
630                    value,
631                    value_span,
632                });
633            }
634            Token::Ident(_, Keyword::CYCLE) => {
635                let cycle_span = parser.consume_keyword(Keyword::CYCLE)?;
636                options.push(SequenceOption::Cycle(cycle_span));
637            }
638            Token::Ident(_, Keyword::NO) => {
639                // Could be NO MINVALUE, NO MAXVALUE, or NO CYCLE
640                let no_span = parser.consume_keyword(Keyword::NO)?;
641                match &parser.token {
642                    Token::Ident(_, Keyword::MINVALUE) => {
643                        let minvalue_span = parser.consume_keyword(Keyword::MINVALUE)?;
644                        let span = no_span.join_span(&minvalue_span);
645                        options.push(SequenceOption::NoMinValue(span));
646                    }
647                    Token::Ident(_, Keyword::MAXVALUE) => {
648                        let maxvalue_span = parser.consume_keyword(Keyword::MAXVALUE)?;
649                        let span = no_span.join_span(&maxvalue_span);
650                        options.push(SequenceOption::NoMaxValue(span));
651                    }
652                    Token::Ident(_, Keyword::CYCLE) => {
653                        let cycle_span = parser.consume_keyword(Keyword::CYCLE)?;
654                        let span = no_span.join_span(&cycle_span);
655                        options.push(SequenceOption::NoCycle(span));
656                    }
657                    _ => parser.expected_failure("'MINVALUE', 'MAXVALUE' or 'CYCLE' after 'NO'")?,
658                }
659            }
660            Token::Ident(_, Keyword::OWNED) => {
661                let owned_span = parser.consume_keyword(Keyword::OWNED)?;
662                let by_span = parser.consume_keyword(Keyword::BY)?;
663                if let Token::Ident(_, Keyword::NONE) = parser.token {
664                    let none_span = parser.consume_keyword(Keyword::NONE)?;
665                    options.push(SequenceOption::OwnedByNone {
666                        owned_span,
667                        by_span,
668                        none_span,
669                    });
670                } else {
671                    let table_column = parse_qualified_name_unreserved(parser)?;
672                    options.push(SequenceOption::OwnedBy {
673                        owned_span,
674                        by_span,
675                        table_column,
676                    });
677                }
678            }
679            _ => break,
680        }
681    }
682    Ok(options)
683}
684
685/// CREATE SEQUENCE statement (PostgreSQL)
686#[derive(Clone, Debug)]
687pub struct CreateSequence<'a> {
688    /// Span of "CREATE"
689    pub create_span: Span,
690    /// Span of optional TEMPORARY/TEMP keyword
691    pub temporary: Option<Span>,
692    /// Span of "SEQUENCE"
693    pub sequence_span: Span,
694    /// Span of "IF NOT EXISTS" if specified
695    pub if_not_exists: Option<Span>,
696    /// Name of the created sequence
697    pub name: QualifiedName<'a>,
698    /// Sequence options
699    pub options: Vec<SequenceOption<'a>>,
700}
701
702impl Spanned for CreateSequence<'_> {
703    fn span(&self) -> Span {
704        self.create_span
705            .join_span(&self.temporary)
706            .join_span(&self.sequence_span)
707            .join_span(&self.if_not_exists)
708            .join_span(&self.name)
709            .join_span(&self.options)
710    }
711}
712
713fn parse_create_database<'a>(
714    parser: &mut Parser<'a, '_>,
715    create_span: Span,
716    create_options: Vec<CreateOption<'a>>,
717) -> Result<CreateDatabase<'a>, ParseError> {
718    for option in create_options {
719        parser.err("Not supported fo CREATE DATABASE", &option.span());
720    }
721
722    let database_span = parser.consume();
723
724    let if_not_exists = if let Some(if_) = parser.skip_keyword(Keyword::IF) {
725        Some(
726            parser
727                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
728                .join_span(&if_),
729        )
730    } else {
731        None
732    };
733
734    let mut create_options = Vec::new();
735    let name = parser.consume_plain_identifier_unreserved()?;
736    loop {
737        let default_span = parser.skip_keyword(Keyword::DEFAULT);
738        match &parser.token {
739            Token::Ident(_, Keyword::CHARSET) => {
740                let identifier = parser.consume_keyword(Keyword::CHARSET)?;
741                parser.skip_token(Token::Eq);
742                create_options.push(CreateDatabaseOption::CharSet {
743                    default_span,
744                    identifier,
745                    value: parser.consume_plain_identifier_unreserved()?,
746                });
747            }
748            Token::Ident(_, Keyword::CHARACTER) => {
749                let identifier = parser.consume_keywords(&[Keyword::CHARACTER, Keyword::SET])?;
750                parser.skip_token(Token::Eq);
751                create_options.push(CreateDatabaseOption::CharSet {
752                    default_span,
753                    identifier,
754                    value: parser.consume_plain_identifier_unreserved()?,
755                });
756            }
757            Token::Ident(_, Keyword::COLLATE) => {
758                let identifier = parser.consume_keyword(Keyword::COLLATE)?;
759                parser.skip_token(Token::Eq);
760                create_options.push(CreateDatabaseOption::Collate {
761                    default_span,
762                    identifier,
763                    value: parser.consume_plain_identifier_unreserved()?,
764                });
765            }
766            Token::Ident(_, Keyword::ENCRYPTION) => {
767                let identifier = parser.consume_keyword(Keyword::ENCRYPTION)?;
768                parser.skip_token(Token::Eq);
769                let value = parser.consume_string()?;
770
771                create_options.push(CreateDatabaseOption::Encryption {
772                    default_span,
773                    identifier,
774                    value,
775                });
776            }
777            _ => {
778                if default_span.is_some() {
779                    parser.expected_failure("'CHARSET', 'COLLATE' or 'ENCRYPTION'")?;
780                }
781                break;
782            }
783        }
784    }
785
786    Ok(CreateDatabase {
787        create_span,
788        create_options,
789        database_span,
790        if_not_exists,
791        name,
792    })
793}
794
795fn parse_create_schema<'a>(
796    parser: &mut Parser<'a, '_>,
797    create_span: Span,
798    create_options: Vec<CreateOption<'a>>,
799) -> Result<CreateSchema<'a>, ParseError> {
800    let schema_span = parser.consume_keyword(Keyword::SCHEMA)?;
801    parser.postgres_only(&schema_span);
802
803    for option in create_options {
804        parser.err("Not supported for CREATE SCHEMA", &option.span());
805    }
806
807    let if_not_exists = if let Some(if_span) = parser.skip_keyword(Keyword::IF) {
808        Some(
809            parser
810                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
811                .join_span(&if_span),
812        )
813    } else {
814        None
815    };
816
817    // Parse schema name or AUTHORIZATION
818    let name = if matches!(parser.token, Token::Ident(_, Keyword::AUTHORIZATION)) {
819        None
820    } else {
821        Some(parser.consume_plain_identifier_unreserved()?)
822    };
823
824    let authorization = if let Token::Ident(_, Keyword::AUTHORIZATION) = parser.token {
825        let auth_span = parser.consume_keyword(Keyword::AUTHORIZATION)?;
826        let role_name = parser.consume_plain_identifier_unreserved()?;
827        Some((auth_span, role_name))
828    } else {
829        None
830    };
831
832    // TODO: Parse schema elements (CREATE TABLE, CREATE VIEW, GRANT, etc.)
833
834    Ok(CreateSchema {
835        create_span,
836        schema_span,
837        if_not_exists,
838        name,
839        authorization,
840    })
841}
842
843fn parse_create_sequence<'a>(
844    parser: &mut Parser<'a, '_>,
845    create_span: Span,
846    create_options: Vec<CreateOption<'a>>,
847) -> Result<CreateSequence<'a>, ParseError> {
848    let sequence_span = parser.consume_keyword(Keyword::SEQUENCE)?;
849    parser.postgres_only(&sequence_span);
850
851    // Extract TEMPORARY option if present, reject others
852    let mut temporary = None;
853    for option in create_options {
854        match option {
855            CreateOption::Temporary {
856                local_span,
857                temporary_span,
858            } => {
859                temporary = Some(temporary_span.join_span(&local_span));
860            }
861            _ => {
862                parser.err("Not supported for CREATE SEQUENCE", &option.span());
863            }
864        }
865    }
866
867    let if_not_exists = if let Some(if_span) = parser.skip_keyword(Keyword::IF) {
868        Some(
869            parser
870                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
871                .join_span(&if_span),
872        )
873    } else {
874        None
875    };
876
877    // Parse sequence name
878    let name = parse_qualified_name_unreserved(parser)?;
879
880    // Parse sequence options
881    let options = parse_sequence_options(parser)?;
882
883    Ok(CreateSequence {
884        create_span,
885        temporary,
886        sequence_span,
887        if_not_exists,
888        name,
889        options,
890    })
891}
892
893/// CREATE SERVER statement (PostgreSQL)
894#[derive(Clone, Debug)]
895pub struct CreateServer<'a> {
896    /// Span of "CREATE"
897    pub create_span: Span,
898    /// Span of "SERVER"
899    pub server_span: Span,
900    /// Span of "IF NOT EXISTS" if specified
901    pub if_not_exists: Option<Span>,
902    /// Name of the server
903    pub server_name: Identifier<'a>,
904    /// Optional TYPE 'server_type'
905    pub type_: Option<(Span, SString<'a>)>,
906    /// Optional VERSION 'server_version'
907    pub version: Option<(Span, SString<'a>)>,
908    /// FOREIGN DATA WRAPPER fdw_name
909    pub foreign_data_wrapper: (Span, Identifier<'a>),
910    /// OPTIONS (option 'value', ...)
911    pub options: Vec<(Identifier<'a>, SString<'a>)>,
912}
913
914impl Spanned for CreateServer<'_> {
915    fn span(&self) -> Span {
916        self.create_span
917            .join_span(&self.server_span)
918            .join_span(&self.if_not_exists)
919            .join_span(&self.server_name)
920            .join_span(&self.type_)
921            .join_span(&self.version)
922            .join_span(&self.foreign_data_wrapper)
923            .join_span(&self.options)
924    }
925}
926
927fn parse_create_server<'a>(
928    parser: &mut Parser<'a, '_>,
929    create_span: Span,
930    create_options: Vec<CreateOption<'a>>,
931) -> Result<CreateServer<'a>, ParseError> {
932    let server_span = parser.consume_keyword(Keyword::SERVER)?;
933    parser.postgres_only(&server_span);
934
935    for option in create_options {
936        parser.err("Not supported for CREATE SERVER", &option.span());
937    }
938
939    let if_not_exists = if let Some(if_span) = parser.skip_keyword(Keyword::IF) {
940        Some(
941            parser
942                .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
943                .join_span(&if_span),
944        )
945    } else {
946        None
947    };
948
949    // Parse server name
950    let server_name = parser.consume_plain_identifier_unreserved()?;
951
952    // Parse optional TYPE 'server_type'
953    let type_ = if let Some(type_span) = parser.skip_keyword(Keyword::TYPE) {
954        let type_value = parser.consume_string()?;
955        Some((type_span, type_value))
956    } else {
957        None
958    };
959
960    // Parse optional VERSION 'server_version'
961    let version = if let Some(version_span) = parser.skip_keyword(Keyword::VERSION) {
962        let version_value = parser.consume_string()?;
963        Some((version_span, version_value))
964    } else {
965        None
966    };
967
968    // Parse FOREIGN DATA WRAPPER fdw_name
969    let fdw_span = parser.consume_keywords(&[Keyword::FOREIGN, Keyword::DATA, Keyword::WRAPPER])?;
970    let fdw_name = parser.consume_plain_identifier_unreserved()?;
971    let foreign_data_wrapper = (fdw_span, fdw_name);
972
973    // Parse optional OPTIONS (option 'value', ...)
974    let mut options = Vec::new();
975    if parser.skip_keyword(Keyword::OPTIONS).is_some() {
976        parser.consume_token(Token::LParen)?;
977        loop {
978            let option_name = parser.consume_plain_identifier_unreserved()?;
979            let option_value = parser.consume_string()?;
980            options.push((option_name, option_value));
981
982            if parser.skip_token(Token::Comma).is_none() {
983                break;
984            }
985        }
986        parser.consume_token(Token::RParen)?;
987    }
988
989    Ok(CreateServer {
990        create_span,
991        server_span,
992        if_not_exists,
993        server_name,
994        type_,
995        version,
996        foreign_data_wrapper,
997        options,
998    })
999}
1000
1001pub(crate) fn parse_create<'a>(parser: &mut Parser<'a, '_>) -> Result<Statement<'a>, ParseError> {
1002    let create_span = parser.span.clone();
1003    parser.consume_keyword(Keyword::CREATE)?;
1004
1005    let mut create_options = Vec::new();
1006    const CREATABLE: &str = "'TABLE' | 'VIEW' | 'TRIGGER' | 'FUNCTION' | 'PROCEDURE' | 'INDEX' | 'TYPE' | 'DATABASE' | 'DOMAIN' |'EXTENSION' | 'SCHEMA' | 'SEQUENCE' | 'ROLE' | 'SERVER' | 'OPERATOR' | 'CONSTRAINT'";
1007
1008    parser.recovered(
1009        CREATABLE,
1010        &|t| {
1011            matches!(
1012                t,
1013                Token::Ident(
1014                    _,
1015                    Keyword::TABLE
1016                        | Keyword::MATERIALIZED
1017                        | Keyword::VIEW
1018                        | Keyword::TRIGGER
1019                        | Keyword::FUNCTION
1020                        | Keyword::PROCEDURE
1021                        | Keyword::INDEX
1022                        | Keyword::TYPE
1023                        | Keyword::DATABASE
1024                        | Keyword::SCHEMA
1025                        | Keyword::SEQUENCE
1026                        | Keyword::ROLE
1027                        | Keyword::SERVER
1028                        | Keyword::OPERATOR
1029                        | Keyword::EXTENSION
1030                        | Keyword::DOMAIN
1031                        | Keyword::CONSTRAINT
1032                )
1033            )
1034        },
1035        |parser| {
1036            loop {
1037                let v = match &parser.token {
1038                    Token::Ident(_, Keyword::OR) => CreateOption::OrReplace(
1039                        parser.consume_keywords(&[Keyword::OR, Keyword::REPLACE])?,
1040                    ),
1041                    Token::Ident(_, Keyword::LOCAL) => {
1042                        // LOCAL TEMPORARY
1043                        let local_span = parser.consume_keyword(Keyword::LOCAL)?;
1044                        parser.postgres_only(&local_span);
1045                        let temporary_span = parser.consume_keyword(Keyword::TEMPORARY)?;
1046                        CreateOption::Temporary {
1047                            local_span: Some(local_span),
1048                            temporary_span,
1049                        }
1050                    }
1051                    Token::Ident(_, Keyword::TEMPORARY) => {
1052                        let temporary_span = parser.consume_keyword(Keyword::TEMPORARY)?;
1053                        CreateOption::Temporary {
1054                            local_span: None,
1055                            temporary_span,
1056                        }
1057                    }
1058                    Token::Ident(_, Keyword::UNIQUE) => {
1059                        CreateOption::Unique(parser.consume_keyword(Keyword::UNIQUE)?)
1060                    }
1061                    Token::Ident(_, Keyword::ALGORITHM) => {
1062                        let algorithm_span = parser.consume_keyword(Keyword::ALGORITHM)?;
1063                        parser.consume_token(Token::Eq)?;
1064                        let algorithm = match &parser.token {
1065                            Token::Ident(_, Keyword::UNDEFINED) => CreateAlgorithm::Undefined(
1066                                parser.consume_keyword(Keyword::UNDEFINED)?,
1067                            ),
1068                            Token::Ident(_, Keyword::MERGE) => {
1069                                CreateAlgorithm::Merge(parser.consume_keyword(Keyword::MERGE)?)
1070                            }
1071                            Token::Ident(_, Keyword::TEMPTABLE) => CreateAlgorithm::TempTable(
1072                                parser.consume_keyword(Keyword::TEMPTABLE)?,
1073                            ),
1074                            _ => parser.expected_failure("'UNDEFINED', 'MERGE' or 'TEMPTABLE'")?,
1075                        };
1076                        CreateOption::Algorithm(algorithm_span, algorithm)
1077                    }
1078                    Token::Ident(_, Keyword::DEFINER) => {
1079                        let definer_span = parser.consume_keyword(Keyword::DEFINER)?;
1080                        parser.consume_token(Token::Eq)?;
1081                        // TODO user | CURRENT_USER | role | CURRENT_ROLE
1082                        // Accept both plain identifiers and string literals
1083                        let user = match &parser.token {
1084                            Token::String(v, _) => {
1085                                let v = *v;
1086                                Identifier::new(v, parser.consume())
1087                            }
1088                            _ => parser.consume_plain_identifier_unreserved()?,
1089                        };
1090                        parser.consume_token(Token::At)?;
1091                        let host = match &parser.token {
1092                            Token::String(v, _) => {
1093                                let v = *v;
1094                                Identifier::new(v, parser.consume())
1095                            }
1096                            _ => parser.consume_plain_identifier_unreserved()?,
1097                        };
1098                        CreateOption::Definer {
1099                            definer_span,
1100                            user,
1101                            host,
1102                        }
1103                    }
1104                    Token::Ident(_, Keyword::SQL) => {
1105                        let sql_security =
1106                            parser.consume_keywords(&[Keyword::SQL, Keyword::SECURITY])?;
1107                        match &parser.token {
1108                            Token::Ident(_, Keyword::DEFINER) => CreateOption::SqlSecurityDefiner(
1109                                sql_security,
1110                                parser.consume_keyword(Keyword::DEFINER)?,
1111                            ),
1112                            Token::Ident(_, Keyword::INVOKER) => CreateOption::SqlSecurityInvoker(
1113                                sql_security,
1114                                parser.consume_keyword(Keyword::INVOKER)?,
1115                            ),
1116                            Token::Ident(_, Keyword::USER) => CreateOption::SqlSecurityUser(
1117                                sql_security,
1118                                parser.consume_keyword(Keyword::USER)?,
1119                            ),
1120                            _ => parser.expected_failure("'DEFINER', 'INVOKER', 'USER'")?,
1121                        }
1122                    }
1123                    _ => break,
1124                };
1125                create_options.push(v);
1126            }
1127            Ok(())
1128        },
1129    )?;
1130
1131    let r =
1132        match &parser.token {
1133            Token::Ident(_, Keyword::INDEX) => Statement::CreateIndex(Box::new(
1134                parse_create_index(parser, create_span, create_options)?,
1135            )),
1136            Token::Ident(_, Keyword::TABLE) => {
1137                parse_create_table_or_partition_of(parser, create_span, create_options)?
1138            }
1139            Token::Ident(_, Keyword::MATERIALIZED) => {
1140                // MATERIALIZED VIEW
1141                let materialized_span = parser.consume_keyword(Keyword::MATERIALIZED)?;
1142                parser.postgres_only(&materialized_span);
1143                // Don't consume VIEW here, parse_create_view will do it
1144                create_options.push(CreateOption::Materialized(materialized_span));
1145                Statement::CreateView(Box::new(parse_create_view(
1146                    parser,
1147                    create_span,
1148                    create_options,
1149                )?))
1150            }
1151            Token::Ident(_, Keyword::VIEW) => Statement::CreateView(Box::new(parse_create_view(
1152                parser,
1153                create_span,
1154                create_options,
1155            )?)),
1156            Token::Ident(_, Keyword::CONSTRAINT) => Statement::CreateConstraintTrigger(Box::new(
1157                parse_create_constraint_trigger(parser, create_span, create_options)?,
1158            )),
1159            Token::Ident(_, Keyword::DATABASE) => Statement::CreateDatabase(Box::new(
1160                parse_create_database(parser, create_span, create_options)?,
1161            )),
1162            Token::Ident(_, Keyword::DOMAIN) => Statement::CreateDomain(Box::new(
1163                parse_create_domain(parser, create_span, create_options)?,
1164            )),
1165            Token::Ident(_, Keyword::EXTENSION) => Statement::CreateExtension(Box::new(
1166                parse_create_extension(parser, create_span, create_options)?,
1167            )),
1168            Token::Ident(_, Keyword::SCHEMA) => Statement::CreateSchema(Box::new(
1169                parse_create_schema(parser, create_span, create_options)?,
1170            )),
1171            Token::Ident(_, Keyword::SEQUENCE) => Statement::CreateSequence(Box::new(
1172                parse_create_sequence(parser, create_span, create_options)?,
1173            )),
1174            Token::Ident(_, Keyword::FUNCTION) => Statement::CreateFunction(Box::new(
1175                parse_create_function(parser, create_span, create_options)?,
1176            )),
1177            Token::Ident(_, Keyword::PROCEDURE) => Statement::CreateProcedure(Box::new(
1178                parse_create_procedure(parser, create_span, create_options)?,
1179            )),
1180            Token::Ident(_, Keyword::TRIGGER) => Statement::CreateTrigger(Box::new(
1181                parse_create_trigger(parser, create_span, create_options)?,
1182            )),
1183            Token::Ident(_, Keyword::TYPE) => Statement::CreateTypeEnum(Box::new(
1184                parse_create_type(parser, create_span, create_options)?,
1185            )),
1186            Token::Ident(_, Keyword::ROLE) => Statement::CreateRole(Box::new(parse_create_role(
1187                parser,
1188                create_span,
1189                create_options,
1190            )?)),
1191            Token::Ident(_, Keyword::SERVER) => Statement::CreateServer(Box::new(
1192                parse_create_server(parser, create_span, create_options)?,
1193            )),
1194            Token::Ident(_, Keyword::OPERATOR) => {
1195                let operator_span = parser.consume_keyword(Keyword::OPERATOR)?;
1196                match parser.token {
1197                    Token::Ident(_, Keyword::FAMILY) => {
1198                        // CREATE OPERATOR FAMILY
1199                        let family_span = parser.consume_keyword(Keyword::FAMILY)?;
1200                        parser.postgres_only(&family_span);
1201                        Statement::CreateOperatorFamily(Box::new(parse_create_operator_family(
1202                            parser,
1203                            create_span
1204                                .join_span(&operator_span)
1205                                .join_span(&family_span),
1206                            create_options,
1207                        )?))
1208                    }
1209                    Token::Ident(_, Keyword::CLASS) => {
1210                        // CREATE OPERATOR CLASS
1211                        let class_span = parser.consume_keyword(Keyword::CLASS)?;
1212                        Statement::CreateOperatorClass(Box::new(parse_create_operator_class(
1213                            parser,
1214                            create_span.join_span(&operator_span).join_span(&class_span),
1215                            create_options,
1216                        )?))
1217                    }
1218                    _ => {
1219                        // CREATE OPERATOR
1220                        Statement::CreateOperator(Box::new(parse_create_operator(
1221                            parser,
1222                            create_span.join_span(&operator_span),
1223                            create_options,
1224                        )?))
1225                    }
1226                }
1227            }
1228            _ => return parser.expected_failure(CREATABLE),
1229        };
1230    Ok(r)
1231}