1pub mod add_column;
2pub mod add_constraint;
3pub mod create_table;
4pub mod delete_column;
5pub mod delete_table;
6pub mod helpers;
7pub mod modify_column_comment;
8pub mod modify_column_default;
9pub mod modify_column_nullable;
10pub mod modify_column_type;
11pub mod raw_sql;
12pub mod remove_constraint;
13pub mod rename_column;
14pub mod rename_table;
15pub mod types;
16
17pub use helpers::*;
18pub use types::{BuiltQuery, DatabaseBackend, RawSql};
19
20use crate::error::QueryError;
21use vespertide_core::{MigrationAction, TableConstraint, TableDef};
22
23use self::{
24 add_column::build_add_column, add_constraint::build_add_constraint,
25 create_table::build_create_table, delete_column::build_delete_column,
26 delete_table::build_delete_table, modify_column_comment::build_modify_column_comment,
27 modify_column_default::build_modify_column_default,
28 modify_column_nullable::build_modify_column_nullable,
29 modify_column_type::build_modify_column_type, raw_sql::build_raw_sql,
30 remove_constraint::build_remove_constraint, rename_column::build_rename_column,
31 rename_table::build_rename_table,
32};
33
34pub fn build_action_queries(
35 backend: &DatabaseBackend,
36 action: &MigrationAction,
37 current_schema: &[TableDef],
38) -> Result<Vec<BuiltQuery>, QueryError> {
39 build_action_queries_with_pending(backend, action, current_schema, &[])
40}
41
42pub fn build_action_queries_with_pending(
48 backend: &DatabaseBackend,
49 action: &MigrationAction,
50 current_schema: &[TableDef],
51 pending_constraints: &[TableConstraint],
52) -> Result<Vec<BuiltQuery>, QueryError> {
53 match action {
54 MigrationAction::CreateTable {
55 table,
56 columns,
57 constraints,
58 } => build_create_table(backend, table, columns, constraints),
59
60 MigrationAction::DeleteTable { table } => Ok(vec![build_delete_table(table)]),
61
62 MigrationAction::AddColumn {
63 table,
64 column,
65 fill_with,
66 } => build_add_column(backend, table, column, fill_with.as_deref(), current_schema),
67
68 MigrationAction::RenameColumn { table, from, to } => {
69 Ok(vec![build_rename_column(table, from, to)])
70 }
71
72 MigrationAction::DeleteColumn { table, column } => {
73 let column_type = current_schema
75 .iter()
76 .find(|t| t.name == *table)
77 .and_then(|t| t.columns.iter().find(|c| c.name == *column))
78 .map(|c| &c.r#type);
79 Ok(build_delete_column(
80 backend,
81 table,
82 column,
83 column_type,
84 current_schema,
85 ))
86 }
87
88 MigrationAction::ModifyColumnType {
89 table,
90 column,
91 new_type,
92 fill_with,
93 } => build_modify_column_type(
94 backend,
95 table,
96 column,
97 new_type,
98 fill_with.as_ref(),
99 current_schema,
100 ),
101
102 MigrationAction::ModifyColumnNullable {
103 table,
104 column,
105 nullable,
106 fill_with,
107 } => build_modify_column_nullable(
108 backend,
109 table,
110 column,
111 *nullable,
112 fill_with.as_deref(),
113 current_schema,
114 ),
115
116 MigrationAction::ModifyColumnDefault {
117 table,
118 column,
119 new_default,
120 } => build_modify_column_default(
121 backend,
122 table,
123 column,
124 new_default.as_deref(),
125 current_schema,
126 ),
127
128 MigrationAction::ModifyColumnComment {
129 table,
130 column,
131 new_comment,
132 } => build_modify_column_comment(
133 backend,
134 table,
135 column,
136 new_comment.as_deref(),
137 current_schema,
138 ),
139
140 MigrationAction::RenameTable { from, to } => Ok(vec![build_rename_table(from, to)]),
141
142 MigrationAction::RawSql { sql } => Ok(vec![build_raw_sql(sql.clone())]),
143
144 MigrationAction::AddConstraint { table, constraint } => build_add_constraint(
145 backend,
146 table,
147 constraint,
148 current_schema,
149 pending_constraints,
150 ),
151
152 MigrationAction::RemoveConstraint { table, constraint } => {
153 build_remove_constraint(backend, table, constraint, current_schema)
154 }
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use insta::{assert_snapshot, with_settings};
162 use rstest::rstest;
163 use vespertide_core::schema::primary_key::PrimaryKeySyntax;
164 use vespertide_core::{
165 ColumnDef, ColumnType, MigrationAction, ReferenceAction, SimpleColumnType, TableConstraint,
166 };
167
168 fn col(name: &str, ty: ColumnType) -> ColumnDef {
169 ColumnDef {
170 name: name.to_string(),
171 r#type: ty,
172 nullable: true,
173 default: None,
174 comment: None,
175 primary_key: None,
176 unique: None,
177 index: None,
178 foreign_key: None,
179 }
180 }
181
182 #[test]
183 fn test_backend_specific_quoting() {
184 let action = MigrationAction::CreateTable {
185 table: "users".into(),
186 columns: vec![col("id", ColumnType::Simple(SimpleColumnType::Integer))],
187 constraints: vec![],
188 };
189 let result = build_action_queries(&DatabaseBackend::Postgres, &action, &[]).unwrap();
190
191 let pg_sql = result[0].build(DatabaseBackend::Postgres);
193 assert!(pg_sql.contains("\"users\""));
194
195 let mysql_sql = result[0].build(DatabaseBackend::MySql);
197 assert!(mysql_sql.contains("`users`"));
198
199 let sqlite_sql = result[0].build(DatabaseBackend::Sqlite);
201 assert!(sqlite_sql.contains("\"users\""));
202 }
203
204 #[rstest]
205 #[case::create_table_with_default_postgres(
206 "create_table_with_default_postgres",
207 MigrationAction::CreateTable {
208 table: "users".into(),
209 columns: vec![ColumnDef {
210 name: "status".into(),
211 r#type: ColumnType::Simple(SimpleColumnType::Text),
212 nullable: true,
213 default: Some("'active'".into()),
214 comment: None,
215 primary_key: None,
216 unique: None,
217 index: None,
218 foreign_key: None,
219 }],
220 constraints: vec![],
221 },
222 DatabaseBackend::Postgres,
223 &["DEFAULT", "'active'"]
224 )]
225 #[case::create_table_with_default_mysql(
226 "create_table_with_default_mysql",
227 MigrationAction::CreateTable {
228 table: "users".into(),
229 columns: vec![ColumnDef {
230 name: "status".into(),
231 r#type: ColumnType::Simple(SimpleColumnType::Text),
232 nullable: true,
233 default: Some("'active'".into()),
234 comment: None,
235 primary_key: None,
236 unique: None,
237 index: None,
238 foreign_key: None,
239 }],
240 constraints: vec![],
241 },
242 DatabaseBackend::Postgres,
243 &["DEFAULT", "'active'"]
244 )]
245 #[case::create_table_with_default_sqlite(
246 "create_table_with_default_sqlite",
247 MigrationAction::CreateTable {
248 table: "users".into(),
249 columns: vec![ColumnDef {
250 name: "status".into(),
251 r#type: ColumnType::Simple(SimpleColumnType::Text),
252 nullable: true,
253 default: Some("'active'".into()),
254 comment: None,
255 primary_key: None,
256 unique: None,
257 index: None,
258 foreign_key: None,
259 }],
260 constraints: vec![],
261 },
262 DatabaseBackend::Postgres,
263 &["DEFAULT", "'active'"]
264 )]
265 #[case::create_table_with_inline_primary_key_postgres(
266 "create_table_with_inline_primary_key_postgres",
267 MigrationAction::CreateTable {
268 table: "users".into(),
269 columns: vec![ColumnDef {
270 name: "id".into(),
271 r#type: ColumnType::Simple(SimpleColumnType::Integer),
272 nullable: false,
273 default: None,
274 comment: None,
275 primary_key: Some(PrimaryKeySyntax::Bool(true)),
276 unique: None,
277 index: None,
278 foreign_key: None,
279 }],
280 constraints: vec![],
281 },
282 DatabaseBackend::Postgres,
283 &["PRIMARY KEY"]
284 )]
285 #[case::create_table_with_inline_primary_key_mysql(
286 "create_table_with_inline_primary_key_mysql",
287 MigrationAction::CreateTable {
288 table: "users".into(),
289 columns: vec![ColumnDef {
290 name: "id".into(),
291 r#type: ColumnType::Simple(SimpleColumnType::Integer),
292 nullable: false,
293 default: None,
294 comment: None,
295 primary_key: Some(PrimaryKeySyntax::Bool(true)),
296 unique: None,
297 index: None,
298 foreign_key: None,
299 }],
300 constraints: vec![],
301 },
302 DatabaseBackend::Postgres,
303 &["PRIMARY KEY"]
304 )]
305 #[case::create_table_with_inline_primary_key_sqlite(
306 "create_table_with_inline_primary_key_sqlite",
307 MigrationAction::CreateTable {
308 table: "users".into(),
309 columns: vec![ColumnDef {
310 name: "id".into(),
311 r#type: ColumnType::Simple(SimpleColumnType::Integer),
312 nullable: false,
313 default: None,
314 comment: None,
315 primary_key: Some(PrimaryKeySyntax::Bool(true)),
316 unique: None,
317 index: None,
318 foreign_key: None,
319 }],
320 constraints: vec![],
321 },
322 DatabaseBackend::Postgres,
323 &["PRIMARY KEY"]
324 )]
325 #[case::create_table_with_fk_postgres(
326 "create_table_with_fk_postgres",
327 MigrationAction::CreateTable {
328 table: "posts".into(),
329 columns: vec![
330 col("id", ColumnType::Simple(SimpleColumnType::Integer)),
331 col("user_id", ColumnType::Simple(SimpleColumnType::Integer)),
332 ],
333 constraints: vec![TableConstraint::ForeignKey {
334 name: Some("fk_user".into()),
335 columns: vec!["user_id".into()],
336 ref_table: "users".into(),
337 ref_columns: vec!["id".into()],
338 on_delete: Some(ReferenceAction::Cascade),
339 on_update: Some(ReferenceAction::Restrict),
340 }],
341 },
342 DatabaseBackend::Postgres,
343 &["REFERENCES \"users\" (\"id\")", "ON DELETE CASCADE", "ON UPDATE RESTRICT"]
344 )]
345 #[case::create_table_with_fk_mysql(
346 "create_table_with_fk_mysql",
347 MigrationAction::CreateTable {
348 table: "posts".into(),
349 columns: vec![
350 col("id", ColumnType::Simple(SimpleColumnType::Integer)),
351 col("user_id", ColumnType::Simple(SimpleColumnType::Integer)),
352 ],
353 constraints: vec![TableConstraint::ForeignKey {
354 name: Some("fk_user".into()),
355 columns: vec!["user_id".into()],
356 ref_table: "users".into(),
357 ref_columns: vec!["id".into()],
358 on_delete: Some(ReferenceAction::Cascade),
359 on_update: Some(ReferenceAction::Restrict),
360 }],
361 },
362 DatabaseBackend::Postgres,
363 &["REFERENCES \"users\" (\"id\")", "ON DELETE CASCADE", "ON UPDATE RESTRICT"]
364 )]
365 #[case::create_table_with_fk_sqlite(
366 "create_table_with_fk_sqlite",
367 MigrationAction::CreateTable {
368 table: "posts".into(),
369 columns: vec![
370 col("id", ColumnType::Simple(SimpleColumnType::Integer)),
371 col("user_id", ColumnType::Simple(SimpleColumnType::Integer)),
372 ],
373 constraints: vec![TableConstraint::ForeignKey {
374 name: Some("fk_user".into()),
375 columns: vec!["user_id".into()],
376 ref_table: "users".into(),
377 ref_columns: vec!["id".into()],
378 on_delete: Some(ReferenceAction::Cascade),
379 on_update: Some(ReferenceAction::Restrict),
380 }],
381 },
382 DatabaseBackend::Postgres,
383 &["REFERENCES \"users\" (\"id\")", "ON DELETE CASCADE", "ON UPDATE RESTRICT"]
384 )]
385 fn test_build_migration_action(
386 #[case] title: &str,
387 #[case] action: MigrationAction,
388 #[case] backend: DatabaseBackend,
389 #[case] expected: &[&str],
390 ) {
391 let result = build_action_queries(&backend, &action, &[]).unwrap();
392 let sql = result[0].build(backend);
393 for exp in expected {
394 assert!(
395 sql.contains(exp),
396 "Expected SQL to contain '{}', got: {}",
397 exp,
398 sql
399 );
400 }
401
402 with_settings!({ snapshot_suffix => format!("build_migration_action_{}", title) }, {
403 assert_snapshot!(result.iter().map(|q| q.build(backend)).collect::<Vec<String>>().join("\n"));
404 });
405 }
406
407 #[rstest]
408 #[case::rename_column_postgres(DatabaseBackend::Postgres)]
409 #[case::rename_column_mysql(DatabaseBackend::MySql)]
410 #[case::rename_column_sqlite(DatabaseBackend::Sqlite)]
411 fn test_build_action_queries_rename_column(#[case] backend: DatabaseBackend) {
412 let action = MigrationAction::RenameColumn {
414 table: "users".into(),
415 from: "old_name".into(),
416 to: "new_name".into(),
417 };
418 let result = build_action_queries(&backend, &action, &[]).unwrap();
419 assert_eq!(result.len(), 1);
420 let sql = result[0].build(backend);
421 assert!(sql.contains("RENAME"));
422 assert!(sql.contains("old_name"));
423 assert!(sql.contains("new_name"));
424
425 with_settings!({ snapshot_suffix => format!("rename_column_{:?}", backend) }, {
426 assert_snapshot!(sql);
427 });
428 }
429
430 #[rstest]
431 #[case::delete_column_postgres(DatabaseBackend::Postgres)]
432 #[case::delete_column_mysql(DatabaseBackend::MySql)]
433 #[case::delete_column_sqlite(DatabaseBackend::Sqlite)]
434 fn test_build_action_queries_delete_column(#[case] backend: DatabaseBackend) {
435 let action = MigrationAction::DeleteColumn {
437 table: "users".into(),
438 column: "email".into(),
439 };
440 let result = build_action_queries(&backend, &action, &[]).unwrap();
441 assert_eq!(result.len(), 1);
442 let sql = result[0].build(backend);
443 assert!(sql.contains("DROP COLUMN"));
444 assert!(sql.contains("email"));
445
446 with_settings!({ snapshot_suffix => format!("delete_column_{:?}", backend) }, {
447 assert_snapshot!(sql);
448 });
449 }
450
451 #[rstest]
452 #[case::modify_column_type_postgres(DatabaseBackend::Postgres)]
453 #[case::modify_column_type_mysql(DatabaseBackend::MySql)]
454 #[case::modify_column_type_sqlite(DatabaseBackend::Sqlite)]
455 fn test_build_action_queries_modify_column_type(#[case] backend: DatabaseBackend) {
456 let action = MigrationAction::ModifyColumnType {
458 table: "users".into(),
459 column: "age".into(),
460 new_type: ColumnType::Simple(SimpleColumnType::BigInt),
461 fill_with: None,
462 };
463 let current_schema = vec![TableDef {
464 name: "users".into(),
465 description: None,
466 columns: vec![ColumnDef {
467 name: "age".into(),
468 r#type: ColumnType::Simple(SimpleColumnType::Integer),
469 nullable: true,
470 default: None,
471 comment: None,
472 primary_key: None,
473 unique: None,
474 index: None,
475 foreign_key: None,
476 }],
477 constraints: vec![],
478 }];
479 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
480 assert!(!result.is_empty());
481 let sql = result
482 .iter()
483 .map(|q| q.build(backend))
484 .collect::<Vec<String>>()
485 .join("\n");
486 assert!(sql.contains("ALTER TABLE"));
487
488 with_settings!({ snapshot_suffix => format!("modify_column_type_{:?}", backend) }, {
489 assert_snapshot!(sql);
490 });
491 }
492
493 #[rstest]
494 #[case::remove_index_constraint_postgres(DatabaseBackend::Postgres)]
495 #[case::remove_index_constraint_mysql(DatabaseBackend::MySql)]
496 #[case::remove_index_constraint_sqlite(DatabaseBackend::Sqlite)]
497 fn test_build_action_queries_remove_index_constraint(#[case] backend: DatabaseBackend) {
498 let action = MigrationAction::RemoveConstraint {
500 table: "users".into(),
501 constraint: TableConstraint::Index {
502 name: Some("idx_email".into()),
503 columns: vec!["email".into()],
504 },
505 };
506 let result = build_action_queries(&backend, &action, &[]).unwrap();
507 assert_eq!(result.len(), 1);
508 let sql = result[0].build(backend);
509 assert!(sql.contains("DROP INDEX"));
510 assert!(sql.contains("idx_email"));
511
512 with_settings!({ snapshot_suffix => format!("remove_index_constraint_{:?}", backend) }, {
513 assert_snapshot!(sql);
514 });
515 }
516
517 #[rstest]
518 #[case::rename_table_postgres(DatabaseBackend::Postgres)]
519 #[case::rename_table_mysql(DatabaseBackend::MySql)]
520 #[case::rename_table_sqlite(DatabaseBackend::Sqlite)]
521 fn test_build_action_queries_rename_table(#[case] backend: DatabaseBackend) {
522 let action = MigrationAction::RenameTable {
524 from: "old_table".into(),
525 to: "new_table".into(),
526 };
527 let result = build_action_queries(&backend, &action, &[]).unwrap();
528 assert_eq!(result.len(), 1);
529 let sql = result[0].build(backend);
530 assert!(sql.contains("RENAME"));
531 assert!(sql.contains("old_table"));
532 assert!(sql.contains("new_table"));
533
534 with_settings!({ snapshot_suffix => format!("rename_table_{:?}", backend) }, {
535 assert_snapshot!(sql);
536 });
537 }
538
539 #[rstest]
540 #[case::add_constraint_postgres(DatabaseBackend::Postgres)]
541 #[case::add_constraint_mysql(DatabaseBackend::MySql)]
542 #[case::add_constraint_sqlite(DatabaseBackend::Sqlite)]
543 fn test_build_action_queries_add_constraint(#[case] backend: DatabaseBackend) {
544 let action = MigrationAction::AddConstraint {
546 table: "users".into(),
547 constraint: TableConstraint::Unique {
548 name: Some("uq_email".into()),
549 columns: vec!["email".into()],
550 },
551 };
552 let current_schema = vec![TableDef {
553 name: "users".into(),
554 description: None,
555 columns: vec![
556 ColumnDef {
557 name: "id".into(),
558 r#type: ColumnType::Simple(SimpleColumnType::Integer),
559 nullable: false,
560 default: None,
561 comment: None,
562 primary_key: None,
563 unique: None,
564 index: None,
565 foreign_key: None,
566 },
567 ColumnDef {
568 name: "email".into(),
569 r#type: ColumnType::Simple(SimpleColumnType::Text),
570 nullable: true,
571 default: None,
572 comment: None,
573 primary_key: None,
574 unique: None,
575 index: None,
576 foreign_key: None,
577 },
578 ],
579 constraints: vec![],
580 }];
581 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
582 assert!(!result.is_empty());
583 let sql = result
584 .iter()
585 .map(|q| q.build(backend))
586 .collect::<Vec<String>>()
587 .join("\n");
588 assert!(sql.contains("UNIQUE") || sql.contains("uq_email"));
589
590 with_settings!({ snapshot_suffix => format!("add_constraint_{:?}", backend) }, {
591 assert_snapshot!(sql);
592 });
593 }
594
595 #[rstest]
596 #[case::remove_constraint_postgres(DatabaseBackend::Postgres)]
597 #[case::remove_constraint_mysql(DatabaseBackend::MySql)]
598 #[case::remove_constraint_sqlite(DatabaseBackend::Sqlite)]
599 fn test_build_action_queries_remove_constraint(#[case] backend: DatabaseBackend) {
600 let action = MigrationAction::RemoveConstraint {
602 table: "users".into(),
603 constraint: TableConstraint::Unique {
604 name: Some("uq_email".into()),
605 columns: vec!["email".into()],
606 },
607 };
608 let current_schema = vec![TableDef {
609 name: "users".into(),
610 description: None,
611 columns: vec![
612 ColumnDef {
613 name: "id".into(),
614 r#type: ColumnType::Simple(SimpleColumnType::Integer),
615 nullable: false,
616 default: None,
617 comment: None,
618 primary_key: None,
619 unique: None,
620 index: None,
621 foreign_key: None,
622 },
623 ColumnDef {
624 name: "email".into(),
625 r#type: ColumnType::Simple(SimpleColumnType::Text),
626 nullable: true,
627 default: None,
628 comment: None,
629 primary_key: None,
630 unique: None,
631 index: None,
632 foreign_key: None,
633 },
634 ],
635 constraints: vec![TableConstraint::Unique {
636 name: Some("uq_email".into()),
637 columns: vec!["email".into()],
638 }],
639 }];
640 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
641 assert!(!result.is_empty());
642 let sql = result
643 .iter()
644 .map(|q| q.build(backend))
645 .collect::<Vec<String>>()
646 .join("\n");
647 assert!(sql.contains("DROP") || sql.contains("CONSTRAINT"));
648
649 with_settings!({ snapshot_suffix => format!("remove_constraint_{:?}", backend) }, {
650 assert_snapshot!(sql);
651 });
652 }
653
654 #[rstest]
655 #[case::add_column_postgres(DatabaseBackend::Postgres)]
656 #[case::add_column_mysql(DatabaseBackend::MySql)]
657 #[case::add_column_sqlite(DatabaseBackend::Sqlite)]
658 fn test_build_action_queries_add_column(#[case] backend: DatabaseBackend) {
659 let action = MigrationAction::AddColumn {
661 table: "users".into(),
662 column: Box::new(ColumnDef {
663 name: "email".into(),
664 r#type: ColumnType::Simple(SimpleColumnType::Text),
665 nullable: true,
666 default: None,
667 comment: None,
668 primary_key: None,
669 unique: None,
670 index: None,
671 foreign_key: None,
672 }),
673 fill_with: None,
674 };
675 let current_schema = vec![TableDef {
676 name: "users".into(),
677 description: None,
678 columns: vec![ColumnDef {
679 name: "id".into(),
680 r#type: ColumnType::Simple(SimpleColumnType::Integer),
681 nullable: false,
682 default: None,
683 comment: None,
684 primary_key: None,
685 unique: None,
686 index: None,
687 foreign_key: None,
688 }],
689 constraints: vec![],
690 }];
691 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
692 assert!(!result.is_empty());
693 let sql = result
694 .iter()
695 .map(|q| q.build(backend))
696 .collect::<Vec<String>>()
697 .join("\n");
698 assert!(sql.contains("ALTER TABLE"));
699 assert!(sql.contains("ADD COLUMN") || sql.contains("ADD"));
700
701 with_settings!({ snapshot_suffix => format!("add_column_{:?}", backend) }, {
702 assert_snapshot!(sql);
703 });
704 }
705
706 #[rstest]
707 #[case::add_index_constraint_postgres(DatabaseBackend::Postgres)]
708 #[case::add_index_constraint_mysql(DatabaseBackend::MySql)]
709 #[case::add_index_constraint_sqlite(DatabaseBackend::Sqlite)]
710 fn test_build_action_queries_add_index_constraint(#[case] backend: DatabaseBackend) {
711 let action = MigrationAction::AddConstraint {
713 table: "users".into(),
714 constraint: TableConstraint::Index {
715 name: Some("idx_email".into()),
716 columns: vec!["email".into()],
717 },
718 };
719 let result = build_action_queries(&backend, &action, &[]).unwrap();
720 assert_eq!(result.len(), 1);
721 let sql = result[0].build(backend);
722 assert!(sql.contains("CREATE INDEX"));
723 assert!(sql.contains("idx_email"));
724
725 with_settings!({ snapshot_suffix => format!("add_index_constraint_{:?}", backend) }, {
726 assert_snapshot!(sql);
727 });
728 }
729
730 #[rstest]
731 #[case::raw_sql_postgres(DatabaseBackend::Postgres)]
732 #[case::raw_sql_mysql(DatabaseBackend::MySql)]
733 #[case::raw_sql_sqlite(DatabaseBackend::Sqlite)]
734 fn test_build_action_queries_raw_sql(#[case] backend: DatabaseBackend) {
735 let action = MigrationAction::RawSql {
737 sql: "SELECT 1;".into(),
738 };
739 let result = build_action_queries(&backend, &action, &[]).unwrap();
740 assert_eq!(result.len(), 1);
741 let sql = result[0].build(backend);
742 assert_eq!(sql, "SELECT 1;");
743
744 with_settings!({ snapshot_suffix => format!("raw_sql_{:?}", backend) }, {
745 assert_snapshot!(sql);
746 });
747 }
748
749 #[rstest]
751 #[case::add_index_with_custom_name_postgres(
752 DatabaseBackend::Postgres,
753 "hello",
754 vec!["email", "password"]
755 )]
756 #[case::add_index_with_custom_name_mysql(
757 DatabaseBackend::MySql,
758 "hello",
759 vec!["email", "password"]
760 )]
761 #[case::add_index_with_custom_name_sqlite(
762 DatabaseBackend::Sqlite,
763 "hello",
764 vec!["email", "password"]
765 )]
766 #[case::add_index_single_column_postgres(
767 DatabaseBackend::Postgres,
768 "email_idx",
769 vec!["email"]
770 )]
771 #[case::add_index_single_column_mysql(
772 DatabaseBackend::MySql,
773 "email_idx",
774 vec!["email"]
775 )]
776 #[case::add_index_single_column_sqlite(
777 DatabaseBackend::Sqlite,
778 "email_idx",
779 vec!["email"]
780 )]
781 fn test_add_index_with_custom_name(
782 #[case] backend: DatabaseBackend,
783 #[case] index_name: &str,
784 #[case] columns: Vec<&str>,
785 ) {
786 let action = MigrationAction::AddConstraint {
788 table: "user".into(),
789 constraint: TableConstraint::Index {
790 name: Some(index_name.into()),
791 columns: columns.iter().map(|s| s.to_string()).collect(),
792 },
793 };
794 let result = build_action_queries(&backend, &action, &[]).unwrap();
795 let sql = result[0].build(backend);
796
797 let expected_name = format!("ix_user__{}", index_name);
799 assert!(
800 sql.contains(&expected_name),
801 "Expected index name '{}' in SQL: {}",
802 expected_name,
803 sql
804 );
805
806 with_settings!({ snapshot_suffix => format!("add_index_custom_{}_{:?}", index_name, backend) }, {
807 assert_snapshot!(sql);
808 });
809 }
810
811 #[rstest]
812 #[case::add_unnamed_index_single_column_postgres(
813 DatabaseBackend::Postgres,
814 vec!["email"]
815 )]
816 #[case::add_unnamed_index_single_column_mysql(
817 DatabaseBackend::MySql,
818 vec!["email"]
819 )]
820 #[case::add_unnamed_index_single_column_sqlite(
821 DatabaseBackend::Sqlite,
822 vec!["email"]
823 )]
824 #[case::add_unnamed_index_multiple_columns_postgres(
825 DatabaseBackend::Postgres,
826 vec!["email", "password"]
827 )]
828 #[case::add_unnamed_index_multiple_columns_mysql(
829 DatabaseBackend::MySql,
830 vec!["email", "password"]
831 )]
832 #[case::add_unnamed_index_multiple_columns_sqlite(
833 DatabaseBackend::Sqlite,
834 vec!["email", "password"]
835 )]
836 fn test_add_unnamed_index(#[case] backend: DatabaseBackend, #[case] columns: Vec<&str>) {
837 let action = MigrationAction::AddConstraint {
839 table: "user".into(),
840 constraint: TableConstraint::Index {
841 name: None,
842 columns: columns.iter().map(|s| s.to_string()).collect(),
843 },
844 };
845 let result = build_action_queries(&backend, &action, &[]).unwrap();
846 let sql = result[0].build(backend);
847
848 let expected_name = format!("ix_user__{}", columns.join("_"));
850 assert!(
851 sql.contains(&expected_name),
852 "Expected index name '{}' in SQL: {}",
853 expected_name,
854 sql
855 );
856
857 with_settings!({ snapshot_suffix => format!("add_unnamed_index_{}_{:?}", columns.join("_"), backend) }, {
858 assert_snapshot!(sql);
859 });
860 }
861
862 #[rstest]
863 #[case::remove_index_with_custom_name_postgres(
864 DatabaseBackend::Postgres,
865 "hello",
866 vec!["email", "password"]
867 )]
868 #[case::remove_index_with_custom_name_mysql(
869 DatabaseBackend::MySql,
870 "hello",
871 vec!["email", "password"]
872 )]
873 #[case::remove_index_with_custom_name_sqlite(
874 DatabaseBackend::Sqlite,
875 "hello",
876 vec!["email", "password"]
877 )]
878 fn test_remove_index_with_custom_name(
879 #[case] backend: DatabaseBackend,
880 #[case] index_name: &str,
881 #[case] columns: Vec<&str>,
882 ) {
883 let action = MigrationAction::RemoveConstraint {
885 table: "user".into(),
886 constraint: TableConstraint::Index {
887 name: Some(index_name.into()),
888 columns: columns.iter().map(|s| s.to_string()).collect(),
889 },
890 };
891 let result = build_action_queries(&backend, &action, &[]).unwrap();
892 let sql = result[0].build(backend);
893
894 let expected_name = format!("ix_user__{}", index_name);
896 assert!(
897 sql.contains(&expected_name),
898 "Expected index name '{}' in SQL: {}",
899 expected_name,
900 sql
901 );
902
903 with_settings!({ snapshot_suffix => format!("remove_index_custom_{}_{:?}", index_name, backend) }, {
904 assert_snapshot!(sql);
905 });
906 }
907
908 #[rstest]
909 #[case::remove_unnamed_index_single_column_postgres(
910 DatabaseBackend::Postgres,
911 vec!["email"]
912 )]
913 #[case::remove_unnamed_index_single_column_mysql(
914 DatabaseBackend::MySql,
915 vec!["email"]
916 )]
917 #[case::remove_unnamed_index_single_column_sqlite(
918 DatabaseBackend::Sqlite,
919 vec!["email"]
920 )]
921 #[case::remove_unnamed_index_multiple_columns_postgres(
922 DatabaseBackend::Postgres,
923 vec!["email", "password"]
924 )]
925 #[case::remove_unnamed_index_multiple_columns_mysql(
926 DatabaseBackend::MySql,
927 vec!["email", "password"]
928 )]
929 #[case::remove_unnamed_index_multiple_columns_sqlite(
930 DatabaseBackend::Sqlite,
931 vec!["email", "password"]
932 )]
933 fn test_remove_unnamed_index(#[case] backend: DatabaseBackend, #[case] columns: Vec<&str>) {
934 let action = MigrationAction::RemoveConstraint {
936 table: "user".into(),
937 constraint: TableConstraint::Index {
938 name: None,
939 columns: columns.iter().map(|s| s.to_string()).collect(),
940 },
941 };
942 let result = build_action_queries(&backend, &action, &[]).unwrap();
943 let sql = result[0].build(backend);
944
945 let expected_name = format!("ix_user__{}", columns.join("_"));
947 assert!(
948 sql.contains(&expected_name),
949 "Expected index name '{}' in SQL: {}",
950 expected_name,
951 sql
952 );
953
954 with_settings!({ snapshot_suffix => format!("remove_unnamed_index_{}_{:?}", columns.join("_"), backend) }, {
955 assert_snapshot!(sql);
956 });
957 }
958
959 #[rstest]
961 #[case::add_unique_with_custom_name_postgres(
962 DatabaseBackend::Postgres,
963 "email_unique",
964 vec!["email"]
965 )]
966 #[case::add_unique_with_custom_name_mysql(
967 DatabaseBackend::MySql,
968 "email_unique",
969 vec!["email"]
970 )]
971 #[case::add_unique_with_custom_name_sqlite(
972 DatabaseBackend::Sqlite,
973 "email_unique",
974 vec!["email"]
975 )]
976 fn test_add_unique_with_custom_name(
977 #[case] backend: DatabaseBackend,
978 #[case] constraint_name: &str,
979 #[case] columns: Vec<&str>,
980 ) {
981 let action = MigrationAction::AddConstraint {
983 table: "user".into(),
984 constraint: TableConstraint::Unique {
985 name: Some(constraint_name.into()),
986 columns: columns.iter().map(|s| s.to_string()).collect(),
987 },
988 };
989
990 let current_schema = vec![TableDef {
991 name: "user".into(),
992 description: None,
993 columns: vec![ColumnDef {
994 name: "email".into(),
995 r#type: ColumnType::Simple(SimpleColumnType::Text),
996 nullable: true,
997 default: None,
998 comment: None,
999 primary_key: None,
1000 unique: None,
1001 index: None,
1002 foreign_key: None,
1003 }],
1004 constraints: vec![],
1005 }];
1006
1007 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
1008 let sql = result
1009 .iter()
1010 .map(|q| q.build(backend))
1011 .collect::<Vec<String>>()
1012 .join("\n");
1013
1014 let expected_name = format!("uq_user__{}", constraint_name);
1016 assert!(
1017 sql.contains(&expected_name),
1018 "Expected unique constraint name '{}' in SQL: {}",
1019 expected_name,
1020 sql
1021 );
1022
1023 with_settings!({ snapshot_suffix => format!("add_unique_custom_{}_{:?}", constraint_name, backend) }, {
1024 assert_snapshot!(sql);
1025 });
1026 }
1027
1028 #[rstest]
1029 #[case::add_unnamed_unique_single_column_postgres(
1030 DatabaseBackend::Postgres,
1031 vec!["email"]
1032 )]
1033 #[case::add_unnamed_unique_single_column_mysql(
1034 DatabaseBackend::MySql,
1035 vec!["email"]
1036 )]
1037 #[case::add_unnamed_unique_single_column_sqlite(
1038 DatabaseBackend::Sqlite,
1039 vec!["email"]
1040 )]
1041 #[case::add_unnamed_unique_multiple_columns_postgres(
1042 DatabaseBackend::Postgres,
1043 vec!["email", "username"]
1044 )]
1045 #[case::add_unnamed_unique_multiple_columns_mysql(
1046 DatabaseBackend::MySql,
1047 vec!["email", "username"]
1048 )]
1049 #[case::add_unnamed_unique_multiple_columns_sqlite(
1050 DatabaseBackend::Sqlite,
1051 vec!["email", "username"]
1052 )]
1053 fn test_add_unnamed_unique(#[case] backend: DatabaseBackend, #[case] columns: Vec<&str>) {
1054 let action = MigrationAction::AddConstraint {
1056 table: "user".into(),
1057 constraint: TableConstraint::Unique {
1058 name: None,
1059 columns: columns.iter().map(|s| s.to_string()).collect(),
1060 },
1061 };
1062
1063 let schema_columns: Vec<ColumnDef> = columns
1064 .iter()
1065 .map(|col| ColumnDef {
1066 name: col.to_string(),
1067 r#type: ColumnType::Simple(SimpleColumnType::Text),
1068 nullable: true,
1069 default: None,
1070 comment: None,
1071 primary_key: None,
1072 unique: None,
1073 index: None,
1074 foreign_key: None,
1075 })
1076 .collect();
1077
1078 let current_schema = vec![TableDef {
1079 name: "user".into(),
1080 description: None,
1081 columns: schema_columns,
1082 constraints: vec![],
1083 }];
1084
1085 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
1086 let sql = result
1087 .iter()
1088 .map(|q| q.build(backend))
1089 .collect::<Vec<String>>()
1090 .join("\n");
1091
1092 let expected_name = format!("uq_user__{}", columns.join("_"));
1094 assert!(
1095 sql.contains(&expected_name),
1096 "Expected unique constraint name '{}' in SQL: {}",
1097 expected_name,
1098 sql
1099 );
1100
1101 with_settings!({ snapshot_suffix => format!("add_unnamed_unique_{}_{:?}", columns.join("_"), backend) }, {
1102 assert_snapshot!(sql);
1103 });
1104 }
1105
1106 #[rstest]
1107 #[case::remove_unique_with_custom_name_postgres(
1108 DatabaseBackend::Postgres,
1109 "email_unique",
1110 vec!["email"]
1111 )]
1112 #[case::remove_unique_with_custom_name_mysql(
1113 DatabaseBackend::MySql,
1114 "email_unique",
1115 vec!["email"]
1116 )]
1117 #[case::remove_unique_with_custom_name_sqlite(
1118 DatabaseBackend::Sqlite,
1119 "email_unique",
1120 vec!["email"]
1121 )]
1122 fn test_remove_unique_with_custom_name(
1123 #[case] backend: DatabaseBackend,
1124 #[case] constraint_name: &str,
1125 #[case] columns: Vec<&str>,
1126 ) {
1127 let constraint = TableConstraint::Unique {
1129 name: Some(constraint_name.into()),
1130 columns: columns.iter().map(|s| s.to_string()).collect(),
1131 };
1132
1133 let current_schema = vec![TableDef {
1134 name: "user".into(),
1135 description: None,
1136 columns: vec![ColumnDef {
1137 name: "email".into(),
1138 r#type: ColumnType::Simple(SimpleColumnType::Text),
1139 nullable: true,
1140 default: None,
1141 comment: None,
1142 primary_key: None,
1143 unique: None,
1144 index: None,
1145 foreign_key: None,
1146 }],
1147 constraints: vec![constraint.clone()],
1148 }];
1149
1150 let action = MigrationAction::RemoveConstraint {
1151 table: "user".into(),
1152 constraint,
1153 };
1154
1155 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
1156 let sql = result
1157 .iter()
1158 .map(|q| q.build(backend))
1159 .collect::<Vec<String>>()
1160 .join("\n");
1161
1162 if backend != DatabaseBackend::Sqlite {
1164 let expected_name = format!("uq_user__{}", constraint_name);
1165 assert!(
1166 sql.contains(&expected_name),
1167 "Expected unique constraint name '{}' in SQL: {}",
1168 expected_name,
1169 sql
1170 );
1171 }
1172
1173 with_settings!({ snapshot_suffix => format!("remove_unique_custom_{}_{:?}", constraint_name, backend) }, {
1174 assert_snapshot!(sql);
1175 });
1176 }
1177
1178 #[rstest]
1179 #[case::remove_unnamed_unique_single_column_postgres(
1180 DatabaseBackend::Postgres,
1181 vec!["email"]
1182 )]
1183 #[case::remove_unnamed_unique_single_column_mysql(
1184 DatabaseBackend::MySql,
1185 vec!["email"]
1186 )]
1187 #[case::remove_unnamed_unique_single_column_sqlite(
1188 DatabaseBackend::Sqlite,
1189 vec!["email"]
1190 )]
1191 #[case::remove_unnamed_unique_multiple_columns_postgres(
1192 DatabaseBackend::Postgres,
1193 vec!["email", "username"]
1194 )]
1195 #[case::remove_unnamed_unique_multiple_columns_mysql(
1196 DatabaseBackend::MySql,
1197 vec!["email", "username"]
1198 )]
1199 #[case::remove_unnamed_unique_multiple_columns_sqlite(
1200 DatabaseBackend::Sqlite,
1201 vec!["email", "username"]
1202 )]
1203 fn test_remove_unnamed_unique(#[case] backend: DatabaseBackend, #[case] columns: Vec<&str>) {
1204 let constraint = TableConstraint::Unique {
1206 name: None,
1207 columns: columns.iter().map(|s| s.to_string()).collect(),
1208 };
1209
1210 let schema_columns: Vec<ColumnDef> = columns
1211 .iter()
1212 .map(|col| ColumnDef {
1213 name: col.to_string(),
1214 r#type: ColumnType::Simple(SimpleColumnType::Text),
1215 nullable: true,
1216 default: None,
1217 comment: None,
1218 primary_key: None,
1219 unique: None,
1220 index: None,
1221 foreign_key: None,
1222 })
1223 .collect();
1224
1225 let current_schema = vec![TableDef {
1226 name: "user".into(),
1227 description: None,
1228 columns: schema_columns,
1229 constraints: vec![constraint.clone()],
1230 }];
1231
1232 let action = MigrationAction::RemoveConstraint {
1233 table: "user".into(),
1234 constraint,
1235 };
1236
1237 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
1238 let sql = result
1239 .iter()
1240 .map(|q| q.build(backend))
1241 .collect::<Vec<String>>()
1242 .join("\n");
1243
1244 if backend != DatabaseBackend::Sqlite {
1246 let expected_name = format!("uq_user__{}", columns.join("_"));
1247 assert!(
1248 sql.contains(&expected_name),
1249 "Expected unique constraint name '{}' in SQL: {}",
1250 expected_name,
1251 sql
1252 );
1253 }
1254
1255 with_settings!({ snapshot_suffix => format!("remove_unnamed_unique_{}_{:?}", columns.join("_"), backend) }, {
1256 assert_snapshot!(sql);
1257 });
1258 }
1259
1260 #[rstest]
1262 #[case::postgres_modify_nullable(DatabaseBackend::Postgres)]
1263 #[case::mysql_modify_nullable(DatabaseBackend::MySql)]
1264 #[case::sqlite_modify_nullable(DatabaseBackend::Sqlite)]
1265 fn test_build_action_queries_modify_column_nullable(#[case] backend: DatabaseBackend) {
1266 let action = MigrationAction::ModifyColumnNullable {
1267 table: "users".into(),
1268 column: "email".into(),
1269 nullable: false,
1270 fill_with: Some("'unknown'".into()),
1271 };
1272 let current_schema = vec![TableDef {
1273 name: "users".into(),
1274 description: None,
1275 columns: vec![ColumnDef {
1276 name: "email".into(),
1277 r#type: ColumnType::Simple(SimpleColumnType::Text),
1278 nullable: true,
1279 default: None,
1280 comment: None,
1281 primary_key: None,
1282 unique: None,
1283 index: None,
1284 foreign_key: None,
1285 }],
1286 constraints: vec![],
1287 }];
1288 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
1289 assert!(!result.is_empty());
1290 let sql = result
1291 .iter()
1292 .map(|q| q.build(backend))
1293 .collect::<Vec<String>>()
1294 .join("\n");
1295
1296 assert!(sql.contains("UPDATE"));
1298 assert!(sql.contains("unknown"));
1299
1300 let suffix = format!(
1301 "{}_modify_nullable",
1302 match backend {
1303 DatabaseBackend::Postgres => "postgres",
1304 DatabaseBackend::MySql => "mysql",
1305 DatabaseBackend::Sqlite => "sqlite",
1306 }
1307 );
1308
1309 with_settings!({ snapshot_suffix => suffix }, {
1310 assert_snapshot!(sql);
1311 });
1312 }
1313
1314 #[rstest]
1316 #[case::postgres_modify_default(DatabaseBackend::Postgres)]
1317 #[case::mysql_modify_default(DatabaseBackend::MySql)]
1318 #[case::sqlite_modify_default(DatabaseBackend::Sqlite)]
1319 fn test_build_action_queries_modify_column_default(#[case] backend: DatabaseBackend) {
1320 let action = MigrationAction::ModifyColumnDefault {
1321 table: "users".into(),
1322 column: "status".into(),
1323 new_default: Some("'active'".into()),
1324 };
1325 let current_schema = vec![TableDef {
1326 name: "users".into(),
1327 description: None,
1328 columns: vec![ColumnDef {
1329 name: "status".into(),
1330 r#type: ColumnType::Simple(SimpleColumnType::Text),
1331 nullable: true,
1332 default: None,
1333 comment: None,
1334 primary_key: None,
1335 unique: None,
1336 index: None,
1337 foreign_key: None,
1338 }],
1339 constraints: vec![],
1340 }];
1341 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
1342 assert!(!result.is_empty());
1343 let sql = result
1344 .iter()
1345 .map(|q| q.build(backend))
1346 .collect::<Vec<String>>()
1347 .join("\n");
1348
1349 assert!(sql.contains("DEFAULT") || sql.contains("active"));
1351
1352 let suffix = format!(
1353 "{}_modify_default",
1354 match backend {
1355 DatabaseBackend::Postgres => "postgres",
1356 DatabaseBackend::MySql => "mysql",
1357 DatabaseBackend::Sqlite => "sqlite",
1358 }
1359 );
1360
1361 with_settings!({ snapshot_suffix => suffix }, {
1362 assert_snapshot!(sql);
1363 });
1364 }
1365
1366 #[rstest]
1368 #[case::postgres_modify_comment(DatabaseBackend::Postgres)]
1369 #[case::mysql_modify_comment(DatabaseBackend::MySql)]
1370 #[case::sqlite_modify_comment(DatabaseBackend::Sqlite)]
1371 fn test_build_action_queries_modify_column_comment(#[case] backend: DatabaseBackend) {
1372 let action = MigrationAction::ModifyColumnComment {
1373 table: "users".into(),
1374 column: "email".into(),
1375 new_comment: Some("User email address".into()),
1376 };
1377 let current_schema = vec![TableDef {
1378 name: "users".into(),
1379 description: None,
1380 columns: vec![ColumnDef {
1381 name: "email".into(),
1382 r#type: ColumnType::Simple(SimpleColumnType::Text),
1383 nullable: true,
1384 default: None,
1385 comment: None,
1386 primary_key: None,
1387 unique: None,
1388 index: None,
1389 foreign_key: None,
1390 }],
1391 constraints: vec![],
1392 }];
1393 let result = build_action_queries(&backend, &action, ¤t_schema).unwrap();
1394 let sql = result
1395 .iter()
1396 .map(|q| q.build(backend))
1397 .collect::<Vec<String>>()
1398 .join("\n");
1399
1400 if backend != DatabaseBackend::Sqlite {
1402 assert!(sql.contains("COMMENT") || sql.contains("User email address"));
1403 }
1404
1405 let suffix = format!(
1406 "{}_modify_comment",
1407 match backend {
1408 DatabaseBackend::Postgres => "postgres",
1409 DatabaseBackend::MySql => "mysql",
1410 DatabaseBackend::Sqlite => "sqlite",
1411 }
1412 );
1413
1414 with_settings!({ snapshot_suffix => suffix }, {
1415 assert_snapshot!(sql);
1416 });
1417 }
1418
1419 #[rstest]
1420 #[case::create_table_func_default_postgres(DatabaseBackend::Postgres)]
1421 #[case::create_table_func_default_mysql(DatabaseBackend::MySql)]
1422 #[case::create_table_func_default_sqlite(DatabaseBackend::Sqlite)]
1423 fn test_create_table_with_function_default(#[case] backend: DatabaseBackend) {
1424 let action = MigrationAction::CreateTable {
1427 table: "users".into(),
1428 columns: vec![
1429 ColumnDef {
1430 name: "id".into(),
1431 r#type: ColumnType::Simple(SimpleColumnType::Uuid),
1432 nullable: false,
1433 default: Some("gen_random_uuid()".into()),
1434 comment: None,
1435 primary_key: None,
1436 unique: None,
1437 index: None,
1438 foreign_key: None,
1439 },
1440 ColumnDef {
1441 name: "created_at".into(),
1442 r#type: ColumnType::Simple(SimpleColumnType::Timestamptz),
1443 nullable: false,
1444 default: Some("now()".into()),
1445 comment: None,
1446 primary_key: None,
1447 unique: None,
1448 index: None,
1449 foreign_key: None,
1450 },
1451 ],
1452 constraints: vec![],
1453 };
1454 let result = build_action_queries(&backend, &action, &[]).unwrap();
1455 let sql = result
1456 .iter()
1457 .map(|q| q.build(backend))
1458 .collect::<Vec<_>>()
1459 .join(";\n");
1460
1461 with_settings!({ snapshot_suffix => format!("create_table_func_default_{:?}", backend) }, {
1462 assert_snapshot!(sql);
1463 });
1464 }
1465
1466 #[rstest]
1467 #[case::delete_enum_column_postgres(DatabaseBackend::Postgres)]
1468 #[case::delete_enum_column_mysql(DatabaseBackend::MySql)]
1469 #[case::delete_enum_column_sqlite(DatabaseBackend::Sqlite)]
1470 fn test_delete_column_with_enum_type(#[case] backend: DatabaseBackend) {
1471 let action = MigrationAction::DeleteColumn {
1474 table: "orders".into(),
1475 column: "status".into(),
1476 };
1477 let schema = vec![TableDef {
1478 name: "orders".into(),
1479 description: None,
1480 columns: vec![
1481 col("id", ColumnType::Simple(SimpleColumnType::Integer)),
1482 ColumnDef {
1483 name: "status".into(),
1484 r#type: ColumnType::Complex(vespertide_core::ComplexColumnType::Enum {
1485 name: "order_status".into(),
1486 values: vespertide_core::EnumValues::String(vec![
1487 "pending".into(),
1488 "shipped".into(),
1489 ]),
1490 }),
1491 nullable: false,
1492 default: None,
1493 comment: None,
1494 primary_key: None,
1495 unique: None,
1496 index: None,
1497 foreign_key: None,
1498 },
1499 ],
1500 constraints: vec![],
1501 }];
1502 let result = build_action_queries(&backend, &action, &schema).unwrap();
1503 let sql = result
1504 .iter()
1505 .map(|q| q.build(backend))
1506 .collect::<Vec<_>>()
1507 .join(";\n");
1508
1509 with_settings!({ snapshot_suffix => format!("delete_enum_column_{:?}", backend) }, {
1510 assert_snapshot!(sql);
1511 });
1512 }
1513}