Skip to main content

ormdantic_schema/
table.rs

1use ormdantic_core::{QualifiedName, TableId};
2
3use crate::{
4    CheckConstraintDef, ColumnDef, ExclusionConstraintDef, FieldKind, ForeignKeyDef, IndexDef,
5    RelationshipDef, UniqueConstraintDef,
6};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum OracleTableCompression {
10    Enabled,
11    Level(u32),
12}
13
14#[derive(Debug, Clone, PartialEq, Eq, Default)]
15pub struct MysqlTableOptions {
16    pub engine: Option<String>,
17    pub charset: Option<String>,
18    pub collation: Option<String>,
19    pub row_format: Option<String>,
20    pub key_block_size: Option<u32>,
21    pub pack_keys: Option<bool>,
22    pub checksum: Option<bool>,
23    pub delay_key_write: Option<bool>,
24    pub stats_persistent: Option<bool>,
25    pub stats_auto_recalc: Option<bool>,
26    pub stats_sample_pages: Option<u32>,
27    pub avg_row_length: Option<u32>,
28    pub max_rows: Option<u32>,
29    pub min_rows: Option<u32>,
30    pub insert_method: Option<String>,
31    pub data_directory: Option<String>,
32    pub index_directory: Option<String>,
33    pub connection: Option<String>,
34    pub union: Vec<String>,
35    pub partition_by: Option<String>,
36    pub partitions: Option<u32>,
37    pub subpartition_by: Option<String>,
38    pub subpartitions: Option<u32>,
39    pub auto_increment: Option<u32>,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct TableDef {
44    id: Option<TableId>,
45    model_key: String,
46    name: String,
47    primary_key: String,
48    columns: Vec<ColumnDef>,
49    indexes: Vec<IndexDef>,
50    unique_constraints: Vec<UniqueConstraintDef>,
51    relationships: Vec<RelationshipDef>,
52    check_constraints: Vec<CheckConstraintDef>,
53    foreign_keys: Vec<ForeignKeyDef>,
54    exclusion_constraints: Vec<ExclusionConstraintDef>,
55    schema: Option<String>,
56    comment: Option<String>,
57    tablespace: Option<String>,
58    mysql_engine: Option<String>,
59    mysql_charset: Option<String>,
60    mysql_collation: Option<String>,
61    mysql_row_format: Option<String>,
62    mysql_key_block_size: Option<u32>,
63    mysql_pack_keys: Option<bool>,
64    mysql_checksum: Option<bool>,
65    mysql_delay_key_write: Option<bool>,
66    mysql_stats_persistent: Option<bool>,
67    mysql_stats_auto_recalc: Option<bool>,
68    mysql_stats_sample_pages: Option<u32>,
69    mysql_avg_row_length: Option<u32>,
70    mysql_max_rows: Option<u32>,
71    mysql_min_rows: Option<u32>,
72    mysql_insert_method: Option<String>,
73    mysql_data_directory: Option<String>,
74    mysql_index_directory: Option<String>,
75    mysql_connection: Option<String>,
76    mysql_union: Vec<String>,
77    mysql_partition_by: Option<String>,
78    mysql_partitions: Option<u32>,
79    mysql_subpartition_by: Option<String>,
80    mysql_subpartitions: Option<u32>,
81    mysql_auto_increment: Option<u32>,
82    postgres_inherits: Vec<String>,
83    postgres_with: Vec<(String, String)>,
84    postgres_using: Option<String>,
85    postgres_unlogged: bool,
86    postgres_partition_by: Option<String>,
87    postgres_partition_of: Option<String>,
88    postgres_partition_for: Option<String>,
89    sqlite_strict: bool,
90    sqlite_without_rowid: bool,
91    oracle_compress: Option<OracleTableCompression>,
92    mssql_primary_key_nonclustered: bool,
93}
94
95impl TableDef {
96    pub fn new(
97        name: impl Into<String>,
98        primary_key: impl Into<String>,
99        columns: Vec<String>,
100    ) -> Self {
101        let name = name.into();
102        Self {
103            id: None,
104            model_key: name.clone(),
105            name,
106            primary_key: primary_key.into(),
107            columns: columns
108                .into_iter()
109                .map(|column| ColumnDef::new(column, FieldKind::Unknown))
110                .collect(),
111            indexes: Vec::new(),
112            unique_constraints: Vec::new(),
113            relationships: Vec::new(),
114            check_constraints: Vec::new(),
115            foreign_keys: Vec::new(),
116            exclusion_constraints: Vec::new(),
117            schema: None,
118            comment: None,
119            tablespace: None,
120            mysql_engine: None,
121            mysql_charset: None,
122            mysql_collation: None,
123            mysql_row_format: None,
124            mysql_key_block_size: None,
125            mysql_pack_keys: None,
126            mysql_checksum: None,
127            mysql_delay_key_write: None,
128            mysql_stats_persistent: None,
129            mysql_stats_auto_recalc: None,
130            mysql_stats_sample_pages: None,
131            mysql_avg_row_length: None,
132            mysql_max_rows: None,
133            mysql_min_rows: None,
134            mysql_insert_method: None,
135            mysql_data_directory: None,
136            mysql_index_directory: None,
137            mysql_connection: None,
138            mysql_union: Vec::new(),
139            mysql_partition_by: None,
140            mysql_partitions: None,
141            mysql_subpartition_by: None,
142            mysql_subpartitions: None,
143            mysql_auto_increment: None,
144            postgres_inherits: Vec::new(),
145            postgres_with: Vec::new(),
146            postgres_using: None,
147            postgres_unlogged: false,
148            postgres_partition_by: None,
149            postgres_partition_of: None,
150            postgres_partition_for: None,
151            sqlite_strict: false,
152            sqlite_without_rowid: false,
153            oracle_compress: None,
154            mssql_primary_key_nonclustered: false,
155        }
156    }
157
158    pub fn from_parts(
159        name: impl Into<String>,
160        model_key: impl Into<String>,
161        primary_key: impl Into<String>,
162        columns: Vec<ColumnDef>,
163        indexes: Vec<IndexDef>,
164        unique_constraints: Vec<UniqueConstraintDef>,
165        relationships: Vec<RelationshipDef>,
166    ) -> Self {
167        Self {
168            id: None,
169            model_key: model_key.into(),
170            name: name.into(),
171            primary_key: primary_key.into(),
172            columns,
173            indexes,
174            unique_constraints,
175            relationships,
176            check_constraints: Vec::new(),
177            foreign_keys: Vec::new(),
178            exclusion_constraints: Vec::new(),
179            schema: None,
180            comment: None,
181            tablespace: None,
182            mysql_engine: None,
183            mysql_charset: None,
184            mysql_collation: None,
185            mysql_row_format: None,
186            mysql_key_block_size: None,
187            mysql_pack_keys: None,
188            mysql_checksum: None,
189            mysql_delay_key_write: None,
190            mysql_stats_persistent: None,
191            mysql_stats_auto_recalc: None,
192            mysql_stats_sample_pages: None,
193            mysql_avg_row_length: None,
194            mysql_max_rows: None,
195            mysql_min_rows: None,
196            mysql_insert_method: None,
197            mysql_data_directory: None,
198            mysql_index_directory: None,
199            mysql_connection: None,
200            mysql_union: Vec::new(),
201            mysql_partition_by: None,
202            mysql_partitions: None,
203            mysql_subpartition_by: None,
204            mysql_subpartitions: None,
205            mysql_auto_increment: None,
206            postgres_inherits: Vec::new(),
207            postgres_with: Vec::new(),
208            postgres_using: None,
209            postgres_unlogged: false,
210            postgres_partition_by: None,
211            postgres_partition_of: None,
212            postgres_partition_for: None,
213            sqlite_strict: false,
214            sqlite_without_rowid: false,
215            oracle_compress: None,
216            mssql_primary_key_nonclustered: false,
217        }
218    }
219
220    pub fn with_relationships(mut self, relationships: Vec<RelationshipDef>) -> Self {
221        self.relationships = relationships;
222        self
223    }
224
225    pub fn with_schema(mut self, schema: impl Into<String>) -> Self {
226        self.schema = Some(schema.into());
227        self
228    }
229
230    pub fn with_comment(mut self, comment: impl Into<String>) -> Self {
231        self.comment = Some(comment.into());
232        self
233    }
234
235    pub fn with_tablespace(mut self, tablespace: impl Into<String>) -> Self {
236        self.tablespace = Some(tablespace.into());
237        self
238    }
239
240    pub fn with_mysql_engine(mut self, engine: impl Into<String>) -> Self {
241        self.mysql_engine = Some(engine.into());
242        self
243    }
244
245    pub fn with_mysql_charset(mut self, charset: impl Into<String>) -> Self {
246        self.mysql_charset = Some(charset.into());
247        self
248    }
249
250    pub fn with_mysql_collation(mut self, collation: impl Into<String>) -> Self {
251        self.mysql_collation = Some(collation.into());
252        self
253    }
254
255    pub fn with_mysql_row_format(mut self, row_format: impl Into<String>) -> Self {
256        self.mysql_row_format = Some(row_format.into());
257        self
258    }
259
260    pub fn with_mysql_key_block_size(mut self, key_block_size: u32) -> Self {
261        self.mysql_key_block_size = Some(key_block_size);
262        self
263    }
264
265    pub fn with_mysql_pack_keys(mut self, pack_keys: bool) -> Self {
266        self.mysql_pack_keys = Some(pack_keys);
267        self
268    }
269
270    pub fn with_mysql_checksum(mut self, checksum: bool) -> Self {
271        self.mysql_checksum = Some(checksum);
272        self
273    }
274
275    pub fn with_mysql_delay_key_write(mut self, delay_key_write: bool) -> Self {
276        self.mysql_delay_key_write = Some(delay_key_write);
277        self
278    }
279
280    pub fn with_mysql_stats_persistent(mut self, stats_persistent: bool) -> Self {
281        self.mysql_stats_persistent = Some(stats_persistent);
282        self
283    }
284
285    pub fn with_mysql_stats_auto_recalc(mut self, stats_auto_recalc: bool) -> Self {
286        self.mysql_stats_auto_recalc = Some(stats_auto_recalc);
287        self
288    }
289
290    pub fn with_mysql_stats_sample_pages(mut self, stats_sample_pages: u32) -> Self {
291        self.mysql_stats_sample_pages = Some(stats_sample_pages);
292        self
293    }
294
295    pub fn with_mysql_avg_row_length(mut self, avg_row_length: u32) -> Self {
296        self.mysql_avg_row_length = Some(avg_row_length);
297        self
298    }
299
300    pub fn with_mysql_max_rows(mut self, max_rows: u32) -> Self {
301        self.mysql_max_rows = Some(max_rows);
302        self
303    }
304
305    pub fn with_mysql_min_rows(mut self, min_rows: u32) -> Self {
306        self.mysql_min_rows = Some(min_rows);
307        self
308    }
309
310    pub fn with_mysql_insert_method(mut self, insert_method: impl Into<String>) -> Self {
311        self.mysql_insert_method = Some(insert_method.into());
312        self
313    }
314
315    pub fn with_mysql_data_directory(mut self, data_directory: impl Into<String>) -> Self {
316        self.mysql_data_directory = Some(data_directory.into());
317        self
318    }
319
320    pub fn with_mysql_index_directory(mut self, index_directory: impl Into<String>) -> Self {
321        self.mysql_index_directory = Some(index_directory.into());
322        self
323    }
324
325    pub fn with_mysql_connection(mut self, connection: impl Into<String>) -> Self {
326        self.mysql_connection = Some(connection.into());
327        self
328    }
329
330    pub fn with_mysql_union(mut self, tables: Vec<String>) -> Self {
331        self.mysql_union = tables;
332        self
333    }
334
335    pub fn with_mysql_partition_by(mut self, partition_by: impl Into<String>) -> Self {
336        self.mysql_partition_by = Some(partition_by.into());
337        self
338    }
339
340    pub fn with_mysql_partitions(mut self, partitions: u32) -> Self {
341        self.mysql_partitions = Some(partitions);
342        self
343    }
344
345    pub fn with_mysql_subpartition_by(mut self, subpartition_by: impl Into<String>) -> Self {
346        self.mysql_subpartition_by = Some(subpartition_by.into());
347        self
348    }
349
350    pub fn with_mysql_subpartitions(mut self, subpartitions: u32) -> Self {
351        self.mysql_subpartitions = Some(subpartitions);
352        self
353    }
354
355    pub fn with_mysql_auto_increment(mut self, auto_increment: u32) -> Self {
356        self.mysql_auto_increment = Some(auto_increment);
357        self
358    }
359
360    pub fn with_mysql_options(mut self, options: MysqlTableOptions) -> Self {
361        self.mysql_engine = options.engine;
362        self.mysql_charset = options.charset;
363        self.mysql_collation = options.collation;
364        self.mysql_row_format = options.row_format;
365        self.mysql_key_block_size = options.key_block_size;
366        self.mysql_pack_keys = options.pack_keys;
367        self.mysql_checksum = options.checksum;
368        self.mysql_delay_key_write = options.delay_key_write;
369        self.mysql_stats_persistent = options.stats_persistent;
370        self.mysql_stats_auto_recalc = options.stats_auto_recalc;
371        self.mysql_stats_sample_pages = options.stats_sample_pages;
372        self.mysql_avg_row_length = options.avg_row_length;
373        self.mysql_max_rows = options.max_rows;
374        self.mysql_min_rows = options.min_rows;
375        self.mysql_insert_method = options.insert_method;
376        self.mysql_data_directory = options.data_directory;
377        self.mysql_index_directory = options.index_directory;
378        self.mysql_connection = options.connection;
379        self.mysql_union = options.union;
380        self.mysql_partition_by = options.partition_by;
381        self.mysql_partitions = options.partitions;
382        self.mysql_subpartition_by = options.subpartition_by;
383        self.mysql_subpartitions = options.subpartitions;
384        self.mysql_auto_increment = options.auto_increment;
385        self
386    }
387
388    pub fn with_postgres_inherits(mut self, parents: Vec<String>) -> Self {
389        self.postgres_inherits = parents;
390        self
391    }
392
393    pub fn with_postgres_with(mut self, parameters: Vec<(String, String)>) -> Self {
394        self.postgres_with = parameters;
395        self
396    }
397
398    pub fn with_postgres_using(mut self, access_method: impl Into<String>) -> Self {
399        self.postgres_using = Some(access_method.into());
400        self
401    }
402
403    pub fn with_postgres_using_option(mut self, access_method: Option<String>) -> Self {
404        self.postgres_using = access_method;
405        self
406    }
407
408    pub fn postgres_unlogged(mut self) -> Self {
409        self.postgres_unlogged = true;
410        self
411    }
412
413    pub fn with_postgres_unlogged(mut self, unlogged: bool) -> Self {
414        self.postgres_unlogged = unlogged;
415        self
416    }
417
418    pub fn sqlite_strict(mut self) -> Self {
419        self.sqlite_strict = true;
420        self
421    }
422
423    pub fn with_sqlite_strict(mut self, strict: bool) -> Self {
424        self.sqlite_strict = strict;
425        self
426    }
427
428    pub fn sqlite_without_rowid(mut self) -> Self {
429        self.sqlite_without_rowid = true;
430        self
431    }
432
433    pub fn with_sqlite_without_rowid(mut self, without_rowid: bool) -> Self {
434        self.sqlite_without_rowid = without_rowid;
435        self
436    }
437
438    pub fn with_oracle_compress(mut self) -> Self {
439        self.oracle_compress = Some(OracleTableCompression::Enabled);
440        self
441    }
442
443    pub fn with_oracle_compress_level(mut self, level: u32) -> Self {
444        self.oracle_compress = Some(OracleTableCompression::Level(level));
445        self
446    }
447
448    pub fn with_oracle_compress_option(mut self, compress: Option<OracleTableCompression>) -> Self {
449        self.oracle_compress = compress;
450        self
451    }
452
453    pub fn with_mssql_primary_key_nonclustered(mut self, nonclustered: bool) -> Self {
454        self.mssql_primary_key_nonclustered = nonclustered;
455        self
456    }
457
458    pub fn with_postgres_partition_by(mut self, partition_by: impl Into<String>) -> Self {
459        self.postgres_partition_by = Some(partition_by.into());
460        self
461    }
462
463    pub fn with_postgres_partition_by_option(mut self, partition_by: Option<String>) -> Self {
464        self.postgres_partition_by = partition_by;
465        self
466    }
467
468    pub fn with_postgres_partition_of(mut self, parent: impl Into<String>) -> Self {
469        self.postgres_partition_of = Some(parent.into());
470        self
471    }
472
473    pub fn with_postgres_partition_of_option(mut self, parent: Option<String>) -> Self {
474        self.postgres_partition_of = parent;
475        self
476    }
477
478    pub fn with_postgres_partition_for(mut self, bound: impl Into<String>) -> Self {
479        self.postgres_partition_for = Some(bound.into());
480        self
481    }
482
483    pub fn with_postgres_partition_for_option(mut self, bound: Option<String>) -> Self {
484        self.postgres_partition_for = bound;
485        self
486    }
487
488    pub fn with_check_constraints(mut self, check_constraints: Vec<CheckConstraintDef>) -> Self {
489        self.check_constraints = check_constraints;
490        self
491    }
492
493    pub fn with_foreign_keys(mut self, foreign_keys: Vec<ForeignKeyDef>) -> Self {
494        self.foreign_keys = foreign_keys;
495        self
496    }
497
498    pub fn with_exclusion_constraints(
499        mut self,
500        exclusion_constraints: Vec<ExclusionConstraintDef>,
501    ) -> Self {
502        self.exclusion_constraints = exclusion_constraints;
503        self
504    }
505
506    pub fn set_id(&mut self, id: TableId) {
507        self.id = Some(id);
508    }
509
510    pub fn id(&self) -> Option<TableId> {
511        self.id
512    }
513
514    pub fn model_key(&self) -> &str {
515        &self.model_key
516    }
517
518    pub fn name(&self) -> &str {
519        &self.name
520    }
521
522    pub fn primary_key(&self) -> &str {
523        &self.primary_key
524    }
525
526    pub fn columns(&self) -> &[ColumnDef] {
527        &self.columns
528    }
529
530    pub fn column_names(&self) -> impl Iterator<Item = &str> {
531        self.columns.iter().map(|column| column.name())
532    }
533
534    pub fn relationships(&self) -> &[RelationshipDef] {
535        &self.relationships
536    }
537
538    pub fn indexes(&self) -> &[IndexDef] {
539        &self.indexes
540    }
541
542    pub fn unique_constraints(&self) -> &[UniqueConstraintDef] {
543        &self.unique_constraints
544    }
545
546    pub fn check_constraints(&self) -> &[CheckConstraintDef] {
547        &self.check_constraints
548    }
549
550    pub fn foreign_keys(&self) -> &[ForeignKeyDef] {
551        &self.foreign_keys
552    }
553
554    pub fn exclusion_constraints(&self) -> &[ExclusionConstraintDef] {
555        &self.exclusion_constraints
556    }
557
558    pub fn schema(&self) -> Option<&str> {
559        self.schema.as_deref()
560    }
561
562    pub fn comment(&self) -> Option<&str> {
563        self.comment.as_deref()
564    }
565
566    pub fn tablespace(&self) -> Option<&str> {
567        self.tablespace.as_deref()
568    }
569
570    pub fn mysql_engine(&self) -> Option<&str> {
571        self.mysql_engine.as_deref()
572    }
573
574    pub fn mysql_charset(&self) -> Option<&str> {
575        self.mysql_charset.as_deref()
576    }
577
578    pub fn mysql_collation(&self) -> Option<&str> {
579        self.mysql_collation.as_deref()
580    }
581
582    pub fn mysql_row_format(&self) -> Option<&str> {
583        self.mysql_row_format.as_deref()
584    }
585
586    pub fn mysql_key_block_size(&self) -> Option<u32> {
587        self.mysql_key_block_size
588    }
589
590    pub fn mysql_pack_keys(&self) -> Option<bool> {
591        self.mysql_pack_keys
592    }
593
594    pub fn mysql_checksum(&self) -> Option<bool> {
595        self.mysql_checksum
596    }
597
598    pub fn mysql_delay_key_write(&self) -> Option<bool> {
599        self.mysql_delay_key_write
600    }
601
602    pub fn mysql_stats_persistent(&self) -> Option<bool> {
603        self.mysql_stats_persistent
604    }
605
606    pub fn mysql_stats_auto_recalc(&self) -> Option<bool> {
607        self.mysql_stats_auto_recalc
608    }
609
610    pub fn mysql_stats_sample_pages(&self) -> Option<u32> {
611        self.mysql_stats_sample_pages
612    }
613
614    pub fn mysql_avg_row_length(&self) -> Option<u32> {
615        self.mysql_avg_row_length
616    }
617
618    pub fn mysql_max_rows(&self) -> Option<u32> {
619        self.mysql_max_rows
620    }
621
622    pub fn mysql_min_rows(&self) -> Option<u32> {
623        self.mysql_min_rows
624    }
625
626    pub fn mysql_insert_method(&self) -> Option<&str> {
627        self.mysql_insert_method.as_deref()
628    }
629
630    pub fn mysql_data_directory(&self) -> Option<&str> {
631        self.mysql_data_directory.as_deref()
632    }
633
634    pub fn mysql_index_directory(&self) -> Option<&str> {
635        self.mysql_index_directory.as_deref()
636    }
637
638    pub fn mysql_connection(&self) -> Option<&str> {
639        self.mysql_connection.as_deref()
640    }
641
642    pub fn mysql_union(&self) -> &[String] {
643        &self.mysql_union
644    }
645
646    pub fn mysql_partition_by(&self) -> Option<&str> {
647        self.mysql_partition_by.as_deref()
648    }
649
650    pub fn mysql_partitions(&self) -> Option<u32> {
651        self.mysql_partitions
652    }
653
654    pub fn mysql_subpartition_by(&self) -> Option<&str> {
655        self.mysql_subpartition_by.as_deref()
656    }
657
658    pub fn mysql_subpartitions(&self) -> Option<u32> {
659        self.mysql_subpartitions
660    }
661
662    pub fn mysql_auto_increment(&self) -> Option<u32> {
663        self.mysql_auto_increment
664    }
665
666    pub fn postgres_inherits(&self) -> &[String] {
667        &self.postgres_inherits
668    }
669
670    pub fn postgres_with(&self) -> &[(String, String)] {
671        &self.postgres_with
672    }
673
674    pub fn postgres_using(&self) -> Option<&str> {
675        self.postgres_using.as_deref()
676    }
677
678    pub fn is_postgres_unlogged(&self) -> bool {
679        self.postgres_unlogged
680    }
681
682    pub fn postgres_partition_by(&self) -> Option<&str> {
683        self.postgres_partition_by.as_deref()
684    }
685
686    pub fn postgres_partition_of(&self) -> Option<&str> {
687        self.postgres_partition_of.as_deref()
688    }
689
690    pub fn postgres_partition_for(&self) -> Option<&str> {
691        self.postgres_partition_for.as_deref()
692    }
693
694    pub fn is_sqlite_strict(&self) -> bool {
695        self.sqlite_strict
696    }
697
698    pub fn is_sqlite_without_rowid(&self) -> bool {
699        self.sqlite_without_rowid
700    }
701
702    pub fn oracle_compress(&self) -> Option<&OracleTableCompression> {
703        self.oracle_compress.as_ref()
704    }
705
706    pub fn is_mssql_primary_key_nonclustered(&self) -> bool {
707        self.mssql_primary_key_nonclustered
708    }
709
710    pub fn qualified_name(&self) -> QualifiedName {
711        QualifiedName::unchecked(self.schema.clone(), self.name.clone())
712    }
713}