risingwave_sqlparser/ast/
ddl.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13//! AST types specific to CREATE/ALTER variants of [`crate::ast::Statement`]
14//! (commonly referred to as Data Definition Language, or DDL)
15
16#[cfg(not(feature = "std"))]
17use alloc::{boxed::Box, string::ToString, vec::Vec};
18use core::fmt;
19
20#[cfg(feature = "serde")]
21use serde::{Deserialize, Serialize};
22
23use super::FormatEncodeOptions;
24use crate::ast::{
25    DataType, Expr, Ident, ObjectName, SecretRefValue, SetVariableValue, Value,
26    display_comma_separated, display_separated,
27};
28use crate::tokenizer::Token;
29
30#[derive(Debug, Clone, PartialEq, Eq, Hash)]
31#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32pub enum AlterDatabaseOperation {
33    ChangeOwner { new_owner_name: Ident },
34    RenameDatabase { database_name: ObjectName },
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Hash)]
38#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
39pub enum AlterSchemaOperation {
40    ChangeOwner { new_owner_name: Ident },
41    RenameSchema { schema_name: ObjectName },
42    SwapRenameSchema { target_schema: ObjectName },
43}
44
45/// An `ALTER TABLE` (`Statement::AlterTable`) operation
46#[derive(Debug, Clone, PartialEq, Eq, Hash)]
47#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48pub enum AlterTableOperation {
49    /// `ADD <table_constraint>`
50    AddConstraint(TableConstraint),
51    /// `ADD [ COLUMN ] <column_def>`
52    AddColumn {
53        column_def: ColumnDef,
54    },
55    /// TODO: implement `DROP CONSTRAINT <name>`
56    DropConstraint {
57        name: Ident,
58    },
59    /// `DROP [ COLUMN ] [ IF EXISTS ] <column_name> [ CASCADE ]`
60    DropColumn {
61        column_name: Ident,
62        if_exists: bool,
63        cascade: bool,
64    },
65    /// `RENAME [ COLUMN ] <old_column_name> TO <new_column_name>`
66    RenameColumn {
67        old_column_name: Ident,
68        new_column_name: Ident,
69    },
70    /// `RENAME TO <table_name>`
71    RenameTable {
72        table_name: ObjectName,
73    },
74    // CHANGE [ COLUMN ] <old_name> <new_name> <data_type> [ <options> ]
75    ChangeColumn {
76        old_name: Ident,
77        new_name: Ident,
78        data_type: DataType,
79        options: Vec<ColumnOption>,
80    },
81    /// `RENAME CONSTRAINT <old_constraint_name> TO <new_constraint_name>`
82    ///
83    /// Note: this is a PostgreSQL-specific operation.
84    RenameConstraint {
85        old_name: Ident,
86        new_name: Ident,
87    },
88    /// `ALTER [ COLUMN ]`
89    AlterColumn {
90        column_name: Ident,
91        op: AlterColumnOperation,
92    },
93    /// `OWNER TO <owner_name>`
94    ChangeOwner {
95        new_owner_name: Ident,
96    },
97    /// `SET SCHEMA <schema_name>`
98    SetSchema {
99        new_schema_name: ObjectName,
100    },
101    /// `SET PARALLELISM TO <parallelism> [ DEFERRED ]`
102    SetParallelism {
103        parallelism: SetVariableValue,
104        deferred: bool,
105    },
106    RefreshSchema,
107    /// `SET SOURCE_RATE_LIMIT TO <rate_limit>`
108    SetSourceRateLimit {
109        rate_limit: i32,
110    },
111    /// SET BACKFILL_RATE_LIMIT TO <rate_limit>
112    SetBackfillRateLimit {
113        rate_limit: i32,
114    },
115    /// `SET DML_RATE_LIMIT TO <rate_limit>`
116    SetDmlRateLimit {
117        rate_limit: i32,
118    },
119    /// `SWAP WITH <table_name>`
120    SwapRenameTable {
121        target_table: ObjectName,
122    },
123    /// `DROP CONNECTOR`
124    DropConnector,
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, Hash)]
128#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
129pub enum AlterIndexOperation {
130    RenameIndex {
131        index_name: ObjectName,
132    },
133    /// `SET PARALLELISM TO <parallelism> [ DEFERRED ]`
134    SetParallelism {
135        parallelism: SetVariableValue,
136        deferred: bool,
137    },
138}
139
140#[derive(Debug, Clone, PartialEq, Eq, Hash)]
141#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
142pub enum AlterViewOperation {
143    RenameView {
144        view_name: ObjectName,
145    },
146    ChangeOwner {
147        new_owner_name: Ident,
148    },
149    SetSchema {
150        new_schema_name: ObjectName,
151    },
152    /// `SET PARALLELISM TO <parallelism> [ DEFERRED ]`
153    SetParallelism {
154        parallelism: SetVariableValue,
155        deferred: bool,
156    },
157    /// `SET RESOURCE_GROUP TO 'RESOURCE GROUP' [ DEFERRED ]`
158    /// `RESET RESOURCE_GROUP [ DEFERRED ]`
159    SetResourceGroup {
160        resource_group: Option<SetVariableValue>,
161        deferred: bool,
162    },
163    /// `SET BACKFILL_RATE_LIMIT TO <rate_limit>`
164    SetBackfillRateLimit {
165        rate_limit: i32,
166    },
167    /// `SWAP WITH <view_name>`
168    SwapRenameView {
169        target_view: ObjectName,
170    },
171}
172
173#[derive(Debug, Clone, PartialEq, Eq, Hash)]
174#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
175pub enum AlterSinkOperation {
176    RenameSink {
177        sink_name: ObjectName,
178    },
179    ChangeOwner {
180        new_owner_name: Ident,
181    },
182    SetSchema {
183        new_schema_name: ObjectName,
184    },
185    /// `SET PARALLELISM TO <parallelism> [ DEFERRED ]`
186    SetParallelism {
187        parallelism: SetVariableValue,
188        deferred: bool,
189    },
190    /// `SWAP WITH <sink_name>`
191    SwapRenameSink {
192        target_sink: ObjectName,
193    },
194    SetSinkRateLimit {
195        rate_limit: i32,
196    },
197}
198
199#[derive(Debug, Clone, PartialEq, Eq, Hash)]
200#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
201pub enum AlterSubscriptionOperation {
202    RenameSubscription { subscription_name: ObjectName },
203    ChangeOwner { new_owner_name: Ident },
204    SetSchema { new_schema_name: ObjectName },
205    SwapRenameSubscription { target_subscription: ObjectName },
206}
207
208#[derive(Debug, Clone, PartialEq, Eq, Hash)]
209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
210pub enum AlterSourceOperation {
211    RenameSource {
212        source_name: ObjectName,
213    },
214    AddColumn {
215        column_def: ColumnDef,
216    },
217    ChangeOwner {
218        new_owner_name: Ident,
219    },
220    SetSchema {
221        new_schema_name: ObjectName,
222    },
223    FormatEncode {
224        format_encode: FormatEncodeOptions,
225    },
226    RefreshSchema,
227    SetSourceRateLimit {
228        rate_limit: i32,
229    },
230    SwapRenameSource {
231        target_source: ObjectName,
232    },
233    /// `SET PARALLELISM TO <parallelism> [ DEFERRED ]`
234    SetParallelism {
235        parallelism: SetVariableValue,
236        deferred: bool,
237    },
238}
239
240#[derive(Debug, Clone, PartialEq, Eq, Hash)]
241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
242pub enum AlterFunctionOperation {
243    SetSchema { new_schema_name: ObjectName },
244}
245
246#[derive(Debug, Clone, PartialEq, Eq, Hash)]
247#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
248pub enum AlterConnectionOperation {
249    SetSchema { new_schema_name: ObjectName },
250    ChangeOwner { new_owner_name: Ident },
251}
252
253#[derive(Debug, Clone, PartialEq, Eq, Hash)]
254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
255pub enum AlterSecretOperation {
256    ChangeCredential { new_credential: Value },
257}
258
259#[derive(Debug, Clone, PartialEq, Eq, Hash)]
260#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
261pub enum AlterFragmentOperation {
262    AlterBackfillRateLimit { rate_limit: i32 },
263}
264
265impl fmt::Display for AlterDatabaseOperation {
266    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267        match self {
268            AlterDatabaseOperation::ChangeOwner { new_owner_name } => {
269                write!(f, "OWNER TO {}", new_owner_name)
270            }
271            AlterDatabaseOperation::RenameDatabase { database_name } => {
272                write!(f, "RENAME TO {}", database_name)
273            }
274        }
275    }
276}
277
278impl fmt::Display for AlterSchemaOperation {
279    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280        match self {
281            AlterSchemaOperation::ChangeOwner { new_owner_name } => {
282                write!(f, "OWNER TO {}", new_owner_name)
283            }
284            AlterSchemaOperation::RenameSchema { schema_name } => {
285                write!(f, "RENAME TO {}", schema_name)
286            }
287            AlterSchemaOperation::SwapRenameSchema { target_schema } => {
288                write!(f, "SWAP WITH {}", target_schema)
289            }
290        }
291    }
292}
293
294impl fmt::Display for AlterTableOperation {
295    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296        match self {
297            AlterTableOperation::AddConstraint(c) => write!(f, "ADD {}", c),
298            AlterTableOperation::AddColumn { column_def } => {
299                write!(f, "ADD COLUMN {}", column_def)
300            }
301            AlterTableOperation::AlterColumn { column_name, op } => {
302                write!(f, "ALTER COLUMN {} {}", column_name, op)
303            }
304            AlterTableOperation::DropConstraint { name } => write!(f, "DROP CONSTRAINT {}", name),
305            AlterTableOperation::DropColumn {
306                column_name,
307                if_exists,
308                cascade,
309            } => write!(
310                f,
311                "DROP COLUMN {}{}{}",
312                if *if_exists { "IF EXISTS " } else { "" },
313                column_name,
314                if *cascade { " CASCADE" } else { "" }
315            ),
316            AlterTableOperation::RenameColumn {
317                old_column_name,
318                new_column_name,
319            } => write!(
320                f,
321                "RENAME COLUMN {} TO {}",
322                old_column_name, new_column_name
323            ),
324            AlterTableOperation::RenameTable { table_name } => {
325                write!(f, "RENAME TO {}", table_name)
326            }
327            AlterTableOperation::ChangeColumn {
328                old_name,
329                new_name,
330                data_type,
331                options,
332            } => {
333                write!(f, "CHANGE COLUMN {} {} {}", old_name, new_name, data_type)?;
334                if options.is_empty() {
335                    Ok(())
336                } else {
337                    write!(f, " {}", display_separated(options, " "))
338                }
339            }
340            AlterTableOperation::RenameConstraint { old_name, new_name } => {
341                write!(f, "RENAME CONSTRAINT {} TO {}", old_name, new_name)
342            }
343            AlterTableOperation::ChangeOwner { new_owner_name } => {
344                write!(f, "OWNER TO {}", new_owner_name)
345            }
346            AlterTableOperation::SetSchema { new_schema_name } => {
347                write!(f, "SET SCHEMA {}", new_schema_name)
348            }
349            AlterTableOperation::SetParallelism {
350                parallelism,
351                deferred,
352            } => {
353                write!(
354                    f,
355                    "SET PARALLELISM TO {}{}",
356                    parallelism,
357                    if *deferred { " DEFERRED" } else { "" }
358                )
359            }
360            AlterTableOperation::RefreshSchema => {
361                write!(f, "REFRESH SCHEMA")
362            }
363            AlterTableOperation::SetSourceRateLimit { rate_limit } => {
364                write!(f, "SET SOURCE_RATE_LIMIT TO {}", rate_limit)
365            }
366            AlterTableOperation::SetBackfillRateLimit { rate_limit } => {
367                write!(f, "SET BACKFILL_RATE_LIMIT TO {}", rate_limit)
368            }
369            AlterTableOperation::SetDmlRateLimit { rate_limit } => {
370                write!(f, "SET DML_RATE_LIMIT TO {}", rate_limit)
371            }
372            AlterTableOperation::SwapRenameTable { target_table } => {
373                write!(f, "SWAP WITH {}", target_table)
374            }
375            AlterTableOperation::DropConnector => {
376                write!(f, "DROP CONNECTOR")
377            }
378        }
379    }
380}
381
382impl fmt::Display for AlterIndexOperation {
383    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
384        match self {
385            AlterIndexOperation::RenameIndex { index_name } => {
386                write!(f, "RENAME TO {index_name}")
387            }
388            AlterIndexOperation::SetParallelism {
389                parallelism,
390                deferred,
391            } => {
392                write!(
393                    f,
394                    "SET PARALLELISM TO {}{}",
395                    parallelism,
396                    if *deferred { " DEFERRED" } else { "" }
397                )
398            }
399        }
400    }
401}
402
403impl fmt::Display for AlterViewOperation {
404    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405        match self {
406            AlterViewOperation::RenameView { view_name } => {
407                write!(f, "RENAME TO {view_name}")
408            }
409            AlterViewOperation::ChangeOwner { new_owner_name } => {
410                write!(f, "OWNER TO {}", new_owner_name)
411            }
412            AlterViewOperation::SetSchema { new_schema_name } => {
413                write!(f, "SET SCHEMA {}", new_schema_name)
414            }
415            AlterViewOperation::SetParallelism {
416                parallelism,
417                deferred,
418            } => {
419                write!(
420                    f,
421                    "SET PARALLELISM TO {}{}",
422                    parallelism,
423                    if *deferred { " DEFERRED" } else { "" }
424                )
425            }
426            AlterViewOperation::SetBackfillRateLimit { rate_limit } => {
427                write!(f, "SET BACKFILL_RATE_LIMIT TO {}", rate_limit)
428            }
429            AlterViewOperation::SwapRenameView { target_view } => {
430                write!(f, "SWAP WITH {}", target_view)
431            }
432            AlterViewOperation::SetResourceGroup {
433                resource_group,
434                deferred,
435            } => {
436                let deferred = if *deferred { " DEFERRED" } else { "" };
437
438                if let Some(resource_group) = resource_group {
439                    write!(f, "SET RESOURCE_GROUP TO {} {}", resource_group, deferred)
440                } else {
441                    write!(f, "RESET RESOURCE_GROUP {}", deferred)
442                }
443            }
444        }
445    }
446}
447
448impl fmt::Display for AlterSinkOperation {
449    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450        match self {
451            AlterSinkOperation::RenameSink { sink_name } => {
452                write!(f, "RENAME TO {sink_name}")
453            }
454            AlterSinkOperation::ChangeOwner { new_owner_name } => {
455                write!(f, "OWNER TO {}", new_owner_name)
456            }
457            AlterSinkOperation::SetSchema { new_schema_name } => {
458                write!(f, "SET SCHEMA {}", new_schema_name)
459            }
460            AlterSinkOperation::SetParallelism {
461                parallelism,
462                deferred,
463            } => {
464                write!(
465                    f,
466                    "SET PARALLELISM TO {}{}",
467                    parallelism,
468                    if *deferred { " DEFERRED" } else { "" }
469                )
470            }
471            AlterSinkOperation::SwapRenameSink { target_sink } => {
472                write!(f, "SWAP WITH {}", target_sink)
473            }
474            AlterSinkOperation::SetSinkRateLimit { rate_limit } => {
475                write!(f, "SET SINK_RATE_LIMIT TO {}", rate_limit)
476            }
477        }
478    }
479}
480
481impl fmt::Display for AlterSubscriptionOperation {
482    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
483        match self {
484            AlterSubscriptionOperation::RenameSubscription { subscription_name } => {
485                write!(f, "RENAME TO {subscription_name}")
486            }
487            AlterSubscriptionOperation::ChangeOwner { new_owner_name } => {
488                write!(f, "OWNER TO {}", new_owner_name)
489            }
490            AlterSubscriptionOperation::SetSchema { new_schema_name } => {
491                write!(f, "SET SCHEMA {}", new_schema_name)
492            }
493            AlterSubscriptionOperation::SwapRenameSubscription {
494                target_subscription,
495            } => {
496                write!(f, "SWAP WITH {}", target_subscription)
497            }
498        }
499    }
500}
501
502impl fmt::Display for AlterSourceOperation {
503    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
504        match self {
505            AlterSourceOperation::RenameSource { source_name } => {
506                write!(f, "RENAME TO {source_name}")
507            }
508            AlterSourceOperation::AddColumn { column_def } => {
509                write!(f, "ADD COLUMN {column_def}")
510            }
511            AlterSourceOperation::ChangeOwner { new_owner_name } => {
512                write!(f, "OWNER TO {}", new_owner_name)
513            }
514            AlterSourceOperation::SetSchema { new_schema_name } => {
515                write!(f, "SET SCHEMA {}", new_schema_name)
516            }
517            AlterSourceOperation::FormatEncode { format_encode } => {
518                write!(f, "{format_encode}")
519            }
520            AlterSourceOperation::RefreshSchema => {
521                write!(f, "REFRESH SCHEMA")
522            }
523            AlterSourceOperation::SetSourceRateLimit { rate_limit } => {
524                write!(f, "SET SOURCE_RATE_LIMIT TO {}", rate_limit)
525            }
526            AlterSourceOperation::SwapRenameSource { target_source } => {
527                write!(f, "SWAP WITH {}", target_source)
528            }
529            AlterSourceOperation::SetParallelism {
530                parallelism,
531                deferred,
532            } => {
533                write!(
534                    f,
535                    "SET PARALLELISM TO {}{}",
536                    parallelism,
537                    if *deferred { " DEFERRED" } else { "" }
538                )
539            }
540        }
541    }
542}
543
544impl fmt::Display for AlterFunctionOperation {
545    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546        match self {
547            AlterFunctionOperation::SetSchema { new_schema_name } => {
548                write!(f, "SET SCHEMA {new_schema_name}")
549            }
550        }
551    }
552}
553
554impl fmt::Display for AlterConnectionOperation {
555    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
556        match self {
557            AlterConnectionOperation::SetSchema { new_schema_name } => {
558                write!(f, "SET SCHEMA {new_schema_name}")
559            }
560            AlterConnectionOperation::ChangeOwner { new_owner_name } => {
561                write!(f, "OWNER TO {new_owner_name}")
562            }
563        }
564    }
565}
566
567impl fmt::Display for AlterSecretOperation {
568    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
569        match self {
570            AlterSecretOperation::ChangeCredential { new_credential } => {
571                write!(f, "AS {new_credential}")
572            }
573        }
574    }
575}
576
577/// An `ALTER COLUMN` (`Statement::AlterTable`) operation
578#[derive(Debug, Clone, PartialEq, Eq, Hash)]
579#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
580pub enum AlterColumnOperation {
581    /// `SET NOT NULL`
582    SetNotNull,
583    /// `DROP NOT NULL`
584    DropNotNull,
585    /// `SET DEFAULT <expr>`
586    SetDefault { value: Expr },
587    /// `DROP DEFAULT`
588    DropDefault,
589    /// `[SET DATA] TYPE <data_type> [USING <expr>]`
590    SetDataType {
591        data_type: DataType,
592        /// PostgreSQL specific
593        using: Option<Expr>,
594    },
595}
596
597impl fmt::Display for AlterColumnOperation {
598    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
599        match self {
600            AlterColumnOperation::SetNotNull => write!(f, "SET NOT NULL",),
601            AlterColumnOperation::DropNotNull => write!(f, "DROP NOT NULL",),
602            AlterColumnOperation::SetDefault { value } => {
603                write!(f, "SET DEFAULT {}", value)
604            }
605            AlterColumnOperation::DropDefault => {
606                write!(f, "DROP DEFAULT")
607            }
608            AlterColumnOperation::SetDataType { data_type, using } => {
609                if let Some(expr) = using {
610                    write!(f, "SET DATA TYPE {} USING {}", data_type, expr)
611                } else {
612                    write!(f, "SET DATA TYPE {}", data_type)
613                }
614            }
615        }
616    }
617}
618
619impl fmt::Display for AlterFragmentOperation {
620    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
621        match self {
622            AlterFragmentOperation::AlterBackfillRateLimit { rate_limit } => {
623                write!(f, "SET BACKFILL_RATE_LIMIT TO {}", rate_limit)
624            }
625        }
626    }
627}
628
629/// The watermark on source.
630/// `WATERMARK FOR <column> AS (<expr>)`
631#[derive(Debug, Clone, PartialEq, Eq, Hash)]
632#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
633pub struct SourceWatermark {
634    pub column: Ident,
635    pub expr: Expr,
636}
637
638impl fmt::Display for SourceWatermark {
639    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
640        write!(f, "WATERMARK FOR {} AS {}", self.column, self.expr,)
641    }
642}
643
644/// A table-level constraint, specified in a `CREATE TABLE` or an
645/// `ALTER TABLE ADD <constraint>` statement.
646#[derive(Debug, Clone, PartialEq, Eq, Hash)]
647#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
648pub enum TableConstraint {
649    /// `[ CONSTRAINT <name> ] { PRIMARY KEY | UNIQUE } (<columns>)`
650    Unique {
651        name: Option<Ident>,
652        columns: Vec<Ident>,
653        /// Whether this is a `PRIMARY KEY` or just a `UNIQUE` constraint
654        is_primary: bool,
655    },
656    /// A referential integrity constraint (`[ CONSTRAINT <name> ] FOREIGN KEY (<columns>)
657    /// REFERENCES <foreign_table> (<referred_columns>)
658    /// { [ON DELETE <referential_action>] [ON UPDATE <referential_action>] |
659    ///   [ON UPDATE <referential_action>] [ON DELETE <referential_action>]
660    /// }`).
661    ForeignKey {
662        name: Option<Ident>,
663        columns: Vec<Ident>,
664        foreign_table: ObjectName,
665        referred_columns: Vec<Ident>,
666        on_delete: Option<ReferentialAction>,
667        on_update: Option<ReferentialAction>,
668    },
669    /// `[ CONSTRAINT <name> ] CHECK (<expr>)`
670    Check {
671        name: Option<Ident>,
672        expr: Box<Expr>,
673    },
674}
675
676impl fmt::Display for TableConstraint {
677    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
678        match self {
679            TableConstraint::Unique {
680                name,
681                columns,
682                is_primary,
683            } => write!(
684                f,
685                "{}{} ({})",
686                display_constraint_name(name),
687                if *is_primary { "PRIMARY KEY" } else { "UNIQUE" },
688                display_comma_separated(columns)
689            ),
690            TableConstraint::ForeignKey {
691                name,
692                columns,
693                foreign_table,
694                referred_columns,
695                on_delete,
696                on_update,
697            } => {
698                write!(
699                    f,
700                    "{}FOREIGN KEY ({}) REFERENCES {}({})",
701                    display_constraint_name(name),
702                    display_comma_separated(columns),
703                    foreign_table,
704                    display_comma_separated(referred_columns),
705                )?;
706                if let Some(action) = on_delete {
707                    write!(f, " ON DELETE {}", action)?;
708                }
709                if let Some(action) = on_update {
710                    write!(f, " ON UPDATE {}", action)?;
711                }
712                Ok(())
713            }
714            TableConstraint::Check { name, expr } => {
715                write!(f, "{}CHECK ({})", display_constraint_name(name), expr)
716            }
717        }
718    }
719}
720
721/// SQL column definition
722#[derive(Debug, Clone, PartialEq, Eq, Hash)]
723#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
724pub struct ColumnDef {
725    pub name: Ident,
726    pub data_type: Option<DataType>,
727    pub collation: Option<ObjectName>,
728    pub options: Vec<ColumnOptionDef>,
729}
730
731impl ColumnDef {
732    pub fn new(
733        name: Ident,
734        data_type: DataType,
735        collation: Option<ObjectName>,
736        options: Vec<ColumnOptionDef>,
737    ) -> Self {
738        ColumnDef {
739            name,
740            data_type: Some(data_type),
741            collation,
742            options,
743        }
744    }
745
746    pub fn is_generated(&self) -> bool {
747        self.options
748            .iter()
749            .any(|option| matches!(option.option, ColumnOption::GeneratedColumns(_)))
750    }
751}
752
753impl fmt::Display for ColumnDef {
754    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
755        write!(
756            f,
757            "{} {}",
758            self.name,
759            if let Some(data_type) = &self.data_type {
760                data_type.to_string()
761            } else {
762                "None".to_owned()
763            }
764        )?;
765        for option in &self.options {
766            write!(f, " {}", option)?;
767        }
768        Ok(())
769    }
770}
771
772/// An optionally-named `ColumnOption`: `[ CONSTRAINT <name> ] <column-option>`.
773///
774/// Note that implementations are substantially more permissive than the ANSI
775/// specification on what order column options can be presented in, and whether
776/// they are allowed to be named. The specification distinguishes between
777/// constraints (NOT NULL, UNIQUE, PRIMARY KEY, and CHECK), which can be named
778/// and can appear in any order, and other options (DEFAULT, GENERATED), which
779/// cannot be named and must appear in a fixed order. PostgreSQL, however,
780/// allows preceding any option with `CONSTRAINT <name>`, even those that are
781/// not really constraints, like NULL and DEFAULT. MSSQL is less permissive,
782/// allowing DEFAULT, UNIQUE, PRIMARY KEY and CHECK to be named, but not NULL or
783/// NOT NULL constraints (the last of which is in violation of the spec).
784///
785/// For maximum flexibility, we don't distinguish between constraint and
786/// non-constraint options, lumping them all together under the umbrella of
787/// "column options," and we allow any column option to be named.
788#[derive(Debug, Clone, PartialEq, Eq, Hash)]
789#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
790pub struct ColumnOptionDef {
791    pub name: Option<Ident>,
792    pub option: ColumnOption,
793}
794
795impl fmt::Display for ColumnOptionDef {
796    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
797        write!(f, "{}{}", display_constraint_name(&self.name), self.option)
798    }
799}
800
801/// `ColumnOption`s are modifiers that follow a column definition in a `CREATE
802/// TABLE` statement.
803#[derive(Debug, Clone, PartialEq, Eq, Hash)]
804#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
805pub enum ColumnOption {
806    /// `NULL`
807    Null,
808    /// `NOT NULL`
809    NotNull,
810    /// `DEFAULT <restricted-expr>`
811    DefaultValue(Expr),
812    /// Default value from previous bound `DefaultColumnDesc`. Used internally
813    /// for schema change and should not be specified by users.
814    DefaultValueInternal {
815        /// Protobuf encoded `DefaultColumnDesc`.
816        persisted: Box<[u8]>,
817        /// Optional AST for unparsing. If `None`, the default value will be
818        /// shown as `DEFAULT INTERNAL` which is for demonstrating and should
819        /// not be specified by users.
820        expr: Option<Expr>,
821    },
822    /// `{ PRIMARY KEY | UNIQUE }`
823    Unique { is_primary: bool },
824    /// A referential integrity constraint (`[FOREIGN KEY REFERENCES
825    /// <foreign_table> (<referred_columns>)
826    /// { [ON DELETE <referential_action>] [ON UPDATE <referential_action>] |
827    ///   [ON UPDATE <referential_action>] [ON DELETE <referential_action>]
828    /// }`).
829    ForeignKey {
830        foreign_table: ObjectName,
831        referred_columns: Vec<Ident>,
832        on_delete: Option<ReferentialAction>,
833        on_update: Option<ReferentialAction>,
834    },
835    /// `CHECK (<expr>)`
836    Check(Expr),
837    /// Dialect-specific options, such as:
838    /// - MySQL's `AUTO_INCREMENT` or SQLite's `AUTOINCREMENT`
839    /// - ...
840    DialectSpecific(Vec<Token>),
841    /// AS ( <generation_expr> )`
842    GeneratedColumns(Expr),
843}
844
845impl fmt::Display for ColumnOption {
846    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
847        use ColumnOption::*;
848        match self {
849            Null => write!(f, "NULL"),
850            NotNull => write!(f, "NOT NULL"),
851            DefaultValue(expr) => write!(f, "DEFAULT {}", expr),
852            DefaultValueInternal { persisted: _, expr } => {
853                if let Some(expr) = expr {
854                    write!(f, "DEFAULT {}", expr)
855                } else {
856                    write!(f, "DEFAULT INTERNAL")
857                }
858            }
859            Unique { is_primary } => {
860                write!(f, "{}", if *is_primary { "PRIMARY KEY" } else { "UNIQUE" })
861            }
862            ForeignKey {
863                foreign_table,
864                referred_columns,
865                on_delete,
866                on_update,
867            } => {
868                write!(f, "REFERENCES {}", foreign_table)?;
869                if !referred_columns.is_empty() {
870                    write!(f, " ({})", display_comma_separated(referred_columns))?;
871                }
872                if let Some(action) = on_delete {
873                    write!(f, " ON DELETE {}", action)?;
874                }
875                if let Some(action) = on_update {
876                    write!(f, " ON UPDATE {}", action)?;
877                }
878                Ok(())
879            }
880            Check(expr) => write!(f, "CHECK ({})", expr),
881            DialectSpecific(val) => write!(f, "{}", display_separated(val, " ")),
882            GeneratedColumns(expr) => write!(f, "AS {}", expr),
883        }
884    }
885}
886
887fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
888    struct ConstraintName<'a>(&'a Option<Ident>);
889    impl fmt::Display for ConstraintName<'_> {
890        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
891            if let Some(name) = self.0 {
892                write!(f, "CONSTRAINT {} ", name)?;
893            }
894            Ok(())
895        }
896    }
897    ConstraintName(name)
898}
899
900/// `<referential_action> =
901/// { RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT }`
902///
903/// Used in foreign key constraints in `ON UPDATE` and `ON DELETE` options.
904#[derive(Debug, Clone, PartialEq, Eq, Hash)]
905#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
906pub enum ReferentialAction {
907    Restrict,
908    Cascade,
909    SetNull,
910    NoAction,
911    SetDefault,
912}
913
914impl fmt::Display for ReferentialAction {
915    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
916        f.write_str(match self {
917            ReferentialAction::Restrict => "RESTRICT",
918            ReferentialAction::Cascade => "CASCADE",
919            ReferentialAction::SetNull => "SET NULL",
920            ReferentialAction::NoAction => "NO ACTION",
921            ReferentialAction::SetDefault => "SET DEFAULT",
922        })
923    }
924}
925
926/// secure secret definition for webhook source
927#[derive(Debug, Clone, PartialEq, Eq, Hash)]
928#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
929pub struct WebhookSourceInfo {
930    pub secret_ref: Option<SecretRefValue>,
931    pub signature_expr: Expr,
932    pub wait_for_persistence: bool,
933}