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