Skip to main content

ormdantic_schema/
constraints.rs

1#[derive(Debug, Clone, PartialEq, Eq)]
2pub enum OracleIndexCompression {
3    Enabled,
4    Prefix(u32),
5}
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct UniqueConstraintDef {
9    name: String,
10    columns: Vec<String>,
11    timing: ConstraintTiming,
12    nulls_not_distinct: bool,
13    sqlite_on_conflict: Option<String>,
14    mssql_filegroup: Option<String>,
15    mssql_clustered: Option<bool>,
16    oracle_tablespace: Option<String>,
17    oracle_compress: Option<OracleIndexCompression>,
18}
19
20impl UniqueConstraintDef {
21    pub fn new(name: impl Into<String>, columns: Vec<String>) -> Self {
22        Self {
23            name: name.into(),
24            columns,
25            timing: ConstraintTiming::default(),
26            nulls_not_distinct: false,
27            sqlite_on_conflict: None,
28            mssql_filegroup: None,
29            mssql_clustered: None,
30            oracle_tablespace: None,
31            oracle_compress: None,
32        }
33    }
34
35    pub fn with_timing(mut self, timing: ConstraintTiming) -> Self {
36        self.timing = timing;
37        self
38    }
39
40    pub fn nulls_not_distinct(mut self) -> Self {
41        self.nulls_not_distinct = true;
42        self
43    }
44
45    pub fn with_nulls_not_distinct(mut self, nulls_not_distinct: bool) -> Self {
46        self.nulls_not_distinct = nulls_not_distinct;
47        self
48    }
49
50    pub fn with_sqlite_on_conflict(mut self, policy: impl Into<String>) -> Self {
51        self.sqlite_on_conflict = Some(policy.into());
52        self
53    }
54
55    pub fn with_sqlite_on_conflict_option(mut self, policy: Option<String>) -> Self {
56        self.sqlite_on_conflict = policy;
57        self
58    }
59
60    pub fn with_mssql_filegroup(mut self, filegroup: impl Into<String>) -> Self {
61        self.mssql_filegroup = Some(filegroup.into());
62        self
63    }
64
65    pub fn with_mssql_filegroup_option(mut self, filegroup: Option<String>) -> Self {
66        self.mssql_filegroup = filegroup;
67        self
68    }
69
70    pub fn with_mssql_clustered(mut self, clustered: bool) -> Self {
71        self.mssql_clustered = Some(clustered);
72        self
73    }
74
75    pub fn with_mssql_clustered_option(mut self, clustered: Option<bool>) -> Self {
76        self.mssql_clustered = clustered;
77        self
78    }
79
80    pub fn with_oracle_tablespace(mut self, tablespace: impl Into<String>) -> Self {
81        self.oracle_tablespace = Some(tablespace.into());
82        self
83    }
84
85    pub fn with_oracle_tablespace_option(mut self, tablespace: Option<String>) -> Self {
86        self.oracle_tablespace = tablespace;
87        self
88    }
89
90    pub fn with_oracle_compress(mut self) -> Self {
91        self.oracle_compress = Some(OracleIndexCompression::Enabled);
92        self
93    }
94
95    pub fn with_oracle_compress_prefix(mut self, prefix_length: u32) -> Self {
96        self.oracle_compress = Some(OracleIndexCompression::Prefix(prefix_length));
97        self
98    }
99
100    pub fn with_oracle_compress_option(mut self, compress: Option<OracleIndexCompression>) -> Self {
101        self.oracle_compress = compress;
102        self
103    }
104
105    pub fn name(&self) -> &str {
106        &self.name
107    }
108
109    pub fn columns(&self) -> &[String] {
110        &self.columns
111    }
112
113    pub fn timing(&self) -> &ConstraintTiming {
114        &self.timing
115    }
116
117    pub fn is_nulls_not_distinct(&self) -> bool {
118        self.nulls_not_distinct
119    }
120
121    pub fn sqlite_on_conflict(&self) -> Option<&str> {
122        self.sqlite_on_conflict.as_deref()
123    }
124
125    pub fn mssql_filegroup(&self) -> Option<&str> {
126        self.mssql_filegroup.as_deref()
127    }
128
129    pub fn mssql_clustered(&self) -> Option<bool> {
130        self.mssql_clustered
131    }
132
133    pub fn oracle_tablespace(&self) -> Option<&str> {
134        self.oracle_tablespace.as_deref()
135    }
136
137    pub fn oracle_compress(&self) -> Option<&OracleIndexCompression> {
138        self.oracle_compress.as_ref()
139    }
140}
141
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub enum ConstraintDef {
144    Unique(UniqueConstraintDef),
145    Check(CheckConstraintDef),
146    ForeignKey(ForeignKeyDef),
147    Exclusion(ExclusionConstraintDef),
148}
149
150#[derive(Debug, Clone, PartialEq, Eq, Default)]
151pub struct ConstraintTiming {
152    deferrable: Option<bool>,
153    initially_deferred: bool,
154}
155
156impl ConstraintTiming {
157    pub fn new(deferrable: Option<bool>, initially_deferred: bool) -> Self {
158        Self {
159            deferrable: if initially_deferred && deferrable.is_none() {
160                Some(true)
161            } else {
162                deferrable
163            },
164            initially_deferred,
165        }
166    }
167
168    pub fn deferrable(&self) -> Option<bool> {
169        self.deferrable
170    }
171
172    pub fn initially_deferred(&self) -> bool {
173        self.initially_deferred
174    }
175}
176
177#[derive(Debug, Clone, PartialEq, Eq)]
178pub struct CheckConstraintDef {
179    name: Option<String>,
180    expression: String,
181    validated: bool,
182    no_inherit: bool,
183}
184
185impl CheckConstraintDef {
186    pub fn new(expression: impl Into<String>) -> Self {
187        Self {
188            name: None,
189            expression: expression.into(),
190            validated: true,
191            no_inherit: false,
192        }
193    }
194
195    pub fn named(mut self, name: impl Into<String>) -> Self {
196        self.name = Some(name.into());
197        self
198    }
199
200    pub fn validated(mut self, validated: bool) -> Self {
201        self.validated = validated;
202        self
203    }
204
205    pub fn not_validated(self) -> Self {
206        self.validated(false)
207    }
208
209    pub fn no_inherit(mut self) -> Self {
210        self.no_inherit = true;
211        self
212    }
213
214    pub fn name(&self) -> Option<&str> {
215        self.name.as_deref()
216    }
217
218    pub fn expression(&self) -> &str {
219        &self.expression
220    }
221
222    pub fn is_validated(&self) -> bool {
223        self.validated
224    }
225
226    pub fn is_no_inherit(&self) -> bool {
227        self.no_inherit
228    }
229}
230
231#[derive(Debug, Clone, PartialEq, Eq)]
232pub struct ExclusionElementDef {
233    expression: String,
234    operator: String,
235    quoted: bool,
236    opclass: Option<String>,
237}
238
239impl ExclusionElementDef {
240    pub fn column(column: impl Into<String>, operator: impl Into<String>) -> Self {
241        Self {
242            expression: column.into(),
243            operator: operator.into(),
244            quoted: true,
245            opclass: None,
246        }
247    }
248
249    pub fn expression(expression: impl Into<String>, operator: impl Into<String>) -> Self {
250        Self {
251            expression: expression.into(),
252            operator: operator.into(),
253            quoted: false,
254            opclass: None,
255        }
256    }
257
258    pub fn opclass(mut self, opclass: impl Into<String>) -> Self {
259        self.opclass = Some(opclass.into());
260        self
261    }
262
263    pub fn value(&self) -> &str {
264        &self.expression
265    }
266
267    pub fn operator(&self) -> &str {
268        &self.operator
269    }
270
271    pub fn operator_class(&self) -> Option<&str> {
272        self.opclass.as_deref()
273    }
274
275    pub fn is_quoted(&self) -> bool {
276        self.quoted
277    }
278}
279
280#[derive(Debug, Clone, PartialEq, Eq)]
281pub struct ExclusionConstraintDef {
282    name: String,
283    elements: Vec<ExclusionElementDef>,
284    method: String,
285    predicate: Option<String>,
286    timing: ConstraintTiming,
287}
288
289impl ExclusionConstraintDef {
290    pub fn new(name: impl Into<String>, elements: Vec<ExclusionElementDef>) -> Self {
291        Self {
292            name: name.into(),
293            elements,
294            method: "gist".to_string(),
295            predicate: None,
296            timing: ConstraintTiming::default(),
297        }
298    }
299
300    pub fn method(mut self, method: impl Into<String>) -> Self {
301        self.method = method.into();
302        self
303    }
304
305    pub fn where_expr(mut self, predicate: impl Into<String>) -> Self {
306        self.predicate = Some(predicate.into());
307        self
308    }
309
310    pub fn with_timing(mut self, timing: ConstraintTiming) -> Self {
311        self.timing = timing;
312        self
313    }
314
315    pub fn name(&self) -> &str {
316        &self.name
317    }
318
319    pub fn elements(&self) -> &[ExclusionElementDef] {
320        &self.elements
321    }
322
323    pub fn method_name(&self) -> &str {
324        &self.method
325    }
326
327    pub fn predicate(&self) -> Option<&str> {
328        self.predicate.as_deref()
329    }
330
331    pub fn timing(&self) -> &ConstraintTiming {
332        &self.timing
333    }
334}
335
336#[derive(Debug, Clone, PartialEq, Eq)]
337pub enum ForeignKeyAction {
338    Cascade,
339    Restrict,
340    SetNull,
341    SetDefault,
342    NoAction,
343}
344
345#[derive(Debug, Clone, PartialEq, Eq)]
346pub enum ForeignKeyMatch {
347    Simple,
348    Full,
349}
350
351#[derive(Debug, Clone, PartialEq, Eq)]
352pub struct ForeignKeyDef {
353    name: Option<String>,
354    local_columns: Vec<String>,
355    remote_table: String,
356    remote_columns: Vec<String>,
357    on_delete: Option<ForeignKeyAction>,
358    on_update: Option<ForeignKeyAction>,
359    timing: ConstraintTiming,
360    validated: bool,
361    match_type: Option<ForeignKeyMatch>,
362}
363
364impl ForeignKeyDef {
365    pub fn new(
366        local_columns: Vec<String>,
367        remote_table: impl Into<String>,
368        remote_columns: Vec<String>,
369    ) -> Self {
370        Self {
371            name: None,
372            local_columns,
373            remote_table: remote_table.into(),
374            remote_columns,
375            on_delete: None,
376            on_update: None,
377            timing: ConstraintTiming::default(),
378            validated: true,
379            match_type: None,
380        }
381    }
382
383    pub fn named(mut self, name: impl Into<String>) -> Self {
384        self.name = Some(name.into());
385        self
386    }
387
388    pub fn on_delete(mut self, action: ForeignKeyAction) -> Self {
389        self.on_delete = Some(action);
390        self
391    }
392
393    pub fn on_update(mut self, action: ForeignKeyAction) -> Self {
394        self.on_update = Some(action);
395        self
396    }
397
398    pub fn with_timing(mut self, timing: ConstraintTiming) -> Self {
399        self.timing = timing;
400        self
401    }
402
403    pub fn with_match(mut self, match_type: ForeignKeyMatch) -> Self {
404        self.match_type = Some(match_type);
405        self
406    }
407
408    pub fn validated(mut self, validated: bool) -> Self {
409        self.validated = validated;
410        self
411    }
412
413    pub fn not_validated(self) -> Self {
414        self.validated(false)
415    }
416
417    pub fn name(&self) -> Option<&str> {
418        self.name.as_deref()
419    }
420
421    pub fn local_columns(&self) -> &[String] {
422        &self.local_columns
423    }
424
425    pub fn remote_table(&self) -> &str {
426        &self.remote_table
427    }
428
429    pub fn remote_columns(&self) -> &[String] {
430        &self.remote_columns
431    }
432
433    pub fn on_delete_action(&self) -> Option<&ForeignKeyAction> {
434        self.on_delete.as_ref()
435    }
436
437    pub fn on_update_action(&self) -> Option<&ForeignKeyAction> {
438        self.on_update.as_ref()
439    }
440
441    pub fn timing(&self) -> &ConstraintTiming {
442        &self.timing
443    }
444
445    pub fn match_type(&self) -> Option<&ForeignKeyMatch> {
446        self.match_type.as_ref()
447    }
448
449    pub fn is_validated(&self) -> bool {
450        self.validated
451    }
452}