Skip to main content

sqlparser/ast/
ddl.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! AST types specific to CREATE/ALTER variants of [`Statement`](crate::ast::Statement)
19//! (commonly referred to as Data Definition Language, or DDL)
20
21#[cfg(not(feature = "std"))]
22use alloc::{
23    boxed::Box,
24    format,
25    string::{String, ToString},
26    vec,
27    vec::Vec,
28};
29use core::fmt::{self, Display, Write};
30
31#[cfg(feature = "serde")]
32use serde::{Deserialize, Serialize};
33
34#[cfg(feature = "visitor")]
35use sqlparser_derive::{Visit, VisitMut};
36
37use crate::ast::value::escape_single_quote_string;
38use crate::ast::{
39    display_comma_separated, display_separated,
40    table_constraints::{
41        CheckConstraint, ForeignKeyConstraint, PrimaryKeyConstraint, TableConstraint,
42        UniqueConstraint,
43    },
44    ArgMode, AttachedToken, CommentDef, ConditionalStatements, CreateFunctionBody,
45    CreateFunctionUsing, CreateServerOption, CreateTableLikeKind, CreateTableOptions,
46    CreateViewParams, DataType, Expr,
47    FileFormat, FunctionBehavior, FunctionCalledOnNull, FunctionDefinitionSetParam, FunctionDesc,
48    FunctionDeterminismSpecifier, FunctionParallel, FunctionSecurity, HiveDistributionStyle,
49    HiveFormat, HiveIOFormat, HiveRowFormat, HiveSetLocation, Ident, InitializeKind,
50    MySQLColumnPosition, ObjectName, OnCommit, OneOrManyWithParens, OperateFunctionArg,
51    OrderByExpr, ProjectionSelect, Query, RefreshModeKind, ResetConfig, RowAccessPolicy,
52    SequenceOptions, Spanned, SqlOption, StorageLifecyclePolicy, StorageSerializationPolicy,
53    TableVersion, Tag, TriggerEvent, TriggerExecBody, TriggerObject, TriggerPeriod,
54    TriggerReferencing, Value, ValueWithSpan, WrappedCollection,
55};
56use crate::display_utils::{DisplayCommaSeparated, Indent, NewLine, SpaceOrNewline};
57use crate::keywords::Keyword;
58use crate::tokenizer::{Span, Token};
59
60/// Index column type.
61#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
62#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
63#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
64pub struct IndexColumn {
65    /// The indexed column expression.
66    pub column: OrderByExpr,
67    /// Optional operator class (index operator name).
68    pub operator_class: Option<ObjectName>,
69}
70
71impl From<Ident> for IndexColumn {
72    fn from(c: Ident) -> Self {
73        Self {
74            column: OrderByExpr::from(c),
75            operator_class: None,
76        }
77    }
78}
79
80impl<'a> From<&'a str> for IndexColumn {
81    fn from(c: &'a str) -> Self {
82        let ident = Ident::new(c);
83        ident.into()
84    }
85}
86
87impl fmt::Display for IndexColumn {
88    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89        write!(f, "{}", self.column)?;
90        if let Some(operator_class) = &self.operator_class {
91            write!(f, " {operator_class}")?;
92        }
93        Ok(())
94    }
95}
96
97/// ALTER TABLE operation REPLICA IDENTITY values
98/// See [Postgres ALTER TABLE docs](https://www.postgresql.org/docs/current/sql-altertable.html)
99#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
101#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
102pub enum ReplicaIdentity {
103    /// No replica identity (`REPLICA IDENTITY NOTHING`).
104    Nothing,
105    /// Full replica identity (`REPLICA IDENTITY FULL`).
106    Full,
107    /// Default replica identity (`REPLICA IDENTITY DEFAULT`).
108    Default,
109    /// Use the given index as replica identity (`REPLICA IDENTITY USING INDEX`).
110    Index(Ident),
111}
112
113impl fmt::Display for ReplicaIdentity {
114    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115        match self {
116            ReplicaIdentity::Nothing => f.write_str("NOTHING"),
117            ReplicaIdentity::Full => f.write_str("FULL"),
118            ReplicaIdentity::Default => f.write_str("DEFAULT"),
119            ReplicaIdentity::Index(idx) => write!(f, "USING INDEX {idx}"),
120        }
121    }
122}
123
124/// An `ALTER TABLE` (`Statement::AlterTable`) operation
125#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
126#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
127#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
128pub enum AlterTableOperation {
129    /// `ADD <table_constraint> [NOT VALID]`
130    AddConstraint {
131        /// The table constraint to add.
132        constraint: TableConstraint,
133        /// Whether the constraint should be marked `NOT VALID`.
134        not_valid: bool,
135    },
136    /// `ADD [COLUMN] [IF NOT EXISTS] <column_def>`
137    AddColumn {
138        /// `[COLUMN]`.
139        column_keyword: bool,
140        /// `[IF NOT EXISTS]`
141        if_not_exists: bool,
142        /// <column_def>.
143        column_def: ColumnDef,
144        /// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
145        column_position: Option<MySQLColumnPosition>,
146    },
147    /// `ADD PROJECTION [IF NOT EXISTS] name ( SELECT <COLUMN LIST EXPR> [GROUP BY] [ORDER BY])`
148    ///
149    /// Note: this is a ClickHouse-specific operation.
150    /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#add-projection)
151    AddProjection {
152        /// Whether `IF NOT EXISTS` was specified.
153        if_not_exists: bool,
154        /// Name of the projection to add.
155        name: Ident,
156        /// The projection's select clause.
157        select: ProjectionSelect,
158    },
159    /// `DROP PROJECTION [IF EXISTS] name`
160    ///
161    /// Note: this is a ClickHouse-specific operation.
162    /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#drop-projection)
163    DropProjection {
164        /// Whether `IF EXISTS` was specified.
165        if_exists: bool,
166        /// Name of the projection to drop.
167        name: Ident,
168    },
169    /// `MATERIALIZE PROJECTION [IF EXISTS] name [IN PARTITION partition_name]`
170    ///
171    ///  Note: this is a ClickHouse-specific operation.
172    /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#materialize-projection)
173    MaterializeProjection {
174        /// Whether `IF EXISTS` was specified.
175        if_exists: bool,
176        /// Name of the projection to materialize.
177        name: Ident,
178        /// Optional partition name to operate on.
179        partition: Option<Ident>,
180    },
181    /// `CLEAR PROJECTION [IF EXISTS] name [IN PARTITION partition_name]`
182    ///
183    /// Note: this is a ClickHouse-specific operation.
184    /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#clear-projection)
185    ClearProjection {
186        /// Whether `IF EXISTS` was specified.
187        if_exists: bool,
188        /// Name of the projection to clear.
189        name: Ident,
190        /// Optional partition name to operate on.
191        partition: Option<Ident>,
192    },
193    /// `DISABLE ROW LEVEL SECURITY`
194    ///
195    /// Note: this is a PostgreSQL-specific operation.
196    /// Please refer to [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-altertable.html)
197    DisableRowLevelSecurity,
198    /// `DISABLE RULE rewrite_rule_name`
199    ///
200    /// Note: this is a PostgreSQL-specific operation.
201    DisableRule {
202        /// Name of the rule to disable.
203        name: Ident,
204    },
205    /// `DISABLE TRIGGER [ trigger_name | ALL | USER ]`
206    ///
207    /// Note: this is a PostgreSQL-specific operation.
208    DisableTrigger {
209        /// Name of the trigger to disable (or ALL/USER).
210        name: Ident,
211    },
212    /// `DROP CONSTRAINT [ IF EXISTS ] <name>`
213    DropConstraint {
214        /// `IF EXISTS` flag for dropping the constraint.
215        if_exists: bool,
216        /// Name of the constraint to drop.
217        name: Ident,
218        /// Optional drop behavior (`CASCADE`/`RESTRICT`).
219        drop_behavior: Option<DropBehavior>,
220    },
221    /// `DROP [ COLUMN ] [ IF EXISTS ] <column_name> [ , <column_name>, ... ] [ CASCADE ]`
222    DropColumn {
223        /// Whether the `COLUMN` keyword was present.
224        has_column_keyword: bool,
225        /// Names of columns to drop.
226        column_names: Vec<Ident>,
227        /// Whether `IF EXISTS` was specified for the columns.
228        if_exists: bool,
229        /// Optional drop behavior for the column removal.
230        drop_behavior: Option<DropBehavior>,
231    },
232    /// `ATTACH PART|PARTITION <partition_expr>`
233    /// Note: this is a ClickHouse-specific operation, please refer to
234    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#attach-partitionpart)
235    AttachPartition {
236        // PART is not a short form of PARTITION, it's a separate keyword
237        // which represents a physical file on disk and partition is a logical entity.
238        /// Partition expression to attach.
239        partition: Partition,
240    },
241    /// `DETACH PART|PARTITION <partition_expr>`
242    /// Note: this is a ClickHouse-specific operation, please refer to
243    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#detach-partitionpart)
244    DetachPartition {
245        // See `AttachPartition` for more details
246        /// Partition expression to detach.
247        partition: Partition,
248    },
249    /// `FREEZE PARTITION <partition_expr>`
250    /// Note: this is a ClickHouse-specific operation, please refer to
251    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#freeze-partition)
252    FreezePartition {
253        /// Partition to freeze.
254        partition: Partition,
255        /// Optional name for the freeze operation.
256        with_name: Option<Ident>,
257    },
258    /// `UNFREEZE PARTITION <partition_expr>`
259    /// Note: this is a ClickHouse-specific operation, please refer to
260    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#unfreeze-partition)
261    UnfreezePartition {
262        /// Partition to unfreeze.
263        partition: Partition,
264        /// Optional name associated with the unfreeze operation.
265        with_name: Option<Ident>,
266    },
267    /// `DROP PRIMARY KEY`
268    ///
269    /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/alter-table.html)
270    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/constraints-drop)
271    DropPrimaryKey {
272        /// Optional drop behavior for the primary key (`CASCADE`/`RESTRICT`).
273        drop_behavior: Option<DropBehavior>,
274    },
275    /// `DROP FOREIGN KEY <fk_symbol>`
276    ///
277    /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/alter-table.html)
278    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/constraints-drop)
279    DropForeignKey {
280        /// Foreign key symbol/name to drop.
281        name: Ident,
282        /// Optional drop behavior for the foreign key.
283        drop_behavior: Option<DropBehavior>,
284    },
285    /// `DROP INDEX <index_name>`
286    ///
287    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
288    DropIndex {
289        /// Name of the index to drop.
290        name: Ident,
291    },
292    /// `ENABLE ALWAYS RULE rewrite_rule_name`
293    ///
294    /// Note: this is a PostgreSQL-specific operation.
295    EnableAlwaysRule {
296        /// Name of the rule to enable.
297        name: Ident,
298    },
299    /// `ENABLE ALWAYS TRIGGER trigger_name`
300    ///
301    /// Note: this is a PostgreSQL-specific operation.
302    EnableAlwaysTrigger {
303        /// Name of the trigger to enable.
304        name: Ident,
305    },
306    /// `ENABLE REPLICA RULE rewrite_rule_name`
307    ///
308    /// Note: this is a PostgreSQL-specific operation.
309    EnableReplicaRule {
310        /// Name of the replica rule to enable.
311        name: Ident,
312    },
313    /// `ENABLE REPLICA TRIGGER trigger_name`
314    ///
315    /// Note: this is a PostgreSQL-specific operation.
316    EnableReplicaTrigger {
317        /// Name of the replica trigger to enable.
318        name: Ident,
319    },
320    /// `ENABLE ROW LEVEL SECURITY`
321    ///
322    /// Note: this is a PostgreSQL-specific operation.
323    /// Please refer to [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-altertable.html)
324    EnableRowLevelSecurity,
325    /// `FORCE ROW LEVEL SECURITY`
326    ///
327    /// Note: this is a PostgreSQL-specific operation.
328    /// Please refer to [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-altertable.html)
329    ForceRowLevelSecurity,
330    /// `NO FORCE ROW LEVEL SECURITY`
331    ///
332    /// Note: this is a PostgreSQL-specific operation.
333    /// Please refer to [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-altertable.html)
334    NoForceRowLevelSecurity,
335    /// `ENABLE RULE rewrite_rule_name`
336    ///
337    /// Note: this is a PostgreSQL-specific operation.
338    EnableRule {
339        /// Name of the rule to enable.
340        name: Ident,
341    },
342    /// `ENABLE TRIGGER [ trigger_name | ALL | USER ]`
343    ///
344    /// Note: this is a PostgreSQL-specific operation.
345    EnableTrigger {
346        /// Name of the trigger to enable (or ALL/USER).
347        name: Ident,
348    },
349    /// `RENAME TO PARTITION (partition=val)`
350    RenamePartitions {
351        /// Old partition expressions to be renamed.
352        old_partitions: Vec<Expr>,
353        /// New partition expressions corresponding to the old ones.
354        new_partitions: Vec<Expr>,
355    },
356    /// REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING }
357    ///
358    /// Note: this is a PostgreSQL-specific operation.
359    /// Please refer to [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-altertable.html)
360    ReplicaIdentity {
361        /// Replica identity setting to apply.
362        identity: ReplicaIdentity,
363    },
364    /// Add Partitions
365    AddPartitions {
366        /// Whether `IF NOT EXISTS` was present when adding partitions.
367        if_not_exists: bool,
368        /// New partitions to add.
369        new_partitions: Vec<Partition>,
370    },
371    /// `DROP PARTITIONS ...` / drop partitions from the table.
372    DropPartitions {
373        /// Partitions to drop (expressions).
374        partitions: Vec<Expr>,
375        /// Whether `IF EXISTS` was specified for dropping partitions.
376        if_exists: bool,
377    },
378    /// `RENAME [ COLUMN ] <old_column_name> TO <new_column_name>`
379    RenameColumn {
380        /// Existing column name to rename.
381        old_column_name: Ident,
382        /// New column name.
383        new_column_name: Ident,
384    },
385    /// `RENAME TO <table_name>`
386    RenameTable {
387        /// The new table name or renaming kind.
388        table_name: RenameTableNameKind,
389    },
390    // CHANGE [ COLUMN ] <old_name> <new_name> <data_type> [ <options> ]
391    /// Change an existing column's name, type, and options.
392    ChangeColumn {
393        /// Old column name.
394        old_name: Ident,
395        /// New column name.
396        new_name: Ident,
397        /// New data type for the column.
398        data_type: DataType,
399        /// Column options to apply after the change.
400        options: Vec<ColumnOption>,
401        /// MySQL-specific column position (`FIRST`/`AFTER`).
402        column_position: Option<MySQLColumnPosition>,
403    },
404    // CHANGE [ COLUMN ] <col_name> <data_type> [ <options> ]
405    /// Modify an existing column's type and options.
406    ModifyColumn {
407        /// Column name to modify.
408        col_name: Ident,
409        /// New data type for the column.
410        data_type: DataType,
411        /// Column options to set.
412        options: Vec<ColumnOption>,
413        /// MySQL-specific column position (`FIRST`/`AFTER`).
414        column_position: Option<MySQLColumnPosition>,
415    },
416    /// `RENAME CONSTRAINT <old_constraint_name> TO <new_constraint_name>`
417    ///
418    /// Note: this is a PostgreSQL-specific operation.
419    /// Rename a constraint on the table.
420    RenameConstraint {
421        /// Existing constraint name.
422        old_name: Ident,
423        /// New constraint name.
424        new_name: Ident,
425    },
426    /// `ALTER [ COLUMN ]`
427    /// Alter a specific column with the provided operation.
428    AlterColumn {
429        /// The column to alter.
430        column_name: Ident,
431        /// Operation to apply to the column.
432        op: AlterColumnOperation,
433    },
434    /// 'SWAP WITH <table_name>'
435    ///
436    /// Note: this is Snowflake specific <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
437    SwapWith {
438        /// Table name to swap with.
439        table_name: ObjectName,
440    },
441    /// 'SET TBLPROPERTIES ( { property_key [ = ] property_val } [, ...] )'
442    SetTblProperties {
443        /// Table properties specified as SQL options.
444        table_properties: Vec<SqlOption>,
445    },
446    /// `OWNER TO { <new_owner> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }`
447    ///
448    /// Note: this is PostgreSQL-specific <https://www.postgresql.org/docs/current/sql-altertable.html>
449    OwnerTo {
450        /// The new owner to assign to the table.
451        new_owner: Owner,
452    },
453    /// Snowflake table clustering options
454    /// <https://docs.snowflake.com/en/sql-reference/sql/alter-table#clustering-actions-clusteringaction>
455    ClusterBy {
456        /// Expressions used for clustering the table.
457        exprs: Vec<Expr>,
458    },
459    /// Remove the clustering key from the table.
460    DropClusteringKey,
461    /// Redshift `ALTER SORTKEY (column_list)`
462    /// <https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_TABLE.html>
463    AlterSortKey {
464        /// Column references in the sort key.
465        columns: Vec<Expr>,
466    },
467    /// Suspend background reclustering operations.
468    SuspendRecluster,
469    /// Resume background reclustering operations.
470    ResumeRecluster,
471    /// `REFRESH [ '<subpath>' ]`
472    ///
473    /// Note: this is Snowflake specific for dynamic/external tables
474    /// <https://docs.snowflake.com/en/sql-reference/sql/alter-dynamic-table>
475    /// <https://docs.snowflake.com/en/sql-reference/sql/alter-external-table>
476    Refresh {
477        /// Optional subpath for external table refresh
478        subpath: Option<String>,
479    },
480    /// `SUSPEND`
481    ///
482    /// Note: this is Snowflake specific for dynamic tables <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
483    Suspend,
484    /// `RESUME`
485    ///
486    /// Note: this is Snowflake specific for dynamic tables <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
487    Resume,
488    /// `ALGORITHM [=] { DEFAULT | INSTANT | INPLACE | COPY }`
489    ///
490    /// [MySQL]-specific table alter algorithm.
491    ///
492    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
493    Algorithm {
494        /// Whether the `=` sign was used (`ALGORITHM = ...`).
495        equals: bool,
496        /// The algorithm to use for the alter operation (MySQL-specific).
497        algorithm: AlterTableAlgorithm,
498    },
499
500    /// `LOCK [=] { DEFAULT | NONE | SHARED | EXCLUSIVE }`
501    ///
502    /// [MySQL]-specific table alter lock.
503    ///
504    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
505    Lock {
506        /// Whether the `=` sign was used (`LOCK = ...`).
507        equals: bool,
508        /// The locking behavior to apply (MySQL-specific).
509        lock: AlterTableLock,
510    },
511    /// `AUTO_INCREMENT [=] <value>`
512    ///
513    /// [MySQL]-specific table option for raising current auto increment value.
514    ///
515    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
516    AutoIncrement {
517        /// Whether the `=` sign was used (`AUTO_INCREMENT = ...`).
518        equals: bool,
519        /// Value to set for the auto-increment counter.
520        value: ValueWithSpan,
521    },
522    /// `VALIDATE CONSTRAINT <name>`
523    ValidateConstraint {
524        /// Name of the constraint to validate.
525        name: Ident,
526    },
527    /// Arbitrary parenthesized `SET` options.
528    ///
529    /// Example:
530    /// ```sql
531    /// SET (scale_factor = 0.01, threshold = 500)`
532    /// ```
533    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertable.html)
534    SetOptionsParens {
535        /// Parenthesized options supplied to `SET (...)`.
536        options: Vec<SqlOption>,
537    },
538}
539
540/// An `ALTER Policy` (`Statement::AlterPolicy`) operation
541///
542/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-altertable.html)
543#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
544#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
545#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
546pub enum AlterPolicyOperation {
547    /// Rename the policy to `new_name`.
548    Rename {
549        /// The new identifier for the policy.
550        new_name: Ident,
551    },
552    /// Apply/modify policy properties.
553    Apply {
554        /// Optional list of owners the policy applies to.
555        to: Option<Vec<Owner>>,
556        /// Optional `USING` expression for the policy.
557        using: Option<Expr>,
558        /// Optional `WITH CHECK` expression for the policy.
559        with_check: Option<Expr>,
560    },
561}
562
563impl fmt::Display for AlterPolicyOperation {
564    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
565        match self {
566            AlterPolicyOperation::Rename { new_name } => {
567                write!(f, " RENAME TO {new_name}")
568            }
569            AlterPolicyOperation::Apply {
570                to,
571                using,
572                with_check,
573            } => {
574                if let Some(to) = to {
575                    write!(f, " TO {}", display_comma_separated(to))?;
576                }
577                if let Some(using) = using {
578                    write!(f, " USING ({using})")?;
579                }
580                if let Some(with_check) = with_check {
581                    write!(f, " WITH CHECK ({with_check})")?;
582                }
583                Ok(())
584            }
585        }
586    }
587}
588
589/// [MySQL] `ALTER TABLE` algorithm.
590///
591/// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
592#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
593#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
594#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
595/// Algorithm option for `ALTER TABLE` operations (MySQL-specific).
596pub enum AlterTableAlgorithm {
597    /// Default algorithm selection.
598    Default,
599    /// `INSTANT` algorithm.
600    Instant,
601    /// `INPLACE` algorithm.
602    Inplace,
603    /// `COPY` algorithm.
604    Copy,
605}
606
607impl fmt::Display for AlterTableAlgorithm {
608    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
609        f.write_str(match self {
610            Self::Default => "DEFAULT",
611            Self::Instant => "INSTANT",
612            Self::Inplace => "INPLACE",
613            Self::Copy => "COPY",
614        })
615    }
616}
617
618/// [MySQL] `ALTER TABLE` lock.
619///
620/// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
621#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
622#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
623#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
624/// Locking behavior for `ALTER TABLE` (MySQL-specific).
625pub enum AlterTableLock {
626    /// `DEFAULT` lock behavior.
627    Default,
628    /// `NONE` lock.
629    None,
630    /// `SHARED` lock.
631    Shared,
632    /// `EXCLUSIVE` lock.
633    Exclusive,
634}
635
636impl fmt::Display for AlterTableLock {
637    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
638        f.write_str(match self {
639            Self::Default => "DEFAULT",
640            Self::None => "NONE",
641            Self::Shared => "SHARED",
642            Self::Exclusive => "EXCLUSIVE",
643        })
644    }
645}
646
647#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
648#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
649#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
650/// New owner specification for `ALTER TABLE ... OWNER TO ...`
651pub enum Owner {
652    /// A specific user/role identifier.
653    Ident(Ident),
654    /// `CURRENT_ROLE` keyword.
655    CurrentRole,
656    /// `CURRENT_USER` keyword.
657    CurrentUser,
658    /// `SESSION_USER` keyword.
659    SessionUser,
660}
661
662impl fmt::Display for Owner {
663    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
664        match self {
665            Owner::Ident(ident) => write!(f, "{ident}"),
666            Owner::CurrentRole => write!(f, "CURRENT_ROLE"),
667            Owner::CurrentUser => write!(f, "CURRENT_USER"),
668            Owner::SessionUser => write!(f, "SESSION_USER"),
669        }
670    }
671}
672
673#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
674#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
675#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
676/// New connector owner specification for `ALTER CONNECTOR ... OWNER TO ...`
677pub enum AlterConnectorOwner {
678    /// `USER <ident>` connector owner.
679    User(Ident),
680    /// `ROLE <ident>` connector owner.
681    Role(Ident),
682}
683
684impl fmt::Display for AlterConnectorOwner {
685    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
686        match self {
687            AlterConnectorOwner::User(ident) => write!(f, "USER {ident}"),
688            AlterConnectorOwner::Role(ident) => write!(f, "ROLE {ident}"),
689        }
690    }
691}
692
693#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
695#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
696/// Alterations that can be applied to an index.
697pub enum AlterIndexOperation {
698    /// Rename the index to `index_name`.
699    RenameIndex {
700        /// The new name for the index.
701        index_name: ObjectName,
702    },
703}
704
705impl fmt::Display for AlterTableOperation {
706    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
707        match self {
708            AlterTableOperation::AddPartitions {
709                if_not_exists,
710                new_partitions,
711            } => write!(
712                f,
713                "ADD{ine} {}",
714                display_separated(new_partitions, " "),
715                ine = if *if_not_exists { " IF NOT EXISTS" } else { "" }
716            ),
717            AlterTableOperation::AddConstraint {
718                not_valid,
719                constraint,
720            } => {
721                write!(f, "ADD {constraint}")?;
722                if *not_valid {
723                    write!(f, " NOT VALID")?;
724                }
725                Ok(())
726            }
727            AlterTableOperation::AddColumn {
728                column_keyword,
729                if_not_exists,
730                column_def,
731                column_position,
732            } => {
733                write!(f, "ADD")?;
734                if *column_keyword {
735                    write!(f, " COLUMN")?;
736                }
737                if *if_not_exists {
738                    write!(f, " IF NOT EXISTS")?;
739                }
740                write!(f, " {column_def}")?;
741
742                if let Some(position) = column_position {
743                    write!(f, " {position}")?;
744                }
745
746                Ok(())
747            }
748            AlterTableOperation::AddProjection {
749                if_not_exists,
750                name,
751                select: query,
752            } => {
753                write!(f, "ADD PROJECTION")?;
754                if *if_not_exists {
755                    write!(f, " IF NOT EXISTS")?;
756                }
757                write!(f, " {name} ({query})")
758            }
759            AlterTableOperation::Algorithm { equals, algorithm } => {
760                write!(
761                    f,
762                    "ALGORITHM {}{}",
763                    if *equals { "= " } else { "" },
764                    algorithm
765                )
766            }
767            AlterTableOperation::DropProjection { if_exists, name } => {
768                write!(f, "DROP PROJECTION")?;
769                if *if_exists {
770                    write!(f, " IF EXISTS")?;
771                }
772                write!(f, " {name}")
773            }
774            AlterTableOperation::MaterializeProjection {
775                if_exists,
776                name,
777                partition,
778            } => {
779                write!(f, "MATERIALIZE PROJECTION")?;
780                if *if_exists {
781                    write!(f, " IF EXISTS")?;
782                }
783                write!(f, " {name}")?;
784                if let Some(partition) = partition {
785                    write!(f, " IN PARTITION {partition}")?;
786                }
787                Ok(())
788            }
789            AlterTableOperation::ClearProjection {
790                if_exists,
791                name,
792                partition,
793            } => {
794                write!(f, "CLEAR PROJECTION")?;
795                if *if_exists {
796                    write!(f, " IF EXISTS")?;
797                }
798                write!(f, " {name}")?;
799                if let Some(partition) = partition {
800                    write!(f, " IN PARTITION {partition}")?;
801                }
802                Ok(())
803            }
804            AlterTableOperation::AlterColumn { column_name, op } => {
805                write!(f, "ALTER COLUMN {column_name} {op}")
806            }
807            AlterTableOperation::DisableRowLevelSecurity => {
808                write!(f, "DISABLE ROW LEVEL SECURITY")
809            }
810            AlterTableOperation::DisableRule { name } => {
811                write!(f, "DISABLE RULE {name}")
812            }
813            AlterTableOperation::DisableTrigger { name } => {
814                write!(f, "DISABLE TRIGGER {name}")
815            }
816            AlterTableOperation::DropPartitions {
817                partitions,
818                if_exists,
819            } => write!(
820                f,
821                "DROP{ie} PARTITION ({})",
822                display_comma_separated(partitions),
823                ie = if *if_exists { " IF EXISTS" } else { "" }
824            ),
825            AlterTableOperation::DropConstraint {
826                if_exists,
827                name,
828                drop_behavior,
829            } => {
830                write!(
831                    f,
832                    "DROP CONSTRAINT {}{}",
833                    if *if_exists { "IF EXISTS " } else { "" },
834                    name
835                )?;
836                if let Some(drop_behavior) = drop_behavior {
837                    write!(f, " {drop_behavior}")?;
838                }
839                Ok(())
840            }
841            AlterTableOperation::DropPrimaryKey { drop_behavior } => {
842                write!(f, "DROP PRIMARY KEY")?;
843                if let Some(drop_behavior) = drop_behavior {
844                    write!(f, " {drop_behavior}")?;
845                }
846                Ok(())
847            }
848            AlterTableOperation::DropForeignKey {
849                name,
850                drop_behavior,
851            } => {
852                write!(f, "DROP FOREIGN KEY {name}")?;
853                if let Some(drop_behavior) = drop_behavior {
854                    write!(f, " {drop_behavior}")?;
855                }
856                Ok(())
857            }
858            AlterTableOperation::DropIndex { name } => write!(f, "DROP INDEX {name}"),
859            AlterTableOperation::DropColumn {
860                has_column_keyword,
861                column_names: column_name,
862                if_exists,
863                drop_behavior,
864            } => {
865                write!(
866                    f,
867                    "DROP {}{}{}",
868                    if *has_column_keyword { "COLUMN " } else { "" },
869                    if *if_exists { "IF EXISTS " } else { "" },
870                    display_comma_separated(column_name),
871                )?;
872                if let Some(drop_behavior) = drop_behavior {
873                    write!(f, " {drop_behavior}")?;
874                }
875                Ok(())
876            }
877            AlterTableOperation::AttachPartition { partition } => {
878                write!(f, "ATTACH {partition}")
879            }
880            AlterTableOperation::DetachPartition { partition } => {
881                write!(f, "DETACH {partition}")
882            }
883            AlterTableOperation::EnableAlwaysRule { name } => {
884                write!(f, "ENABLE ALWAYS RULE {name}")
885            }
886            AlterTableOperation::EnableAlwaysTrigger { name } => {
887                write!(f, "ENABLE ALWAYS TRIGGER {name}")
888            }
889            AlterTableOperation::EnableReplicaRule { name } => {
890                write!(f, "ENABLE REPLICA RULE {name}")
891            }
892            AlterTableOperation::EnableReplicaTrigger { name } => {
893                write!(f, "ENABLE REPLICA TRIGGER {name}")
894            }
895            AlterTableOperation::EnableRowLevelSecurity => {
896                write!(f, "ENABLE ROW LEVEL SECURITY")
897            }
898            AlterTableOperation::ForceRowLevelSecurity => {
899                write!(f, "FORCE ROW LEVEL SECURITY")
900            }
901            AlterTableOperation::NoForceRowLevelSecurity => {
902                write!(f, "NO FORCE ROW LEVEL SECURITY")
903            }
904            AlterTableOperation::EnableRule { name } => {
905                write!(f, "ENABLE RULE {name}")
906            }
907            AlterTableOperation::EnableTrigger { name } => {
908                write!(f, "ENABLE TRIGGER {name}")
909            }
910            AlterTableOperation::RenamePartitions {
911                old_partitions,
912                new_partitions,
913            } => write!(
914                f,
915                "PARTITION ({}) RENAME TO PARTITION ({})",
916                display_comma_separated(old_partitions),
917                display_comma_separated(new_partitions)
918            ),
919            AlterTableOperation::RenameColumn {
920                old_column_name,
921                new_column_name,
922            } => write!(f, "RENAME COLUMN {old_column_name} TO {new_column_name}"),
923            AlterTableOperation::RenameTable { table_name } => {
924                write!(f, "RENAME {table_name}")
925            }
926            AlterTableOperation::ChangeColumn {
927                old_name,
928                new_name,
929                data_type,
930                options,
931                column_position,
932            } => {
933                write!(f, "CHANGE COLUMN {old_name} {new_name} {data_type}")?;
934                if !options.is_empty() {
935                    write!(f, " {}", display_separated(options, " "))?;
936                }
937                if let Some(position) = column_position {
938                    write!(f, " {position}")?;
939                }
940
941                Ok(())
942            }
943            AlterTableOperation::ModifyColumn {
944                col_name,
945                data_type,
946                options,
947                column_position,
948            } => {
949                write!(f, "MODIFY COLUMN {col_name} {data_type}")?;
950                if !options.is_empty() {
951                    write!(f, " {}", display_separated(options, " "))?;
952                }
953                if let Some(position) = column_position {
954                    write!(f, " {position}")?;
955                }
956
957                Ok(())
958            }
959            AlterTableOperation::RenameConstraint { old_name, new_name } => {
960                write!(f, "RENAME CONSTRAINT {old_name} TO {new_name}")
961            }
962            AlterTableOperation::SwapWith { table_name } => {
963                write!(f, "SWAP WITH {table_name}")
964            }
965            AlterTableOperation::OwnerTo { new_owner } => {
966                write!(f, "OWNER TO {new_owner}")
967            }
968            AlterTableOperation::SetTblProperties { table_properties } => {
969                write!(
970                    f,
971                    "SET TBLPROPERTIES({})",
972                    display_comma_separated(table_properties)
973                )
974            }
975            AlterTableOperation::FreezePartition {
976                partition,
977                with_name,
978            } => {
979                write!(f, "FREEZE {partition}")?;
980                if let Some(name) = with_name {
981                    write!(f, " WITH NAME {name}")?;
982                }
983                Ok(())
984            }
985            AlterTableOperation::UnfreezePartition {
986                partition,
987                with_name,
988            } => {
989                write!(f, "UNFREEZE {partition}")?;
990                if let Some(name) = with_name {
991                    write!(f, " WITH NAME {name}")?;
992                }
993                Ok(())
994            }
995            AlterTableOperation::ClusterBy { exprs } => {
996                write!(f, "CLUSTER BY ({})", display_comma_separated(exprs))?;
997                Ok(())
998            }
999            AlterTableOperation::DropClusteringKey => {
1000                write!(f, "DROP CLUSTERING KEY")?;
1001                Ok(())
1002            }
1003            AlterTableOperation::AlterSortKey { columns } => {
1004                write!(f, "ALTER SORTKEY({})", display_comma_separated(columns))?;
1005                Ok(())
1006            }
1007            AlterTableOperation::SuspendRecluster => {
1008                write!(f, "SUSPEND RECLUSTER")?;
1009                Ok(())
1010            }
1011            AlterTableOperation::ResumeRecluster => {
1012                write!(f, "RESUME RECLUSTER")?;
1013                Ok(())
1014            }
1015            AlterTableOperation::Refresh { subpath } => {
1016                write!(f, "REFRESH")?;
1017                if let Some(path) = subpath {
1018                    write!(f, " '{path}'")?;
1019                }
1020                Ok(())
1021            }
1022            AlterTableOperation::Suspend => {
1023                write!(f, "SUSPEND")
1024            }
1025            AlterTableOperation::Resume => {
1026                write!(f, "RESUME")
1027            }
1028            AlterTableOperation::AutoIncrement { equals, value } => {
1029                write!(
1030                    f,
1031                    "AUTO_INCREMENT {}{}",
1032                    if *equals { "= " } else { "" },
1033                    value
1034                )
1035            }
1036            AlterTableOperation::Lock { equals, lock } => {
1037                write!(f, "LOCK {}{}", if *equals { "= " } else { "" }, lock)
1038            }
1039            AlterTableOperation::ReplicaIdentity { identity } => {
1040                write!(f, "REPLICA IDENTITY {identity}")
1041            }
1042            AlterTableOperation::ValidateConstraint { name } => {
1043                write!(f, "VALIDATE CONSTRAINT {name}")
1044            }
1045            AlterTableOperation::SetOptionsParens { options } => {
1046                write!(f, "SET ({})", display_comma_separated(options))
1047            }
1048        }
1049    }
1050}
1051
1052impl fmt::Display for AlterIndexOperation {
1053    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1054        match self {
1055            AlterIndexOperation::RenameIndex { index_name } => {
1056                write!(f, "RENAME TO {index_name}")
1057            }
1058        }
1059    }
1060}
1061
1062/// An `ALTER TYPE` statement (`Statement::AlterType`)
1063#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1064#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1065#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1066pub struct AlterType {
1067    /// Name of the type being altered (may be schema-qualified).
1068    pub name: ObjectName,
1069    /// The specific alteration operation to perform.
1070    pub operation: AlterTypeOperation,
1071}
1072
1073/// An [AlterType] operation
1074#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1075#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1076#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1077pub enum AlterTypeOperation {
1078    /// Rename the type.
1079    Rename(AlterTypeRename),
1080    /// Add a new value to the type (for enum-like types).
1081    AddValue(AlterTypeAddValue),
1082    /// Rename an existing value of the type.
1083    RenameValue(AlterTypeRenameValue),
1084}
1085
1086/// See [AlterTypeOperation::Rename]
1087#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1088#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1089#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1090pub struct AlterTypeRename {
1091    /// The new name for the type.
1092    pub new_name: Ident,
1093}
1094
1095/// See [AlterTypeOperation::AddValue]
1096#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1097#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1098#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1099pub struct AlterTypeAddValue {
1100    /// If true, do not error when the value already exists (`IF NOT EXISTS`).
1101    pub if_not_exists: bool,
1102    /// The identifier for the new value to add.
1103    pub value: Ident,
1104    /// Optional relative position for the new value (`BEFORE` / `AFTER`).
1105    pub position: Option<AlterTypeAddValuePosition>,
1106}
1107
1108/// See [AlterTypeAddValue]
1109#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1110#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1111#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1112pub enum AlterTypeAddValuePosition {
1113    /// Place the new value before the given neighbor value.
1114    Before(Ident),
1115    /// Place the new value after the given neighbor value.
1116    After(Ident),
1117}
1118
1119/// See [AlterTypeOperation::RenameValue]
1120#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1121#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1122#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1123pub struct AlterTypeRenameValue {
1124    /// Existing value identifier to rename.
1125    pub from: Ident,
1126    /// New identifier for the value.
1127    pub to: Ident,
1128}
1129
1130impl fmt::Display for AlterTypeOperation {
1131    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1132        match self {
1133            Self::Rename(AlterTypeRename { new_name }) => {
1134                write!(f, "RENAME TO {new_name}")
1135            }
1136            Self::AddValue(AlterTypeAddValue {
1137                if_not_exists,
1138                value,
1139                position,
1140            }) => {
1141                write!(f, "ADD VALUE")?;
1142                if *if_not_exists {
1143                    write!(f, " IF NOT EXISTS")?;
1144                }
1145                write!(f, " {value}")?;
1146                match position {
1147                    Some(AlterTypeAddValuePosition::Before(neighbor_value)) => {
1148                        write!(f, " BEFORE {neighbor_value}")?;
1149                    }
1150                    Some(AlterTypeAddValuePosition::After(neighbor_value)) => {
1151                        write!(f, " AFTER {neighbor_value}")?;
1152                    }
1153                    None => {}
1154                };
1155                Ok(())
1156            }
1157            Self::RenameValue(AlterTypeRenameValue { from, to }) => {
1158                write!(f, "RENAME VALUE {from} TO {to}")
1159            }
1160        }
1161    }
1162}
1163
1164/// `ALTER OPERATOR` statement
1165/// See <https://www.postgresql.org/docs/current/sql-alteroperator.html>
1166#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1167#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1168#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1169pub struct AlterOperator {
1170    /// Operator name (can be schema-qualified)
1171    pub name: ObjectName,
1172    /// Left operand type (`None` if no left operand)
1173    pub left_type: Option<DataType>,
1174    /// Right operand type
1175    pub right_type: DataType,
1176    /// The operation to perform
1177    pub operation: AlterOperatorOperation,
1178}
1179
1180/// An [AlterOperator] operation
1181#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1182#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1183#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1184pub enum AlterOperatorOperation {
1185    /// `OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }`
1186    OwnerTo(Owner),
1187    /// `SET SCHEMA new_schema`
1188    /// Set the operator's schema name.
1189    SetSchema {
1190        /// New schema name for the operator
1191        schema_name: ObjectName,
1192    },
1193    /// `SET ( options )`
1194    Set {
1195        /// List of operator options to set
1196        options: Vec<OperatorOption>,
1197    },
1198}
1199
1200/// Option for `ALTER OPERATOR SET` operation
1201#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1202#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1203#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1204pub enum OperatorOption {
1205    /// `RESTRICT = { res_proc | NONE }`
1206    Restrict(Option<ObjectName>),
1207    /// `JOIN = { join_proc | NONE }`
1208    Join(Option<ObjectName>),
1209    /// `COMMUTATOR = com_op`
1210    Commutator(ObjectName),
1211    /// `NEGATOR = neg_op`
1212    Negator(ObjectName),
1213    /// `HASHES`
1214    Hashes,
1215    /// `MERGES`
1216    Merges,
1217}
1218
1219impl fmt::Display for AlterOperator {
1220    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1221        write!(f, "ALTER OPERATOR {} (", self.name)?;
1222        if let Some(left_type) = &self.left_type {
1223            write!(f, "{}", left_type)?;
1224        } else {
1225            write!(f, "NONE")?;
1226        }
1227        write!(f, ", {}) {}", self.right_type, self.operation)
1228    }
1229}
1230
1231impl fmt::Display for AlterOperatorOperation {
1232    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1233        match self {
1234            Self::OwnerTo(owner) => write!(f, "OWNER TO {}", owner),
1235            Self::SetSchema { schema_name } => write!(f, "SET SCHEMA {}", schema_name),
1236            Self::Set { options } => {
1237                write!(f, "SET (")?;
1238                for (i, option) in options.iter().enumerate() {
1239                    if i > 0 {
1240                        write!(f, ", ")?;
1241                    }
1242                    write!(f, "{}", option)?;
1243                }
1244                write!(f, ")")
1245            }
1246        }
1247    }
1248}
1249
1250impl fmt::Display for OperatorOption {
1251    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1252        match self {
1253            Self::Restrict(Some(proc_name)) => write!(f, "RESTRICT = {}", proc_name),
1254            Self::Restrict(None) => write!(f, "RESTRICT = NONE"),
1255            Self::Join(Some(proc_name)) => write!(f, "JOIN = {}", proc_name),
1256            Self::Join(None) => write!(f, "JOIN = NONE"),
1257            Self::Commutator(op_name) => write!(f, "COMMUTATOR = {}", op_name),
1258            Self::Negator(op_name) => write!(f, "NEGATOR = {}", op_name),
1259            Self::Hashes => write!(f, "HASHES"),
1260            Self::Merges => write!(f, "MERGES"),
1261        }
1262    }
1263}
1264
1265/// An `ALTER COLUMN` (`Statement::AlterTable`) operation
1266#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1267#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1268#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1269pub enum AlterColumnOperation {
1270    /// `SET NOT NULL`
1271    SetNotNull,
1272    /// `DROP NOT NULL`
1273    DropNotNull,
1274    /// `SET DEFAULT <expr>`
1275    /// Set the column default value.
1276    SetDefault {
1277        /// Expression representing the new default value.
1278        value: Expr,
1279    },
1280    /// `DROP DEFAULT`
1281    DropDefault,
1282    /// `[SET DATA] TYPE <data_type> [USING <expr>]`
1283    SetDataType {
1284        /// Target data type for the column.
1285        data_type: DataType,
1286        /// PostgreSQL-specific `USING <expr>` expression for conversion.
1287        using: Option<Expr>,
1288        /// Set to true if the statement includes the `SET DATA TYPE` keywords.
1289        had_set: bool,
1290    },
1291
1292    /// `ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]`
1293    ///
1294    /// Note: this is a PostgreSQL-specific operation.
1295    AddGenerated {
1296        /// Optional `GENERATED AS` specifier (e.g. `ALWAYS` or `BY DEFAULT`).
1297        generated_as: Option<GeneratedAs>,
1298        /// Optional sequence options for identity generation.
1299        sequence_options: Option<Vec<SequenceOptions>>,
1300    },
1301}
1302
1303impl fmt::Display for AlterColumnOperation {
1304    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1305        match self {
1306            AlterColumnOperation::SetNotNull => write!(f, "SET NOT NULL",),
1307            AlterColumnOperation::DropNotNull => write!(f, "DROP NOT NULL",),
1308            AlterColumnOperation::SetDefault { value } => {
1309                write!(f, "SET DEFAULT {value}")
1310            }
1311            AlterColumnOperation::DropDefault => {
1312                write!(f, "DROP DEFAULT")
1313            }
1314            AlterColumnOperation::SetDataType {
1315                data_type,
1316                using,
1317                had_set,
1318            } => {
1319                if *had_set {
1320                    write!(f, "SET DATA ")?;
1321                }
1322                write!(f, "TYPE {data_type}")?;
1323                if let Some(expr) = using {
1324                    write!(f, " USING {expr}")?;
1325                }
1326                Ok(())
1327            }
1328            AlterColumnOperation::AddGenerated {
1329                generated_as,
1330                sequence_options,
1331            } => {
1332                let generated_as = match generated_as {
1333                    Some(GeneratedAs::Always) => " ALWAYS",
1334                    Some(GeneratedAs::ByDefault) => " BY DEFAULT",
1335                    _ => "",
1336                };
1337
1338                write!(f, "ADD GENERATED{generated_as} AS IDENTITY",)?;
1339                if let Some(options) = sequence_options {
1340                    write!(f, " (")?;
1341
1342                    for sequence_option in options {
1343                        write!(f, "{sequence_option}")?;
1344                    }
1345
1346                    write!(f, " )")?;
1347                }
1348                Ok(())
1349            }
1350        }
1351    }
1352}
1353
1354/// Representation whether a definition can can contains the KEY or INDEX keywords with the same
1355/// meaning.
1356///
1357/// This enum initially is directed to `FULLTEXT`,`SPATIAL`, and `UNIQUE` indexes on create table
1358/// statements of `MySQL` [(1)].
1359///
1360/// [1]: https://dev.mysql.com/doc/refman/8.0/en/create-table.html
1361#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1362#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1363#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1364pub enum KeyOrIndexDisplay {
1365    /// Nothing to display
1366    None,
1367    /// Display the KEY keyword
1368    Key,
1369    /// Display the INDEX keyword
1370    Index,
1371}
1372
1373impl KeyOrIndexDisplay {
1374    /// Check if this is the `None` variant.
1375    pub fn is_none(self) -> bool {
1376        matches!(self, Self::None)
1377    }
1378}
1379
1380impl fmt::Display for KeyOrIndexDisplay {
1381    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1382        let left_space = matches!(f.align(), Some(fmt::Alignment::Right));
1383
1384        if left_space && !self.is_none() {
1385            f.write_char(' ')?
1386        }
1387
1388        match self {
1389            KeyOrIndexDisplay::None => {
1390                write!(f, "")
1391            }
1392            KeyOrIndexDisplay::Key => {
1393                write!(f, "KEY")
1394            }
1395            KeyOrIndexDisplay::Index => {
1396                write!(f, "INDEX")
1397            }
1398        }
1399    }
1400}
1401
1402/// Indexing method used by that index.
1403///
1404/// This structure isn't present on ANSI, but is found at least in [`MySQL` CREATE TABLE][1],
1405/// [`MySQL` CREATE INDEX][2], and [Postgresql CREATE INDEX][3] statements.
1406///
1407/// [1]: https://dev.mysql.com/doc/refman/8.0/en/create-table.html
1408/// [2]: https://dev.mysql.com/doc/refman/8.0/en/create-index.html
1409/// [3]: https://www.postgresql.org/docs/14/sql-createindex.html
1410#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1411#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1412#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1413pub enum IndexType {
1414    /// B-Tree index (commonly default for many databases).
1415    BTree,
1416    /// Hash index.
1417    Hash,
1418    /// Generalized Inverted Index (GIN).
1419    GIN,
1420    /// Generalized Search Tree (GiST) index.
1421    GiST,
1422    /// Space-partitioned GiST (SPGiST) index.
1423    SPGiST,
1424    /// Block Range Index (BRIN).
1425    BRIN,
1426    /// Bloom filter based index.
1427    Bloom,
1428    /// Users may define their own index types, which would
1429    /// not be covered by the above variants.
1430    Custom(Ident),
1431}
1432
1433impl fmt::Display for IndexType {
1434    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1435        match self {
1436            Self::BTree => write!(f, "BTREE"),
1437            Self::Hash => write!(f, "HASH"),
1438            Self::GIN => write!(f, "GIN"),
1439            Self::GiST => write!(f, "GIST"),
1440            Self::SPGiST => write!(f, "SPGIST"),
1441            Self::BRIN => write!(f, "BRIN"),
1442            Self::Bloom => write!(f, "BLOOM"),
1443            Self::Custom(name) => write!(f, "{name}"),
1444        }
1445    }
1446}
1447
1448/// MySQL index option, used in [`CREATE TABLE`], [`CREATE INDEX`], and [`ALTER TABLE`].
1449///
1450/// [`CREATE TABLE`]: https://dev.mysql.com/doc/refman/8.4/en/create-table.html
1451/// [`CREATE INDEX`]: https://dev.mysql.com/doc/refman/8.4/en/create-index.html
1452/// [`ALTER TABLE`]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
1453#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1454#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1455#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1456pub enum IndexOption {
1457    /// `USING { BTREE | HASH }`: Index type to use for the index.
1458    ///
1459    /// Note that we permissively parse non-MySQL index types, like `GIN`.
1460    Using(IndexType),
1461    /// `COMMENT 'string'`: Specifies a comment for the index.
1462    Comment(String),
1463}
1464
1465impl fmt::Display for IndexOption {
1466    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1467        match self {
1468            Self::Using(index_type) => write!(f, "USING {index_type}"),
1469            Self::Comment(s) => write!(f, "COMMENT '{s}'"),
1470        }
1471    }
1472}
1473
1474/// [PostgreSQL] unique index nulls handling option: `[ NULLS [ NOT ] DISTINCT ]`
1475///
1476/// [PostgreSQL]: https://www.postgresql.org/docs/17/sql-altertable.html
1477#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
1478#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1479#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1480pub enum NullsDistinctOption {
1481    /// Not specified
1482    None,
1483    /// NULLS DISTINCT
1484    Distinct,
1485    /// NULLS NOT DISTINCT
1486    NotDistinct,
1487}
1488
1489impl fmt::Display for NullsDistinctOption {
1490    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1491        match self {
1492            Self::None => Ok(()),
1493            Self::Distinct => write!(f, " NULLS DISTINCT"),
1494            Self::NotDistinct => write!(f, " NULLS NOT DISTINCT"),
1495        }
1496    }
1497}
1498
1499#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1500#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1501#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1502/// A parameter of a stored procedure or function declaration.
1503pub struct ProcedureParam {
1504    /// Parameter name.
1505    pub name: Ident,
1506    /// Parameter data type.
1507    pub data_type: DataType,
1508    /// Optional mode (`IN`, `OUT`, `INOUT`, etc.).
1509    pub mode: Option<ArgMode>,
1510    /// Optional default expression for the parameter.
1511    pub default: Option<Expr>,
1512}
1513
1514impl fmt::Display for ProcedureParam {
1515    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1516        if let Some(mode) = &self.mode {
1517            if let Some(default) = &self.default {
1518                write!(f, "{mode} {} {} = {}", self.name, self.data_type, default)
1519            } else {
1520                write!(f, "{mode} {} {}", self.name, self.data_type)
1521            }
1522        } else if let Some(default) = &self.default {
1523            write!(f, "{} {} = {}", self.name, self.data_type, default)
1524        } else {
1525            write!(f, "{} {}", self.name, self.data_type)
1526        }
1527    }
1528}
1529
1530/// SQL column definition
1531#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1532#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1533#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1534pub struct ColumnDef {
1535    /// Column name.
1536    pub name: Ident,
1537    /// Column data type.
1538    pub data_type: DataType,
1539    /// Column options (defaults, constraints, generated, etc.).
1540    pub options: Vec<ColumnOptionDef>,
1541}
1542
1543impl fmt::Display for ColumnDef {
1544    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1545        if self.data_type == DataType::Unspecified {
1546            write!(f, "{}", self.name)?;
1547        } else {
1548            write!(f, "{} {}", self.name, self.data_type)?;
1549        }
1550        for option in &self.options {
1551            write!(f, " {option}")?;
1552        }
1553        Ok(())
1554    }
1555}
1556
1557/// Column definition specified in a `CREATE VIEW` statement.
1558///
1559/// Syntax
1560/// ```markdown
1561/// <name> [data_type][OPTIONS(option, ...)]
1562///
1563/// option: <name> = <value>
1564/// ```
1565///
1566/// Examples:
1567/// ```sql
1568/// name
1569/// age OPTIONS(description = "age column", tag = "prod")
1570/// amount COMMENT 'The total amount for the order line'
1571/// created_at DateTime64
1572/// ```
1573#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1574#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1575#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1576pub struct ViewColumnDef {
1577    /// Column identifier.
1578    pub name: Ident,
1579    /// Optional data type for the column.
1580    pub data_type: Option<DataType>,
1581    /// Optional column options (defaults, comments, etc.).
1582    pub options: Option<ColumnOptions>,
1583}
1584
1585#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1587#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1588/// Representation of how multiple `ColumnOption`s are grouped for a column.
1589pub enum ColumnOptions {
1590    /// Options separated by comma: `OPTIONS(a, b, c)`.
1591    CommaSeparated(Vec<ColumnOption>),
1592    /// Options separated by spaces: `OPTION_A OPTION_B`.
1593    SpaceSeparated(Vec<ColumnOption>),
1594}
1595
1596impl ColumnOptions {
1597    /// Get the column options as a slice.
1598    pub fn as_slice(&self) -> &[ColumnOption] {
1599        match self {
1600            ColumnOptions::CommaSeparated(options) => options.as_slice(),
1601            ColumnOptions::SpaceSeparated(options) => options.as_slice(),
1602        }
1603    }
1604}
1605
1606impl fmt::Display for ViewColumnDef {
1607    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1608        write!(f, "{}", self.name)?;
1609        if let Some(data_type) = self.data_type.as_ref() {
1610            write!(f, " {data_type}")?;
1611        }
1612        if let Some(options) = self.options.as_ref() {
1613            match options {
1614                ColumnOptions::CommaSeparated(column_options) => {
1615                    write!(f, " {}", display_comma_separated(column_options.as_slice()))?;
1616                }
1617                ColumnOptions::SpaceSeparated(column_options) => {
1618                    write!(f, " {}", display_separated(column_options.as_slice(), " "))?
1619                }
1620            }
1621        }
1622        Ok(())
1623    }
1624}
1625
1626/// An optionally-named `ColumnOption`: `[ CONSTRAINT <name> ] <column-option>`.
1627///
1628/// Note that implementations are substantially more permissive than the ANSI
1629/// specification on what order column options can be presented in, and whether
1630/// they are allowed to be named. The specification distinguishes between
1631/// constraints (NOT NULL, UNIQUE, PRIMARY KEY, and CHECK), which can be named
1632/// and can appear in any order, and other options (DEFAULT, GENERATED), which
1633/// cannot be named and must appear in a fixed order. `PostgreSQL`, however,
1634/// allows preceding any option with `CONSTRAINT <name>`, even those that are
1635/// not really constraints, like NULL and DEFAULT. MSSQL is less permissive,
1636/// allowing DEFAULT, UNIQUE, PRIMARY KEY and CHECK to be named, but not NULL or
1637/// NOT NULL constraints (the last of which is in violation of the spec).
1638///
1639/// For maximum flexibility, we don't distinguish between constraint and
1640/// non-constraint options, lumping them all together under the umbrella of
1641/// "column options," and we allow any column option to be named.
1642#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1643#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1644#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1645pub struct ColumnOptionDef {
1646    /// Optional name of the constraint.
1647    pub name: Option<Ident>,
1648    /// The actual column option (e.g. `NOT NULL`, `DEFAULT`, `GENERATED`, ...).
1649    pub option: ColumnOption,
1650}
1651
1652impl fmt::Display for ColumnOptionDef {
1653    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1654        write!(f, "{}{}", display_constraint_name(&self.name), self.option)
1655    }
1656}
1657
1658/// Identity is a column option for defining an identity or autoincrement column in a `CREATE TABLE` statement.
1659/// Syntax
1660/// ```sql
1661/// { IDENTITY | AUTOINCREMENT } [ (seed , increment) | START num INCREMENT num ] [ ORDER | NOORDER ]
1662/// ```
1663/// [MS SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property
1664/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1665#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1666#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1667#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1668pub enum IdentityPropertyKind {
1669    /// An identity property declared via the `AUTOINCREMENT` key word
1670    /// Example:
1671    /// ```sql
1672    ///  AUTOINCREMENT(100, 1) NOORDER
1673    ///  AUTOINCREMENT START 100 INCREMENT 1 ORDER
1674    /// ```
1675    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1676    Autoincrement(IdentityProperty),
1677    /// An identity property declared via the `IDENTITY` key word
1678    /// Example, [MS SQL Server] or [Snowflake]:
1679    /// ```sql
1680    ///  IDENTITY(100, 1)
1681    /// ```
1682    /// [Snowflake]
1683    /// ```sql
1684    ///  IDENTITY(100, 1) ORDER
1685    ///  IDENTITY START 100 INCREMENT 1 NOORDER
1686    /// ```
1687    /// [MS SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property
1688    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1689    Identity(IdentityProperty),
1690}
1691
1692impl fmt::Display for IdentityPropertyKind {
1693    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1694        let (command, property) = match self {
1695            IdentityPropertyKind::Identity(property) => ("IDENTITY", property),
1696            IdentityPropertyKind::Autoincrement(property) => ("AUTOINCREMENT", property),
1697        };
1698        write!(f, "{command}")?;
1699        if let Some(parameters) = &property.parameters {
1700            write!(f, "{parameters}")?;
1701        }
1702        if let Some(order) = &property.order {
1703            write!(f, "{order}")?;
1704        }
1705        Ok(())
1706    }
1707}
1708
1709/// Properties for the `IDENTITY` / `AUTOINCREMENT` column option.
1710#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1711#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1712#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1713pub struct IdentityProperty {
1714    /// Optional parameters specifying seed/increment for the identity column.
1715    pub parameters: Option<IdentityPropertyFormatKind>,
1716    /// Optional ordering specifier (`ORDER` / `NOORDER`).
1717    pub order: Option<IdentityPropertyOrder>,
1718}
1719
1720/// A format of parameters of identity column.
1721///
1722/// It is [Snowflake] specific.
1723/// Syntax
1724/// ```sql
1725/// (seed , increment) | START num INCREMENT num
1726/// ```
1727/// [MS SQL Server] uses one way of representing these parameters.
1728/// Syntax
1729/// ```sql
1730/// (seed , increment)
1731/// ```
1732/// [MS SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property
1733/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1734#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1735#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1736#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1737pub enum IdentityPropertyFormatKind {
1738    /// A parameters of identity column declared like parameters of function call
1739    /// Example:
1740    /// ```sql
1741    ///  (100, 1)
1742    /// ```
1743    /// [MS SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property
1744    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1745    FunctionCall(IdentityParameters),
1746    /// A parameters of identity column declared with keywords `START` and `INCREMENT`
1747    /// Example:
1748    /// ```sql
1749    ///  START 100 INCREMENT 1
1750    /// ```
1751    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1752    StartAndIncrement(IdentityParameters),
1753}
1754
1755impl fmt::Display for IdentityPropertyFormatKind {
1756    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1757        match self {
1758            IdentityPropertyFormatKind::FunctionCall(parameters) => {
1759                write!(f, "({}, {})", parameters.seed, parameters.increment)
1760            }
1761            IdentityPropertyFormatKind::StartAndIncrement(parameters) => {
1762                write!(
1763                    f,
1764                    " START {} INCREMENT {}",
1765                    parameters.seed, parameters.increment
1766                )
1767            }
1768        }
1769    }
1770}
1771/// Parameters specifying seed and increment for identity columns.
1772#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1773#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1774#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1775pub struct IdentityParameters {
1776    /// The initial seed expression for the identity column.
1777    pub seed: Expr,
1778    /// The increment expression for the identity column.
1779    pub increment: Expr,
1780}
1781
1782/// The identity column option specifies how values are generated for the auto-incremented column, either in increasing or decreasing order.
1783/// Syntax
1784/// ```sql
1785/// ORDER | NOORDER
1786/// ```
1787/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1788#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
1789#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1790#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1791pub enum IdentityPropertyOrder {
1792    /// `ORDER` - preserve ordering for generated values (where supported).
1793    Order,
1794    /// `NOORDER` - do not enforce ordering for generated values.
1795    NoOrder,
1796}
1797
1798impl fmt::Display for IdentityPropertyOrder {
1799    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1800        match self {
1801            IdentityPropertyOrder::Order => write!(f, " ORDER"),
1802            IdentityPropertyOrder::NoOrder => write!(f, " NOORDER"),
1803        }
1804    }
1805}
1806
1807/// Column policy that identify a security policy of access to a column.
1808/// Syntax
1809/// ```sql
1810/// [ WITH ] MASKING POLICY <policy_name> [ USING ( <col_name> , <cond_col1> , ... ) ]
1811/// [ WITH ] PROJECTION POLICY <policy_name>
1812/// ```
1813/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1814#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1815#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1816#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1817pub enum ColumnPolicy {
1818    /// `MASKING POLICY (<property>)`
1819    MaskingPolicy(ColumnPolicyProperty),
1820    /// `PROJECTION POLICY (<property>)`
1821    ProjectionPolicy(ColumnPolicyProperty),
1822}
1823
1824impl fmt::Display for ColumnPolicy {
1825    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1826        let (command, property) = match self {
1827            ColumnPolicy::MaskingPolicy(property) => ("MASKING POLICY", property),
1828            ColumnPolicy::ProjectionPolicy(property) => ("PROJECTION POLICY", property),
1829        };
1830        if property.with {
1831            write!(f, "WITH ")?;
1832        }
1833        write!(f, "{command} {}", property.policy_name)?;
1834        if let Some(using_columns) = &property.using_columns {
1835            write!(f, " USING ({})", display_comma_separated(using_columns))?;
1836        }
1837        Ok(())
1838    }
1839}
1840
1841#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1842#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1843#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1844/// Properties describing a column policy (masking or projection).
1845pub struct ColumnPolicyProperty {
1846    /// This flag indicates that the column policy option is declared using the `WITH` prefix.
1847    /// Example
1848    /// ```sql
1849    /// WITH PROJECTION POLICY sample_policy
1850    /// ```
1851    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1852    pub with: bool,
1853    /// The name of the policy to apply to the column.
1854    pub policy_name: ObjectName,
1855    /// Optional list of column identifiers referenced by the policy.
1856    pub using_columns: Option<Vec<Ident>>,
1857}
1858
1859/// Tags option of column
1860/// Syntax
1861/// ```sql
1862/// [ WITH ] TAG ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] )
1863/// ```
1864/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1865#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1866#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1867#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1868pub struct TagsColumnOption {
1869    /// This flag indicates that the tags option is declared using the `WITH` prefix.
1870    /// Example:
1871    /// ```sql
1872    /// WITH TAG (A = 'Tag A')
1873    /// ```
1874    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1875    pub with: bool,
1876    /// List of tags to attach to the column.
1877    pub tags: Vec<Tag>,
1878}
1879
1880impl fmt::Display for TagsColumnOption {
1881    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1882        if self.with {
1883            write!(f, "WITH ")?;
1884        }
1885        write!(f, "TAG ({})", display_comma_separated(&self.tags))?;
1886        Ok(())
1887    }
1888}
1889
1890/// `ColumnOption`s are modifiers that follow a column definition in a `CREATE
1891/// TABLE` statement.
1892#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1893#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1894#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1895pub enum ColumnOption {
1896    /// `NULL`
1897    Null,
1898    /// `NOT NULL`
1899    NotNull,
1900    /// `DEFAULT <restricted-expr>`
1901    Default(Expr),
1902
1903    /// `MATERIALIZE <expr>`
1904    /// Syntax: `b INT MATERIALIZE (a + 1)`
1905    ///
1906    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/create/table#default_values)
1907    Materialized(Expr),
1908    /// `EPHEMERAL [<expr>]`
1909    ///
1910    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/create/table#default_values)
1911    Ephemeral(Option<Expr>),
1912    /// `ALIAS <expr>`
1913    ///
1914    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/create/table#default_values)
1915    Alias(Expr),
1916
1917    /// `PRIMARY KEY [<constraint_characteristics>]`
1918    PrimaryKey(PrimaryKeyConstraint),
1919    /// `UNIQUE [<constraint_characteristics>]`
1920    Unique(UniqueConstraint),
1921    /// A referential integrity constraint (`REFERENCES <foreign_table> (<referred_columns>)
1922    /// [ MATCH { FULL | PARTIAL | SIMPLE } ]
1923    /// { [ON DELETE <referential_action>] [ON UPDATE <referential_action>] |
1924    ///   [ON UPDATE <referential_action>] [ON DELETE <referential_action>]
1925    /// }
1926    /// [<constraint_characteristics>]
1927    /// `).
1928    ForeignKey(ForeignKeyConstraint),
1929    /// `CHECK (<expr>)`
1930    Check(CheckConstraint),
1931    /// Dialect-specific options, such as:
1932    /// - MySQL's `AUTO_INCREMENT` or SQLite's `AUTOINCREMENT`
1933    /// - ...
1934    DialectSpecific(Vec<Token>),
1935    /// `CHARACTER SET <name>` column option
1936    CharacterSet(ObjectName),
1937    /// `COLLATE <name>` column option
1938    Collation(ObjectName),
1939    /// `COMMENT '<text>'` column option
1940    Comment(String),
1941    /// `ON UPDATE <expr>` column option
1942    OnUpdate(Expr),
1943    /// `Generated`s are modifiers that follow a column definition in a `CREATE
1944    /// TABLE` statement.
1945    Generated {
1946        /// How the column is generated (e.g. `GENERATED ALWAYS`, `BY DEFAULT`, or expression-stored).
1947        generated_as: GeneratedAs,
1948        /// Sequence/identity options when generation is backed by a sequence.
1949        sequence_options: Option<Vec<SequenceOptions>>,
1950        /// Optional expression used to generate the column value.
1951        generation_expr: Option<Expr>,
1952        /// Mode of the generated expression (`VIRTUAL` or `STORED`) when `generation_expr` is present.
1953        generation_expr_mode: Option<GeneratedExpressionMode>,
1954        /// false if 'GENERATED ALWAYS' is skipped (option starts with AS)
1955        generated_keyword: bool,
1956    },
1957    /// BigQuery specific: Explicit column options in a view [1] or table [2]
1958    /// Syntax
1959    /// ```sql
1960    /// OPTIONS(description="field desc")
1961    /// ```
1962    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#view_column_option_list
1963    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_option_list
1964    Options(Vec<SqlOption>),
1965    /// Creates an identity or an autoincrement column in a table.
1966    /// Syntax
1967    /// ```sql
1968    /// { IDENTITY | AUTOINCREMENT } [ (seed , increment) | START num INCREMENT num ] [ ORDER | NOORDER ]
1969    /// ```
1970    /// [MS SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property
1971    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1972    Identity(IdentityPropertyKind),
1973    /// SQLite specific: ON CONFLICT option on column definition
1974    /// <https://www.sqlite.org/lang_conflict.html>
1975    OnConflict(Keyword),
1976    /// Snowflake specific: an option of specifying security masking or projection policy to set on a column.
1977    /// Syntax:
1978    /// ```sql
1979    /// [ WITH ] MASKING POLICY <policy_name> [ USING ( <col_name> , <cond_col1> , ... ) ]
1980    /// [ WITH ] PROJECTION POLICY <policy_name>
1981    /// ```
1982    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1983    Policy(ColumnPolicy),
1984    /// Snowflake specific: Specifies the tag name and the tag string value.
1985    /// Syntax:
1986    /// ```sql
1987    /// [ WITH ] TAG ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] )
1988    /// ```
1989    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
1990    Tags(TagsColumnOption),
1991    /// MySQL specific: Spatial reference identifier
1992    /// Syntax:
1993    /// ```sql
1994    /// CREATE TABLE geom (g GEOMETRY NOT NULL SRID 4326);
1995    /// ```
1996    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/creating-spatial-indexes.html
1997    Srid(Box<Expr>),
1998    /// MySQL specific: Column is invisible via SELECT *
1999    /// Syntax:
2000    /// ```sql
2001    /// CREATE TABLE t (foo INT, bar INT INVISIBLE);
2002    /// ```
2003    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/invisible-columns.html
2004    Invisible,
2005}
2006
2007impl From<UniqueConstraint> for ColumnOption {
2008    fn from(c: UniqueConstraint) -> Self {
2009        ColumnOption::Unique(c)
2010    }
2011}
2012
2013impl From<PrimaryKeyConstraint> for ColumnOption {
2014    fn from(c: PrimaryKeyConstraint) -> Self {
2015        ColumnOption::PrimaryKey(c)
2016    }
2017}
2018
2019impl From<CheckConstraint> for ColumnOption {
2020    fn from(c: CheckConstraint) -> Self {
2021        ColumnOption::Check(c)
2022    }
2023}
2024impl From<ForeignKeyConstraint> for ColumnOption {
2025    fn from(fk: ForeignKeyConstraint) -> Self {
2026        ColumnOption::ForeignKey(fk)
2027    }
2028}
2029
2030impl fmt::Display for ColumnOption {
2031    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2032        use ColumnOption::*;
2033        match self {
2034            Null => write!(f, "NULL"),
2035            NotNull => write!(f, "NOT NULL"),
2036            Default(expr) => write!(f, "DEFAULT {expr}"),
2037            Materialized(expr) => write!(f, "MATERIALIZED {expr}"),
2038            Ephemeral(expr) => {
2039                if let Some(e) = expr {
2040                    write!(f, "EPHEMERAL {e}")
2041                } else {
2042                    write!(f, "EPHEMERAL")
2043                }
2044            }
2045            Alias(expr) => write!(f, "ALIAS {expr}"),
2046            PrimaryKey(constraint) => {
2047                write!(f, "PRIMARY KEY")?;
2048                if let Some(characteristics) = &constraint.characteristics {
2049                    write!(f, " {characteristics}")?;
2050                }
2051                Ok(())
2052            }
2053            Unique(constraint) => {
2054                write!(f, "UNIQUE{:>}", constraint.index_type_display)?;
2055                if let Some(characteristics) = &constraint.characteristics {
2056                    write!(f, " {characteristics}")?;
2057                }
2058                Ok(())
2059            }
2060            ForeignKey(constraint) => {
2061                write!(f, "REFERENCES {}", constraint.foreign_table)?;
2062                if !constraint.referred_columns.is_empty() {
2063                    write!(
2064                        f,
2065                        " ({})",
2066                        display_comma_separated(&constraint.referred_columns)
2067                    )?;
2068                }
2069                if let Some(match_kind) = &constraint.match_kind {
2070                    write!(f, " {match_kind}")?;
2071                }
2072                if let Some(action) = &constraint.on_delete {
2073                    write!(f, " ON DELETE {action}")?;
2074                }
2075                if let Some(action) = &constraint.on_update {
2076                    write!(f, " ON UPDATE {action}")?;
2077                }
2078                if let Some(characteristics) = &constraint.characteristics {
2079                    write!(f, " {characteristics}")?;
2080                }
2081                Ok(())
2082            }
2083            Check(constraint) => write!(f, "{constraint}"),
2084            DialectSpecific(val) => write!(f, "{}", display_separated(val, " ")),
2085            CharacterSet(n) => write!(f, "CHARACTER SET {n}"),
2086            Collation(n) => write!(f, "COLLATE {n}"),
2087            Comment(v) => write!(f, "COMMENT '{}'", escape_single_quote_string(v)),
2088            OnUpdate(expr) => write!(f, "ON UPDATE {expr}"),
2089            Generated {
2090                generated_as,
2091                sequence_options,
2092                generation_expr,
2093                generation_expr_mode,
2094                generated_keyword,
2095            } => {
2096                if let Some(expr) = generation_expr {
2097                    let modifier = match generation_expr_mode {
2098                        None => "",
2099                        Some(GeneratedExpressionMode::Virtual) => " VIRTUAL",
2100                        Some(GeneratedExpressionMode::Stored) => " STORED",
2101                    };
2102                    if *generated_keyword {
2103                        write!(f, "GENERATED ALWAYS AS ({expr}){modifier}")?;
2104                    } else {
2105                        write!(f, "AS ({expr}){modifier}")?;
2106                    }
2107                    Ok(())
2108                } else {
2109                    // Like Postgres - generated from sequence
2110                    let when = match generated_as {
2111                        GeneratedAs::Always => "ALWAYS",
2112                        GeneratedAs::ByDefault => "BY DEFAULT",
2113                        // ExpStored goes with an expression, handled above
2114                        GeneratedAs::ExpStored => "",
2115                    };
2116                    write!(f, "GENERATED {when} AS IDENTITY")?;
2117                    if sequence_options.is_some() {
2118                        let so = sequence_options.as_ref().unwrap();
2119                        if !so.is_empty() {
2120                            write!(f, " (")?;
2121                        }
2122                        for sequence_option in so {
2123                            write!(f, "{sequence_option}")?;
2124                        }
2125                        if !so.is_empty() {
2126                            write!(f, " )")?;
2127                        }
2128                    }
2129                    Ok(())
2130                }
2131            }
2132            Options(options) => {
2133                write!(f, "OPTIONS({})", display_comma_separated(options))
2134            }
2135            Identity(parameters) => {
2136                write!(f, "{parameters}")
2137            }
2138            OnConflict(keyword) => {
2139                write!(f, "ON CONFLICT {keyword:?}")?;
2140                Ok(())
2141            }
2142            Policy(parameters) => {
2143                write!(f, "{parameters}")
2144            }
2145            Tags(tags) => {
2146                write!(f, "{tags}")
2147            }
2148            Srid(srid) => {
2149                write!(f, "SRID {srid}")
2150            }
2151            Invisible => {
2152                write!(f, "INVISIBLE")
2153            }
2154        }
2155    }
2156}
2157
2158/// `GeneratedAs`s are modifiers that follow a column option in a `generated`.
2159/// 'ExpStored' is used for a column generated from an expression and stored.
2160#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
2161#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2162#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2163pub enum GeneratedAs {
2164    /// `GENERATED ALWAYS`
2165    Always,
2166    /// `GENERATED BY DEFAULT`
2167    ByDefault,
2168    /// Expression-based generated column that is stored (used internally for expression-stored columns)
2169    ExpStored,
2170}
2171
2172/// `GeneratedExpressionMode`s are modifiers that follow an expression in a `generated`.
2173/// No modifier is typically the same as Virtual.
2174#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
2175#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2176#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2177pub enum GeneratedExpressionMode {
2178    /// `VIRTUAL` generated expression
2179    Virtual,
2180    /// `STORED` generated expression
2181    Stored,
2182}
2183
2184#[must_use]
2185pub(crate) fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
2186    struct ConstraintName<'a>(&'a Option<Ident>);
2187    impl fmt::Display for ConstraintName<'_> {
2188        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2189            if let Some(name) = self.0 {
2190                write!(f, "CONSTRAINT {name} ")?;
2191            }
2192            Ok(())
2193        }
2194    }
2195    ConstraintName(name)
2196}
2197
2198/// If `option` is
2199/// * `Some(inner)` => create display struct for `"{prefix}{inner}{postfix}"`
2200/// * `_` => do nothing
2201#[must_use]
2202pub(crate) fn display_option<'a, T: fmt::Display>(
2203    prefix: &'a str,
2204    postfix: &'a str,
2205    option: &'a Option<T>,
2206) -> impl fmt::Display + 'a {
2207    struct OptionDisplay<'a, T>(&'a str, &'a str, &'a Option<T>);
2208    impl<T: fmt::Display> fmt::Display for OptionDisplay<'_, T> {
2209        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2210            if let Some(inner) = self.2 {
2211                let (prefix, postfix) = (self.0, self.1);
2212                write!(f, "{prefix}{inner}{postfix}")?;
2213            }
2214            Ok(())
2215        }
2216    }
2217    OptionDisplay(prefix, postfix, option)
2218}
2219
2220/// If `option` is
2221/// * `Some(inner)` => create display struct for `" {inner}"`
2222/// * `_` => do nothing
2223#[must_use]
2224pub(crate) fn display_option_spaced<T: fmt::Display>(option: &Option<T>) -> impl fmt::Display + '_ {
2225    display_option(" ", "", option)
2226}
2227
2228/// `<constraint_characteristics> = [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ]`
2229///
2230/// Used in UNIQUE and foreign key constraints. The individual settings may occur in any order.
2231#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Default, Eq, Ord, Hash)]
2232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2233#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2234pub struct ConstraintCharacteristics {
2235    /// `[ DEFERRABLE | NOT DEFERRABLE ]`
2236    pub deferrable: Option<bool>,
2237    /// `[ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]`
2238    pub initially: Option<DeferrableInitial>,
2239    /// `[ ENFORCED | NOT ENFORCED ]`
2240    pub enforced: Option<bool>,
2241}
2242
2243/// Initial setting for deferrable constraints (`INITIALLY IMMEDIATE` or `INITIALLY DEFERRED`).
2244#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2245#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2246#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2247pub enum DeferrableInitial {
2248    /// `INITIALLY IMMEDIATE`
2249    Immediate,
2250    /// `INITIALLY DEFERRED`
2251    Deferred,
2252}
2253
2254impl ConstraintCharacteristics {
2255    fn deferrable_text(&self) -> Option<&'static str> {
2256        self.deferrable.map(|deferrable| {
2257            if deferrable {
2258                "DEFERRABLE"
2259            } else {
2260                "NOT DEFERRABLE"
2261            }
2262        })
2263    }
2264
2265    fn initially_immediate_text(&self) -> Option<&'static str> {
2266        self.initially
2267            .map(|initially_immediate| match initially_immediate {
2268                DeferrableInitial::Immediate => "INITIALLY IMMEDIATE",
2269                DeferrableInitial::Deferred => "INITIALLY DEFERRED",
2270            })
2271    }
2272
2273    fn enforced_text(&self) -> Option<&'static str> {
2274        self.enforced.map(
2275            |enforced| {
2276                if enforced {
2277                    "ENFORCED"
2278                } else {
2279                    "NOT ENFORCED"
2280                }
2281            },
2282        )
2283    }
2284}
2285
2286impl fmt::Display for ConstraintCharacteristics {
2287    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2288        let deferrable = self.deferrable_text();
2289        let initially_immediate = self.initially_immediate_text();
2290        let enforced = self.enforced_text();
2291
2292        match (deferrable, initially_immediate, enforced) {
2293            (None, None, None) => Ok(()),
2294            (None, None, Some(enforced)) => write!(f, "{enforced}"),
2295            (None, Some(initial), None) => write!(f, "{initial}"),
2296            (None, Some(initial), Some(enforced)) => write!(f, "{initial} {enforced}"),
2297            (Some(deferrable), None, None) => write!(f, "{deferrable}"),
2298            (Some(deferrable), None, Some(enforced)) => write!(f, "{deferrable} {enforced}"),
2299            (Some(deferrable), Some(initial), None) => write!(f, "{deferrable} {initial}"),
2300            (Some(deferrable), Some(initial), Some(enforced)) => {
2301                write!(f, "{deferrable} {initial} {enforced}")
2302            }
2303        }
2304    }
2305}
2306
2307/// `<referential_action> =
2308/// { RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT }`
2309///
2310/// Used in foreign key constraints in `ON UPDATE` and `ON DELETE` options.
2311#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2312#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2313#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2314pub enum ReferentialAction {
2315    /// `RESTRICT` - disallow action if it would break referential integrity.
2316    Restrict,
2317    /// `CASCADE` - propagate the action to referencing rows.
2318    Cascade,
2319    /// `SET NULL` - set referencing columns to NULL.
2320    SetNull,
2321    /// `NO ACTION` - no action at the time; may be deferred.
2322    NoAction,
2323    /// `SET DEFAULT` - set referencing columns to their default values.
2324    SetDefault,
2325}
2326
2327impl fmt::Display for ReferentialAction {
2328    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2329        f.write_str(match self {
2330            ReferentialAction::Restrict => "RESTRICT",
2331            ReferentialAction::Cascade => "CASCADE",
2332            ReferentialAction::SetNull => "SET NULL",
2333            ReferentialAction::NoAction => "NO ACTION",
2334            ReferentialAction::SetDefault => "SET DEFAULT",
2335        })
2336    }
2337}
2338
2339/// `<drop behavior> ::= CASCADE | RESTRICT`.
2340///
2341/// Used in `DROP` statements.
2342#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2343#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2344#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2345pub enum DropBehavior {
2346    /// `RESTRICT` - refuse to drop if there are any dependent objects.
2347    Restrict,
2348    /// `CASCADE` - automatically drop objects that depend on the object being dropped.
2349    Cascade,
2350}
2351
2352impl fmt::Display for DropBehavior {
2353    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2354        f.write_str(match self {
2355            DropBehavior::Restrict => "RESTRICT",
2356            DropBehavior::Cascade => "CASCADE",
2357        })
2358    }
2359}
2360
2361/// SQL user defined type definition
2362#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2363#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2364#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2365pub enum UserDefinedTypeRepresentation {
2366    /// Composite type: `CREATE TYPE name AS (attributes)`
2367    Composite {
2368        /// List of attributes for the composite type.
2369        attributes: Vec<UserDefinedTypeCompositeAttributeDef>,
2370    },
2371    /// Enum type: `CREATE TYPE name AS ENUM (labels)`
2372    ///
2373    /// Note: this is PostgreSQL-specific. See <https://www.postgresql.org/docs/current/sql-createtype.html>
2374    /// Enum type: `CREATE TYPE name AS ENUM (labels)`
2375    Enum {
2376        /// Labels that make up the enum type.
2377        labels: Vec<Ident>,
2378    },
2379    /// Range type: `CREATE TYPE name AS RANGE (options)`
2380    ///
2381    /// Note: this is PostgreSQL-specific. See <https://www.postgresql.org/docs/current/sql-createtype.html>
2382    Range {
2383        /// Options for the range type definition.
2384        options: Vec<UserDefinedTypeRangeOption>,
2385    },
2386    /// Base type (SQL definition): `CREATE TYPE name (options)`
2387    ///
2388    /// Note the lack of `AS` keyword
2389    ///
2390    /// Note: this is PostgreSQL-specific. See <https://www.postgresql.org/docs/current/sql-createtype.html>
2391    SqlDefinition {
2392        /// Options for SQL definition of the user-defined type.
2393        options: Vec<UserDefinedTypeSqlDefinitionOption>,
2394    },
2395}
2396
2397impl fmt::Display for UserDefinedTypeRepresentation {
2398    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2399        match self {
2400            Self::Composite { attributes } => {
2401                write!(f, "AS ({})", display_comma_separated(attributes))
2402            }
2403            Self::Enum { labels } => {
2404                write!(f, "AS ENUM ({})", display_comma_separated(labels))
2405            }
2406            Self::Range { options } => {
2407                write!(f, "AS RANGE ({})", display_comma_separated(options))
2408            }
2409            Self::SqlDefinition { options } => {
2410                write!(f, "({})", display_comma_separated(options))
2411            }
2412        }
2413    }
2414}
2415
2416/// SQL user defined type attribute definition
2417#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2418#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2419#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2420pub struct UserDefinedTypeCompositeAttributeDef {
2421    /// Attribute name.
2422    pub name: Ident,
2423    /// Attribute data type.
2424    pub data_type: DataType,
2425    /// Optional collation for the attribute.
2426    pub collation: Option<ObjectName>,
2427}
2428
2429impl fmt::Display for UserDefinedTypeCompositeAttributeDef {
2430    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2431        write!(f, "{} {}", self.name, self.data_type)?;
2432        if let Some(collation) = &self.collation {
2433            write!(f, " COLLATE {collation}")?;
2434        }
2435        Ok(())
2436    }
2437}
2438
2439/// Internal length specification for PostgreSQL user-defined base types.
2440///
2441/// Specifies the internal length in bytes of the new type's internal representation.
2442/// The default assumption is that it is variable-length.
2443///
2444/// # PostgreSQL Documentation
2445/// See: <https://www.postgresql.org/docs/current/sql-createtype.html>
2446///
2447/// # Examples
2448/// ```sql
2449/// CREATE TYPE mytype (
2450///     INPUT = in_func,
2451///     OUTPUT = out_func,
2452///     INTERNALLENGTH = 16  -- Fixed 16-byte length
2453/// );
2454///
2455/// CREATE TYPE mytype2 (
2456///     INPUT = in_func,
2457///     OUTPUT = out_func,
2458///     INTERNALLENGTH = VARIABLE  -- Variable length
2459/// );
2460/// ```
2461#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2462#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2463#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2464pub enum UserDefinedTypeInternalLength {
2465    /// Fixed internal length: `INTERNALLENGTH = <number>`
2466    Fixed(u64),
2467    /// Variable internal length: `INTERNALLENGTH = VARIABLE`
2468    Variable,
2469}
2470
2471impl fmt::Display for UserDefinedTypeInternalLength {
2472    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2473        match self {
2474            UserDefinedTypeInternalLength::Fixed(n) => write!(f, "{}", n),
2475            UserDefinedTypeInternalLength::Variable => write!(f, "VARIABLE"),
2476        }
2477    }
2478}
2479
2480/// Alignment specification for PostgreSQL user-defined base types.
2481///
2482/// Specifies the storage alignment requirement for values of the data type.
2483/// The allowed values equate to alignment on 1, 2, 4, or 8 byte boundaries.
2484/// Note that variable-length types must have an alignment of at least 4, since
2485/// they necessarily contain an int4 as their first component.
2486///
2487/// # PostgreSQL Documentation
2488/// See: <https://www.postgresql.org/docs/current/sql-createtype.html>
2489///
2490/// # Examples
2491/// ```sql
2492/// CREATE TYPE mytype (
2493///     INPUT = in_func,
2494///     OUTPUT = out_func,
2495///     ALIGNMENT = int4  -- 4-byte alignment
2496/// );
2497/// ```
2498#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2499#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2500#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2501pub enum Alignment {
2502    /// Single-byte alignment: `ALIGNMENT = char`
2503    Char,
2504    /// 2-byte alignment: `ALIGNMENT = int2`
2505    Int2,
2506    /// 4-byte alignment: `ALIGNMENT = int4`
2507    Int4,
2508    /// 8-byte alignment: `ALIGNMENT = double`
2509    Double,
2510}
2511
2512impl fmt::Display for Alignment {
2513    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2514        match self {
2515            Alignment::Char => write!(f, "char"),
2516            Alignment::Int2 => write!(f, "int2"),
2517            Alignment::Int4 => write!(f, "int4"),
2518            Alignment::Double => write!(f, "double"),
2519        }
2520    }
2521}
2522
2523/// Storage specification for PostgreSQL user-defined base types.
2524///
2525/// Specifies the storage strategy for values of the data type:
2526/// - `plain`: Prevents compression and out-of-line storage (for fixed-length types)
2527/// - `external`: Allows out-of-line storage but not compression
2528/// - `extended`: Allows both compression and out-of-line storage (default for most types)
2529/// - `main`: Allows compression but discourages out-of-line storage
2530///
2531/// # PostgreSQL Documentation
2532/// See: <https://www.postgresql.org/docs/current/sql-createtype.html>
2533///
2534/// # Examples
2535/// ```sql
2536/// CREATE TYPE mytype (
2537///     INPUT = in_func,
2538///     OUTPUT = out_func,
2539///     STORAGE = plain
2540/// );
2541/// ```
2542#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2543#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2544#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2545pub enum UserDefinedTypeStorage {
2546    /// No compression or out-of-line storage: `STORAGE = plain`
2547    Plain,
2548    /// Out-of-line storage allowed, no compression: `STORAGE = external`
2549    External,
2550    /// Both compression and out-of-line storage allowed: `STORAGE = extended`
2551    Extended,
2552    /// Compression allowed, out-of-line discouraged: `STORAGE = main`
2553    Main,
2554}
2555
2556impl fmt::Display for UserDefinedTypeStorage {
2557    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2558        match self {
2559            UserDefinedTypeStorage::Plain => write!(f, "plain"),
2560            UserDefinedTypeStorage::External => write!(f, "external"),
2561            UserDefinedTypeStorage::Extended => write!(f, "extended"),
2562            UserDefinedTypeStorage::Main => write!(f, "main"),
2563        }
2564    }
2565}
2566
2567/// Options for PostgreSQL `CREATE TYPE ... AS RANGE` statement.
2568///
2569/// Range types are data types representing a range of values of some element type
2570/// (called the range's subtype). These options configure the behavior of the range type.
2571///
2572/// # PostgreSQL Documentation
2573/// See: <https://www.postgresql.org/docs/current/sql-createtype.html>
2574///
2575/// # Examples
2576/// ```sql
2577/// CREATE TYPE int4range AS RANGE (
2578///     SUBTYPE = int4,
2579///     SUBTYPE_OPCLASS = int4_ops,
2580///     CANONICAL = int4range_canonical,
2581///     SUBTYPE_DIFF = int4range_subdiff
2582/// );
2583/// ```
2584#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2585#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2586#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2587pub enum UserDefinedTypeRangeOption {
2588    /// The element type that the range type will represent: `SUBTYPE = subtype`
2589    Subtype(DataType),
2590    /// The operator class for the subtype: `SUBTYPE_OPCLASS = subtype_operator_class`
2591    SubtypeOpClass(ObjectName),
2592    /// Collation to use for ordering the subtype: `COLLATION = collation`
2593    Collation(ObjectName),
2594    /// Function to convert range values to canonical form: `CANONICAL = canonical_function`
2595    Canonical(ObjectName),
2596    /// Function to compute the difference between two subtype values: `SUBTYPE_DIFF = subtype_diff_function`
2597    SubtypeDiff(ObjectName),
2598    /// Name of the corresponding multirange type: `MULTIRANGE_TYPE_NAME = multirange_type_name`
2599    MultirangeTypeName(ObjectName),
2600}
2601
2602impl fmt::Display for UserDefinedTypeRangeOption {
2603    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2604        match self {
2605            UserDefinedTypeRangeOption::Subtype(dt) => write!(f, "SUBTYPE = {}", dt),
2606            UserDefinedTypeRangeOption::SubtypeOpClass(name) => {
2607                write!(f, "SUBTYPE_OPCLASS = {}", name)
2608            }
2609            UserDefinedTypeRangeOption::Collation(name) => write!(f, "COLLATION = {}", name),
2610            UserDefinedTypeRangeOption::Canonical(name) => write!(f, "CANONICAL = {}", name),
2611            UserDefinedTypeRangeOption::SubtypeDiff(name) => write!(f, "SUBTYPE_DIFF = {}", name),
2612            UserDefinedTypeRangeOption::MultirangeTypeName(name) => {
2613                write!(f, "MULTIRANGE_TYPE_NAME = {}", name)
2614            }
2615        }
2616    }
2617}
2618
2619/// Options for PostgreSQL `CREATE TYPE ... (<options>)` statement (base type definition).
2620///
2621/// Base types are the lowest-level data types in PostgreSQL. To define a new base type,
2622/// you must specify functions that convert it to and from text representation, and optionally
2623/// binary representation and other properties.
2624///
2625/// Note: This syntax uses parentheses directly after the type name, without the `AS` keyword.
2626///
2627/// # PostgreSQL Documentation
2628/// See: <https://www.postgresql.org/docs/current/sql-createtype.html>
2629///
2630/// # Examples
2631/// ```sql
2632/// CREATE TYPE complex (
2633///     INPUT = complex_in,
2634///     OUTPUT = complex_out,
2635///     INTERNALLENGTH = 16,
2636///     ALIGNMENT = double
2637/// );
2638/// ```
2639#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2640#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2641#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2642pub enum UserDefinedTypeSqlDefinitionOption {
2643    /// Function to convert from external text representation to internal: `INPUT = input_function`
2644    Input(ObjectName),
2645    /// Function to convert from internal to external text representation: `OUTPUT = output_function`
2646    Output(ObjectName),
2647    /// Function to convert from external binary representation to internal: `RECEIVE = receive_function`
2648    Receive(ObjectName),
2649    /// Function to convert from internal to external binary representation: `SEND = send_function`
2650    Send(ObjectName),
2651    /// Function to convert type modifiers from text array to internal form: `TYPMOD_IN = type_modifier_input_function`
2652    TypmodIn(ObjectName),
2653    /// Function to convert type modifiers from internal to text form: `TYPMOD_OUT = type_modifier_output_function`
2654    TypmodOut(ObjectName),
2655    /// Function to compute statistics for the data type: `ANALYZE = analyze_function`
2656    Analyze(ObjectName),
2657    /// Function to handle subscripting operations: `SUBSCRIPT = subscript_function`
2658    Subscript(ObjectName),
2659    /// Internal storage size in bytes, or VARIABLE for variable-length: `INTERNALLENGTH = { internallength | VARIABLE }`
2660    InternalLength(UserDefinedTypeInternalLength),
2661    /// Indicates values are passed by value rather than by reference: `PASSEDBYVALUE`
2662    PassedByValue,
2663    /// Storage alignment requirement (1, 2, 4, or 8 bytes): `ALIGNMENT = alignment`
2664    Alignment(Alignment),
2665    /// Storage strategy for varlena types: `STORAGE = storage`
2666    Storage(UserDefinedTypeStorage),
2667    /// Copy properties from an existing type: `LIKE = like_type`
2668    Like(ObjectName),
2669    /// Type category for implicit casting rules (single char): `CATEGORY = category`
2670    Category(char),
2671    /// Whether this type is preferred within its category: `PREFERRED = preferred`
2672    Preferred(bool),
2673    /// Default value for the type: `DEFAULT = default`
2674    Default(Expr),
2675    /// Element type for array types: `ELEMENT = element`
2676    Element(DataType),
2677    /// Delimiter character for array value display: `DELIMITER = delimiter`
2678    Delimiter(String),
2679    /// Whether the type supports collation: `COLLATABLE = collatable`
2680    Collatable(bool),
2681}
2682
2683impl fmt::Display for UserDefinedTypeSqlDefinitionOption {
2684    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2685        match self {
2686            UserDefinedTypeSqlDefinitionOption::Input(name) => write!(f, "INPUT = {}", name),
2687            UserDefinedTypeSqlDefinitionOption::Output(name) => write!(f, "OUTPUT = {}", name),
2688            UserDefinedTypeSqlDefinitionOption::Receive(name) => write!(f, "RECEIVE = {}", name),
2689            UserDefinedTypeSqlDefinitionOption::Send(name) => write!(f, "SEND = {}", name),
2690            UserDefinedTypeSqlDefinitionOption::TypmodIn(name) => write!(f, "TYPMOD_IN = {}", name),
2691            UserDefinedTypeSqlDefinitionOption::TypmodOut(name) => {
2692                write!(f, "TYPMOD_OUT = {}", name)
2693            }
2694            UserDefinedTypeSqlDefinitionOption::Analyze(name) => write!(f, "ANALYZE = {}", name),
2695            UserDefinedTypeSqlDefinitionOption::Subscript(name) => {
2696                write!(f, "SUBSCRIPT = {}", name)
2697            }
2698            UserDefinedTypeSqlDefinitionOption::InternalLength(len) => {
2699                write!(f, "INTERNALLENGTH = {}", len)
2700            }
2701            UserDefinedTypeSqlDefinitionOption::PassedByValue => write!(f, "PASSEDBYVALUE"),
2702            UserDefinedTypeSqlDefinitionOption::Alignment(align) => {
2703                write!(f, "ALIGNMENT = {}", align)
2704            }
2705            UserDefinedTypeSqlDefinitionOption::Storage(storage) => {
2706                write!(f, "STORAGE = {}", storage)
2707            }
2708            UserDefinedTypeSqlDefinitionOption::Like(name) => write!(f, "LIKE = {}", name),
2709            UserDefinedTypeSqlDefinitionOption::Category(c) => write!(f, "CATEGORY = '{}'", c),
2710            UserDefinedTypeSqlDefinitionOption::Preferred(b) => write!(f, "PREFERRED = {}", b),
2711            UserDefinedTypeSqlDefinitionOption::Default(expr) => write!(f, "DEFAULT = {}", expr),
2712            UserDefinedTypeSqlDefinitionOption::Element(dt) => write!(f, "ELEMENT = {}", dt),
2713            UserDefinedTypeSqlDefinitionOption::Delimiter(s) => {
2714                write!(f, "DELIMITER = '{}'", escape_single_quote_string(s))
2715            }
2716            UserDefinedTypeSqlDefinitionOption::Collatable(b) => write!(f, "COLLATABLE = {}", b),
2717        }
2718    }
2719}
2720
2721/// PARTITION statement used in ALTER TABLE et al. such as in Hive and ClickHouse SQL.
2722/// For example, ClickHouse's OPTIMIZE TABLE supports syntax like PARTITION ID 'partition_id' and PARTITION expr.
2723/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
2724#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
2725#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2726#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2727pub enum Partition {
2728    /// ClickHouse supports PARTITION ID 'partition_id' syntax.
2729    Identifier(Ident),
2730    /// ClickHouse supports PARTITION expr syntax.
2731    Expr(Expr),
2732    /// ClickHouse supports PART expr which represents physical partition in disk.
2733    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#attach-partitionpart)
2734    Part(Expr),
2735    /// Hive supports multiple partitions in PARTITION (part1, part2, ...) syntax.
2736    Partitions(Vec<Expr>),
2737}
2738
2739impl fmt::Display for Partition {
2740    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2741        match self {
2742            Partition::Identifier(id) => write!(f, "PARTITION ID {id}"),
2743            Partition::Expr(expr) => write!(f, "PARTITION {expr}"),
2744            Partition::Part(expr) => write!(f, "PART {expr}"),
2745            Partition::Partitions(partitions) => {
2746                write!(f, "PARTITION ({})", display_comma_separated(partitions))
2747            }
2748        }
2749    }
2750}
2751
2752/// DEDUPLICATE statement used in OPTIMIZE TABLE et al. such as in ClickHouse SQL
2753/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
2754#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2755#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2756#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2757pub enum Deduplicate {
2758    /// DEDUPLICATE ALL
2759    All,
2760    /// DEDUPLICATE BY expr
2761    ByExpression(Expr),
2762}
2763
2764impl fmt::Display for Deduplicate {
2765    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2766        match self {
2767            Deduplicate::All => write!(f, "DEDUPLICATE"),
2768            Deduplicate::ByExpression(expr) => write!(f, "DEDUPLICATE BY {expr}"),
2769        }
2770    }
2771}
2772
2773/// Hive supports `CLUSTERED BY` statement in `CREATE TABLE`.
2774/// Syntax: `CLUSTERED BY (col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS`
2775///
2776/// [Hive](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable)
2777#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2778#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2779#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2780pub struct ClusteredBy {
2781    /// columns used for clustering
2782    pub columns: Vec<Ident>,
2783    /// optional sorted by expressions
2784    pub sorted_by: Option<Vec<OrderByExpr>>,
2785    /// number of buckets
2786    pub num_buckets: Value,
2787}
2788
2789impl fmt::Display for ClusteredBy {
2790    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2791        write!(
2792            f,
2793            "CLUSTERED BY ({})",
2794            display_comma_separated(&self.columns)
2795        )?;
2796        if let Some(ref sorted_by) = self.sorted_by {
2797            write!(f, " SORTED BY ({})", display_comma_separated(sorted_by))?;
2798        }
2799        write!(f, " INTO {} BUCKETS", self.num_buckets)
2800    }
2801}
2802
2803/// CREATE INDEX statement.
2804#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2805#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2806#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2807pub struct CreateIndex {
2808    /// index name
2809    pub name: Option<ObjectName>,
2810    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
2811    /// table name
2812    pub table_name: ObjectName,
2813    /// Index type used in the statement. Can also be found inside [`CreateIndex::index_options`]
2814    /// depending on the position of the option within the statement.
2815    pub using: Option<IndexType>,
2816    /// columns included in the index
2817    pub columns: Vec<IndexColumn>,
2818    /// whether the index is unique
2819    pub unique: bool,
2820    /// whether the index is created concurrently
2821    pub concurrently: bool,
2822    /// IF NOT EXISTS clause
2823    pub if_not_exists: bool,
2824    /// INCLUDE clause: <https://www.postgresql.org/docs/current/sql-createindex.html>
2825    pub include: Vec<Ident>,
2826    /// NULLS DISTINCT / NOT DISTINCT clause: <https://www.postgresql.org/docs/current/sql-createindex.html>
2827    pub nulls_distinct: Option<bool>,
2828    /// WITH clause: <https://www.postgresql.org/docs/current/sql-createindex.html>
2829    pub with: Vec<Expr>,
2830    /// WHERE clause: <https://www.postgresql.org/docs/current/sql-createindex.html>
2831    pub predicate: Option<Expr>,
2832    /// Index options: <https://www.postgresql.org/docs/current/sql-createindex.html>
2833    pub index_options: Vec<IndexOption>,
2834    /// [MySQL] allows a subset of options normally used for `ALTER TABLE`:
2835    ///
2836    /// - `ALGORITHM`
2837    /// - `LOCK`
2838    ///
2839    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/create-index.html
2840    pub alter_options: Vec<AlterTableOperation>,
2841}
2842
2843impl fmt::Display for CreateIndex {
2844    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2845        write!(
2846            f,
2847            "CREATE {unique}INDEX {concurrently}{if_not_exists}",
2848            unique = if self.unique { "UNIQUE " } else { "" },
2849            concurrently = if self.concurrently {
2850                "CONCURRENTLY "
2851            } else {
2852                ""
2853            },
2854            if_not_exists = if self.if_not_exists {
2855                "IF NOT EXISTS "
2856            } else {
2857                ""
2858            },
2859        )?;
2860        if let Some(value) = &self.name {
2861            write!(f, "{value} ")?;
2862        }
2863        write!(f, "ON {}", self.table_name)?;
2864        if let Some(value) = &self.using {
2865            write!(f, " USING {value} ")?;
2866        }
2867        write!(f, "({})", display_comma_separated(&self.columns))?;
2868        if !self.include.is_empty() {
2869            write!(f, " INCLUDE ({})", display_comma_separated(&self.include))?;
2870        }
2871        if let Some(value) = self.nulls_distinct {
2872            if value {
2873                write!(f, " NULLS DISTINCT")?;
2874            } else {
2875                write!(f, " NULLS NOT DISTINCT")?;
2876            }
2877        }
2878        if !self.with.is_empty() {
2879            write!(f, " WITH ({})", display_comma_separated(&self.with))?;
2880        }
2881        if let Some(predicate) = &self.predicate {
2882            write!(f, " WHERE {predicate}")?;
2883        }
2884        if !self.index_options.is_empty() {
2885            write!(f, " {}", display_separated(&self.index_options, " "))?;
2886        }
2887        if !self.alter_options.is_empty() {
2888            write!(f, " {}", display_separated(&self.alter_options, " "))?;
2889        }
2890        Ok(())
2891    }
2892}
2893
2894/// CREATE TABLE statement.
2895#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2896#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2897#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2898pub struct CreateTable {
2899    /// `OR REPLACE` clause
2900    pub or_replace: bool,
2901    /// `TEMP` or `TEMPORARY` clause
2902    pub temporary: bool,
2903    /// `EXTERNAL` clause
2904    pub external: bool,
2905    /// `DYNAMIC` clause
2906    pub dynamic: bool,
2907    /// `GLOBAL` clause
2908    pub global: Option<bool>,
2909    /// `IF NOT EXISTS` clause
2910    pub if_not_exists: bool,
2911    /// `TRANSIENT` clause
2912    pub transient: bool,
2913    /// `VOLATILE` clause
2914    pub volatile: bool,
2915    /// `ICEBERG` clause
2916    pub iceberg: bool,
2917    /// `SNAPSHOT` clause
2918    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_snapshot_table_statement>
2919    pub snapshot: bool,
2920    /// Table name
2921    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
2922    pub name: ObjectName,
2923    /// Column definitions
2924    pub columns: Vec<ColumnDef>,
2925    /// Table constraints
2926    pub constraints: Vec<TableConstraint>,
2927    /// Hive-specific distribution style
2928    pub hive_distribution: HiveDistributionStyle,
2929    /// Hive-specific formats like `ROW FORMAT DELIMITED` or `ROW FORMAT SERDE 'serde_class' WITH SERDEPROPERTIES (...)`
2930    pub hive_formats: Option<HiveFormat>,
2931    /// Table options
2932    pub table_options: CreateTableOptions,
2933    /// General comment for the table
2934    pub file_format: Option<FileFormat>,
2935    /// Location of the table data
2936    pub location: Option<String>,
2937    /// Query used to populate the table
2938    pub query: Option<Box<Query>>,
2939    /// If the table should be created without a rowid (SQLite)
2940    pub without_rowid: bool,
2941    /// `LIKE` clause
2942    pub like: Option<CreateTableLikeKind>,
2943    /// `CLONE` clause
2944    pub clone: Option<ObjectName>,
2945    /// Table version (for systems that support versioned tables)
2946    pub version: Option<TableVersion>,
2947    /// For Hive dialect, the table comment is after the column definitions without `=`,
2948    /// so the `comment` field is optional and different than the comment field in the general options list.
2949    /// [Hive](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable)
2950    pub comment: Option<CommentDef>,
2951    /// ClickHouse "ON COMMIT" clause:
2952    /// <https://clickhouse.com/docs/en/sql-reference/statements/create/table/>
2953    pub on_commit: Option<OnCommit>,
2954    /// ClickHouse "ON CLUSTER" clause:
2955    /// <https://clickhouse.com/docs/en/sql-reference/distributed-ddl/>
2956    pub on_cluster: Option<Ident>,
2957    /// ClickHouse "PRIMARY KEY " clause.
2958    /// <https://clickhouse.com/docs/en/sql-reference/statements/create/table/>
2959    pub primary_key: Option<Box<Expr>>,
2960    /// ClickHouse "ORDER BY " clause. Note that omitted ORDER BY is different
2961    /// than empty (represented as ()), the latter meaning "no sorting".
2962    /// <https://clickhouse.com/docs/en/sql-reference/statements/create/table/>
2963    pub order_by: Option<OneOrManyWithParens<Expr>>,
2964    /// BigQuery: A partition expression for the table.
2965    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#partition_expression>
2966    pub partition_by: Option<Box<Expr>>,
2967    /// BigQuery: Table clustering column list.
2968    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
2969    /// Snowflake: Table clustering list which contains base column, expressions on base columns.
2970    /// <https://docs.snowflake.com/en/user-guide/tables-clustering-keys#defining-a-clustering-key-for-a-table>
2971    pub cluster_by: Option<WrappedCollection<Vec<Expr>>>,
2972    /// Hive: Table clustering column list.
2973    /// <https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable>
2974    pub clustered_by: Option<ClusteredBy>,
2975    /// Postgres `INHERITs` clause, which contains the list of tables from which
2976    /// the new table inherits.
2977    /// <https://www.postgresql.org/docs/current/ddl-inherit.html>
2978    /// <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-INHERITS>
2979    pub inherits: Option<Vec<ObjectName>>,
2980    /// PostgreSQL `PARTITION OF` clause to create a partition of a parent table.
2981    /// Contains the parent table name.
2982    /// <https://www.postgresql.org/docs/current/sql-createtable.html>
2983    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
2984    pub partition_of: Option<ObjectName>,
2985    /// PostgreSQL partition bound specification for PARTITION OF.
2986    /// <https://www.postgresql.org/docs/current/sql-createtable.html>
2987    pub for_values: Option<ForValues>,
2988    /// SQLite "STRICT" clause.
2989    /// if the "STRICT" table-option keyword is added to the end, after the closing ")",
2990    /// then strict typing rules apply to that table.
2991    pub strict: bool,
2992    /// Snowflake "COPY GRANTS" clause
2993    /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
2994    pub copy_grants: bool,
2995    /// Snowflake "ENABLE_SCHEMA_EVOLUTION" clause
2996    /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
2997    pub enable_schema_evolution: Option<bool>,
2998    /// Snowflake "CHANGE_TRACKING" clause
2999    /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
3000    pub change_tracking: Option<bool>,
3001    /// Snowflake "DATA_RETENTION_TIME_IN_DAYS" clause
3002    /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
3003    pub data_retention_time_in_days: Option<u64>,
3004    /// Snowflake "MAX_DATA_EXTENSION_TIME_IN_DAYS" clause
3005    /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
3006    pub max_data_extension_time_in_days: Option<u64>,
3007    /// Snowflake "DEFAULT_DDL_COLLATION" clause
3008    /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
3009    pub default_ddl_collation: Option<String>,
3010    /// Snowflake "WITH AGGREGATION POLICY" clause
3011    /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
3012    pub with_aggregation_policy: Option<ObjectName>,
3013    /// Snowflake "WITH ROW ACCESS POLICY" clause
3014    /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
3015    pub with_row_access_policy: Option<RowAccessPolicy>,
3016    /// Snowflake `WITH STORAGE LIFECYCLE POLICY` clause
3017    /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
3018    pub with_storage_lifecycle_policy: Option<StorageLifecyclePolicy>,
3019    /// Snowflake "WITH TAG" clause
3020    /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
3021    pub with_tags: Option<Vec<Tag>>,
3022    /// Snowflake "EXTERNAL_VOLUME" clause for Iceberg tables
3023    /// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
3024    pub external_volume: Option<String>,
3025    /// Snowflake "BASE_LOCATION" clause for Iceberg tables
3026    /// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
3027    pub base_location: Option<String>,
3028    /// Snowflake "CATALOG" clause for Iceberg tables
3029    /// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
3030    pub catalog: Option<String>,
3031    /// Snowflake "CATALOG_SYNC" clause for Iceberg tables
3032    /// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
3033    pub catalog_sync: Option<String>,
3034    /// Snowflake "STORAGE_SERIALIZATION_POLICY" clause for Iceberg tables
3035    /// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
3036    pub storage_serialization_policy: Option<StorageSerializationPolicy>,
3037    /// Snowflake "TARGET_LAG" clause for dybamic tables
3038    /// <https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table>
3039    pub target_lag: Option<String>,
3040    /// Snowflake "WAREHOUSE" clause for dybamic tables
3041    /// <https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table>
3042    pub warehouse: Option<Ident>,
3043    /// Snowflake "REFRESH_MODE" clause for dybamic tables
3044    /// <https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table>
3045    pub refresh_mode: Option<RefreshModeKind>,
3046    /// Snowflake "INITIALIZE" clause for dybamic tables
3047    /// <https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table>
3048    pub initialize: Option<InitializeKind>,
3049    /// Snowflake "REQUIRE USER" clause for dybamic tables
3050    /// <https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table>
3051    pub require_user: bool,
3052    /// Redshift `DISTSTYLE` option
3053    /// <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html>
3054    pub diststyle: Option<DistStyle>,
3055    /// Redshift `DISTKEY` option
3056    /// <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html>
3057    pub distkey: Option<Expr>,
3058    /// Redshift `SORTKEY` option
3059    /// <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html>
3060    pub sortkey: Option<Vec<Expr>>,
3061    /// Redshift `BACKUP` option: `BACKUP { YES | NO }`
3062    /// <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html>
3063    pub backup: Option<bool>,
3064}
3065
3066impl fmt::Display for CreateTable {
3067    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3068        // We want to allow the following options
3069        // Empty column list, allowed by PostgreSQL:
3070        //   `CREATE TABLE t ()`
3071        // No columns provided for CREATE TABLE AS:
3072        //   `CREATE TABLE t AS SELECT a from t2`
3073        // Columns provided for CREATE TABLE AS:
3074        //   `CREATE TABLE t (a INT) AS SELECT a from t2`
3075        write!(
3076            f,
3077            "CREATE {or_replace}{external}{global}{temporary}{transient}{volatile}{dynamic}{iceberg}{snapshot}TABLE {if_not_exists}{name}",
3078            or_replace = if self.or_replace { "OR REPLACE " } else { "" },
3079            external = if self.external { "EXTERNAL " } else { "" },
3080            snapshot = if self.snapshot { "SNAPSHOT " } else { "" },
3081            global = self.global
3082                .map(|global| {
3083                    if global {
3084                        "GLOBAL "
3085                    } else {
3086                        "LOCAL "
3087                    }
3088                })
3089                .unwrap_or(""),
3090            if_not_exists = if self.if_not_exists { "IF NOT EXISTS " } else { "" },
3091            temporary = if self.temporary { "TEMPORARY " } else { "" },
3092            transient = if self.transient { "TRANSIENT " } else { "" },
3093            volatile = if self.volatile { "VOLATILE " } else { "" },
3094            // Only for Snowflake
3095            iceberg = if self.iceberg { "ICEBERG " } else { "" },
3096            dynamic = if self.dynamic { "DYNAMIC " } else { "" },
3097            name = self.name,
3098        )?;
3099        if let Some(partition_of) = &self.partition_of {
3100            write!(f, " PARTITION OF {partition_of}")?;
3101        }
3102        if let Some(on_cluster) = &self.on_cluster {
3103            write!(f, " ON CLUSTER {on_cluster}")?;
3104        }
3105        if !self.columns.is_empty() || !self.constraints.is_empty() {
3106            f.write_str(" (")?;
3107            NewLine.fmt(f)?;
3108            Indent(DisplayCommaSeparated(&self.columns)).fmt(f)?;
3109            if !self.columns.is_empty() && !self.constraints.is_empty() {
3110                f.write_str(",")?;
3111                SpaceOrNewline.fmt(f)?;
3112            }
3113            Indent(DisplayCommaSeparated(&self.constraints)).fmt(f)?;
3114            NewLine.fmt(f)?;
3115            f.write_str(")")?;
3116        } else if self.query.is_none()
3117            && self.like.is_none()
3118            && self.clone.is_none()
3119            && self.partition_of.is_none()
3120        {
3121            // PostgreSQL allows `CREATE TABLE t ();`, but requires empty parens
3122            f.write_str(" ()")?;
3123        } else if let Some(CreateTableLikeKind::Parenthesized(like_in_columns_list)) = &self.like {
3124            write!(f, " ({like_in_columns_list})")?;
3125        }
3126        if let Some(for_values) = &self.for_values {
3127            write!(f, " {for_values}")?;
3128        }
3129
3130        // Hive table comment should be after column definitions, please refer to:
3131        // [Hive](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable)
3132        if let Some(comment) = &self.comment {
3133            write!(f, " COMMENT '{comment}'")?;
3134        }
3135
3136        // Only for SQLite
3137        if self.without_rowid {
3138            write!(f, " WITHOUT ROWID")?;
3139        }
3140
3141        if let Some(CreateTableLikeKind::Plain(like)) = &self.like {
3142            write!(f, " {like}")?;
3143        }
3144
3145        if let Some(c) = &self.clone {
3146            write!(f, " CLONE {c}")?;
3147        }
3148
3149        if let Some(version) = &self.version {
3150            write!(f, " {version}")?;
3151        }
3152
3153        match &self.hive_distribution {
3154            HiveDistributionStyle::PARTITIONED { columns } => {
3155                write!(f, " PARTITIONED BY ({})", display_comma_separated(columns))?;
3156            }
3157            HiveDistributionStyle::SKEWED {
3158                columns,
3159                on,
3160                stored_as_directories,
3161            } => {
3162                write!(
3163                    f,
3164                    " SKEWED BY ({})) ON ({})",
3165                    display_comma_separated(columns),
3166                    display_comma_separated(on)
3167                )?;
3168                if *stored_as_directories {
3169                    write!(f, " STORED AS DIRECTORIES")?;
3170                }
3171            }
3172            _ => (),
3173        }
3174
3175        if let Some(clustered_by) = &self.clustered_by {
3176            write!(f, " {clustered_by}")?;
3177        }
3178
3179        if let Some(HiveFormat {
3180            row_format,
3181            serde_properties,
3182            storage,
3183            location,
3184        }) = &self.hive_formats
3185        {
3186            match row_format {
3187                Some(HiveRowFormat::SERDE { class }) => write!(f, " ROW FORMAT SERDE '{class}'")?,
3188                Some(HiveRowFormat::DELIMITED { delimiters }) => {
3189                    write!(f, " ROW FORMAT DELIMITED")?;
3190                    if !delimiters.is_empty() {
3191                        write!(f, " {}", display_separated(delimiters, " "))?;
3192                    }
3193                }
3194                None => (),
3195            }
3196            match storage {
3197                Some(HiveIOFormat::IOF {
3198                    input_format,
3199                    output_format,
3200                }) => write!(
3201                    f,
3202                    " STORED AS INPUTFORMAT {input_format} OUTPUTFORMAT {output_format}"
3203                )?,
3204                Some(HiveIOFormat::FileFormat { format }) if !self.external => {
3205                    write!(f, " STORED AS {format}")?
3206                }
3207                _ => (),
3208            }
3209            if let Some(serde_properties) = serde_properties.as_ref() {
3210                write!(
3211                    f,
3212                    " WITH SERDEPROPERTIES ({})",
3213                    display_comma_separated(serde_properties)
3214                )?;
3215            }
3216            if !self.external {
3217                if let Some(loc) = location {
3218                    write!(f, " LOCATION '{loc}'")?;
3219                }
3220            }
3221        }
3222        if self.external {
3223            if let Some(file_format) = self.file_format {
3224                write!(f, " STORED AS {file_format}")?;
3225            }
3226            if let Some(location) = &self.location {
3227                write!(f, " LOCATION '{location}'")?;
3228            }
3229        }
3230
3231        match &self.table_options {
3232            options @ CreateTableOptions::With(_)
3233            | options @ CreateTableOptions::Plain(_)
3234            | options @ CreateTableOptions::TableProperties(_) => write!(f, " {options}")?,
3235            _ => (),
3236        }
3237
3238        if let Some(primary_key) = &self.primary_key {
3239            write!(f, " PRIMARY KEY {primary_key}")?;
3240        }
3241        if let Some(order_by) = &self.order_by {
3242            write!(f, " ORDER BY {order_by}")?;
3243        }
3244        if let Some(inherits) = &self.inherits {
3245            write!(f, " INHERITS ({})", display_comma_separated(inherits))?;
3246        }
3247        if let Some(partition_by) = self.partition_by.as_ref() {
3248            write!(f, " PARTITION BY {partition_by}")?;
3249        }
3250        if let Some(cluster_by) = self.cluster_by.as_ref() {
3251            write!(f, " CLUSTER BY {cluster_by}")?;
3252        }
3253        if let options @ CreateTableOptions::Options(_) = &self.table_options {
3254            write!(f, " {options}")?;
3255        }
3256        if let Some(external_volume) = self.external_volume.as_ref() {
3257            write!(f, " EXTERNAL_VOLUME='{external_volume}'")?;
3258        }
3259
3260        if let Some(catalog) = self.catalog.as_ref() {
3261            write!(f, " CATALOG='{catalog}'")?;
3262        }
3263
3264        if self.iceberg {
3265            if let Some(base_location) = self.base_location.as_ref() {
3266                write!(f, " BASE_LOCATION='{base_location}'")?;
3267            }
3268        }
3269
3270        if let Some(catalog_sync) = self.catalog_sync.as_ref() {
3271            write!(f, " CATALOG_SYNC='{catalog_sync}'")?;
3272        }
3273
3274        if let Some(storage_serialization_policy) = self.storage_serialization_policy.as_ref() {
3275            write!(
3276                f,
3277                " STORAGE_SERIALIZATION_POLICY={storage_serialization_policy}"
3278            )?;
3279        }
3280
3281        if self.copy_grants {
3282            write!(f, " COPY GRANTS")?;
3283        }
3284
3285        if let Some(is_enabled) = self.enable_schema_evolution {
3286            write!(
3287                f,
3288                " ENABLE_SCHEMA_EVOLUTION={}",
3289                if is_enabled { "TRUE" } else { "FALSE" }
3290            )?;
3291        }
3292
3293        if let Some(is_enabled) = self.change_tracking {
3294            write!(
3295                f,
3296                " CHANGE_TRACKING={}",
3297                if is_enabled { "TRUE" } else { "FALSE" }
3298            )?;
3299        }
3300
3301        if let Some(data_retention_time_in_days) = self.data_retention_time_in_days {
3302            write!(
3303                f,
3304                " DATA_RETENTION_TIME_IN_DAYS={data_retention_time_in_days}",
3305            )?;
3306        }
3307
3308        if let Some(max_data_extension_time_in_days) = self.max_data_extension_time_in_days {
3309            write!(
3310                f,
3311                " MAX_DATA_EXTENSION_TIME_IN_DAYS={max_data_extension_time_in_days}",
3312            )?;
3313        }
3314
3315        if let Some(default_ddl_collation) = &self.default_ddl_collation {
3316            write!(f, " DEFAULT_DDL_COLLATION='{default_ddl_collation}'",)?;
3317        }
3318
3319        if let Some(with_aggregation_policy) = &self.with_aggregation_policy {
3320            write!(f, " WITH AGGREGATION POLICY {with_aggregation_policy}",)?;
3321        }
3322
3323        if let Some(row_access_policy) = &self.with_row_access_policy {
3324            write!(f, " {row_access_policy}",)?;
3325        }
3326
3327        if let Some(storage_lifecycle_policy) = &self.with_storage_lifecycle_policy {
3328            write!(f, " {storage_lifecycle_policy}",)?;
3329        }
3330
3331        if let Some(tag) = &self.with_tags {
3332            write!(f, " WITH TAG ({})", display_comma_separated(tag.as_slice()))?;
3333        }
3334
3335        if let Some(target_lag) = &self.target_lag {
3336            write!(f, " TARGET_LAG='{target_lag}'")?;
3337        }
3338
3339        if let Some(warehouse) = &self.warehouse {
3340            write!(f, " WAREHOUSE={warehouse}")?;
3341        }
3342
3343        if let Some(refresh_mode) = &self.refresh_mode {
3344            write!(f, " REFRESH_MODE={refresh_mode}")?;
3345        }
3346
3347        if let Some(initialize) = &self.initialize {
3348            write!(f, " INITIALIZE={initialize}")?;
3349        }
3350
3351        if self.require_user {
3352            write!(f, " REQUIRE USER")?;
3353        }
3354
3355        if self.on_commit.is_some() {
3356            let on_commit = match self.on_commit {
3357                Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS",
3358                Some(OnCommit::PreserveRows) => "ON COMMIT PRESERVE ROWS",
3359                Some(OnCommit::Drop) => "ON COMMIT DROP",
3360                None => "",
3361            };
3362            write!(f, " {on_commit}")?;
3363        }
3364        if self.strict {
3365            write!(f, " STRICT")?;
3366        }
3367        if let Some(backup) = self.backup {
3368            write!(f, " BACKUP {}", if backup { "YES" } else { "NO" })?;
3369        }
3370        if let Some(diststyle) = &self.diststyle {
3371            write!(f, " DISTSTYLE {diststyle}")?;
3372        }
3373        if let Some(distkey) = &self.distkey {
3374            write!(f, " DISTKEY({distkey})")?;
3375        }
3376        if let Some(sortkey) = &self.sortkey {
3377            write!(f, " SORTKEY({})", display_comma_separated(sortkey))?;
3378        }
3379        if let Some(query) = &self.query {
3380            write!(f, " AS {query}")?;
3381        }
3382        Ok(())
3383    }
3384}
3385
3386/// PostgreSQL partition bound specification for `PARTITION OF`.
3387///
3388/// Specifies partition bounds for a child partition table.
3389///
3390/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createtable.html)
3391#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3392#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3393#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3394pub enum ForValues {
3395    /// `FOR VALUES IN (expr, ...)`
3396    In(Vec<Expr>),
3397    /// `FOR VALUES FROM (expr|MINVALUE|MAXVALUE, ...) TO (expr|MINVALUE|MAXVALUE, ...)`
3398    From {
3399        /// The lower bound values for the partition.
3400        from: Vec<PartitionBoundValue>,
3401        /// The upper bound values for the partition.
3402        to: Vec<PartitionBoundValue>,
3403    },
3404    /// `FOR VALUES WITH (MODULUS n, REMAINDER r)`
3405    With {
3406        /// The modulus value for hash partitioning.
3407        modulus: u64,
3408        /// The remainder value for hash partitioning.
3409        remainder: u64,
3410    },
3411    /// `DEFAULT`
3412    Default,
3413}
3414
3415impl fmt::Display for ForValues {
3416    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3417        match self {
3418            ForValues::In(values) => {
3419                write!(f, "FOR VALUES IN ({})", display_comma_separated(values))
3420            }
3421            ForValues::From { from, to } => {
3422                write!(
3423                    f,
3424                    "FOR VALUES FROM ({}) TO ({})",
3425                    display_comma_separated(from),
3426                    display_comma_separated(to)
3427                )
3428            }
3429            ForValues::With { modulus, remainder } => {
3430                write!(
3431                    f,
3432                    "FOR VALUES WITH (MODULUS {modulus}, REMAINDER {remainder})"
3433                )
3434            }
3435            ForValues::Default => write!(f, "DEFAULT"),
3436        }
3437    }
3438}
3439
3440/// A value in a partition bound specification.
3441///
3442/// Used in RANGE partition bounds where values can be expressions,
3443/// MINVALUE (negative infinity), or MAXVALUE (positive infinity).
3444#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3445#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3446#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3447pub enum PartitionBoundValue {
3448    /// An expression representing a partition bound value.
3449    Expr(Expr),
3450    /// Represents negative infinity in partition bounds.
3451    MinValue,
3452    /// Represents positive infinity in partition bounds.
3453    MaxValue,
3454}
3455
3456impl fmt::Display for PartitionBoundValue {
3457    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3458        match self {
3459            PartitionBoundValue::Expr(expr) => write!(f, "{expr}"),
3460            PartitionBoundValue::MinValue => write!(f, "MINVALUE"),
3461            PartitionBoundValue::MaxValue => write!(f, "MAXVALUE"),
3462        }
3463    }
3464}
3465
3466/// Redshift distribution style for `CREATE TABLE`.
3467///
3468/// See [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
3469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3472pub enum DistStyle {
3473    /// `DISTSTYLE AUTO`
3474    Auto,
3475    /// `DISTSTYLE EVEN`
3476    Even,
3477    /// `DISTSTYLE KEY`
3478    Key,
3479    /// `DISTSTYLE ALL`
3480    All,
3481}
3482
3483impl fmt::Display for DistStyle {
3484    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3485        match self {
3486            DistStyle::Auto => write!(f, "AUTO"),
3487            DistStyle::Even => write!(f, "EVEN"),
3488            DistStyle::Key => write!(f, "KEY"),
3489            DistStyle::All => write!(f, "ALL"),
3490        }
3491    }
3492}
3493
3494
3495#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3496#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3497#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3498/// ```sql
3499/// CREATE DOMAIN name [ AS ] data_type
3500///         [ COLLATE collation ]
3501///         [ DEFAULT expression ]
3502///         [ domain_constraint [ ... ] ]
3503///
3504///     where domain_constraint is:
3505///
3506///     [ CONSTRAINT constraint_name ]
3507///     { NOT NULL | NULL | CHECK (expression) }
3508/// ```
3509/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createdomain.html)
3510pub struct CreateDomain {
3511    /// The name of the domain to be created.
3512    pub name: ObjectName,
3513    /// The data type of the domain.
3514    pub data_type: DataType,
3515    /// The collation of the domain.
3516    pub collation: Option<Ident>,
3517    /// The default value of the domain.
3518    pub default: Option<Expr>,
3519    /// The constraints of the domain.
3520    pub constraints: Vec<TableConstraint>,
3521}
3522
3523impl fmt::Display for CreateDomain {
3524    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3525        write!(
3526            f,
3527            "CREATE DOMAIN {name} AS {data_type}",
3528            name = self.name,
3529            data_type = self.data_type
3530        )?;
3531        if let Some(collation) = &self.collation {
3532            write!(f, " COLLATE {collation}")?;
3533        }
3534        if let Some(default) = &self.default {
3535            write!(f, " DEFAULT {default}")?;
3536        }
3537        if !self.constraints.is_empty() {
3538            write!(f, " {}", display_separated(&self.constraints, " "))?;
3539        }
3540        Ok(())
3541    }
3542}
3543
3544/// The return type of a `CREATE FUNCTION` statement.
3545#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3546#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3547#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3548pub enum FunctionReturnType {
3549    /// `RETURNS <type>`
3550    DataType(DataType),
3551    /// `RETURNS SETOF <type>`
3552    ///
3553    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
3554    SetOf(DataType),
3555}
3556
3557impl fmt::Display for FunctionReturnType {
3558    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3559        match self {
3560            FunctionReturnType::DataType(data_type) => write!(f, "{data_type}"),
3561            FunctionReturnType::SetOf(data_type) => write!(f, "SETOF {data_type}"),
3562        }
3563    }
3564}
3565
3566#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3567#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3568#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3569/// CREATE FUNCTION statement
3570pub struct CreateFunction {
3571    /// True if this is a `CREATE OR ALTER FUNCTION` statement
3572    ///
3573    /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#or-alter)
3574    pub or_alter: bool,
3575    /// True if this is a `CREATE OR REPLACE FUNCTION` statement
3576    pub or_replace: bool,
3577    /// True if this is a `CREATE TEMPORARY FUNCTION` statement
3578    pub temporary: bool,
3579    /// True if this is a `CREATE IF NOT EXISTS FUNCTION` statement
3580    pub if_not_exists: bool,
3581    /// Name of the function to be created.
3582    pub name: ObjectName,
3583    /// List of arguments for the function.
3584    pub args: Option<Vec<OperateFunctionArg>>,
3585    /// The return type of the function.
3586    pub return_type: Option<FunctionReturnType>,
3587    /// The expression that defines the function.
3588    ///
3589    /// Examples:
3590    /// ```sql
3591    /// AS ((SELECT 1))
3592    /// AS "console.log();"
3593    /// ```
3594    pub function_body: Option<CreateFunctionBody>,
3595    /// Behavior attribute for the function
3596    ///
3597    /// IMMUTABLE | STABLE | VOLATILE
3598    ///
3599    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
3600    pub behavior: Option<FunctionBehavior>,
3601    /// CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
3602    ///
3603    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
3604    pub called_on_null: Option<FunctionCalledOnNull>,
3605    /// PARALLEL { UNSAFE | RESTRICTED | SAFE }
3606    ///
3607    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
3608    pub parallel: Option<FunctionParallel>,
3609    /// SECURITY { DEFINER | INVOKER }
3610    ///
3611    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
3612    pub security: Option<FunctionSecurity>,
3613    /// SET configuration_parameter clauses
3614    ///
3615    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
3616    pub set_params: Vec<FunctionDefinitionSetParam>,
3617    /// USING ... (Hive only)
3618    pub using: Option<CreateFunctionUsing>,
3619    /// Language used in a UDF definition.
3620    ///
3621    /// Example:
3622    /// ```sql
3623    /// CREATE FUNCTION foo() LANGUAGE js AS "console.log();"
3624    /// ```
3625    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_javascript_udf)
3626    pub language: Option<Ident>,
3627    /// Determinism keyword used for non-sql UDF definitions.
3628    ///
3629    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
3630    pub determinism_specifier: Option<FunctionDeterminismSpecifier>,
3631    /// List of options for creating the function.
3632    ///
3633    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
3634    pub options: Option<Vec<SqlOption>>,
3635    /// Connection resource for a remote function.
3636    ///
3637    /// Example:
3638    /// ```sql
3639    /// CREATE FUNCTION foo()
3640    /// RETURNS FLOAT64
3641    /// REMOTE WITH CONNECTION us.myconnection
3642    /// ```
3643    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_remote_function)
3644    pub remote_connection: Option<ObjectName>,
3645}
3646
3647impl fmt::Display for CreateFunction {
3648    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3649        write!(
3650            f,
3651            "CREATE {or_alter}{or_replace}{temp}FUNCTION {if_not_exists}{name}",
3652            name = self.name,
3653            temp = if self.temporary { "TEMPORARY " } else { "" },
3654            or_alter = if self.or_alter { "OR ALTER " } else { "" },
3655            or_replace = if self.or_replace { "OR REPLACE " } else { "" },
3656            if_not_exists = if self.if_not_exists {
3657                "IF NOT EXISTS "
3658            } else {
3659                ""
3660            },
3661        )?;
3662        if let Some(args) = &self.args {
3663            write!(f, "({})", display_comma_separated(args))?;
3664        }
3665        if let Some(return_type) = &self.return_type {
3666            write!(f, " RETURNS {return_type}")?;
3667        }
3668        if let Some(determinism_specifier) = &self.determinism_specifier {
3669            write!(f, " {determinism_specifier}")?;
3670        }
3671        if let Some(language) = &self.language {
3672            write!(f, " LANGUAGE {language}")?;
3673        }
3674        if let Some(behavior) = &self.behavior {
3675            write!(f, " {behavior}")?;
3676        }
3677        if let Some(called_on_null) = &self.called_on_null {
3678            write!(f, " {called_on_null}")?;
3679        }
3680        if let Some(parallel) = &self.parallel {
3681            write!(f, " {parallel}")?;
3682        }
3683        if let Some(security) = &self.security {
3684            write!(f, " {security}")?;
3685        }
3686        for set_param in &self.set_params {
3687            write!(f, " {set_param}")?;
3688        }
3689        if let Some(remote_connection) = &self.remote_connection {
3690            write!(f, " REMOTE WITH CONNECTION {remote_connection}")?;
3691        }
3692        if let Some(CreateFunctionBody::AsBeforeOptions { body, link_symbol }) = &self.function_body
3693        {
3694            write!(f, " AS {body}")?;
3695            if let Some(link_symbol) = link_symbol {
3696                write!(f, ", {link_symbol}")?;
3697            }
3698        }
3699        if let Some(CreateFunctionBody::Return(function_body)) = &self.function_body {
3700            write!(f, " RETURN {function_body}")?;
3701        }
3702        if let Some(CreateFunctionBody::AsReturnExpr(function_body)) = &self.function_body {
3703            write!(f, " AS RETURN {function_body}")?;
3704        }
3705        if let Some(CreateFunctionBody::AsReturnSelect(function_body)) = &self.function_body {
3706            write!(f, " AS RETURN {function_body}")?;
3707        }
3708        if let Some(using) = &self.using {
3709            write!(f, " {using}")?;
3710        }
3711        if let Some(options) = &self.options {
3712            write!(
3713                f,
3714                " OPTIONS({})",
3715                display_comma_separated(options.as_slice())
3716            )?;
3717        }
3718        if let Some(CreateFunctionBody::AsAfterOptions(function_body)) = &self.function_body {
3719            write!(f, " AS {function_body}")?;
3720        }
3721        if let Some(CreateFunctionBody::AsBeginEnd(bes)) = &self.function_body {
3722            write!(f, " AS {bes}")?;
3723        }
3724        Ok(())
3725    }
3726}
3727
3728/// ```sql
3729/// CREATE CONNECTOR [IF NOT EXISTS] connector_name
3730/// [TYPE datasource_type]
3731/// [URL datasource_url]
3732/// [COMMENT connector_comment]
3733/// [WITH DCPROPERTIES(property_name=property_value, ...)]
3734/// ```
3735///
3736/// [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3737#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3738#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3739#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3740pub struct CreateConnector {
3741    /// The name of the connector to be created.
3742    pub name: Ident,
3743    /// Whether `IF NOT EXISTS` was specified.
3744    pub if_not_exists: bool,
3745    /// The type of the connector.
3746    pub connector_type: Option<String>,
3747    /// The URL of the connector.
3748    pub url: Option<String>,
3749    /// The comment for the connector.
3750    pub comment: Option<CommentDef>,
3751    /// The DC properties for the connector.
3752    pub with_dcproperties: Option<Vec<SqlOption>>,
3753}
3754
3755impl fmt::Display for CreateConnector {
3756    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3757        write!(
3758            f,
3759            "CREATE CONNECTOR {if_not_exists}{name}",
3760            if_not_exists = if self.if_not_exists {
3761                "IF NOT EXISTS "
3762            } else {
3763                ""
3764            },
3765            name = self.name,
3766        )?;
3767
3768        if let Some(connector_type) = &self.connector_type {
3769            write!(f, " TYPE '{connector_type}'")?;
3770        }
3771
3772        if let Some(url) = &self.url {
3773            write!(f, " URL '{url}'")?;
3774        }
3775
3776        if let Some(comment) = &self.comment {
3777            write!(f, " COMMENT = '{comment}'")?;
3778        }
3779
3780        if let Some(with_dcproperties) = &self.with_dcproperties {
3781            write!(
3782                f,
3783                " WITH DCPROPERTIES({})",
3784                display_comma_separated(with_dcproperties)
3785            )?;
3786        }
3787
3788        Ok(())
3789    }
3790}
3791
3792/// An `ALTER SCHEMA` (`Statement::AlterSchema`) operation.
3793///
3794/// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3795/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterschema.html)
3796#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3797#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3798#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3799pub enum AlterSchemaOperation {
3800    /// Set the default collation for the schema.
3801    SetDefaultCollate {
3802        /// The collation to set as default.
3803        collate: Expr,
3804    },
3805    /// Add a replica to the schema.
3806    AddReplica {
3807        /// The replica to add.
3808        replica: Ident,
3809        /// Optional options for the replica.
3810        options: Option<Vec<SqlOption>>,
3811    },
3812    /// Drop a replica from the schema.
3813    DropReplica {
3814        /// The replica to drop.
3815        replica: Ident,
3816    },
3817    /// Set options for the schema.
3818    SetOptionsParens {
3819        /// The options to set.
3820        options: Vec<SqlOption>,
3821    },
3822    /// Rename the schema.
3823    Rename {
3824        /// The new name for the schema.
3825        name: ObjectName,
3826    },
3827    /// Change the owner of the schema.
3828    OwnerTo {
3829        /// The new owner of the schema.
3830        owner: Owner,
3831    },
3832}
3833
3834impl fmt::Display for AlterSchemaOperation {
3835    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3836        match self {
3837            AlterSchemaOperation::SetDefaultCollate { collate } => {
3838                write!(f, "SET DEFAULT COLLATE {collate}")
3839            }
3840            AlterSchemaOperation::AddReplica { replica, options } => {
3841                write!(f, "ADD REPLICA {replica}")?;
3842                if let Some(options) = options {
3843                    write!(f, " OPTIONS ({})", display_comma_separated(options))?;
3844                }
3845                Ok(())
3846            }
3847            AlterSchemaOperation::DropReplica { replica } => write!(f, "DROP REPLICA {replica}"),
3848            AlterSchemaOperation::SetOptionsParens { options } => {
3849                write!(f, "SET OPTIONS ({})", display_comma_separated(options))
3850            }
3851            AlterSchemaOperation::Rename { name } => write!(f, "RENAME TO {name}"),
3852            AlterSchemaOperation::OwnerTo { owner } => write!(f, "OWNER TO {owner}"),
3853        }
3854    }
3855}
3856/// `RenameTableNameKind` is the kind used in an `ALTER TABLE _ RENAME` statement.
3857///
3858/// Note: [MySQL] is the only database that supports the AS keyword for this operation.
3859///
3860/// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
3861#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3862#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3863#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3864pub enum RenameTableNameKind {
3865    /// `AS new_table_name`
3866    As(ObjectName),
3867    /// `TO new_table_name`
3868    To(ObjectName),
3869}
3870
3871impl fmt::Display for RenameTableNameKind {
3872    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3873        match self {
3874            RenameTableNameKind::As(name) => write!(f, "AS {name}"),
3875            RenameTableNameKind::To(name) => write!(f, "TO {name}"),
3876        }
3877    }
3878}
3879
3880#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3881#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3882#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3883/// An `ALTER SCHEMA` (`Statement::AlterSchema`) statement.
3884pub struct AlterSchema {
3885    /// The schema name to alter.
3886    pub name: ObjectName,
3887    /// Whether `IF EXISTS` was specified.
3888    pub if_exists: bool,
3889    /// The list of operations to perform on the schema.
3890    pub operations: Vec<AlterSchemaOperation>,
3891}
3892
3893impl fmt::Display for AlterSchema {
3894    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3895        write!(f, "ALTER SCHEMA ")?;
3896        if self.if_exists {
3897            write!(f, "IF EXISTS ")?;
3898        }
3899        write!(f, "{}", self.name)?;
3900        for operation in &self.operations {
3901            write!(f, " {operation}")?;
3902        }
3903
3904        Ok(())
3905    }
3906}
3907
3908impl Spanned for RenameTableNameKind {
3909    fn span(&self) -> Span {
3910        match self {
3911            RenameTableNameKind::As(name) => name.span(),
3912            RenameTableNameKind::To(name) => name.span(),
3913        }
3914    }
3915}
3916
3917#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
3918#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3919#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3920/// Whether the syntax used for the trigger object (ROW or STATEMENT) is `FOR` or `FOR EACH`.
3921pub enum TriggerObjectKind {
3922    /// The `FOR` syntax is used.
3923    For(TriggerObject),
3924    /// The `FOR EACH` syntax is used.
3925    ForEach(TriggerObject),
3926}
3927
3928impl Display for TriggerObjectKind {
3929    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3930        match self {
3931            TriggerObjectKind::For(obj) => write!(f, "FOR {obj}"),
3932            TriggerObjectKind::ForEach(obj) => write!(f, "FOR EACH {obj}"),
3933        }
3934    }
3935}
3936
3937#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3938#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3939#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3940/// CREATE TRIGGER
3941///
3942/// Examples:
3943///
3944/// ```sql
3945/// CREATE TRIGGER trigger_name
3946/// BEFORE INSERT ON table_name
3947/// FOR EACH ROW
3948/// EXECUTE FUNCTION trigger_function();
3949/// ```
3950///
3951/// Postgres: <https://www.postgresql.org/docs/current/sql-createtrigger.html>
3952/// SQL Server: <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql>
3953pub struct CreateTrigger {
3954    /// True if this is a `CREATE OR ALTER TRIGGER` statement
3955    ///
3956    /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16#arguments)
3957    pub or_alter: bool,
3958    /// True if this is a temporary trigger.
3959    ///
3960    /// Examples:
3961    ///
3962    /// ```sql
3963    /// CREATE TEMP TRIGGER trigger_name
3964    /// ```
3965    ///
3966    /// or
3967    ///
3968    /// ```sql
3969    /// CREATE TEMPORARY TRIGGER trigger_name;
3970    /// CREATE TEMP TRIGGER trigger_name;
3971    /// ```
3972    ///
3973    /// [SQLite](https://sqlite.org/lang_createtrigger.html#temp_triggers_on_non_temp_tables)
3974    pub temporary: bool,
3975    /// The `OR REPLACE` clause is used to re-create the trigger if it already exists.
3976    ///
3977    /// Example:
3978    /// ```sql
3979    /// CREATE OR REPLACE TRIGGER trigger_name
3980    /// AFTER INSERT ON table_name
3981    /// FOR EACH ROW
3982    /// EXECUTE FUNCTION trigger_function();
3983    /// ```
3984    pub or_replace: bool,
3985    /// The `CONSTRAINT` keyword is used to create a trigger as a constraint.
3986    pub is_constraint: bool,
3987    /// The name of the trigger to be created.
3988    pub name: ObjectName,
3989    /// Determines whether the function is called before, after, or instead of the event.
3990    ///
3991    /// Example of BEFORE:
3992    ///
3993    /// ```sql
3994    /// CREATE TRIGGER trigger_name
3995    /// BEFORE INSERT ON table_name
3996    /// FOR EACH ROW
3997    /// EXECUTE FUNCTION trigger_function();
3998    /// ```
3999    ///
4000    /// Example of AFTER:
4001    ///
4002    /// ```sql
4003    /// CREATE TRIGGER trigger_name
4004    /// AFTER INSERT ON table_name
4005    /// FOR EACH ROW
4006    /// EXECUTE FUNCTION trigger_function();
4007    /// ```
4008    ///
4009    /// Example of INSTEAD OF:
4010    ///
4011    /// ```sql
4012    /// CREATE TRIGGER trigger_name
4013    /// INSTEAD OF INSERT ON table_name
4014    /// FOR EACH ROW
4015    /// EXECUTE FUNCTION trigger_function();
4016    /// ```
4017    pub period: Option<TriggerPeriod>,
4018    /// Whether the trigger period was specified before the target table name.
4019    /// This does not refer to whether the period is BEFORE, AFTER, or INSTEAD OF,
4020    /// but rather the position of the period clause in relation to the table name.
4021    ///
4022    /// ```sql
4023    /// -- period_before_table == true: Postgres, MySQL, and standard SQL
4024    /// CREATE TRIGGER t BEFORE INSERT ON table_name ...;
4025    /// -- period_before_table == false: MSSQL
4026    /// CREATE TRIGGER t ON table_name BEFORE INSERT ...;
4027    /// ```
4028    pub period_before_table: bool,
4029    /// Multiple events can be specified using OR, such as `INSERT`, `UPDATE`, `DELETE`, or `TRUNCATE`.
4030    pub events: Vec<TriggerEvent>,
4031    /// The table on which the trigger is to be created.
4032    pub table_name: ObjectName,
4033    /// The optional referenced table name that can be referenced via
4034    /// the `FROM` keyword.
4035    pub referenced_table_name: Option<ObjectName>,
4036    /// This keyword immediately precedes the declaration of one or two relation names that provide access to the transition relations of the triggering statement.
4037    pub referencing: Vec<TriggerReferencing>,
4038    /// This specifies whether the trigger function should be fired once for
4039    /// every row affected by the trigger event, or just once per SQL statement.
4040    /// This is optional in some SQL dialects, such as SQLite, and if not specified, in
4041    /// those cases, the implied default is `FOR EACH ROW`.
4042    pub trigger_object: Option<TriggerObjectKind>,
4043    ///  Triggering conditions
4044    pub condition: Option<Expr>,
4045    /// Execute logic block
4046    pub exec_body: Option<TriggerExecBody>,
4047    /// For MSSQL and dialects where statements are preceded by `AS`
4048    pub statements_as: bool,
4049    /// For SQL dialects with statement(s) for a body
4050    pub statements: Option<ConditionalStatements>,
4051    /// The characteristic of the trigger, which include whether the trigger is `DEFERRABLE`, `INITIALLY DEFERRED`, or `INITIALLY IMMEDIATE`,
4052    pub characteristics: Option<ConstraintCharacteristics>,
4053}
4054
4055impl Display for CreateTrigger {
4056    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4057        let CreateTrigger {
4058            or_alter,
4059            temporary,
4060            or_replace,
4061            is_constraint,
4062            name,
4063            period_before_table,
4064            period,
4065            events,
4066            table_name,
4067            referenced_table_name,
4068            referencing,
4069            trigger_object,
4070            condition,
4071            exec_body,
4072            statements_as,
4073            statements,
4074            characteristics,
4075        } = self;
4076        write!(
4077            f,
4078            "CREATE {temporary}{or_alter}{or_replace}{is_constraint}TRIGGER {name} ",
4079            temporary = if *temporary { "TEMPORARY " } else { "" },
4080            or_alter = if *or_alter { "OR ALTER " } else { "" },
4081            or_replace = if *or_replace { "OR REPLACE " } else { "" },
4082            is_constraint = if *is_constraint { "CONSTRAINT " } else { "" },
4083        )?;
4084
4085        if *period_before_table {
4086            if let Some(p) = period {
4087                write!(f, "{p} ")?;
4088            }
4089            if !events.is_empty() {
4090                write!(f, "{} ", display_separated(events, " OR "))?;
4091            }
4092            write!(f, "ON {table_name}")?;
4093        } else {
4094            write!(f, "ON {table_name} ")?;
4095            if let Some(p) = period {
4096                write!(f, "{p}")?;
4097            }
4098            if !events.is_empty() {
4099                write!(f, " {}", display_separated(events, ", "))?;
4100            }
4101        }
4102
4103        if let Some(referenced_table_name) = referenced_table_name {
4104            write!(f, " FROM {referenced_table_name}")?;
4105        }
4106
4107        if let Some(characteristics) = characteristics {
4108            write!(f, " {characteristics}")?;
4109        }
4110
4111        if !referencing.is_empty() {
4112            write!(f, " REFERENCING {}", display_separated(referencing, " "))?;
4113        }
4114
4115        if let Some(trigger_object) = trigger_object {
4116            write!(f, " {trigger_object}")?;
4117        }
4118        if let Some(condition) = condition {
4119            write!(f, " WHEN {condition}")?;
4120        }
4121        if let Some(exec_body) = exec_body {
4122            write!(f, " EXECUTE {exec_body}")?;
4123        }
4124        if let Some(statements) = statements {
4125            if *statements_as {
4126                write!(f, " AS")?;
4127            }
4128            write!(f, " {statements}")?;
4129        }
4130        Ok(())
4131    }
4132}
4133
4134#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4135#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4136#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4137/// DROP TRIGGER
4138///
4139/// ```sql
4140/// DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
4141/// ```
4142///
4143pub struct DropTrigger {
4144    /// Whether to include the `IF EXISTS` clause.
4145    pub if_exists: bool,
4146    /// The name of the trigger to be dropped.
4147    pub trigger_name: ObjectName,
4148    /// The name of the table from which the trigger is to be dropped.
4149    pub table_name: Option<ObjectName>,
4150    /// `CASCADE` or `RESTRICT`
4151    pub option: Option<ReferentialAction>,
4152}
4153
4154impl fmt::Display for DropTrigger {
4155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4156        let DropTrigger {
4157            if_exists,
4158            trigger_name,
4159            table_name,
4160            option,
4161        } = self;
4162        write!(f, "DROP TRIGGER")?;
4163        if *if_exists {
4164            write!(f, " IF EXISTS")?;
4165        }
4166        match &table_name {
4167            Some(table_name) => write!(f, " {trigger_name} ON {table_name}")?,
4168            None => write!(f, " {trigger_name}")?,
4169        };
4170        if let Some(option) = option {
4171            write!(f, " {option}")?;
4172        }
4173        Ok(())
4174    }
4175}
4176
4177/// A `TRUNCATE` statement.
4178///
4179/// ```sql
4180/// TRUNCATE TABLE [IF EXISTS] table_names [PARTITION (partitions)] [RESTART IDENTITY | CONTINUE IDENTITY] [CASCADE | RESTRICT] [ON CLUSTER cluster_name]
4181/// ```
4182#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4183#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4184#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4185pub struct Truncate {
4186    /// Table names to truncate
4187    pub table_names: Vec<super::TruncateTableTarget>,
4188    /// Optional partition specification
4189    pub partitions: Option<Vec<Expr>>,
4190    /// TABLE - optional keyword
4191    pub table: bool,
4192    /// Snowflake/Redshift-specific option: [ IF EXISTS ]
4193    pub if_exists: bool,
4194    /// Postgres-specific option: [ RESTART IDENTITY | CONTINUE IDENTITY ]
4195    pub identity: Option<super::TruncateIdentityOption>,
4196    /// Postgres-specific option: [ CASCADE | RESTRICT ]
4197    pub cascade: Option<super::CascadeOption>,
4198    /// ClickHouse-specific option: [ ON CLUSTER cluster_name ]
4199    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/truncate/)
4200    pub on_cluster: Option<Ident>,
4201}
4202
4203impl fmt::Display for Truncate {
4204    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4205        let table = if self.table { "TABLE " } else { "" };
4206        let if_exists = if self.if_exists { "IF EXISTS " } else { "" };
4207
4208        write!(
4209            f,
4210            "TRUNCATE {table}{if_exists}{table_names}",
4211            table_names = display_comma_separated(&self.table_names)
4212        )?;
4213
4214        if let Some(identity) = &self.identity {
4215            match identity {
4216                super::TruncateIdentityOption::Restart => write!(f, " RESTART IDENTITY")?,
4217                super::TruncateIdentityOption::Continue => write!(f, " CONTINUE IDENTITY")?,
4218            }
4219        }
4220        if let Some(cascade) = &self.cascade {
4221            match cascade {
4222                super::CascadeOption::Cascade => write!(f, " CASCADE")?,
4223                super::CascadeOption::Restrict => write!(f, " RESTRICT")?,
4224            }
4225        }
4226
4227        if let Some(ref parts) = &self.partitions {
4228            if !parts.is_empty() {
4229                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4230            }
4231        }
4232        if let Some(on_cluster) = &self.on_cluster {
4233            write!(f, " ON CLUSTER {on_cluster}")?;
4234        }
4235        Ok(())
4236    }
4237}
4238
4239impl Spanned for Truncate {
4240    fn span(&self) -> Span {
4241        Span::union_iter(
4242            self.table_names.iter().map(|i| i.name.span()).chain(
4243                self.partitions
4244                    .iter()
4245                    .flat_map(|i| i.iter().map(|k| k.span())),
4246            ),
4247        )
4248    }
4249}
4250
4251/// An `MSCK` statement.
4252///
4253/// ```sql
4254/// MSCK [REPAIR] TABLE table_name [ADD|DROP|SYNC PARTITIONS]
4255/// ```
4256/// MSCK (Hive) - MetaStore Check command
4257#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4259#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4260pub struct Msck {
4261    /// Table name to check
4262    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4263    pub table_name: ObjectName,
4264    /// Whether to repair the table
4265    pub repair: bool,
4266    /// Partition action (ADD, DROP, or SYNC)
4267    pub partition_action: Option<super::AddDropSync>,
4268}
4269
4270impl fmt::Display for Msck {
4271    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4272        write!(
4273            f,
4274            "MSCK {repair}TABLE {table}",
4275            repair = if self.repair { "REPAIR " } else { "" },
4276            table = self.table_name
4277        )?;
4278        if let Some(pa) = &self.partition_action {
4279            write!(f, " {pa}")?;
4280        }
4281        Ok(())
4282    }
4283}
4284
4285impl Spanned for Msck {
4286    fn span(&self) -> Span {
4287        self.table_name.span()
4288    }
4289}
4290
4291/// CREATE VIEW statement.
4292#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4293#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4294#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4295pub struct CreateView {
4296    /// True if this is a `CREATE OR ALTER VIEW` statement
4297    ///
4298    /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql)
4299    pub or_alter: bool,
4300    /// The `OR REPLACE` clause is used to re-create the view if it already exists.
4301    pub or_replace: bool,
4302    /// if true, has MATERIALIZED view modifier
4303    pub materialized: bool,
4304    /// Snowflake: SECURE view modifier
4305    /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
4306    pub secure: bool,
4307    /// View name
4308    pub name: ObjectName,
4309    /// If `if_not_exists` is true, this flag is set to true if the view name comes before the `IF NOT EXISTS` clause.
4310    /// Example:
4311    /// ```sql
4312    /// CREATE VIEW myview IF NOT EXISTS AS SELECT 1`
4313    ///  ```
4314    /// Otherwise, the flag is set to false if the view name comes after the clause
4315    /// Example:
4316    /// ```sql
4317    /// CREATE VIEW IF NOT EXISTS myview AS SELECT 1`
4318    ///  ```
4319    pub name_before_not_exists: bool,
4320    /// Optional column definitions
4321    pub columns: Vec<ViewColumnDef>,
4322    /// The query that defines the view.
4323    pub query: Box<Query>,
4324    /// Table options (e.g., WITH (..), OPTIONS (...))
4325    pub options: CreateTableOptions,
4326    /// BigQuery: CLUSTER BY columns
4327    pub cluster_by: Vec<Ident>,
4328    /// Snowflake: Views can have comments in Snowflake.
4329    /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
4330    pub comment: Option<String>,
4331    /// if true, has RedShift [`WITH NO SCHEMA BINDING`] clause <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html>
4332    pub with_no_schema_binding: bool,
4333    /// if true, has SQLite `IF NOT EXISTS` clause <https://www.sqlite.org/lang_createview.html>
4334    pub if_not_exists: bool,
4335    /// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
4336    pub temporary: bool,
4337    /// Snowflake: `COPY GRANTS` clause
4338    /// <https://docs.snowflake.com/en/sql-reference/sql/create-view>
4339    pub copy_grants: bool,
4340    /// if not None, has Clickhouse `TO` clause, specify the table into which to insert results
4341    /// <https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
4342    pub to: Option<ObjectName>,
4343    /// MySQL: Optional parameters for the view algorithm, definer, and security context
4344    pub params: Option<CreateViewParams>,
4345}
4346
4347impl fmt::Display for CreateView {
4348    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4349        write!(
4350            f,
4351            "CREATE {or_alter}{or_replace}",
4352            or_alter = if self.or_alter { "OR ALTER " } else { "" },
4353            or_replace = if self.or_replace { "OR REPLACE " } else { "" },
4354        )?;
4355        if let Some(ref params) = self.params {
4356            params.fmt(f)?;
4357        }
4358        write!(
4359            f,
4360            "{secure}{materialized}{temporary}VIEW {if_not_and_name}{to}",
4361            if_not_and_name = if self.if_not_exists {
4362                if self.name_before_not_exists {
4363                    format!("{} IF NOT EXISTS", self.name)
4364                } else {
4365                    format!("IF NOT EXISTS {}", self.name)
4366                }
4367            } else {
4368                format!("{}", self.name)
4369            },
4370            secure = if self.secure { "SECURE " } else { "" },
4371            materialized = if self.materialized {
4372                "MATERIALIZED "
4373            } else {
4374                ""
4375            },
4376            temporary = if self.temporary { "TEMPORARY " } else { "" },
4377            to = self
4378                .to
4379                .as_ref()
4380                .map(|to| format!(" TO {to}"))
4381                .unwrap_or_default()
4382        )?;
4383        if self.copy_grants {
4384            write!(f, " COPY GRANTS")?;
4385        }
4386        if !self.columns.is_empty() {
4387            write!(f, " ({})", display_comma_separated(&self.columns))?;
4388        }
4389        if matches!(self.options, CreateTableOptions::With(_)) {
4390            write!(f, " {}", self.options)?;
4391        }
4392        if let Some(ref comment) = self.comment {
4393            write!(f, " COMMENT = '{}'", escape_single_quote_string(comment))?;
4394        }
4395        if !self.cluster_by.is_empty() {
4396            write!(
4397                f,
4398                " CLUSTER BY ({})",
4399                display_comma_separated(&self.cluster_by)
4400            )?;
4401        }
4402        if matches!(self.options, CreateTableOptions::Options(_)) {
4403            write!(f, " {}", self.options)?;
4404        }
4405        f.write_str(" AS")?;
4406        SpaceOrNewline.fmt(f)?;
4407        self.query.fmt(f)?;
4408        if self.with_no_schema_binding {
4409            write!(f, " WITH NO SCHEMA BINDING")?;
4410        }
4411        Ok(())
4412    }
4413}
4414
4415/// CREATE EXTENSION statement
4416/// Note: this is a PostgreSQL-specific statement
4417#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4418#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4419#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4420pub struct CreateExtension {
4421    /// Extension name
4422    pub name: Ident,
4423    /// Whether `IF NOT EXISTS` was specified for the CREATE EXTENSION.
4424    pub if_not_exists: bool,
4425    /// Whether `CASCADE` was specified for the CREATE EXTENSION.
4426    pub cascade: bool,
4427    /// Optional schema name for the extension.
4428    pub schema: Option<Ident>,
4429    /// Optional version for the extension.
4430    pub version: Option<Ident>,
4431}
4432
4433impl fmt::Display for CreateExtension {
4434    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4435        write!(
4436            f,
4437            "CREATE EXTENSION {if_not_exists}{name}",
4438            if_not_exists = if self.if_not_exists {
4439                "IF NOT EXISTS "
4440            } else {
4441                ""
4442            },
4443            name = self.name
4444        )?;
4445        if self.cascade || self.schema.is_some() || self.version.is_some() {
4446            write!(f, " WITH")?;
4447
4448            if let Some(name) = &self.schema {
4449                write!(f, " SCHEMA {name}")?;
4450            }
4451            if let Some(version) = &self.version {
4452                write!(f, " VERSION {version}")?;
4453            }
4454            if self.cascade {
4455                write!(f, " CASCADE")?;
4456            }
4457        }
4458
4459        Ok(())
4460    }
4461}
4462
4463impl Spanned for CreateExtension {
4464    fn span(&self) -> Span {
4465        Span::empty()
4466    }
4467}
4468
4469/// DROP EXTENSION statement
4470/// Note: this is a PostgreSQL-specific statement
4471///
4472/// # References
4473///
4474/// PostgreSQL Documentation:
4475/// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4476#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4477#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4478#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4479pub struct DropExtension {
4480    /// One or more extension names to drop
4481    pub names: Vec<Ident>,
4482    /// Whether `IF EXISTS` was specified for the DROP EXTENSION.
4483    pub if_exists: bool,
4484    /// `CASCADE` or `RESTRICT` behaviour for the drop.
4485    pub cascade_or_restrict: Option<ReferentialAction>,
4486}
4487
4488impl fmt::Display for DropExtension {
4489    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4490        write!(f, "DROP EXTENSION")?;
4491        if self.if_exists {
4492            write!(f, " IF EXISTS")?;
4493        }
4494        write!(f, " {}", display_comma_separated(&self.names))?;
4495        if let Some(cascade_or_restrict) = &self.cascade_or_restrict {
4496            write!(f, " {cascade_or_restrict}")?;
4497        }
4498        Ok(())
4499    }
4500}
4501
4502impl Spanned for DropExtension {
4503    fn span(&self) -> Span {
4504        Span::empty()
4505    }
4506}
4507
4508/// CREATE COLLATION statement.
4509/// Note: this is a PostgreSQL-specific statement.
4510#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4511#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4512#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4513pub struct CreateCollation {
4514    /// Whether `IF NOT EXISTS` was specified.
4515    pub if_not_exists: bool,
4516    /// Name of the collation being created.
4517    pub name: ObjectName,
4518    /// Source definition for the collation.
4519    pub definition: CreateCollationDefinition,
4520}
4521
4522/// Definition forms supported by `CREATE COLLATION`.
4523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4526pub enum CreateCollationDefinition {
4527    /// Create from an existing collation.
4528    ///
4529    /// ```sql
4530    /// CREATE COLLATION name FROM existing_collation
4531    /// ```
4532    From(ObjectName),
4533    /// Create with an option list.
4534    ///
4535    /// ```sql
4536    /// CREATE COLLATION name (key = value, ...)
4537    /// ```
4538    Options(Vec<SqlOption>),
4539}
4540
4541impl fmt::Display for CreateCollation {
4542    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4543        write!(
4544            f,
4545            "CREATE COLLATION {if_not_exists}{name}",
4546            if_not_exists = if self.if_not_exists {
4547                "IF NOT EXISTS "
4548            } else {
4549                ""
4550            },
4551            name = self.name
4552        )?;
4553        match &self.definition {
4554            CreateCollationDefinition::From(existing_collation) => {
4555                write!(f, " FROM {existing_collation}")
4556            }
4557            CreateCollationDefinition::Options(options) => {
4558                write!(f, " ({})", display_comma_separated(options))
4559            }
4560        }
4561    }
4562}
4563
4564impl Spanned for CreateCollation {
4565    fn span(&self) -> Span {
4566        Span::empty()
4567    }
4568}
4569
4570/// ALTER COLLATION statement.
4571/// Note: this is a PostgreSQL-specific statement.
4572#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4573#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4574#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4575pub struct AlterCollation {
4576    /// Name of the collation being altered.
4577    pub name: ObjectName,
4578    /// The operation to perform on the collation.
4579    pub operation: AlterCollationOperation,
4580}
4581
4582/// Operations supported by `ALTER COLLATION`.
4583#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4584#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4585#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4586pub enum AlterCollationOperation {
4587    /// Rename the collation.
4588    ///
4589    /// ```sql
4590    /// ALTER COLLATION name RENAME TO new_name
4591    /// ```
4592    RenameTo {
4593        /// New collation name.
4594        new_name: Ident,
4595    },
4596    /// Change the collation owner.
4597    ///
4598    /// ```sql
4599    /// ALTER COLLATION name OWNER TO role_name
4600    /// ```
4601    OwnerTo(Owner),
4602    /// Move the collation to another schema.
4603    ///
4604    /// ```sql
4605    /// ALTER COLLATION name SET SCHEMA new_schema
4606    /// ```
4607    SetSchema {
4608        /// Target schema name.
4609        schema_name: ObjectName,
4610    },
4611    /// Refresh collation version metadata.
4612    ///
4613    /// ```sql
4614    /// ALTER COLLATION name REFRESH VERSION
4615    /// ```
4616    RefreshVersion,
4617}
4618
4619impl fmt::Display for AlterCollationOperation {
4620    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4621        match self {
4622            AlterCollationOperation::RenameTo { new_name } => write!(f, "RENAME TO {new_name}"),
4623            AlterCollationOperation::OwnerTo(owner) => write!(f, "OWNER TO {owner}"),
4624            AlterCollationOperation::SetSchema { schema_name } => {
4625                write!(f, "SET SCHEMA {schema_name}")
4626            }
4627            AlterCollationOperation::RefreshVersion => write!(f, "REFRESH VERSION"),
4628        }
4629    }
4630}
4631
4632impl fmt::Display for AlterCollation {
4633    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4634        write!(f, "ALTER COLLATION {} {}", self.name, self.operation)
4635    }
4636}
4637
4638impl Spanned for AlterCollation {
4639    fn span(&self) -> Span {
4640        Span::empty()
4641    }
4642}
4643
4644/// Table type for ALTER TABLE statements.
4645/// Used to distinguish between regular tables, Iceberg tables, and Dynamic tables.
4646#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4647#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4648#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4649pub enum AlterTableType {
4650    /// Iceberg table type
4651    /// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
4652    Iceberg,
4653    /// Dynamic table type
4654    /// <https://docs.snowflake.com/en/sql-reference/sql/alter-dynamic-table>
4655    Dynamic,
4656    /// External table type
4657    /// <https://docs.snowflake.com/en/sql-reference/sql/alter-external-table>
4658    External,
4659}
4660
4661/// ALTER TABLE statement
4662#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4663#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4664#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4665pub struct AlterTable {
4666    /// Table name
4667    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4668    pub name: ObjectName,
4669    /// Whether `IF EXISTS` was specified for the `ALTER TABLE`.
4670    pub if_exists: bool,
4671    /// Whether the `ONLY` keyword was used (restrict scope to the named table).
4672    pub only: bool,
4673    /// List of `ALTER TABLE` operations to apply.
4674    pub operations: Vec<AlterTableOperation>,
4675    /// Optional Hive `SET LOCATION` clause for the alter operation.
4676    pub location: Option<HiveSetLocation>,
4677    /// ClickHouse dialect supports `ON CLUSTER` clause for ALTER TABLE
4678    /// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
4679    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
4680    pub on_cluster: Option<Ident>,
4681    /// Table type: None for regular tables, Some(AlterTableType) for Iceberg or Dynamic tables
4682    pub table_type: Option<AlterTableType>,
4683    /// Token that represents the end of the statement (semicolon or EOF)
4684    pub end_token: AttachedToken,
4685}
4686
4687impl fmt::Display for AlterTable {
4688    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4689        match &self.table_type {
4690            Some(AlterTableType::Iceberg) => write!(f, "ALTER ICEBERG TABLE ")?,
4691            Some(AlterTableType::Dynamic) => write!(f, "ALTER DYNAMIC TABLE ")?,
4692            Some(AlterTableType::External) => write!(f, "ALTER EXTERNAL TABLE ")?,
4693            None => write!(f, "ALTER TABLE ")?,
4694        }
4695
4696        if self.if_exists {
4697            write!(f, "IF EXISTS ")?;
4698        }
4699        if self.only {
4700            write!(f, "ONLY ")?;
4701        }
4702        write!(f, "{} ", &self.name)?;
4703        if let Some(cluster) = &self.on_cluster {
4704            write!(f, "ON CLUSTER {cluster} ")?;
4705        }
4706        write!(f, "{}", display_comma_separated(&self.operations))?;
4707        if let Some(loc) = &self.location {
4708            write!(f, " {loc}")?
4709        }
4710        Ok(())
4711    }
4712}
4713
4714/// DROP FUNCTION statement
4715#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4716#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4717#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4718pub struct DropFunction {
4719    /// Whether to include the `IF EXISTS` clause.
4720    pub if_exists: bool,
4721    /// One or more functions to drop
4722    pub func_desc: Vec<FunctionDesc>,
4723    /// `CASCADE` or `RESTRICT`
4724    pub drop_behavior: Option<DropBehavior>,
4725}
4726
4727impl fmt::Display for DropFunction {
4728    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4729        write!(
4730            f,
4731            "DROP FUNCTION{} {}",
4732            if self.if_exists { " IF EXISTS" } else { "" },
4733            display_comma_separated(&self.func_desc),
4734        )?;
4735        if let Some(op) = &self.drop_behavior {
4736            write!(f, " {op}")?;
4737        }
4738        Ok(())
4739    }
4740}
4741
4742impl Spanned for DropFunction {
4743    fn span(&self) -> Span {
4744        Span::empty()
4745    }
4746}
4747
4748/// CREATE OPERATOR statement
4749/// See <https://www.postgresql.org/docs/current/sql-createoperator.html>
4750#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4751#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4752#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4753pub struct CreateOperator {
4754    /// Operator name (can be schema-qualified)
4755    pub name: ObjectName,
4756    /// FUNCTION or PROCEDURE parameter (function name)
4757    pub function: ObjectName,
4758    /// Whether PROCEDURE keyword was used (vs FUNCTION)
4759    pub is_procedure: bool,
4760    /// LEFTARG parameter (left operand type)
4761    pub left_arg: Option<DataType>,
4762    /// RIGHTARG parameter (right operand type)
4763    pub right_arg: Option<DataType>,
4764    /// Operator options (COMMUTATOR, NEGATOR, RESTRICT, JOIN, HASHES, MERGES)
4765    pub options: Vec<OperatorOption>,
4766}
4767
4768/// CREATE OPERATOR FAMILY statement
4769/// See <https://www.postgresql.org/docs/current/sql-createopfamily.html>
4770#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4771#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4772#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4773pub struct CreateOperatorFamily {
4774    /// Operator family name (can be schema-qualified)
4775    pub name: ObjectName,
4776    /// Index method (btree, hash, gist, gin, etc.)
4777    pub using: Ident,
4778}
4779
4780/// CREATE OPERATOR CLASS statement
4781/// See <https://www.postgresql.org/docs/current/sql-createopclass.html>
4782#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4783#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4784#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4785pub struct CreateOperatorClass {
4786    /// Operator class name (can be schema-qualified)
4787    pub name: ObjectName,
4788    /// Whether this is the default operator class for the type
4789    pub default: bool,
4790    /// The data type
4791    pub for_type: DataType,
4792    /// Index method (btree, hash, gist, gin, etc.)
4793    pub using: Ident,
4794    /// Optional operator family name
4795    pub family: Option<ObjectName>,
4796    /// List of operator class items (operators, functions, storage)
4797    pub items: Vec<OperatorClassItem>,
4798}
4799
4800impl fmt::Display for CreateOperator {
4801    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4802        write!(f, "CREATE OPERATOR {} (", self.name)?;
4803
4804        let function_keyword = if self.is_procedure {
4805            "PROCEDURE"
4806        } else {
4807            "FUNCTION"
4808        };
4809        let mut params = vec![format!("{} = {}", function_keyword, self.function)];
4810
4811        if let Some(left_arg) = &self.left_arg {
4812            params.push(format!("LEFTARG = {}", left_arg));
4813        }
4814        if let Some(right_arg) = &self.right_arg {
4815            params.push(format!("RIGHTARG = {}", right_arg));
4816        }
4817
4818        for option in &self.options {
4819            params.push(option.to_string());
4820        }
4821
4822        write!(f, "{}", params.join(", "))?;
4823        write!(f, ")")
4824    }
4825}
4826
4827impl fmt::Display for CreateOperatorFamily {
4828    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4829        write!(
4830            f,
4831            "CREATE OPERATOR FAMILY {} USING {}",
4832            self.name, self.using
4833        )
4834    }
4835}
4836
4837impl fmt::Display for CreateOperatorClass {
4838    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4839        write!(f, "CREATE OPERATOR CLASS {}", self.name)?;
4840        if self.default {
4841            write!(f, " DEFAULT")?;
4842        }
4843        write!(f, " FOR TYPE {} USING {}", self.for_type, self.using)?;
4844        if let Some(family) = &self.family {
4845            write!(f, " FAMILY {}", family)?;
4846        }
4847        write!(f, " AS {}", display_comma_separated(&self.items))
4848    }
4849}
4850
4851/// Operator argument types for CREATE OPERATOR CLASS
4852#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4853#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4854#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4855pub struct OperatorArgTypes {
4856    /// Left-hand operand data type for the operator.
4857    pub left: DataType,
4858    /// Right-hand operand data type for the operator.
4859    pub right: DataType,
4860}
4861
4862impl fmt::Display for OperatorArgTypes {
4863    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4864        write!(f, "{}, {}", self.left, self.right)
4865    }
4866}
4867
4868/// An item in a CREATE OPERATOR CLASS statement
4869#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4870#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4871#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4872pub enum OperatorClassItem {
4873    /// `OPERATOR` clause describing a specific operator implementation.
4874    Operator {
4875        /// Strategy number identifying the operator position in the opclass.
4876        strategy_number: u64,
4877        /// The operator name referenced by this clause.
4878        operator_name: ObjectName,
4879        /// Optional operator argument types.
4880        op_types: Option<OperatorArgTypes>,
4881        /// Optional purpose such as `FOR SEARCH` or `FOR ORDER BY`.
4882        purpose: Option<OperatorPurpose>,
4883    },
4884    /// `FUNCTION` clause describing a support function for the operator class.
4885    Function {
4886        /// Support function number for this entry.
4887        support_number: u64,
4888        /// Optional function argument types for the operator class.
4889        op_types: Option<Vec<DataType>>,
4890        /// The function name implementing the support function.
4891        function_name: ObjectName,
4892        /// Function argument types for the support function.
4893        argument_types: Vec<DataType>,
4894    },
4895    /// `STORAGE` clause specifying the storage type.
4896    Storage {
4897        /// The storage data type.
4898        storage_type: DataType,
4899    },
4900}
4901
4902/// Purpose of an operator in an operator class
4903#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4904#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4905#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4906pub enum OperatorPurpose {
4907    /// Purpose: used for index/search operations.
4908    ForSearch,
4909    /// Purpose: used for ORDER BY; optionally includes a sort family name.
4910    ForOrderBy {
4911        /// Optional sort family object name.
4912        sort_family: ObjectName,
4913    },
4914}
4915
4916impl fmt::Display for OperatorClassItem {
4917    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4918        match self {
4919            OperatorClassItem::Operator {
4920                strategy_number,
4921                operator_name,
4922                op_types,
4923                purpose,
4924            } => {
4925                write!(f, "OPERATOR {strategy_number} {operator_name}")?;
4926                if let Some(types) = op_types {
4927                    write!(f, " ({types})")?;
4928                }
4929                if let Some(purpose) = purpose {
4930                    write!(f, " {purpose}")?;
4931                }
4932                Ok(())
4933            }
4934            OperatorClassItem::Function {
4935                support_number,
4936                op_types,
4937                function_name,
4938                argument_types,
4939            } => {
4940                write!(f, "FUNCTION {support_number}")?;
4941                if let Some(types) = op_types {
4942                    write!(f, " ({})", display_comma_separated(types))?;
4943                }
4944                write!(f, " {function_name}")?;
4945                if !argument_types.is_empty() {
4946                    write!(f, "({})", display_comma_separated(argument_types))?;
4947                }
4948                Ok(())
4949            }
4950            OperatorClassItem::Storage { storage_type } => {
4951                write!(f, "STORAGE {storage_type}")
4952            }
4953        }
4954    }
4955}
4956
4957impl fmt::Display for OperatorPurpose {
4958    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4959        match self {
4960            OperatorPurpose::ForSearch => write!(f, "FOR SEARCH"),
4961            OperatorPurpose::ForOrderBy { sort_family } => {
4962                write!(f, "FOR ORDER BY {sort_family}")
4963            }
4964        }
4965    }
4966}
4967
4968/// `DROP OPERATOR` statement
4969/// See <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4970#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4971#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4972#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4973pub struct DropOperator {
4974    /// `IF EXISTS` clause
4975    pub if_exists: bool,
4976    /// One or more operators to drop with their signatures
4977    pub operators: Vec<DropOperatorSignature>,
4978    /// `CASCADE or RESTRICT`
4979    pub drop_behavior: Option<DropBehavior>,
4980}
4981
4982/// Operator signature for a `DROP OPERATOR` statement
4983#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4984#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4985#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4986pub struct DropOperatorSignature {
4987    /// Operator name
4988    pub name: ObjectName,
4989    /// Left operand type
4990    pub left_type: Option<DataType>,
4991    /// Right operand type
4992    pub right_type: DataType,
4993}
4994
4995impl fmt::Display for DropOperatorSignature {
4996    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4997        write!(f, "{} (", self.name)?;
4998        if let Some(left_type) = &self.left_type {
4999            write!(f, "{}", left_type)?;
5000        } else {
5001            write!(f, "NONE")?;
5002        }
5003        write!(f, ", {})", self.right_type)
5004    }
5005}
5006
5007impl fmt::Display for DropOperator {
5008    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5009        write!(f, "DROP OPERATOR")?;
5010        if self.if_exists {
5011            write!(f, " IF EXISTS")?;
5012        }
5013        write!(f, " {}", display_comma_separated(&self.operators))?;
5014        if let Some(drop_behavior) = &self.drop_behavior {
5015            write!(f, " {}", drop_behavior)?;
5016        }
5017        Ok(())
5018    }
5019}
5020
5021impl Spanned for DropOperator {
5022    fn span(&self) -> Span {
5023        Span::empty()
5024    }
5025}
5026
5027/// `DROP OPERATOR FAMILY` statement
5028/// See <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
5029#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5030#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5031#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5032pub struct DropOperatorFamily {
5033    /// `IF EXISTS` clause
5034    pub if_exists: bool,
5035    /// One or more operator families to drop
5036    pub names: Vec<ObjectName>,
5037    /// Index method (btree, hash, gist, gin, etc.)
5038    pub using: Ident,
5039    /// `CASCADE or RESTRICT`
5040    pub drop_behavior: Option<DropBehavior>,
5041}
5042
5043impl fmt::Display for DropOperatorFamily {
5044    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5045        write!(f, "DROP OPERATOR FAMILY")?;
5046        if self.if_exists {
5047            write!(f, " IF EXISTS")?;
5048        }
5049        write!(f, " {}", display_comma_separated(&self.names))?;
5050        write!(f, " USING {}", self.using)?;
5051        if let Some(drop_behavior) = &self.drop_behavior {
5052            write!(f, " {}", drop_behavior)?;
5053        }
5054        Ok(())
5055    }
5056}
5057
5058impl Spanned for DropOperatorFamily {
5059    fn span(&self) -> Span {
5060        Span::empty()
5061    }
5062}
5063
5064/// `DROP OPERATOR CLASS` statement
5065/// See <https://www.postgresql.org/docs/current/sql-dropopclass.html>
5066#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5067#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5068#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5069pub struct DropOperatorClass {
5070    /// `IF EXISTS` clause
5071    pub if_exists: bool,
5072    /// One or more operator classes to drop
5073    pub names: Vec<ObjectName>,
5074    /// Index method (btree, hash, gist, gin, etc.)
5075    pub using: Ident,
5076    /// `CASCADE or RESTRICT`
5077    pub drop_behavior: Option<DropBehavior>,
5078}
5079
5080impl fmt::Display for DropOperatorClass {
5081    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5082        write!(f, "DROP OPERATOR CLASS")?;
5083        if self.if_exists {
5084            write!(f, " IF EXISTS")?;
5085        }
5086        write!(f, " {}", display_comma_separated(&self.names))?;
5087        write!(f, " USING {}", self.using)?;
5088        if let Some(drop_behavior) = &self.drop_behavior {
5089            write!(f, " {}", drop_behavior)?;
5090        }
5091        Ok(())
5092    }
5093}
5094
5095impl Spanned for DropOperatorClass {
5096    fn span(&self) -> Span {
5097        Span::empty()
5098    }
5099}
5100
5101/// An item in an ALTER OPERATOR FAMILY ADD statement
5102#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5103#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5104#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5105pub enum OperatorFamilyItem {
5106    /// `OPERATOR` clause in an operator family modification.
5107    Operator {
5108        /// Strategy number for the operator.
5109        strategy_number: u64,
5110        /// Operator name referenced by this entry.
5111        operator_name: ObjectName,
5112        /// Operator argument types.
5113        op_types: Vec<DataType>,
5114        /// Optional purpose such as `FOR SEARCH` or `FOR ORDER BY`.
5115        purpose: Option<OperatorPurpose>,
5116    },
5117    /// `FUNCTION` clause in an operator family modification.
5118    Function {
5119        /// Support function number.
5120        support_number: u64,
5121        /// Optional operator argument types for the function.
5122        op_types: Option<Vec<DataType>>,
5123        /// Function name for the support function.
5124        function_name: ObjectName,
5125        /// Function argument types.
5126        argument_types: Vec<DataType>,
5127    },
5128}
5129
5130/// An item in an ALTER OPERATOR FAMILY DROP statement
5131#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5133#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5134pub enum OperatorFamilyDropItem {
5135    /// `OPERATOR` clause for DROP within an operator family.
5136    Operator {
5137        /// Strategy number for the operator.
5138        strategy_number: u64,
5139        /// Operator argument types.
5140        op_types: Vec<DataType>,
5141    },
5142    /// `FUNCTION` clause for DROP within an operator family.
5143    Function {
5144        /// Support function number.
5145        support_number: u64,
5146        /// Operator argument types for the function.
5147        op_types: Vec<DataType>,
5148    },
5149}
5150
5151impl fmt::Display for OperatorFamilyItem {
5152    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5153        match self {
5154            OperatorFamilyItem::Operator {
5155                strategy_number,
5156                operator_name,
5157                op_types,
5158                purpose,
5159            } => {
5160                write!(
5161                    f,
5162                    "OPERATOR {strategy_number} {operator_name} ({})",
5163                    display_comma_separated(op_types)
5164                )?;
5165                if let Some(purpose) = purpose {
5166                    write!(f, " {purpose}")?;
5167                }
5168                Ok(())
5169            }
5170            OperatorFamilyItem::Function {
5171                support_number,
5172                op_types,
5173                function_name,
5174                argument_types,
5175            } => {
5176                write!(f, "FUNCTION {support_number}")?;
5177                if let Some(types) = op_types {
5178                    write!(f, " ({})", display_comma_separated(types))?;
5179                }
5180                write!(f, " {function_name}")?;
5181                if !argument_types.is_empty() {
5182                    write!(f, "({})", display_comma_separated(argument_types))?;
5183                }
5184                Ok(())
5185            }
5186        }
5187    }
5188}
5189
5190impl fmt::Display for OperatorFamilyDropItem {
5191    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5192        match self {
5193            OperatorFamilyDropItem::Operator {
5194                strategy_number,
5195                op_types,
5196            } => {
5197                write!(
5198                    f,
5199                    "OPERATOR {strategy_number} ({})",
5200                    display_comma_separated(op_types)
5201                )
5202            }
5203            OperatorFamilyDropItem::Function {
5204                support_number,
5205                op_types,
5206            } => {
5207                write!(
5208                    f,
5209                    "FUNCTION {support_number} ({})",
5210                    display_comma_separated(op_types)
5211                )
5212            }
5213        }
5214    }
5215}
5216
5217/// `ALTER OPERATOR FAMILY` statement
5218/// See <https://www.postgresql.org/docs/current/sql-alteropfamily.html>
5219#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5220#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5221#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5222pub struct AlterOperatorFamily {
5223    /// Operator family name (can be schema-qualified)
5224    pub name: ObjectName,
5225    /// Index method (btree, hash, gist, gin, etc.)
5226    pub using: Ident,
5227    /// The operation to perform
5228    pub operation: AlterOperatorFamilyOperation,
5229}
5230
5231/// An [AlterOperatorFamily] operation
5232#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5233#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5234#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5235pub enum AlterOperatorFamilyOperation {
5236    /// `ADD { OPERATOR ... | FUNCTION ... } [, ...]`
5237    Add {
5238        /// List of operator family items to add
5239        items: Vec<OperatorFamilyItem>,
5240    },
5241    /// `DROP { OPERATOR ... | FUNCTION ... } [, ...]`
5242    Drop {
5243        /// List of operator family items to drop
5244        items: Vec<OperatorFamilyDropItem>,
5245    },
5246    /// `RENAME TO new_name`
5247    RenameTo {
5248        /// The new name for the operator family.
5249        new_name: ObjectName,
5250    },
5251    /// `OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }`
5252    OwnerTo(Owner),
5253    /// `SET SCHEMA new_schema`
5254    SetSchema {
5255        /// The target schema name.
5256        schema_name: ObjectName,
5257    },
5258}
5259
5260impl fmt::Display for AlterOperatorFamily {
5261    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5262        write!(
5263            f,
5264            "ALTER OPERATOR FAMILY {} USING {}",
5265            self.name, self.using
5266        )?;
5267        write!(f, " {}", self.operation)
5268    }
5269}
5270
5271impl fmt::Display for AlterOperatorFamilyOperation {
5272    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5273        match self {
5274            AlterOperatorFamilyOperation::Add { items } => {
5275                write!(f, "ADD {}", display_comma_separated(items))
5276            }
5277            AlterOperatorFamilyOperation::Drop { items } => {
5278                write!(f, "DROP {}", display_comma_separated(items))
5279            }
5280            AlterOperatorFamilyOperation::RenameTo { new_name } => {
5281                write!(f, "RENAME TO {new_name}")
5282            }
5283            AlterOperatorFamilyOperation::OwnerTo(owner) => {
5284                write!(f, "OWNER TO {owner}")
5285            }
5286            AlterOperatorFamilyOperation::SetSchema { schema_name } => {
5287                write!(f, "SET SCHEMA {schema_name}")
5288            }
5289        }
5290    }
5291}
5292
5293impl Spanned for AlterOperatorFamily {
5294    fn span(&self) -> Span {
5295        Span::empty()
5296    }
5297}
5298
5299/// `ALTER OPERATOR CLASS` statement
5300/// See <https://www.postgresql.org/docs/current/sql-alteropclass.html>
5301#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5303#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5304pub struct AlterOperatorClass {
5305    /// Operator class name (can be schema-qualified)
5306    pub name: ObjectName,
5307    /// Index method (btree, hash, gist, gin, etc.)
5308    pub using: Ident,
5309    /// The operation to perform
5310    pub operation: AlterOperatorClassOperation,
5311}
5312
5313/// An [AlterOperatorClass] operation
5314#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5315#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5316#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5317pub enum AlterOperatorClassOperation {
5318    /// `RENAME TO new_name`
5319    /// Rename the operator class to a new name.
5320    RenameTo {
5321        /// The new name for the operator class.
5322        new_name: ObjectName,
5323    },
5324    /// `OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }`
5325    OwnerTo(Owner),
5326    /// `SET SCHEMA new_schema`
5327    /// Set the schema for the operator class.
5328    SetSchema {
5329        /// The target schema name.
5330        schema_name: ObjectName,
5331    },
5332}
5333
5334impl fmt::Display for AlterOperatorClass {
5335    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5336        write!(f, "ALTER OPERATOR CLASS {} USING {}", self.name, self.using)?;
5337        write!(f, " {}", self.operation)
5338    }
5339}
5340
5341impl fmt::Display for AlterOperatorClassOperation {
5342    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5343        match self {
5344            AlterOperatorClassOperation::RenameTo { new_name } => {
5345                write!(f, "RENAME TO {new_name}")
5346            }
5347            AlterOperatorClassOperation::OwnerTo(owner) => {
5348                write!(f, "OWNER TO {owner}")
5349            }
5350            AlterOperatorClassOperation::SetSchema { schema_name } => {
5351                write!(f, "SET SCHEMA {schema_name}")
5352            }
5353        }
5354    }
5355}
5356
5357impl Spanned for AlterOperatorClass {
5358    fn span(&self) -> Span {
5359        Span::empty()
5360    }
5361}
5362
5363/// `ALTER FUNCTION` / `ALTER AGGREGATE` statement.
5364#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5365#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5366#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5367pub struct AlterFunction {
5368    /// Object type being altered.
5369    pub kind: AlterFunctionKind,
5370    /// Function or aggregate signature.
5371    pub function: FunctionDesc,
5372    /// `ORDER BY` argument list for aggregate signatures.
5373    ///
5374    /// This is only used for `ALTER AGGREGATE`.
5375    pub aggregate_order_by: Option<Vec<OperateFunctionArg>>,
5376    /// Whether the aggregate signature uses `*`.
5377    ///
5378    /// This is only used for `ALTER AGGREGATE`.
5379    pub aggregate_star: bool,
5380    /// Operation applied to the object.
5381    pub operation: AlterFunctionOperation,
5382}
5383
5384/// Function-like object type used by [`AlterFunction`].
5385#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5386#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5387#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5388pub enum AlterFunctionKind {
5389    /// `FUNCTION`
5390    Function,
5391    /// `AGGREGATE`
5392    Aggregate,
5393}
5394
5395impl fmt::Display for AlterFunctionKind {
5396    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5397        match self {
5398            Self::Function => write!(f, "FUNCTION"),
5399            Self::Aggregate => write!(f, "AGGREGATE"),
5400        }
5401    }
5402}
5403
5404/// Operation for `ALTER FUNCTION` / `ALTER AGGREGATE`.
5405#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5406#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5407#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5408pub enum AlterFunctionOperation {
5409    /// `RENAME TO new_name`
5410    RenameTo {
5411        /// New unqualified function or aggregate name.
5412        new_name: Ident,
5413    },
5414    /// `OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }`
5415    OwnerTo(Owner),
5416    /// `SET SCHEMA schema_name`
5417    SetSchema {
5418        /// The target schema name.
5419        schema_name: ObjectName,
5420    },
5421    /// `[ NO ] DEPENDS ON EXTENSION extension_name`
5422    DependsOnExtension {
5423        /// `true` when `NO DEPENDS ON EXTENSION`.
5424        no: bool,
5425        /// Extension name.
5426        extension_name: ObjectName,
5427    },
5428    /// `action [ ... ] [ RESTRICT ]` (function only).
5429    Actions {
5430        /// One or more function actions.
5431        actions: Vec<AlterFunctionAction>,
5432        /// Whether `RESTRICT` is present.
5433        restrict: bool,
5434    },
5435}
5436
5437/// Function action in `ALTER FUNCTION ... action [ ... ] [ RESTRICT ]`.
5438#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5439#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5440#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5441pub enum AlterFunctionAction {
5442    /// `CALLED ON NULL INPUT` / `RETURNS NULL ON NULL INPUT` / `STRICT`
5443    CalledOnNull(FunctionCalledOnNull),
5444    /// `IMMUTABLE` / `STABLE` / `VOLATILE`
5445    Behavior(FunctionBehavior),
5446    /// `[ NOT ] LEAKPROOF`
5447    Leakproof(bool),
5448    /// `[ EXTERNAL ] SECURITY { DEFINER | INVOKER }`
5449    Security {
5450        /// Whether the optional `EXTERNAL` keyword was present.
5451        external: bool,
5452        /// Security mode.
5453        security: FunctionSecurity,
5454    },
5455    /// `PARALLEL { UNSAFE | RESTRICTED | SAFE }`
5456    Parallel(FunctionParallel),
5457    /// `COST execution_cost`
5458    Cost(Expr),
5459    /// `ROWS result_rows`
5460    Rows(Expr),
5461    /// `SUPPORT support_function`
5462    Support(ObjectName),
5463    /// `SET configuration_parameter { TO | = } { value | DEFAULT }`
5464    /// or `SET configuration_parameter FROM CURRENT`
5465    Set(FunctionDefinitionSetParam),
5466    /// `RESET configuration_parameter` or `RESET ALL`
5467    Reset(ResetConfig),
5468}
5469
5470impl fmt::Display for AlterFunction {
5471    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5472        write!(f, "ALTER {} ", self.kind)?;
5473        match self.kind {
5474            AlterFunctionKind::Function => {
5475                write!(f, "{} ", self.function)?;
5476            }
5477            AlterFunctionKind::Aggregate => {
5478                write!(f, "{}(", self.function.name)?;
5479                if self.aggregate_star {
5480                    write!(f, "*")?;
5481                } else {
5482                    if let Some(args) = &self.function.args {
5483                        write!(f, "{}", display_comma_separated(args))?;
5484                    }
5485                    if let Some(order_by_args) = &self.aggregate_order_by {
5486                        if self
5487                            .function
5488                            .args
5489                            .as_ref()
5490                            .is_some_and(|args| !args.is_empty())
5491                        {
5492                            write!(f, " ")?;
5493                        }
5494                        write!(f, "ORDER BY {}", display_comma_separated(order_by_args))?;
5495                    }
5496                }
5497                write!(f, ") ")?;
5498            }
5499        }
5500        write!(f, "{}", self.operation)
5501    }
5502}
5503
5504impl fmt::Display for AlterFunctionOperation {
5505    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5506        match self {
5507            AlterFunctionOperation::RenameTo { new_name } => {
5508                write!(f, "RENAME TO {new_name}")
5509            }
5510            AlterFunctionOperation::OwnerTo(owner) => write!(f, "OWNER TO {owner}"),
5511            AlterFunctionOperation::SetSchema { schema_name } => {
5512                write!(f, "SET SCHEMA {schema_name}")
5513            }
5514            AlterFunctionOperation::DependsOnExtension { no, extension_name } => {
5515                if *no {
5516                    write!(f, "NO DEPENDS ON EXTENSION {extension_name}")
5517                } else {
5518                    write!(f, "DEPENDS ON EXTENSION {extension_name}")
5519                }
5520            }
5521            AlterFunctionOperation::Actions { actions, restrict } => {
5522                write!(f, "{}", display_separated(actions, " "))?;
5523                if *restrict {
5524                    write!(f, " RESTRICT")?;
5525                }
5526                Ok(())
5527            }
5528        }
5529    }
5530}
5531
5532impl fmt::Display for AlterFunctionAction {
5533    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5534        match self {
5535            AlterFunctionAction::CalledOnNull(called_on_null) => write!(f, "{called_on_null}"),
5536            AlterFunctionAction::Behavior(behavior) => write!(f, "{behavior}"),
5537            AlterFunctionAction::Leakproof(leakproof) => {
5538                if *leakproof {
5539                    write!(f, "LEAKPROOF")
5540                } else {
5541                    write!(f, "NOT LEAKPROOF")
5542                }
5543            }
5544            AlterFunctionAction::Security { external, security } => {
5545                if *external {
5546                    write!(f, "EXTERNAL ")?;
5547                }
5548                write!(f, "{security}")
5549            }
5550            AlterFunctionAction::Parallel(parallel) => write!(f, "{parallel}"),
5551            AlterFunctionAction::Cost(execution_cost) => write!(f, "COST {execution_cost}"),
5552            AlterFunctionAction::Rows(result_rows) => write!(f, "ROWS {result_rows}"),
5553            AlterFunctionAction::Support(support_function) => {
5554                write!(f, "SUPPORT {support_function}")
5555            }
5556            AlterFunctionAction::Set(set_param) => write!(f, "{set_param}"),
5557            AlterFunctionAction::Reset(reset_config) => match reset_config {
5558                ResetConfig::ALL => write!(f, "RESET ALL"),
5559                ResetConfig::ConfigName(name) => write!(f, "RESET {name}"),
5560            },
5561        }
5562    }
5563}
5564
5565impl Spanned for AlterFunction {
5566    fn span(&self) -> Span {
5567        Span::empty()
5568    }
5569}
5570
5571/// CREATE POLICY statement.
5572///
5573/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
5574#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5575#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5576#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5577pub struct CreatePolicy {
5578    /// Name of the policy.
5579    pub name: Ident,
5580    /// Table the policy is defined on.
5581    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
5582    pub table_name: ObjectName,
5583    /// Optional policy type (e.g., `PERMISSIVE` / `RESTRICTIVE`).
5584    pub policy_type: Option<CreatePolicyType>,
5585    /// Optional command the policy applies to (e.g., `SELECT`).
5586    pub command: Option<CreatePolicyCommand>,
5587    /// Optional list of grantee owners.
5588    pub to: Option<Vec<Owner>>,
5589    /// Optional expression for the `USING` clause.
5590    pub using: Option<Expr>,
5591    /// Optional expression for the `WITH CHECK` clause.
5592    pub with_check: Option<Expr>,
5593}
5594
5595impl fmt::Display for CreatePolicy {
5596    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5597        write!(
5598            f,
5599            "CREATE POLICY {name} ON {table_name}",
5600            name = self.name,
5601            table_name = self.table_name,
5602        )?;
5603        if let Some(ref policy_type) = self.policy_type {
5604            write!(f, " AS {policy_type}")?;
5605        }
5606        if let Some(ref command) = self.command {
5607            write!(f, " FOR {command}")?;
5608        }
5609        if let Some(ref to) = self.to {
5610            write!(f, " TO {}", display_comma_separated(to))?;
5611        }
5612        if let Some(ref using) = self.using {
5613            write!(f, " USING ({using})")?;
5614        }
5615        if let Some(ref with_check) = self.with_check {
5616            write!(f, " WITH CHECK ({with_check})")?;
5617        }
5618        Ok(())
5619    }
5620}
5621
5622/// Policy type for a `CREATE POLICY` statement.
5623/// ```sql
5624/// AS [ PERMISSIVE | RESTRICTIVE ]
5625/// ```
5626/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
5627#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
5628#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5629#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5630pub enum CreatePolicyType {
5631    /// Policy allows operations unless explicitly denied.
5632    Permissive,
5633    /// Policy denies operations unless explicitly allowed.
5634    Restrictive,
5635}
5636
5637impl fmt::Display for CreatePolicyType {
5638    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5639        match self {
5640            CreatePolicyType::Permissive => write!(f, "PERMISSIVE"),
5641            CreatePolicyType::Restrictive => write!(f, "RESTRICTIVE"),
5642        }
5643    }
5644}
5645
5646/// Command that a policy can apply to (FOR clause).
5647/// ```sql
5648/// FOR [ALL | SELECT | INSERT | UPDATE | DELETE]
5649/// ```
5650/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
5651#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
5652#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5653#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5654pub enum CreatePolicyCommand {
5655    /// Applies to all commands.
5656    All,
5657    /// Applies to SELECT.
5658    Select,
5659    /// Applies to INSERT.
5660    Insert,
5661    /// Applies to UPDATE.
5662    Update,
5663    /// Applies to DELETE.
5664    Delete,
5665}
5666
5667impl fmt::Display for CreatePolicyCommand {
5668    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5669        match self {
5670            CreatePolicyCommand::All => write!(f, "ALL"),
5671            CreatePolicyCommand::Select => write!(f, "SELECT"),
5672            CreatePolicyCommand::Insert => write!(f, "INSERT"),
5673            CreatePolicyCommand::Update => write!(f, "UPDATE"),
5674            CreatePolicyCommand::Delete => write!(f, "DELETE"),
5675        }
5676    }
5677}
5678
5679/// DROP POLICY statement.
5680///
5681/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
5682#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5683#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5684#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5685pub struct DropPolicy {
5686    /// `true` when `IF EXISTS` was present.
5687    pub if_exists: bool,
5688    /// Name of the policy to drop.
5689    pub name: Ident,
5690    /// Name of the table the policy applies to.
5691    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
5692    pub table_name: ObjectName,
5693    /// Optional drop behavior (`CASCADE` or `RESTRICT`).
5694    pub drop_behavior: Option<DropBehavior>,
5695}
5696
5697impl fmt::Display for DropPolicy {
5698    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5699        write!(
5700            f,
5701            "DROP POLICY {if_exists}{name} ON {table_name}",
5702            if_exists = if self.if_exists { "IF EXISTS " } else { "" },
5703            name = self.name,
5704            table_name = self.table_name
5705        )?;
5706        if let Some(ref behavior) = self.drop_behavior {
5707            write!(f, " {behavior}")?;
5708        }
5709        Ok(())
5710    }
5711}
5712
5713impl From<CreatePolicy> for crate::ast::Statement {
5714    fn from(v: CreatePolicy) -> Self {
5715        crate::ast::Statement::CreatePolicy(v)
5716    }
5717}
5718
5719impl From<DropPolicy> for crate::ast::Statement {
5720    fn from(v: DropPolicy) -> Self {
5721        crate::ast::Statement::DropPolicy(v)
5722    }
5723}
5724
5725/// ALTER POLICY statement.
5726///
5727/// ```sql
5728/// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
5729/// ```
5730/// (Postgresql-specific)
5731#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5732#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5733#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5734pub struct AlterPolicy {
5735    /// Policy name to alter.
5736    pub name: Ident,
5737    /// Target table name the policy is defined on.
5738    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
5739    pub table_name: ObjectName,
5740    /// Optional operation specific to the policy alteration.
5741    pub operation: AlterPolicyOperation,
5742}
5743
5744impl fmt::Display for AlterPolicy {
5745    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5746        write!(
5747            f,
5748            "ALTER POLICY {name} ON {table_name}{operation}",
5749            name = self.name,
5750            table_name = self.table_name,
5751            operation = self.operation
5752        )
5753    }
5754}
5755
5756impl From<AlterPolicy> for crate::ast::Statement {
5757    fn from(v: AlterPolicy) -> Self {
5758        crate::ast::Statement::AlterPolicy(v)
5759    }
5760}
5761
5762/// The handler/validator clause of a `CREATE FOREIGN DATA WRAPPER` statement.
5763///
5764/// Specifies either a named function or the absence of a function.
5765#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5766#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5767#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5768pub enum FdwRoutineClause {
5769    /// A named function, e.g. `HANDLER myhandler` or `VALIDATOR myvalidator`.
5770    Function(ObjectName),
5771    /// The `NO HANDLER` or `NO VALIDATOR` form.
5772    NoFunction,
5773}
5774
5775/// A `CREATE FOREIGN DATA WRAPPER` statement.
5776///
5777/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html)
5778#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5779#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5780#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5781pub struct CreateForeignDataWrapper {
5782    /// The name of the foreign-data wrapper.
5783    pub name: Ident,
5784    /// Optional `HANDLER handler_function` or `NO HANDLER` clause.
5785    pub handler: Option<FdwRoutineClause>,
5786    /// Optional `VALIDATOR validator_function` or `NO VALIDATOR` clause.
5787    pub validator: Option<FdwRoutineClause>,
5788    /// Optional `OPTIONS (key 'value', ...)` clause.
5789    pub options: Option<Vec<CreateServerOption>>,
5790}
5791
5792impl fmt::Display for CreateForeignDataWrapper {
5793    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5794        write!(f, "CREATE FOREIGN DATA WRAPPER {}", self.name)?;
5795        if let Some(handler) = &self.handler {
5796            match handler {
5797                FdwRoutineClause::Function(name) => write!(f, " HANDLER {name}")?,
5798                FdwRoutineClause::NoFunction => write!(f, " NO HANDLER")?,
5799            }
5800        }
5801        if let Some(validator) = &self.validator {
5802            match validator {
5803                FdwRoutineClause::Function(name) => write!(f, " VALIDATOR {name}")?,
5804                FdwRoutineClause::NoFunction => write!(f, " NO VALIDATOR")?,
5805            }
5806        }
5807        if let Some(options) = &self.options {
5808            write!(f, " OPTIONS ({})", display_comma_separated(options))?;
5809        }
5810        Ok(())
5811    }
5812}
5813
5814impl From<CreateForeignDataWrapper> for crate::ast::Statement {
5815    fn from(v: CreateForeignDataWrapper) -> Self {
5816        crate::ast::Statement::CreateForeignDataWrapper(v)
5817    }
5818}
5819
5820/// A `CREATE FOREIGN TABLE` statement.
5821///
5822/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigntable.html)
5823#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5824#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5825#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5826pub struct CreateForeignTable {
5827    /// The foreign table name.
5828    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
5829    pub name: ObjectName,
5830    /// Whether `IF NOT EXISTS` was specified.
5831    pub if_not_exists: bool,
5832    /// Column definitions.
5833    pub columns: Vec<ColumnDef>,
5834    /// The `SERVER server_name` clause.
5835    pub server_name: Ident,
5836    /// Optional `OPTIONS (key 'value', ...)` clause at the table level.
5837    pub options: Option<Vec<CreateServerOption>>,
5838}
5839
5840impl fmt::Display for CreateForeignTable {
5841    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5842        write!(
5843            f,
5844            "CREATE FOREIGN TABLE {if_not_exists}{name} ({columns}) SERVER {server_name}",
5845            if_not_exists = if self.if_not_exists { "IF NOT EXISTS " } else { "" },
5846            name = self.name,
5847            columns = display_comma_separated(&self.columns),
5848            server_name = self.server_name,
5849        )?;
5850        if let Some(options) = &self.options {
5851            write!(f, " OPTIONS ({})", display_comma_separated(options))?;
5852        }
5853        Ok(())
5854    }
5855}
5856
5857impl From<CreateForeignTable> for crate::ast::Statement {
5858    fn from(v: CreateForeignTable) -> Self {
5859        crate::ast::Statement::CreateForeignTable(v)
5860    }
5861}
5862
5863/// CREATE AGGREGATE statement.
5864/// See <https://www.postgresql.org/docs/current/sql-createaggregate.html>
5865#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5866#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5867#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5868pub struct CreateAggregate {
5869    /// True if `OR REPLACE` was specified.
5870    pub or_replace: bool,
5871    /// The aggregate name (can be schema-qualified).
5872    pub name: ObjectName,
5873    /// Input argument types. Empty for zero-argument aggregates.
5874    pub args: Vec<DataType>,
5875    /// The options listed inside the required parentheses after the argument
5876    /// list (e.g. `SFUNC`, `STYPE`, `FINALFUNC`, `PARALLEL`, …).
5877    pub options: Vec<CreateAggregateOption>,
5878}
5879
5880impl fmt::Display for CreateAggregate {
5881    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5882        write!(f, "CREATE")?;
5883        if self.or_replace {
5884            write!(f, " OR REPLACE")?;
5885        }
5886        write!(f, " AGGREGATE {}", self.name)?;
5887        write!(f, " ({})", display_comma_separated(&self.args))?;
5888        write!(f, " (")?;
5889        for (i, option) in self.options.iter().enumerate() {
5890            if i > 0 {
5891                write!(f, ", ")?;
5892            }
5893            write!(f, "{option}")?;
5894        }
5895        write!(f, ")")
5896    }
5897}
5898
5899impl From<CreateAggregate> for crate::ast::Statement {
5900    fn from(v: CreateAggregate) -> Self {
5901        crate::ast::Statement::CreateAggregate(v)
5902    }
5903}
5904
5905/// A single option in a `CREATE AGGREGATE` options list.
5906///
5907/// See <https://www.postgresql.org/docs/current/sql-createaggregate.html>
5908#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5909#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5910#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5911pub enum CreateAggregateOption {
5912    /// `SFUNC = state_transition_function`
5913    Sfunc(ObjectName),
5914    /// `STYPE = state_data_type`
5915    Stype(DataType),
5916    /// `SSPACE = state_data_size` (in bytes)
5917    Sspace(u64),
5918    /// `FINALFUNC = final_function`
5919    Finalfunc(ObjectName),
5920    /// `FINALFUNC_EXTRA` — pass extra dummy arguments to the final function.
5921    FinalfuncExtra,
5922    /// `FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE }`
5923    FinalfuncModify(AggregateModifyKind),
5924    /// `COMBINEFUNC = combine_function`
5925    Combinefunc(ObjectName),
5926    /// `SERIALFUNC = serial_function`
5927    Serialfunc(ObjectName),
5928    /// `DESERIALFUNC = deserial_function`
5929    Deserialfunc(ObjectName),
5930    /// `INITCOND = initial_condition` (a string literal)
5931    Initcond(Value),
5932    /// `MSFUNC = moving_state_transition_function`
5933    Msfunc(ObjectName),
5934    /// `MINVFUNC = moving_inverse_transition_function`
5935    Minvfunc(ObjectName),
5936    /// `MSTYPE = moving_state_data_type`
5937    Mstype(DataType),
5938    /// `MSSPACE = moving_state_data_size` (in bytes)
5939    Msspace(u64),
5940    /// `MFINALFUNC = moving_final_function`
5941    Mfinalfunc(ObjectName),
5942    /// `MFINALFUNC_EXTRA`
5943    MfinalfuncExtra,
5944    /// `MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE }`
5945    MfinalfuncModify(AggregateModifyKind),
5946    /// `MINITCOND = moving_initial_condition` (a string literal)
5947    Minitcond(Value),
5948    /// `SORTOP = sort_operator`
5949    Sortop(ObjectName),
5950    /// `PARALLEL = { SAFE | RESTRICTED | UNSAFE }`
5951    Parallel(FunctionParallel),
5952    /// `HYPOTHETICAL` — marks the aggregate as hypothetical-set.
5953    Hypothetical,
5954}
5955
5956impl fmt::Display for CreateAggregateOption {
5957    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5958        match self {
5959            Self::Sfunc(name) => write!(f, "SFUNC = {name}"),
5960            Self::Stype(data_type) => write!(f, "STYPE = {data_type}"),
5961            Self::Sspace(size) => write!(f, "SSPACE = {size}"),
5962            Self::Finalfunc(name) => write!(f, "FINALFUNC = {name}"),
5963            Self::FinalfuncExtra => write!(f, "FINALFUNC_EXTRA"),
5964            Self::FinalfuncModify(kind) => write!(f, "FINALFUNC_MODIFY = {kind}"),
5965            Self::Combinefunc(name) => write!(f, "COMBINEFUNC = {name}"),
5966            Self::Serialfunc(name) => write!(f, "SERIALFUNC = {name}"),
5967            Self::Deserialfunc(name) => write!(f, "DESERIALFUNC = {name}"),
5968            Self::Initcond(cond) => write!(f, "INITCOND = {cond}"),
5969            Self::Msfunc(name) => write!(f, "MSFUNC = {name}"),
5970            Self::Minvfunc(name) => write!(f, "MINVFUNC = {name}"),
5971            Self::Mstype(data_type) => write!(f, "MSTYPE = {data_type}"),
5972            Self::Msspace(size) => write!(f, "MSSPACE = {size}"),
5973            Self::Mfinalfunc(name) => write!(f, "MFINALFUNC = {name}"),
5974            Self::MfinalfuncExtra => write!(f, "MFINALFUNC_EXTRA"),
5975            Self::MfinalfuncModify(kind) => write!(f, "MFINALFUNC_MODIFY = {kind}"),
5976            Self::Minitcond(cond) => write!(f, "MINITCOND = {cond}"),
5977            Self::Sortop(name) => write!(f, "SORTOP = {name}"),
5978            Self::Parallel(parallel) => {
5979                let kind = match parallel {
5980                    FunctionParallel::Safe => "SAFE",
5981                    FunctionParallel::Restricted => "RESTRICTED",
5982                    FunctionParallel::Unsafe => "UNSAFE",
5983                };
5984                write!(f, "PARALLEL = {kind}")
5985            }
5986            Self::Hypothetical => write!(f, "HYPOTHETICAL"),
5987        }
5988    }
5989}
5990
5991/// Modifier kind for `FINALFUNC_MODIFY` / `MFINALFUNC_MODIFY` in `CREATE AGGREGATE`.
5992///
5993/// See <https://www.postgresql.org/docs/current/sql-createaggregate.html>
5994#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5995#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5996#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5997pub enum AggregateModifyKind {
5998    /// The final function does not modify the transition state.
5999    ReadOnly,
6000    /// The transition state may be shared between aggregate calls.
6001    Shareable,
6002    /// The final function may modify the transition state.
6003    ReadWrite,
6004}
6005
6006impl fmt::Display for AggregateModifyKind {
6007    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6008        match self {
6009            Self::ReadOnly => write!(f, "READ_ONLY"),
6010            Self::Shareable => write!(f, "SHAREABLE"),
6011            Self::ReadWrite => write!(f, "READ_WRITE"),
6012        }
6013    }
6014}
6015
6016/// `CREATE TEXT SEARCH CONFIGURATION` statement.
6017///
6018/// Note: this is a PostgreSQL-specific statement.
6019/// <https://www.postgresql.org/docs/current/sql-createtsconfig.html>
6020#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6021#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6022#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6023pub struct CreateTextSearchConfiguration {
6024    /// Name of the text search configuration being created.
6025    pub name: ObjectName,
6026    /// Options list — must include `PARSER = parser_name`.
6027    pub options: Vec<SqlOption>,
6028}
6029
6030impl fmt::Display for CreateTextSearchConfiguration {
6031    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6032        write!(
6033            f,
6034            "CREATE TEXT SEARCH CONFIGURATION {name} ({options})",
6035            name = self.name,
6036            options = display_comma_separated(&self.options),
6037        )
6038    }
6039}
6040
6041impl From<CreateTextSearchConfiguration> for crate::ast::Statement {
6042    fn from(v: CreateTextSearchConfiguration) -> Self {
6043        crate::ast::Statement::CreateTextSearchConfiguration(v)
6044    }
6045}
6046
6047/// `CREATE TEXT SEARCH DICTIONARY` statement.
6048///
6049/// Note: this is a PostgreSQL-specific statement.
6050/// <https://www.postgresql.org/docs/current/sql-createtsdictionary.html>
6051#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6052#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6053#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6054pub struct CreateTextSearchDictionary {
6055    /// Name of the text search dictionary being created.
6056    pub name: ObjectName,
6057    /// Options list — must include `TEMPLATE = template_name`.
6058    pub options: Vec<SqlOption>,
6059}
6060
6061impl fmt::Display for CreateTextSearchDictionary {
6062    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6063        write!(
6064            f,
6065            "CREATE TEXT SEARCH DICTIONARY {name} ({options})",
6066            name = self.name,
6067            options = display_comma_separated(&self.options),
6068        )
6069    }
6070}
6071
6072impl From<CreateTextSearchDictionary> for crate::ast::Statement {
6073    fn from(v: CreateTextSearchDictionary) -> Self {
6074        crate::ast::Statement::CreateTextSearchDictionary(v)
6075    }
6076}
6077
6078/// `CREATE TEXT SEARCH PARSER` statement.
6079///
6080/// Note: this is a PostgreSQL-specific statement.
6081/// <https://www.postgresql.org/docs/current/sql-createtsparser.html>
6082#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6083#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6084#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6085pub struct CreateTextSearchParser {
6086    /// Name of the text search parser being created.
6087    pub name: ObjectName,
6088    /// Options list — must include `START`, `GETTOKEN`, `END`, `LEXTYPES` (and optionally `HEADLINE`).
6089    pub options: Vec<SqlOption>,
6090}
6091
6092impl fmt::Display for CreateTextSearchParser {
6093    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6094        write!(
6095            f,
6096            "CREATE TEXT SEARCH PARSER {name} ({options})",
6097            name = self.name,
6098            options = display_comma_separated(&self.options),
6099        )
6100    }
6101}
6102
6103impl From<CreateTextSearchParser> for crate::ast::Statement {
6104    fn from(v: CreateTextSearchParser) -> Self {
6105        crate::ast::Statement::CreateTextSearchParser(v)
6106    }
6107}
6108
6109/// `CREATE TEXT SEARCH TEMPLATE` statement.
6110///
6111/// Note: this is a PostgreSQL-specific statement.
6112/// <https://www.postgresql.org/docs/current/sql-createtstemplate.html>
6113#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6114#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6115#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6116pub struct CreateTextSearchTemplate {
6117    /// Name of the text search template being created.
6118    pub name: ObjectName,
6119    /// Options list — must include `LEXIZE` (and optionally `INIT`).
6120    pub options: Vec<SqlOption>,
6121}
6122
6123impl fmt::Display for CreateTextSearchTemplate {
6124    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6125        write!(
6126            f,
6127            "CREATE TEXT SEARCH TEMPLATE {name} ({options})",
6128            name = self.name,
6129            options = display_comma_separated(&self.options),
6130        )
6131    }
6132}
6133
6134impl From<CreateTextSearchTemplate> for crate::ast::Statement {
6135    fn from(v: CreateTextSearchTemplate) -> Self {
6136        crate::ast::Statement::CreateTextSearchTemplate(v)
6137    }
6138}