1use super::common::{NullsOrder, OrderDir, SchemaRef};
2use super::conditions::Conditions;
3use super::custom::{CustomConstraint, CustomFieldType, CustomSchemaMutation};
4use super::expr::Expr;
5
6#[derive(Debug, Clone)]
12pub enum SchemaMutationStmt {
13 CreateTable {
15 schema: SchemaDef,
16 if_not_exists: bool,
17 temporary: bool,
18 unlogged: bool,
19 tablespace: Option<String>,
20 partition_by: Option<PartitionByDef>,
21 inherits: Option<Vec<SchemaRef>>,
22 using_method: Option<String>,
23 with_options: Option<Vec<(String, String)>>,
24 on_commit: Option<OnCommitAction>,
25 table_options: Option<Vec<(String, String)>>,
27 without_rowid: bool,
29 strict: bool,
31 },
32 DropTable {
33 schema_ref: SchemaRef,
34 if_exists: bool,
35 cascade: bool,
36 },
37 RenameTable {
38 schema_ref: SchemaRef,
39 new_name: String,
40 },
41 TruncateTable {
42 schema_ref: SchemaRef,
43 restart_identity: bool,
44 cascade: bool,
45 },
46
47 AddColumn {
49 schema_ref: SchemaRef,
50 column: Box<ColumnDef>,
51 if_not_exists: bool,
52 position: Option<ColumnPosition>,
53 },
54 DropColumn {
55 schema_ref: SchemaRef,
56 name: String,
57 if_exists: bool,
58 cascade: bool,
59 },
60 RenameColumn {
61 schema_ref: SchemaRef,
62 old_name: String,
63 new_name: String,
64 },
65 AlterColumnType {
66 schema_ref: SchemaRef,
67 column_name: String,
68 new_type: FieldType,
69 using_expr: Option<Expr>,
70 },
71 AlterColumnDefault {
72 schema_ref: SchemaRef,
73 column_name: String,
74 default: Option<Expr>,
75 },
76 AlterColumnNullability {
77 schema_ref: SchemaRef,
78 column_name: String,
79 not_null: bool,
80 },
81
82 AddConstraint {
84 schema_ref: SchemaRef,
85 constraint: ConstraintDef,
86 not_valid: bool,
87 },
88 DropConstraint {
89 schema_ref: SchemaRef,
90 constraint_name: String,
91 if_exists: bool,
92 cascade: bool,
93 },
94 RenameConstraint {
95 schema_ref: SchemaRef,
96 old_name: String,
97 new_name: String,
98 },
99 ValidateConstraint {
100 schema_ref: SchemaRef,
101 constraint_name: String,
102 },
103
104 CreateIndex {
106 schema_ref: SchemaRef,
107 index: IndexDef,
108 if_not_exists: bool,
109 concurrently: bool,
110 },
111 DropIndex {
112 schema_ref: SchemaRef,
113 index_name: String,
114 if_exists: bool,
115 concurrently: bool,
116 cascade: bool,
117 },
118
119 CreateExtension {
121 name: String,
122 if_not_exists: bool,
123 schema: Option<String>,
124 version: Option<String>,
125 cascade: bool,
126 },
127 DropExtension {
128 name: String,
129 if_exists: bool,
130 cascade: bool,
131 },
132
133 CreateCollation {
135 name: String,
136 if_not_exists: bool,
137 locale: Option<String>,
138 lc_collate: Option<String>,
139 lc_ctype: Option<String>,
140 provider: Option<String>,
141 deterministic: Option<bool>,
142 from_collation: Option<String>,
143 },
144 DropCollation {
145 name: String,
146 if_exists: bool,
147 cascade: bool,
148 },
149
150 Custom(Box<dyn CustomSchemaMutation>),
152}
153
154impl SchemaMutationStmt {
155 pub fn create_table(schema: SchemaDef) -> Self {
156 Self::CreateTable {
157 schema,
158 if_not_exists: false,
159 temporary: false,
160 unlogged: false,
161 tablespace: None,
162 partition_by: None,
163 inherits: None,
164 using_method: None,
165 with_options: None,
166 on_commit: None,
167 table_options: None,
168 without_rowid: false,
169 strict: false,
170 }
171 }
172
173 pub fn drop_table(name: &str) -> Self {
174 Self::DropTable {
175 schema_ref: SchemaRef::new(name),
176 if_exists: false,
177 cascade: false,
178 }
179 }
180
181 pub fn drop_table_if_exists(name: &str) -> Self {
182 Self::DropTable {
183 schema_ref: SchemaRef::new(name),
184 if_exists: true,
185 cascade: false,
186 }
187 }
188
189 pub fn create_index(table: &str, index: IndexDef) -> Self {
190 Self::CreateIndex {
191 schema_ref: SchemaRef::new(table),
192 index,
193 if_not_exists: false,
194 concurrently: false,
195 }
196 }
197
198 pub fn drop_index(table: &str, name: &str) -> Self {
199 Self::DropIndex {
200 schema_ref: SchemaRef::new(table),
201 index_name: name.to_string(),
202 if_exists: false,
203 concurrently: false,
204 cascade: false,
205 }
206 }
207
208 pub fn add_column(table: &str, column: ColumnDef) -> Self {
209 Self::AddColumn {
210 schema_ref: SchemaRef::new(table),
211 column: Box::new(column),
212 if_not_exists: false,
213 position: None,
214 }
215 }
216
217 pub fn drop_column(table: &str, name: &str) -> Self {
218 Self::DropColumn {
219 schema_ref: SchemaRef::new(table),
220 name: name.to_string(),
221 if_exists: false,
222 cascade: false,
223 }
224 }
225
226 pub fn rename_table(old: &str, new_name: &str) -> Self {
227 Self::RenameTable {
228 schema_ref: SchemaRef::new(old),
229 new_name: new_name.to_string(),
230 }
231 }
232
233 pub fn rename_column(table: &str, old: &str, new_name: &str) -> Self {
234 Self::RenameColumn {
235 schema_ref: SchemaRef::new(table),
236 old_name: old.to_string(),
237 new_name: new_name.to_string(),
238 }
239 }
240
241 pub fn truncate(table: &str) -> Self {
242 Self::TruncateTable {
243 schema_ref: SchemaRef::new(table),
244 restart_identity: false,
245 cascade: false,
246 }
247 }
248
249 pub fn create_collation(name: &str) -> Self {
250 Self::CreateCollation {
251 name: name.to_string(),
252 if_not_exists: false,
253 locale: None,
254 lc_collate: None,
255 lc_ctype: None,
256 provider: None,
257 deterministic: None,
258 from_collation: None,
259 }
260 }
261
262 pub fn drop_collation(name: &str) -> Self {
263 Self::DropCollation {
264 name: name.to_string(),
265 if_exists: false,
266 cascade: false,
267 }
268 }
269}
270
271#[derive(Debug, Clone)]
277pub struct SchemaDef {
278 pub name: String,
279 pub namespace: Option<String>,
280 pub columns: Vec<ColumnDef>,
281 pub constraints: Option<Vec<ConstraintDef>>,
282 pub indexes: Option<Vec<IndexDef>>,
283 pub like_tables: Option<Vec<LikeTableDef>>,
284}
285
286impl SchemaDef {
287 pub fn new(name: impl Into<String>) -> Self {
288 Self {
289 name: name.into(),
290 namespace: None,
291 columns: Vec::new(),
292 constraints: None,
293 indexes: None,
294 like_tables: None,
295 }
296 }
297}
298
299#[derive(Debug, Clone)]
305pub struct ColumnDef {
306 pub name: String,
307 pub field_type: FieldType,
308 pub not_null: bool,
309 pub default: Option<Expr>,
310 pub generated: Option<GeneratedColumn>,
311 pub identity: Option<IdentityColumn>,
312 pub collation: Option<String>,
313 pub comment: Option<String>,
314 pub storage: Option<String>,
315 pub compression: Option<String>,
316}
317
318impl ColumnDef {
319 pub fn new(name: impl Into<String>, field_type: FieldType) -> Self {
320 Self {
321 name: name.into(),
322 field_type,
323 not_null: false,
324 default: None,
325 generated: None,
326 identity: None,
327 collation: None,
328 comment: None,
329 storage: None,
330 compression: None,
331 }
332 }
333
334 pub fn not_null(mut self) -> Self {
335 self.not_null = true;
336 self
337 }
338
339 pub fn default(mut self, expr: Expr) -> Self {
340 self.default = Some(expr);
341 self
342 }
343
344 pub fn generated(mut self, expr: Expr, stored: bool) -> Self {
345 self.generated = Some(GeneratedColumn { expr, stored });
346 self
347 }
348
349 pub fn collation(mut self, name: impl Into<String>) -> Self {
350 self.collation = Some(name.into());
351 self
352 }
353}
354
355#[derive(Debug, Clone)]
357pub enum FieldType {
358 Scalar(String),
362
363 Parameterized { name: String, params: Vec<String> },
365
366 Array(Box<FieldType>),
368
369 Vector(i64),
371
372 Custom(Box<dyn CustomFieldType>),
374}
375
376impl FieldType {
377 pub fn scalar(name: impl Into<String>) -> Self {
378 Self::Scalar(name.into())
379 }
380
381 pub fn parameterized(name: impl Into<String>, params: Vec<impl Into<String>>) -> Self {
382 Self::Parameterized {
383 name: name.into(),
384 params: params.into_iter().map(Into::into).collect(),
385 }
386 }
387}
388
389#[derive(Debug, Clone)]
391pub struct GeneratedColumn {
392 pub expr: Expr,
393 pub stored: bool,
394}
395
396#[derive(Debug, Clone, Default)]
398pub struct IdentityColumn {
399 pub always: bool,
400 pub start: Option<i64>,
401 pub increment: Option<i64>,
402 pub min_value: Option<i64>,
403 pub max_value: Option<i64>,
404 pub cycle: bool,
405 pub cache: Option<i64>,
406}
407
408#[derive(Debug, Clone)]
410pub enum ColumnPosition {
411 First,
412 After(String),
413}
414
415#[derive(Debug, Clone)]
421pub enum ConstraintDef {
422 PrimaryKey {
423 name: Option<String>,
424 columns: Vec<String>,
425 include: Option<Vec<String>>,
426 },
427
428 ForeignKey {
429 name: Option<String>,
430 columns: Vec<String>,
431 ref_table: SchemaRef,
432 ref_columns: Vec<String>,
433 on_delete: Option<ReferentialAction>,
434 on_update: Option<ReferentialAction>,
435 deferrable: Option<DeferrableConstraint>,
436 match_type: Option<MatchType>,
437 },
438
439 Unique {
440 name: Option<String>,
441 columns: Vec<String>,
442 include: Option<Vec<String>>,
443 nulls_distinct: Option<bool>,
444 condition: Option<Conditions>,
445 },
446
447 Check {
448 name: Option<String>,
449 condition: Conditions,
450 no_inherit: bool,
451 enforced: Option<bool>,
452 },
453
454 Exclusion {
455 name: Option<String>,
456 elements: Vec<ExclusionElement>,
457 index_method: String,
458 condition: Option<Conditions>,
459 },
460
461 Custom(Box<dyn CustomConstraint>),
463}
464
465impl ConstraintDef {
466 pub fn primary_key(columns: Vec<&str>) -> Self {
467 Self::PrimaryKey {
468 name: None,
469 columns: columns.into_iter().map(String::from).collect(),
470 include: None,
471 }
472 }
473
474 pub fn foreign_key(columns: Vec<&str>, ref_table: &str, ref_columns: Vec<&str>) -> Self {
475 Self::ForeignKey {
476 name: None,
477 columns: columns.into_iter().map(String::from).collect(),
478 ref_table: SchemaRef::new(ref_table),
479 ref_columns: ref_columns.into_iter().map(String::from).collect(),
480 on_delete: None,
481 on_update: None,
482 deferrable: None,
483 match_type: None,
484 }
485 }
486
487 pub fn unique(columns: Vec<&str>) -> Self {
488 Self::Unique {
489 name: None,
490 columns: columns.into_iter().map(String::from).collect(),
491 include: None,
492 nulls_distinct: None,
493 condition: None,
494 }
495 }
496
497 pub fn check(condition: Conditions) -> Self {
498 Self::Check {
499 name: None,
500 condition,
501 no_inherit: false,
502 enforced: None,
503 }
504 }
505}
506
507#[derive(Debug, Clone, PartialEq, Eq)]
509pub enum ReferentialAction {
510 NoAction,
511 Restrict,
512 Cascade,
513 SetNull(Option<Vec<String>>),
514 SetDefault(Option<Vec<String>>),
515}
516
517#[derive(Debug, Clone, Copy, PartialEq, Eq)]
519pub struct DeferrableConstraint {
520 pub deferrable: bool,
521 pub initially_deferred: bool,
522}
523
524#[derive(Debug, Clone, Copy, PartialEq, Eq)]
526pub enum MatchType {
527 Full,
528 Partial,
529 Simple,
530}
531
532#[derive(Debug, Clone)]
534pub struct ExclusionElement {
535 pub column: String,
536 pub operator: String,
537 pub opclass: Option<String>,
538}
539
540#[derive(Debug, Clone)]
546pub struct IndexDef {
547 pub name: String,
548 pub columns: Vec<IndexColumnDef>,
549 pub unique: bool,
550 pub index_type: Option<String>,
551 pub include: Option<Vec<String>>,
552 pub condition: Option<Conditions>,
553 pub parameters: Option<Vec<(String, String)>>,
554 pub tablespace: Option<String>,
555 pub nulls_distinct: Option<bool>,
556}
557
558impl IndexDef {
559 pub fn new(name: impl Into<String>, columns: Vec<IndexColumnDef>) -> Self {
560 Self {
561 name: name.into(),
562 columns,
563 unique: false,
564 index_type: None,
565 include: None,
566 condition: None,
567 parameters: None,
568 tablespace: None,
569 nulls_distinct: None,
570 }
571 }
572
573 pub fn unique(mut self) -> Self {
574 self.unique = true;
575 self
576 }
577}
578
579#[derive(Debug, Clone)]
581pub struct IndexColumnDef {
582 pub expr: IndexExpr,
583 pub direction: Option<OrderDir>,
584 pub nulls: Option<NullsOrder>,
585 pub opclass: Option<String>,
586 pub collation: Option<String>,
587}
588
589impl IndexColumnDef {
590 pub fn column(name: impl Into<String>) -> Self {
591 Self {
592 expr: IndexExpr::Column(name.into()),
593 direction: None,
594 nulls: None,
595 opclass: None,
596 collation: None,
597 }
598 }
599
600 pub fn expression(expr: Expr) -> Self {
601 Self {
602 expr: IndexExpr::Expression(expr),
603 direction: None,
604 nulls: None,
605 opclass: None,
606 collation: None,
607 }
608 }
609
610 pub fn asc(mut self) -> Self {
611 self.direction = Some(OrderDir::Asc);
612 self
613 }
614
615 pub fn desc(mut self) -> Self {
616 self.direction = Some(OrderDir::Desc);
617 self
618 }
619
620 pub fn nulls_first(mut self) -> Self {
621 self.nulls = Some(NullsOrder::First);
622 self
623 }
624
625 pub fn nulls_last(mut self) -> Self {
626 self.nulls = Some(NullsOrder::Last);
627 self
628 }
629}
630
631#[derive(Debug, Clone)]
633pub enum IndexExpr {
634 Column(String),
635 Expression(Expr),
636}
637
638#[derive(Debug, Clone)]
644pub struct PartitionByDef {
645 pub strategy: PartitionStrategy,
646 pub columns: Vec<PartitionColumnDef>,
647}
648
649#[derive(Debug, Clone, Copy, PartialEq, Eq)]
651pub enum PartitionStrategy {
652 Range,
653 List,
654 Hash,
655}
656
657#[derive(Debug, Clone)]
659pub struct PartitionColumnDef {
660 pub expr: IndexExpr,
661 pub collation: Option<String>,
662 pub opclass: Option<String>,
663}
664
665#[derive(Debug, Clone)]
671pub struct LikeTableDef {
672 pub source_table: SchemaRef,
673 pub options: Vec<LikeOption>,
674}
675
676#[derive(Debug, Clone)]
678pub struct LikeOption {
679 pub kind: LikeOptionKind,
680 pub include: bool,
681}
682
683#[derive(Debug, Clone, Copy, PartialEq, Eq)]
685pub enum LikeOptionKind {
686 Comments,
687 Compression,
688 Constraints,
689 Defaults,
690 Generated,
691 Identity,
692 Indexes,
693 Statistics,
694 Storage,
695 All,
696}
697
698#[derive(Debug, Clone, Copy, PartialEq, Eq)]
704pub enum OnCommitAction {
705 PreserveRows,
706 DeleteRows,
707 Drop,
708}