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 attribute_number: Option<i16>,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
29 pub missing_value: Option<uqa_core::Value>,
30 pub primary_key: bool,
31 pub not_null: bool,
32 #[serde(default)]
35 pub not_null_explicit: bool,
36 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub not_null_name: Option<String>,
41 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub not_null_identity: Option<ConstraintCatalogIdentity>,
44 #[serde(default = "default_true")]
47 pub not_null_validated: bool,
48 #[serde(default)]
51 pub not_null_no_inherit: bool,
52 #[serde(default = "default_true", skip_serializing_if = "is_true")]
54 pub not_null_is_local: bool,
55 #[serde(
57 default,
58 deserialize_with = "deserialize_auto_increment",
59 skip_serializing_if = "Option::is_none"
60 )]
61 pub auto_increment: Option<AutoIncrement>,
62 #[serde(default)]
65 pub unique: bool,
66 #[serde(default, skip_serializing_if = "Option::is_none")]
70 pub default: Option<Expr>,
71 #[serde(default, skip_serializing_if = "Option::is_none")]
75 pub generated: Option<GeneratedColumn>,
76 #[serde(default, skip_serializing_if = "Option::is_none")]
78 pub default_catalog_oid: Option<i64>,
79 #[serde(default, skip_serializing_if = "Option::is_none")]
82 pub check: Option<Expr>,
83 #[serde(default, skip_serializing_if = "Option::is_none")]
84 pub check_name: Option<String>,
85 #[serde(default = "default_true")]
86 pub check_enforced: bool,
87 #[serde(default = "default_true")]
88 pub check_validated: bool,
89 #[serde(default)]
90 pub check_no_inherit: bool,
91 #[serde(default = "default_true", skip_serializing_if = "is_true")]
93 pub check_is_local: bool,
94 #[serde(default, skip_serializing_if = "Option::is_none")]
96 pub check_object_id: Option<[u8; 16]>,
97 #[serde(default, skip_serializing_if = "Option::is_none")]
99 pub check_catalog_oid: Option<i64>,
100 #[serde(default, skip_serializing_if = "Option::is_none")]
102 pub references: Option<ForeignKeyRef>,
103}
104
105impl ColumnDef {
106 #[must_use]
108 pub fn nullable(name: impl Into<String>, ty: ColumnType) -> Self {
109 Self {
110 name: name.into(),
111 ty,
112 object_id: None,
113 attribute_number: None,
114 missing_value: None,
115 primary_key: false,
116 not_null: false,
117 not_null_explicit: false,
118 not_null_name: None,
119 not_null_identity: None,
120 not_null_validated: true,
121 not_null_no_inherit: false,
122 not_null_is_local: true,
123 auto_increment: None,
124 unique: false,
125 default: None,
126 generated: None,
127 check: None,
128 check_name: None,
129 check_enforced: true,
130 check_validated: true,
131 check_no_inherit: false,
132 check_is_local: true,
133 check_object_id: None,
134 check_catalog_oid: None,
135 default_catalog_oid: None,
136 references: None,
137 }
138 }
139}
140
141pub use uqa_core::catalog_identity::CatalogObjectIdentity as ConstraintCatalogIdentity;
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
145#[allow(clippy::struct_excessive_bools)]
146pub struct ForeignKeyRef {
147 #[serde(default, skip_serializing_if = "Option::is_none")]
149 pub referenced_index: Option<[u8; 16]>,
150 #[serde(default, skip_serializing_if = "Option::is_none")]
151 pub referenced_key: Option<String>,
152 #[serde(default, skip_serializing_if = "Option::is_none")]
153 pub name: Option<String>,
154 #[serde(default, skip_serializing_if = "Option::is_none")]
156 pub object_id: Option<[u8; 16]>,
157 #[serde(default, skip_serializing_if = "Option::is_none")]
159 pub catalog_identity: Option<ConstraintCatalogIdentity>,
160 pub table: String,
161 #[serde(default, skip_serializing_if = "Option::is_none")]
162 pub column: Option<String>,
163 #[serde(default)]
164 pub on_update: ForeignKeyAction,
165 #[serde(default)]
166 pub on_delete: ForeignKeyAction,
167 #[serde(default)]
168 pub match_type: ForeignKeyMatch,
169 #[serde(default = "default_true")]
170 pub enforced: bool,
171 #[serde(default = "default_true")]
172 pub validated: bool,
173 #[serde(default)]
174 pub deferrable: bool,
175 #[serde(default)]
176 pub initially_deferred: bool,
177 #[serde(default)]
179 pub period: bool,
180 #[serde(default, skip_serializing_if = "Vec::is_empty")]
182 pub referenced_partitions: Vec<super::ReferencedPartitionConstraint>,
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct CreateTable {
187 pub name: String,
188 pub qualifier: String,
190 pub columns: Vec<ColumnDef>,
191 pub if_not_exists: bool,
194 #[allow(dead_code)]
197 pub checks: Vec<TableCheck>,
198 pub foreign_keys: Vec<ForeignKey>,
200 #[serde(default, skip_serializing_if = "Vec::is_empty")]
202 pub foreign_key_order: Vec<DeclaredForeignKey>,
203 #[serde(default)]
208 pub key_constraints: Vec<TableKeyConstraint>,
209 #[serde(default)]
211 pub persistence: RelationPersistence,
212 #[serde(default)]
214 pub on_commit: OnCommitAction,
215 #[serde(default)]
219 pub hierarchy: TableHierarchy,
220 #[serde(default, skip_serializing_if = "Vec::is_empty")]
222 pub check_order: Vec<DeclaredCheck>,
223 #[serde(default, skip_serializing_if = "Vec::is_empty")]
225 pub element_order: Vec<DeclaredElement>,
226 #[serde(default, skip_serializing_if = "Vec::is_empty")]
228 pub not_null_declarations: Vec<NotNullDeclaration>,
229 #[serde(default, skip_serializing_if = "Vec::is_empty")]
231 pub untyped_columns: Vec<String>,
232}
233
234#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
236pub enum DeclaredElement {
237 Column(ColumnDeclaration),
239 NotNull(NotNullDeclaration),
241 PrimaryKey { columns: Vec<String> },
243 DeferrableKey,
245}
246
247#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
249pub enum DeclaredForeignKey {
250 Column(String),
251 Table(usize),
252}
253
254#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
256pub struct NotNullDeclaration {
257 pub column: String,
258 pub name: Option<String>,
259 pub no_inherit: bool,
260 pub explicit: bool,
262}
263
264#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
266pub struct ColumnDeclaration {
267 pub serial: bool,
269 pub serial_array: bool,
271 pub clauses: Vec<ColumnClause>,
272}
273
274#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
276pub struct ColumnClause {
277 pub kind: ColumnClauseKind,
278 pub name: Option<String>,
280 pub no_inherit: bool,
281}
282
283#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
285pub enum ColumnClauseKind {
286 Null,
287 NotNull,
288 Default,
289 Identity,
290 Generated,
291 Check,
292 PrimaryKey,
293 Unique,
294 ForeignKey,
295 Deferrable,
296 NotDeferrable,
297 InitiallyDeferred,
298 InitiallyImmediate,
299 Enforced,
300 NotEnforced,
301}
302
303#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
305pub enum DeclaredCheck {
306 Column(String),
308 Table(usize),
310}
311
312#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
314pub struct DeferredCreateTable {
315 pub name: String,
316 pub persistence: RelationPersistence,
317 pub definition_sql: String,
318}
319
320#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
321pub enum TableKeyConstraintKind {
322 PrimaryKey,
323 Unique,
324}
325
326impl TableKeyConstraintKind {
327 #[must_use]
329 pub const fn sql_label(self) -> &'static str {
330 match self {
331 Self::PrimaryKey => "PRIMARY KEY",
332 Self::Unique => "UNIQUE",
333 }
334 }
335}
336
337#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
339pub struct TableKeyConstraint {
340 #[serde(default, skip_serializing_if = "Option::is_none")]
342 pub catalog_identity: Option<ConstraintCatalogIdentity>,
343 #[serde(default, skip_serializing_if = "Option::is_none")]
345 pub index_identity: Option<ConstraintCatalogIdentity>,
346 pub name: Option<String>,
347 pub kind: TableKeyConstraintKind,
348 pub columns: Vec<String>,
349 #[serde(default, skip_serializing_if = "Vec::is_empty")]
351 pub included_columns: Vec<String>,
352 #[serde(default)]
355 pub nulls_not_distinct: bool,
356 #[serde(default)]
358 pub without_overlaps: bool,
359}
360
361#[derive(Debug, Clone, Default, Serialize, Deserialize)]
366pub struct TableConstraintSet {
367 #[serde(default, skip_serializing_if = "Vec::is_empty")]
369 pub dropped_attributes: Vec<crate::catalog::relation_attributes::DroppedAttribute>,
370 #[serde(default, skip_serializing_if = "Option::is_none")]
372 pub columns_declared: Option<bool>,
373 #[serde(default)]
374 pub checks: Vec<TableCheck>,
375 #[serde(default)]
376 pub foreign_keys: Vec<ForeignKey>,
377 #[serde(default)]
378 pub key_constraints: Vec<TableKeyConstraint>,
379 #[serde(default)]
381 pub persistence: RelationPersistence,
382 #[serde(default)]
384 pub on_commit: OnCommitAction,
385 #[serde(default)]
387 pub hierarchy: TableHierarchy,
388 #[serde(default, skip_serializing_if = "Option::is_none")]
390 pub catalog_oids: Option<crate::catalog::relation_oids::RelationCatalogOids>,
391 #[serde(default, skip_serializing_if = "Option::is_none")]
393 pub row_type_array_name: Option<String>,
394}
395
396#[derive(Debug, Clone, Serialize, Deserialize)]
399#[expect(
400 clippy::struct_excessive_bools,
401 reason = "CHECK catalog flags are independent PostgreSQL properties"
402)]
403pub struct TableCheck {
404 pub name: Option<String>,
405 #[serde(default, skip_serializing_if = "Option::is_none")]
407 pub object_id: Option<[u8; 16]>,
408 #[serde(default, skip_serializing_if = "Option::is_none")]
409 pub catalog_oid: Option<i64>,
410 #[serde(default = "default_true", skip_serializing_if = "is_true")]
412 pub is_local: bool,
413 pub expr: Expr,
414 #[serde(default = "default_true")]
415 pub enforced: bool,
416 #[serde(default = "default_true")]
417 pub validated: bool,
418 #[serde(default)]
419 pub no_inherit: bool,
420 #[serde(default, skip_serializing_if = "Option::is_none")]
422 pub partition_constraint: Option<DetachedPartitionConstraint>,
423}
424
425#[derive(Debug, Clone, Serialize, Deserialize)]
426pub struct DetachedPartitionConstraint {
427 pub spec: PartitionSpec,
428 pub bound: PartitionBound,
429}
430
431#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
433#[allow(clippy::struct_excessive_bools)]
434pub struct ForeignKey {
435 #[serde(default, skip_serializing_if = "Option::is_none")]
437 pub referenced_index: Option<[u8; 16]>,
438 #[serde(default, skip_serializing_if = "Option::is_none")]
440 pub referenced_key: Option<String>,
441 pub name: Option<String>,
442 #[serde(default, skip_serializing_if = "Option::is_none")]
444 pub object_id: Option<[u8; 16]>,
445 #[serde(default, skip_serializing_if = "Option::is_none")]
447 pub catalog_identity: Option<ConstraintCatalogIdentity>,
448 pub local_columns: Vec<String>,
449 pub ref_table: String,
450 pub ref_columns: Vec<String>,
451 #[serde(default)]
452 pub on_update: ForeignKeyAction,
453 #[serde(default)]
454 pub on_delete: ForeignKeyAction,
455 #[serde(default)]
459 pub on_delete_set_columns: Vec<String>,
460 #[serde(default)]
461 pub match_type: ForeignKeyMatch,
462 #[serde(default = "default_true")]
463 pub enforced: bool,
464 #[serde(default = "default_true")]
465 pub validated: bool,
466 #[serde(default)]
467 pub deferrable: bool,
468 #[serde(default)]
469 pub initially_deferred: bool,
470 #[serde(default)]
472 pub period: bool,
473 #[serde(default, skip_serializing_if = "Vec::is_empty")]
475 pub referenced_partitions: Vec<super::ReferencedPartitionConstraint>,
476}
477
478const fn default_true() -> bool {
479 true
480}
481
482#[expect(
483 clippy::trivially_copy_pass_by_ref,
484 reason = "serde skip_serializing_if requires a borrowed field"
485)]
486const fn is_true(value: &bool) -> bool {
487 *value
488}
489
490#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
491pub enum ForeignKeyAction {
492 #[default]
493 NoAction,
494 Restrict,
495 Cascade,
496 SetNull,
497 SetDefault,
498}
499
500#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
501pub enum ForeignKeyMatch {
502 #[default]
503 Simple,
504 Full,
505}