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 = "default_true")]
41 pub not_null_validated: bool,
42 #[serde(default)]
45 pub not_null_no_inherit: bool,
46 #[serde(default = "default_true", skip_serializing_if = "is_true")]
48 pub not_null_is_local: bool,
49 #[serde(
51 default,
52 deserialize_with = "deserialize_auto_increment",
53 skip_serializing_if = "Option::is_none"
54 )]
55 pub auto_increment: Option<AutoIncrement>,
56 #[serde(default)]
59 pub unique: bool,
60 #[serde(default, skip_serializing_if = "Option::is_none")]
64 pub default: Option<Expr>,
65 #[serde(default, skip_serializing_if = "Option::is_none")]
69 pub generated: Option<GeneratedColumn>,
70 #[serde(default, skip_serializing_if = "Option::is_none")]
73 pub check: Option<Expr>,
74 #[serde(default, skip_serializing_if = "Option::is_none")]
75 pub check_name: Option<String>,
76 #[serde(default = "default_true")]
77 pub check_enforced: bool,
78 #[serde(default = "default_true")]
79 pub check_validated: bool,
80 #[serde(default)]
81 pub check_no_inherit: bool,
82 #[serde(default = "default_true", skip_serializing_if = "is_true")]
84 pub check_is_local: bool,
85 #[serde(default, skip_serializing_if = "Option::is_none")]
87 pub check_object_id: Option<[u8; 16]>,
88 #[serde(default, skip_serializing_if = "Option::is_none")]
90 pub references: Option<ForeignKeyRef>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
95#[allow(clippy::struct_excessive_bools)]
96pub struct ForeignKeyRef {
97 #[serde(default, skip_serializing_if = "Option::is_none")]
98 pub referenced_key: Option<String>,
99 #[serde(default, skip_serializing_if = "Option::is_none")]
100 pub name: Option<String>,
101 #[serde(default, skip_serializing_if = "Option::is_none")]
104 pub object_id: Option<[u8; 16]>,
105 pub table: String,
106 #[serde(default, skip_serializing_if = "Option::is_none")]
107 pub column: Option<String>,
108 #[serde(default)]
109 pub on_update: ForeignKeyAction,
110 #[serde(default)]
111 pub on_delete: ForeignKeyAction,
112 #[serde(default)]
113 pub match_type: ForeignKeyMatch,
114 #[serde(default = "default_true")]
115 pub enforced: bool,
116 #[serde(default = "default_true")]
117 pub validated: bool,
118 #[serde(default)]
119 pub deferrable: bool,
120 #[serde(default)]
121 pub initially_deferred: bool,
122 #[serde(default)]
124 pub period: bool,
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct CreateTable {
129 pub name: String,
130 pub qualifier: String,
132 pub columns: Vec<ColumnDef>,
133 pub if_not_exists: bool,
136 #[allow(dead_code)]
139 pub checks: Vec<TableCheck>,
140 pub foreign_keys: Vec<ForeignKey>,
142 #[serde(default)]
147 pub key_constraints: Vec<TableKeyConstraint>,
148 #[serde(default)]
150 pub persistence: RelationPersistence,
151 #[serde(default)]
153 pub on_commit: OnCommitAction,
154 #[serde(default)]
158 pub hierarchy: TableHierarchy,
159}
160
161#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
163pub struct DeferredCreateTable {
164 pub name: String,
165 pub persistence: RelationPersistence,
166 pub definition_sql: String,
167}
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
170pub enum TableKeyConstraintKind {
171 PrimaryKey,
172 Unique,
173}
174
175#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
177pub struct TableKeyConstraint {
178 pub name: Option<String>,
179 pub kind: TableKeyConstraintKind,
180 pub columns: Vec<String>,
181 #[serde(default)]
184 pub nulls_not_distinct: bool,
185 #[serde(default)]
187 pub without_overlaps: bool,
188}
189
190#[derive(Debug, Clone, Default, Serialize, Deserialize)]
195pub struct TableConstraintSet {
196 #[serde(default, skip_serializing_if = "Option::is_none")]
198 pub columns_declared: Option<bool>,
199 #[serde(default)]
200 pub checks: Vec<TableCheck>,
201 #[serde(default)]
202 pub foreign_keys: Vec<ForeignKey>,
203 #[serde(default)]
204 pub key_constraints: Vec<TableKeyConstraint>,
205 #[serde(default)]
207 pub persistence: RelationPersistence,
208 #[serde(default)]
210 pub on_commit: OnCommitAction,
211 #[serde(default)]
213 pub hierarchy: TableHierarchy,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
219#[expect(
220 clippy::struct_excessive_bools,
221 reason = "CHECK catalog flags are independent PostgreSQL properties"
222)]
223pub struct TableCheck {
224 pub name: Option<String>,
225 #[serde(default, skip_serializing_if = "Option::is_none")]
227 pub object_id: Option<[u8; 16]>,
228 #[serde(default = "default_true", skip_serializing_if = "is_true")]
230 pub is_local: bool,
231 pub expr: Expr,
232 #[serde(default = "default_true")]
233 pub enforced: bool,
234 #[serde(default = "default_true")]
235 pub validated: bool,
236 #[serde(default)]
237 pub no_inherit: bool,
238 #[serde(default, skip_serializing_if = "Option::is_none")]
240 pub partition_constraint: Option<DetachedPartitionConstraint>,
241}
242
243#[derive(Debug, Clone, Serialize, Deserialize)]
244pub struct DetachedPartitionConstraint {
245 pub spec: PartitionSpec,
246 pub bound: PartitionBound,
247}
248
249#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
251#[allow(clippy::struct_excessive_bools)]
252pub struct ForeignKey {
253 #[serde(default, skip_serializing_if = "Option::is_none")]
255 pub referenced_key: Option<String>,
256 pub name: Option<String>,
257 #[serde(default, skip_serializing_if = "Option::is_none")]
260 pub object_id: Option<[u8; 16]>,
261 pub local_columns: Vec<String>,
262 pub ref_table: String,
263 pub ref_columns: Vec<String>,
264 #[serde(default)]
265 pub on_update: ForeignKeyAction,
266 #[serde(default)]
267 pub on_delete: ForeignKeyAction,
268 #[serde(default)]
272 pub on_delete_set_columns: Vec<String>,
273 #[serde(default)]
274 pub match_type: ForeignKeyMatch,
275 #[serde(default = "default_true")]
276 pub enforced: bool,
277 #[serde(default = "default_true")]
278 pub validated: bool,
279 #[serde(default)]
280 pub deferrable: bool,
281 #[serde(default)]
282 pub initially_deferred: bool,
283 #[serde(default)]
285 pub period: bool,
286}
287
288const fn default_true() -> bool {
289 true
290}
291
292#[expect(
293 clippy::trivially_copy_pass_by_ref,
294 reason = "serde skip_serializing_if requires a borrowed field"
295)]
296const fn is_true(value: &bool) -> bool {
297 *value
298}
299
300#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
301pub enum ForeignKeyAction {
302 #[default]
303 NoAction,
304 Restrict,
305 Cascade,
306 SetNull,
307 SetDefault,
308}
309
310#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
311pub enum ForeignKeyMatch {
312 #[default]
313 Simple,
314 Full,
315}