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 collation_oid: Option<u32>,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
26 pub object_id: Option<[u8; 16]>,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
29 pub attribute_number: Option<i16>,
30 #[serde(default, skip_serializing_if = "Option::is_none")]
32 pub missing_value: Option<uqa_core::Value>,
33 pub primary_key: bool,
34 pub not_null: bool,
35 #[serde(default)]
38 pub not_null_explicit: bool,
39 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub not_null_name: Option<String>,
44 #[serde(default, skip_serializing_if = "Option::is_none")]
46 pub not_null_identity: Option<ConstraintCatalogIdentity>,
47 #[serde(default = "default_true")]
50 pub not_null_validated: bool,
51 #[serde(default)]
54 pub not_null_no_inherit: bool,
55 #[serde(default = "default_true", skip_serializing_if = "is_true")]
57 pub not_null_is_local: bool,
58 #[serde(
60 default,
61 deserialize_with = "deserialize_auto_increment",
62 skip_serializing_if = "Option::is_none"
63 )]
64 pub auto_increment: Option<AutoIncrement>,
65 #[serde(default)]
68 pub unique: bool,
69 #[serde(default, skip_serializing_if = "Option::is_none")]
73 pub default: Option<Expr>,
74 #[serde(default, skip_serializing_if = "Option::is_none")]
78 pub generated: Option<GeneratedColumn>,
79 #[serde(default, skip_serializing_if = "Option::is_none")]
81 pub default_catalog_oid: Option<i64>,
82 #[serde(default, skip_serializing_if = "Option::is_none")]
85 pub check: Option<Expr>,
86 #[serde(default, skip_serializing_if = "Option::is_none")]
87 pub check_name: Option<String>,
88 #[serde(default = "default_true")]
89 pub check_enforced: bool,
90 #[serde(default = "default_true")]
91 pub check_validated: bool,
92 #[serde(default)]
93 pub check_no_inherit: bool,
94 #[serde(default = "default_true", skip_serializing_if = "is_true")]
96 pub check_is_local: bool,
97 #[serde(default, skip_serializing_if = "Option::is_none")]
99 pub check_object_id: Option<[u8; 16]>,
100 #[serde(default, skip_serializing_if = "Option::is_none")]
102 pub check_catalog_oid: Option<i64>,
103 #[serde(default, skip_serializing_if = "Option::is_none")]
105 pub references: Option<ForeignKeyRef>,
106}
107
108impl ColumnDef {
109 #[must_use]
111 pub fn nullable(name: impl Into<String>, ty: ColumnType) -> Self {
112 Self {
113 name: name.into(),
114 ty,
115 collation_oid: None,
116 object_id: None,
117 attribute_number: None,
118 missing_value: None,
119 primary_key: false,
120 not_null: false,
121 not_null_explicit: false,
122 not_null_name: None,
123 not_null_identity: None,
124 not_null_validated: true,
125 not_null_no_inherit: false,
126 not_null_is_local: true,
127 auto_increment: None,
128 unique: false,
129 default: None,
130 generated: None,
131 check: None,
132 check_name: None,
133 check_enforced: true,
134 check_validated: true,
135 check_no_inherit: false,
136 check_is_local: true,
137 check_object_id: None,
138 check_catalog_oid: None,
139 default_catalog_oid: None,
140 references: None,
141 }
142 }
143}
144
145pub use uqa_core::catalog_identity::CatalogObjectIdentity as ConstraintCatalogIdentity;
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
149#[allow(clippy::struct_excessive_bools)]
150pub struct ForeignKeyRef {
151 #[serde(default, skip_serializing_if = "Option::is_none")]
153 pub referenced_index: Option<[u8; 16]>,
154 #[serde(default, skip_serializing_if = "Option::is_none")]
155 pub referenced_key: Option<String>,
156 #[serde(default, skip_serializing_if = "Option::is_none")]
157 pub name: Option<String>,
158 #[serde(default, skip_serializing_if = "Option::is_none")]
160 pub object_id: Option<[u8; 16]>,
161 #[serde(default, skip_serializing_if = "Option::is_none")]
163 pub catalog_identity: Option<ConstraintCatalogIdentity>,
164 pub table: String,
165 #[serde(default, skip_serializing_if = "Option::is_none")]
166 pub column: Option<String>,
167 #[serde(default)]
168 pub on_update: ForeignKeyAction,
169 #[serde(default)]
170 pub on_delete: ForeignKeyAction,
171 #[serde(default)]
172 pub match_type: ForeignKeyMatch,
173 #[serde(default = "default_true")]
174 pub enforced: bool,
175 #[serde(default = "default_true")]
176 pub validated: bool,
177 #[serde(default)]
178 pub deferrable: bool,
179 #[serde(default)]
180 pub initially_deferred: bool,
181 #[serde(default)]
183 pub period: bool,
184 #[serde(default, skip_serializing_if = "Vec::is_empty")]
186 pub referenced_partitions: Vec<super::ReferencedPartitionConstraint>,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct CreateTable {
191 pub name: String,
192 pub qualifier: String,
194 pub columns: Vec<ColumnDef>,
195 pub if_not_exists: bool,
198 #[allow(dead_code)]
201 pub checks: Vec<TableCheck>,
202 pub foreign_keys: Vec<ForeignKey>,
204 #[serde(default, skip_serializing_if = "Vec::is_empty")]
206 pub foreign_key_order: Vec<DeclaredForeignKey>,
207 #[serde(default)]
212 pub key_constraints: Vec<TableKeyConstraint>,
213 #[serde(default)]
215 pub persistence: RelationPersistence,
216 #[serde(default)]
218 pub on_commit: OnCommitAction,
219 #[serde(default)]
223 pub hierarchy: TableHierarchy,
224 #[serde(default, skip_serializing_if = "Vec::is_empty")]
226 pub check_order: Vec<DeclaredCheck>,
227 #[serde(default, skip_serializing_if = "Vec::is_empty")]
229 pub element_order: Vec<DeclaredElement>,
230 #[serde(default, skip_serializing_if = "Vec::is_empty")]
232 pub not_null_declarations: Vec<NotNullDeclaration>,
233 #[serde(default, skip_serializing_if = "Vec::is_empty")]
235 pub untyped_columns: Vec<String>,
236}
237
238#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
240pub enum DeclaredElement {
241 Column(ColumnDeclaration),
243 NotNull(NotNullDeclaration),
245 PrimaryKey { columns: Vec<String> },
247 DeferrableKey,
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
253pub enum DeclaredForeignKey {
254 Column(String),
255 Table(usize),
256}
257
258#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
260pub struct NotNullDeclaration {
261 pub column: String,
262 pub name: Option<String>,
263 pub no_inherit: bool,
264 pub explicit: bool,
266}
267
268#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
270pub struct ColumnDeclaration {
271 #[serde(default, skip_serializing_if = "Option::is_none")]
273 pub collation: Option<String>,
274 pub serial: bool,
276 pub serial_array: bool,
278 pub clauses: Vec<ColumnClause>,
279}
280
281#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
283pub struct ColumnClause {
284 pub kind: ColumnClauseKind,
285 pub name: Option<String>,
287 pub no_inherit: bool,
288}
289
290#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
292pub enum ColumnClauseKind {
293 Null,
294 NotNull,
295 Default,
296 Identity,
297 Generated,
298 Check,
299 PrimaryKey,
300 Unique,
301 ForeignKey,
302 Deferrable,
303 NotDeferrable,
304 InitiallyDeferred,
305 InitiallyImmediate,
306 Enforced,
307 NotEnforced,
308}
309
310#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
312pub enum DeclaredCheck {
313 Column(String),
315 Table(usize),
317}
318
319#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
321pub struct DeferredCreateTable {
322 pub name: String,
323 pub persistence: RelationPersistence,
324 pub definition_sql: String,
325}
326
327#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
328pub enum TableKeyConstraintKind {
329 PrimaryKey,
330 Unique,
331}
332
333impl TableKeyConstraintKind {
334 #[must_use]
336 pub const fn sql_label(self) -> &'static str {
337 match self {
338 Self::PrimaryKey => "PRIMARY KEY",
339 Self::Unique => "UNIQUE",
340 }
341 }
342}
343
344#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
346pub struct TableKeyConstraint {
347 #[serde(default, skip_serializing_if = "Option::is_none")]
349 pub catalog_identity: Option<ConstraintCatalogIdentity>,
350 #[serde(default, skip_serializing_if = "Option::is_none")]
352 pub index_identity: Option<ConstraintCatalogIdentity>,
353 pub name: Option<String>,
354 pub kind: TableKeyConstraintKind,
355 pub columns: Vec<String>,
356 #[serde(default, skip_serializing_if = "Vec::is_empty")]
358 pub included_columns: Vec<String>,
359 #[serde(default)]
362 pub nulls_not_distinct: bool,
363 #[serde(default)]
365 pub without_overlaps: bool,
366}
367
368#[derive(Debug, Clone, Default, Serialize, Deserialize)]
373pub struct TableConstraintSet {
374 #[serde(default, skip_serializing_if = "Vec::is_empty")]
376 pub dropped_attributes: Vec<crate::catalog::relation_attributes::DroppedAttribute>,
377 #[serde(default, skip_serializing_if = "Option::is_none")]
379 pub columns_declared: Option<bool>,
380 #[serde(default)]
381 pub checks: Vec<TableCheck>,
382 #[serde(default)]
383 pub foreign_keys: Vec<ForeignKey>,
384 #[serde(default)]
385 pub key_constraints: Vec<TableKeyConstraint>,
386 #[serde(default)]
388 pub persistence: RelationPersistence,
389 #[serde(default)]
391 pub on_commit: OnCommitAction,
392 #[serde(default)]
394 pub hierarchy: TableHierarchy,
395 #[serde(default, skip_serializing_if = "Option::is_none")]
397 pub catalog_oids: Option<crate::catalog::relation_oids::RelationCatalogOids>,
398 #[serde(default, skip_serializing_if = "Option::is_none")]
400 pub row_type_array_name: Option<String>,
401}
402
403#[derive(Debug, Clone, Serialize, Deserialize)]
406#[expect(
407 clippy::struct_excessive_bools,
408 reason = "CHECK catalog flags are independent PostgreSQL properties"
409)]
410pub struct TableCheck {
411 pub name: Option<String>,
412 #[serde(default, skip_serializing_if = "Option::is_none")]
414 pub object_id: Option<[u8; 16]>,
415 #[serde(default, skip_serializing_if = "Option::is_none")]
416 pub catalog_oid: Option<i64>,
417 #[serde(default = "default_true", skip_serializing_if = "is_true")]
419 pub is_local: bool,
420 pub expr: Expr,
421 #[serde(default = "default_true")]
422 pub enforced: bool,
423 #[serde(default = "default_true")]
424 pub validated: bool,
425 #[serde(default)]
426 pub no_inherit: bool,
427 #[serde(default, skip_serializing_if = "Option::is_none")]
429 pub partition_constraint: Option<DetachedPartitionConstraint>,
430}
431
432#[derive(Debug, Clone, Serialize, Deserialize)]
433pub struct DetachedPartitionConstraint {
434 pub spec: PartitionSpec,
435 pub bound: PartitionBound,
436}
437
438#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
440#[allow(clippy::struct_excessive_bools)]
441pub struct ForeignKey {
442 #[serde(default, skip_serializing_if = "Option::is_none")]
444 pub referenced_index: Option<[u8; 16]>,
445 #[serde(default, skip_serializing_if = "Option::is_none")]
447 pub referenced_key: Option<String>,
448 pub name: Option<String>,
449 #[serde(default, skip_serializing_if = "Option::is_none")]
451 pub object_id: Option<[u8; 16]>,
452 #[serde(default, skip_serializing_if = "Option::is_none")]
454 pub catalog_identity: Option<ConstraintCatalogIdentity>,
455 pub local_columns: Vec<String>,
456 pub ref_table: String,
457 pub ref_columns: Vec<String>,
458 #[serde(default)]
459 pub on_update: ForeignKeyAction,
460 #[serde(default)]
461 pub on_delete: ForeignKeyAction,
462 #[serde(default)]
466 pub on_delete_set_columns: Vec<String>,
467 #[serde(default)]
468 pub match_type: ForeignKeyMatch,
469 #[serde(default = "default_true")]
470 pub enforced: bool,
471 #[serde(default = "default_true")]
472 pub validated: bool,
473 #[serde(default)]
474 pub deferrable: bool,
475 #[serde(default)]
476 pub initially_deferred: bool,
477 #[serde(default)]
479 pub period: bool,
480 #[serde(default, skip_serializing_if = "Vec::is_empty")]
482 pub referenced_partitions: Vec<super::ReferencedPartitionConstraint>,
483}
484
485const fn default_true() -> bool {
486 true
487}
488
489#[expect(
490 clippy::trivially_copy_pass_by_ref,
491 reason = "serde skip_serializing_if requires a borrowed field"
492)]
493const fn is_true(value: &bool) -> bool {
494 *value
495}
496
497#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
498pub enum ForeignKeyAction {
499 #[default]
500 NoAction,
501 Restrict,
502 Cascade,
503 SetNull,
504 SetDefault,
505}
506
507#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
508pub enum ForeignKeyMatch {
509 #[default]
510 Simple,
511 Full,
512}