Skip to main content

uqa_sql/ast/
table_alteration.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! The `ALTER TABLE` statement and the actions it applies in order.
8
9use serde::{Deserialize, Serialize};
10
11use super::{
12    default_true, AutoIncrementKind, ColumnDeclaration, ColumnDef, ColumnType, DeferredSQLError,
13    EventEnableMode, Expr, ForeignKey, IdentitySequenceDeclaration, PartitionBound,
14    RelationPersistence, RoleSpecification, SequenceDeclaration, TableCheck, TableKeyConstraint,
15};
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct AlterTableStmt {
19    pub table: String,
20    /// Local SQL relation identifier used while binding new or replaced generation expressions.
21    pub qualifier: String,
22    pub if_exists: bool,
23    /// Whether the target omitted `ONLY` and therefore allows recursive ALTER behavior.
24    #[serde(default = "default_true")]
25    pub recurse: bool,
26    pub actions: Vec<AlterTableAction>,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
30#[expect(
31    clippy::large_enum_variant,
32    reason = "preserves the stable AST serde shape"
33)]
34pub enum AlterTableAction {
35    AddInheritance {
36        parent: String,
37    },
38    DropInheritance {
39        parent: String,
40    },
41    AttachPartition {
42        partition: String,
43        bound: PartitionBound,
44    },
45    DetachPartition {
46        partition: String,
47        concurrently: bool,
48        finalize: bool,
49    },
50    AddColumn {
51        column: ColumnDef,
52        #[serde(default)]
53        checks: Vec<TableCheck>,
54        #[serde(default)]
55        foreign_keys: Vec<ForeignKey>,
56        #[serde(default)]
57        key_constraints: Vec<TableKeyConstraint>,
58        if_not_exists: bool,
59        /// The clauses the column writes, which `transformColumnDefinition` checks once the relation is found.
60        #[serde(default)]
61        declaration: ColumnDeclaration,
62    },
63    AddKeyConstraint {
64        constraint: TableKeyConstraint,
65    },
66    AddCheckConstraint {
67        constraint: TableCheck,
68    },
69    AddForeignKeyConstraint {
70        constraint: ForeignKey,
71    },
72    AddNotNullConstraint {
73        name: Option<String>,
74        column: String,
75        validated: bool,
76        no_inherit: bool,
77    },
78    ValidateConstraint {
79        name: String,
80    },
81    AlterConstraint {
82        name: String,
83        enforceability: Option<bool>,
84        deferrability: Option<(bool, bool)>,
85        no_inherit: Option<bool>,
86    },
87    DropConstraint {
88        name: String,
89        if_exists: bool,
90        cascade: bool,
91    },
92    DropColumn {
93        name: String,
94        if_exists: bool,
95        cascade: bool,
96    },
97    RenameColumn {
98        from: String,
99        to: String,
100    },
101    RenameTable {
102        to: String,
103    },
104    RenameTrigger {
105        from: String,
106        to: String,
107    },
108    RenameConstraint {
109        from: String,
110        to: String,
111    },
112    RenameRule {
113        from: String,
114        to: String,
115    },
116    SetPersistence {
117        persistence: RelationPersistence,
118    },
119    ChangeOwner {
120        owner: RoleSpecification,
121    },
122    SetSchema {
123        schema: String,
124    },
125    SetTriggerEnableMode {
126        name: Option<String>,
127        user_only: bool,
128        mode: EventEnableMode,
129    },
130    SetRuleEnableMode {
131        name: String,
132        mode: EventEnableMode,
133    },
134    SetDefault {
135        name: String,
136        default: Expr,
137    },
138    DropDefault {
139        name: String,
140    },
141    SetExpression {
142        name: String,
143        expression: Expr,
144    },
145    DropExpression {
146        name: String,
147        if_exists: bool,
148    },
149    SetNotNull {
150        name: String,
151    },
152    DropNotNull {
153        name: String,
154    },
155    AlterColumnType {
156        name: String,
157        ty: ColumnType,
158        #[serde(default, skip_serializing_if = "Option::is_none")]
159        collation: Option<String>,
160        #[serde(default, skip_serializing_if = "Option::is_none")]
161        using: Option<Expr>,
162    },
163    /// `ALTER COLUMN name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( options ) ]`.
164    AddIdentity {
165        name: String,
166        kind: AutoIncrementKind,
167        #[serde(default, skip_serializing_if = "Option::is_none")]
168        declaration: Option<Box<IdentitySequenceDeclaration>>,
169    },
170    /// `ALTER COLUMN name` followed by `SET GENERATED { ALWAYS | BY DEFAULT }`, `RESTART [ [ WITH ] value ]` and `SET sequence_option` in any combination.
171    SetIdentity {
172        name: String,
173        /// The generation `SET GENERATED` gives the column.
174        kind: Option<AutoIncrementKind>,
175        /// Whether `SET GENERATED` is repeated, which `PostgreSQL` reports after it has changed the sequence.
176        repeated_kind: bool,
177        /// The sequence options, kept as written: `PostgreSQL` reads them as `ALTER SEQUENCE` reads its options, and only for an identity column.
178        #[serde(default)]
179        sequence: SequenceDeclaration,
180        /// The first error collecting the sequence options raised, which waits until they are read.
181        #[serde(default, skip_serializing_if = "Option::is_none")]
182        error: Option<DeferredSQLError>,
183    },
184    /// `ALTER COLUMN name DROP IDENTITY [ IF EXISTS ]`.
185    DropIdentity {
186        name: String,
187        if_exists: bool,
188    },
189}