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        using: Option<Expr>,
160    },
161    /// `ALTER COLUMN name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( options ) ]`.
162    AddIdentity {
163        name: String,
164        kind: AutoIncrementKind,
165        #[serde(default, skip_serializing_if = "Option::is_none")]
166        declaration: Option<Box<IdentitySequenceDeclaration>>,
167    },
168    /// `ALTER COLUMN name` followed by `SET GENERATED { ALWAYS | BY DEFAULT }`, `RESTART [ [ WITH ] value ]` and `SET sequence_option` in any combination.
169    SetIdentity {
170        name: String,
171        /// The generation `SET GENERATED` gives the column.
172        kind: Option<AutoIncrementKind>,
173        /// Whether `SET GENERATED` is repeated, which `PostgreSQL` reports after it has changed the sequence.
174        repeated_kind: bool,
175        /// The sequence options, kept as written: `PostgreSQL` reads them as `ALTER SEQUENCE` reads its options, and only for an identity column.
176        #[serde(default)]
177        sequence: SequenceDeclaration,
178        /// The first error collecting the sequence options raised, which waits until they are read.
179        #[serde(default, skip_serializing_if = "Option::is_none")]
180        error: Option<DeferredSQLError>,
181    },
182    /// `ALTER COLUMN name DROP IDENTITY [ IF EXISTS ]`.
183    DropIdentity {
184        name: String,
185        if_exists: bool,
186    },
187}