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