1use serde::{Deserialize, Serialize};
10
11use super::{
12 deserialize_auto_increment, AutoIncrement, ColumnType, Expr, GeneratedColumn, OnCommitAction,
13 PartitionBound, PartitionSpec, RelationPersistence, TableHierarchy,
14};
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17#[allow(clippy::struct_excessive_bools)]
18pub struct ColumnDef {
19 pub name: String,
20 pub ty: ColumnType,
21 #[serde(default, skip_serializing_if = "Option::is_none")]
23 pub object_id: Option<[u8; 16]>,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
26 pub missing_value: Option<uqa_core::Value>,
27 pub primary_key: bool,
28 pub not_null: bool,
29 #[serde(default)]
32 pub not_null_explicit: bool,
33 #[serde(default, skip_serializing_if = "Option::is_none")]
37 pub not_null_name: Option<String>,
38 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub not_null_identity: Option<ConstraintCatalogIdentity>,
41 #[serde(default = "default_true")]
44 pub not_null_validated: bool,
45 #[serde(default)]
48 pub not_null_no_inherit: bool,
49 #[serde(default = "default_true", skip_serializing_if = "is_true")]
51 pub not_null_is_local: bool,
52 #[serde(
54 default,
55 deserialize_with = "deserialize_auto_increment",
56 skip_serializing_if = "Option::is_none"
57 )]
58 pub auto_increment: Option<AutoIncrement>,
59 #[serde(default)]
62 pub unique: bool,
63 #[serde(default, skip_serializing_if = "Option::is_none")]
67 pub default: Option<Expr>,
68 #[serde(default, skip_serializing_if = "Option::is_none")]
72 pub generated: Option<GeneratedColumn>,
73 #[serde(default, skip_serializing_if = "Option::is_none")]
76 pub check: Option<Expr>,
77 #[serde(default, skip_serializing_if = "Option::is_none")]
78 pub check_name: Option<String>,
79 #[serde(default = "default_true")]
80 pub check_enforced: bool,
81 #[serde(default = "default_true")]
82 pub check_validated: bool,
83 #[serde(default)]
84 pub check_no_inherit: bool,
85 #[serde(default = "default_true", skip_serializing_if = "is_true")]
87 pub check_is_local: bool,
88 #[serde(default, skip_serializing_if = "Option::is_none")]
90 pub check_object_id: Option<[u8; 16]>,
91 #[serde(default, skip_serializing_if = "Option::is_none")]
93 pub check_catalog_oid: Option<i64>,
94 #[serde(default, skip_serializing_if = "Option::is_none")]
96 pub references: Option<ForeignKeyRef>,
97}
98
99pub use uqa_core::catalog_identity::CatalogObjectIdentity as ConstraintCatalogIdentity;
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103#[allow(clippy::struct_excessive_bools)]
104pub struct ForeignKeyRef {
105 #[serde(default, skip_serializing_if = "Option::is_none")]
107 pub referenced_index: Option<[u8; 16]>,
108 #[serde(default, skip_serializing_if = "Option::is_none")]
109 pub referenced_key: Option<String>,
110 #[serde(default, skip_serializing_if = "Option::is_none")]
111 pub name: Option<String>,
112 #[serde(default, skip_serializing_if = "Option::is_none")]
114 pub object_id: Option<[u8; 16]>,
115 #[serde(default, skip_serializing_if = "Option::is_none")]
117 pub catalog_identity: Option<ConstraintCatalogIdentity>,
118 pub table: String,
119 #[serde(default, skip_serializing_if = "Option::is_none")]
120 pub column: Option<String>,
121 #[serde(default)]
122 pub on_update: ForeignKeyAction,
123 #[serde(default)]
124 pub on_delete: ForeignKeyAction,
125 #[serde(default)]
126 pub match_type: ForeignKeyMatch,
127 #[serde(default = "default_true")]
128 pub enforced: bool,
129 #[serde(default = "default_true")]
130 pub validated: bool,
131 #[serde(default)]
132 pub deferrable: bool,
133 #[serde(default)]
134 pub initially_deferred: bool,
135 #[serde(default)]
137 pub period: bool,
138 #[serde(default, skip_serializing_if = "Vec::is_empty")]
140 pub referenced_partitions: Vec<super::ReferencedPartitionConstraint>,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct CreateTable {
145 pub name: String,
146 pub qualifier: String,
148 pub columns: Vec<ColumnDef>,
149 pub if_not_exists: bool,
152 #[allow(dead_code)]
155 pub checks: Vec<TableCheck>,
156 pub foreign_keys: Vec<ForeignKey>,
158 #[serde(default)]
163 pub key_constraints: Vec<TableKeyConstraint>,
164 #[serde(default)]
166 pub persistence: RelationPersistence,
167 #[serde(default)]
169 pub on_commit: OnCommitAction,
170 #[serde(default)]
174 pub hierarchy: TableHierarchy,
175}
176
177#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
179pub struct DeferredCreateTable {
180 pub name: String,
181 pub persistence: RelationPersistence,
182 pub definition_sql: String,
183}
184
185#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
186pub enum TableKeyConstraintKind {
187 PrimaryKey,
188 Unique,
189}
190
191#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
193pub struct TableKeyConstraint {
194 #[serde(default, skip_serializing_if = "Option::is_none")]
196 pub catalog_identity: Option<ConstraintCatalogIdentity>,
197 pub name: Option<String>,
198 pub kind: TableKeyConstraintKind,
199 pub columns: Vec<String>,
200 #[serde(default, skip_serializing_if = "Vec::is_empty")]
202 pub included_columns: Vec<String>,
203 #[serde(default)]
206 pub nulls_not_distinct: bool,
207 #[serde(default)]
209 pub without_overlaps: bool,
210}
211
212#[derive(Debug, Clone, Default, Serialize, Deserialize)]
217pub struct TableConstraintSet {
218 #[serde(default, skip_serializing_if = "Option::is_none")]
220 pub columns_declared: Option<bool>,
221 #[serde(default)]
222 pub checks: Vec<TableCheck>,
223 #[serde(default)]
224 pub foreign_keys: Vec<ForeignKey>,
225 #[serde(default)]
226 pub key_constraints: Vec<TableKeyConstraint>,
227 #[serde(default)]
229 pub persistence: RelationPersistence,
230 #[serde(default)]
232 pub on_commit: OnCommitAction,
233 #[serde(default)]
235 pub hierarchy: TableHierarchy,
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize)]
241#[expect(
242 clippy::struct_excessive_bools,
243 reason = "CHECK catalog flags are independent PostgreSQL properties"
244)]
245pub struct TableCheck {
246 pub name: Option<String>,
247 #[serde(default, skip_serializing_if = "Option::is_none")]
249 pub object_id: Option<[u8; 16]>,
250 #[serde(default, skip_serializing_if = "Option::is_none")]
251 pub catalog_oid: Option<i64>,
252 #[serde(default = "default_true", skip_serializing_if = "is_true")]
254 pub is_local: bool,
255 pub expr: Expr,
256 #[serde(default = "default_true")]
257 pub enforced: bool,
258 #[serde(default = "default_true")]
259 pub validated: bool,
260 #[serde(default)]
261 pub no_inherit: bool,
262 #[serde(default, skip_serializing_if = "Option::is_none")]
264 pub partition_constraint: Option<DetachedPartitionConstraint>,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize)]
268pub struct DetachedPartitionConstraint {
269 pub spec: PartitionSpec,
270 pub bound: PartitionBound,
271}
272
273#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
275#[allow(clippy::struct_excessive_bools)]
276pub struct ForeignKey {
277 #[serde(default, skip_serializing_if = "Option::is_none")]
279 pub referenced_index: Option<[u8; 16]>,
280 #[serde(default, skip_serializing_if = "Option::is_none")]
282 pub referenced_key: Option<String>,
283 pub name: Option<String>,
284 #[serde(default, skip_serializing_if = "Option::is_none")]
286 pub object_id: Option<[u8; 16]>,
287 #[serde(default, skip_serializing_if = "Option::is_none")]
289 pub catalog_identity: Option<ConstraintCatalogIdentity>,
290 pub local_columns: Vec<String>,
291 pub ref_table: String,
292 pub ref_columns: Vec<String>,
293 #[serde(default)]
294 pub on_update: ForeignKeyAction,
295 #[serde(default)]
296 pub on_delete: ForeignKeyAction,
297 #[serde(default)]
301 pub on_delete_set_columns: Vec<String>,
302 #[serde(default)]
303 pub match_type: ForeignKeyMatch,
304 #[serde(default = "default_true")]
305 pub enforced: bool,
306 #[serde(default = "default_true")]
307 pub validated: bool,
308 #[serde(default)]
309 pub deferrable: bool,
310 #[serde(default)]
311 pub initially_deferred: bool,
312 #[serde(default)]
314 pub period: bool,
315 #[serde(default, skip_serializing_if = "Vec::is_empty")]
317 pub referenced_partitions: Vec<super::ReferencedPartitionConstraint>,
318}
319
320const fn default_true() -> bool {
321 true
322}
323
324#[expect(
325 clippy::trivially_copy_pass_by_ref,
326 reason = "serde skip_serializing_if requires a borrowed field"
327)]
328const fn is_true(value: &bool) -> bool {
329 *value
330}
331
332#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
333pub enum ForeignKeyAction {
334 #[default]
335 NoAction,
336 Restrict,
337 Cascade,
338 SetNull,
339 SetDefault,
340}
341
342#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
343pub enum ForeignKeyMatch {
344 #[default]
345 Simple,
346 Full,
347}