@@ -1,61 +1,45 @@
1−use reshape::migrations::{
2− AddIndex, AlterColumn, ColumnBuilder, ColumnChanges, CreateTableBuilder, Index, Migration,
8fn alter_column_data() {
5fn alter_column_data() {
9− let (mut reshape, mut old_db, mut new_db) = common::setup();
6+ let mut test = Test::new("Alter column");
11− let create_users_table = Migration::new("create_user_table", None).with_action(
12− CreateTableBuilder::default()
14− .primary_key(vec!["id".to_string()])
16− ColumnBuilder::default()
18− .data_type("INTEGER")
21− ColumnBuilder::default()
30− let uppercase_name = Migration::new("uppercase_name", None).with_action(AlterColumn {
31− table: "users".to_string(),
32− column: "name".to_string(),
33− up: Some("UPPER(name)".to_string()),
34− down: Some("LOWER(name)".to_string()),
35− changes: ColumnChanges {
43− let first_migrations = vec![create_users_table.clone()];
8+ test.first_migration(
44− let second_migrations = vec![create_users_table.clone(), uppercase_name.clone()];
9+ r#"
10+ name = "create_user_table"
46− // Run first migration, should automatically finish
12+ [[actions]]
47− reshape.migrate(first_migrations.clone()).unwrap();
13+ type = "create_table"
49− // Update search paths
17+ [[actions.columns]]
50− old_db
18+ name = "id"
51− .simple_query(&reshape::schema_query_for_migration(
19+ type = "INTEGER"
52− &first_migrations.last().unwrap().name,
20+
53− ))
21+ [[actions.columns]]
54− .unwrap();
22+ name = "name"
27+ test.second_migration(
29+ name = "uppercase_name"
32+ type = "alter_column"
40+ test.after_first(|db| {
56− // Insert some test users
41+ // Insert some test users
58− .simple_query(
42+ db.simple_query(
60 INSERT INTO users (id, name) VALUES
44 INSERT INTO users (id, name) VALUES
61 (1, 'john Doe'),
45 (1, 'john Doe'),
@@ -63,98 +47,82 @@ fn alter_column_data() {
65 .unwrap();
49 .unwrap();
67− // Run second migration
52+ test.intermediate(|old_db, new_db| {
68− reshape.migrate(second_migrations.clone()).unwrap();
70− .simple_query(&reshape::schema_query_for_migration(
71− &second_migrations.last().unwrap().name,
75− // Check that the existing users has the altered data
53+ // Check that the existing users has the altered data
76− let expected = vec!["JOHN DOE", "JANE DOE"];
54+ let expected = vec!["JOHN DOE", "JANE DOE"];
77− assert!(new_db
55+ assert!(new_db
78− .query("SELECT name FROM users ORDER BY id", &[],)
56+ .query("SELECT name FROM users ORDER BY id", &[],)
79− .unwrap()
57+ .unwrap()
81− .map(|row| row.get::<_, String>("name"))
59+ .map(|row| row.get::<_, String>("name"))
82− .eq(expected));
60+ .eq(expected));
84− // Insert data using old schema and make sure the new schema gets correct values
62+ // Insert data using old schema and make sure the new schema gets correct values
86− .simple_query("INSERT INTO users (id, name) VALUES (3, 'test testsson')")
64+ .simple_query("INSERT INTO users (id, name) VALUES (3, 'test testsson')")
87− .unwrap();
65+ .unwrap();
88− let result = new_db
66+ let result = new_db
89− .query_one("SELECT name from users WHERE id = 3", &[])
67+ .query_one("SELECT name from users WHERE id = 3", &[])
90− .unwrap();
68+ .unwrap();
91− assert_eq!("TEST TESTSSON", result.get::<_, &str>("name"));
69+ assert_eq!("TEST TESTSSON", result.get::<_, &str>("name"));
93− // Insert data using new schema and make sure the old schema gets correct values
71+ // Insert data using new schema and make sure the old schema gets correct values
95− .simple_query("INSERT INTO users (id, name) VALUES (4, 'TEST TESTSSON')")
73+ .simple_query("INSERT INTO users (id, name) VALUES (4, 'TEST TESTSSON')")
96− .unwrap();
74+ .unwrap();
97− let result = old_db
75+ let result = old_db
98− .query_one("SELECT name from users WHERE id = 4", &[])
76+ .query_one("SELECT name from users WHERE id = 4", &[])
99− .unwrap();
77+ .unwrap();
100− assert_eq!("test testsson", result.get::<_, &str>("name"));
78+ assert_eq!("test testsson", result.get::<_, &str>("name"));
102− reshape.complete().unwrap();
81+ test.run();
103− common::assert_cleaned_up(&mut new_db);
107fn alter_column_set_not_null() {
85fn alter_column_set_not_null() {
108− let (mut reshape, mut old_db, mut new_db) = common::setup();
86+ let mut test = Test::new("Set column not null");
110− let create_users_table = Migration::new("create_user_table", None).with_action(
88+ test.first_migration(
111− CreateTableBuilder::default()
89+ r#"
90+ name = "create_user_table"
93+ type = "create_table"
112− .name("users")
94+ name = "users"
113− .primary_key(vec!["id".to_string()])
95+ primary_key = ["id"]
114− .columns(vec![
97+ [[actions.columns]]
115− ColumnBuilder::default()
116− .name("id")
98+ name = "id"
117− .data_type("INTEGER")
99+ type = "INTEGER"
119− .unwrap(),
101+ [[actions.columns]]
120− ColumnBuilder::default()
121− .name("name")
102+ name = "name"
122− .data_type("TEXT")
103+ type = "TEXT"
129− let set_name_not_null = Migration::new("set_name_not_null", None).with_action(AlterColumn {
130− table: "users".to_string(),
131− column: "name".to_string(),
132− up: Some("COALESCE(name, 'TEST_DEFAULT_VALUE')".to_string()),
133− down: Some("name".to_string()),
134− changes: ColumnChanges {
136− nullable: Some(false),
142− let first_migrations = vec![create_users_table.clone()];
107+ test.second_migration(
143− let second_migrations = vec![create_users_table.clone(), set_name_not_null.clone()];
108+ r#"
109+ name = "set_name_not_null"
145− // Run first migration, should automatically finish
111+ [[actions]]
146− reshape.migrate(first_migrations.clone()).unwrap();
112+ type = "alter_column"
115+ up = "COALESCE(name, 'TEST_DEFAULT_VALUE')"
148− // Update search paths
118+ [actions.changes]
149− old_db
119+ nullable = false
150− .simple_query(&reshape::schema_query_for_migration(
120+ "#,
151− &first_migrations.last().unwrap().name,
121+ );
123+ test.after_first(|db| {
155− // Insert some test users
124+ // Insert some test users
157− .simple_query(
125+ db.simple_query(
159 INSERT INTO users (id, name) VALUES
127 INSERT INTO users (id, name) VALUES
160 (1, 'John Doe'),
128 (1, 'John Doe'),
@@ -162,99 +130,80 @@ fn alter_column_set_not_null() {
164 .unwrap();
132 .unwrap();
166− // Run second migration
135+ test.intermediate(|old_db, new_db| {
167− reshape.migrate(second_migrations.clone()).unwrap();
169− .simple_query(&reshape::schema_query_for_migration(
170− &second_migrations.last().unwrap().name,
174− // Check that existing users got the correct values
136+ // Check that existing users got the correct values
175− let expected = vec!["John Doe", "TEST_DEFAULT_VALUE"];
137+ let expected = vec!["John Doe", "TEST_DEFAULT_VALUE"];
176− assert!(new_db
138+ assert!(new_db
177− .query("SELECT name FROM users ORDER BY id", &[],)
139+ .query("SELECT name FROM users ORDER BY id", &[],)
178− .unwrap()
140+ .unwrap()
180− .map(|row| row.get::<_, String>("name"))
142+ .map(|row| row.get::<_, String>("name"))
181− .eq(expected));
143+ .eq(expected));
183− // Insert data using old schema and make sure the new schema gets correct values
145+ // Insert data using old schema and make sure the new schema gets correct values
185− .simple_query("INSERT INTO users (id, name) VALUES (3, NULL)")
147+ .simple_query("INSERT INTO users (id, name) VALUES (3, NULL)")
186− .unwrap();
148+ .unwrap();
187− let result = new_db
149+ let result = new_db
188− .query_one("SELECT name from users WHERE id = 3", &[])
150+ .query_one("SELECT name from users WHERE id = 3", &[])
189− .unwrap();
151+ .unwrap();
190− assert_eq!("TEST_DEFAULT_VALUE", result.get::<_, &str>("name"));
152+ assert_eq!("TEST_DEFAULT_VALUE", result.get::<_, &str>("name"));
192− // Insert data using new schema and make sure the old schema gets correct values
154+ // Insert data using new schema and make sure the old schema gets correct values
194− .simple_query("INSERT INTO users (id, name) VALUES (4, 'Jane Doe')")
156+ .simple_query("INSERT INTO users (id, name) VALUES (4, 'Jane Doe')")
195− .unwrap();
157+ .unwrap();
196− let result = old_db
158+ let result = old_db
197− .query_one("SELECT name from users WHERE id = 4", &[])
159+ .query_one("SELECT name from users WHERE id = 4", &[])
198− .unwrap();
160+ .unwrap();
199− assert_eq!("Jane Doe", result.get::<_, &str>("name"));
161+ assert_eq!("Jane Doe", result.get::<_, &str>("name"));
201− reshape.complete().unwrap();
164+ test.run();
202− common::assert_cleaned_up(&mut new_db);
206fn alter_column_rename() {
168fn alter_column_rename() {
207− let (mut reshape, mut old_db, mut new_db) = common::setup();
169+ let mut test = Test::new("Rename column");
209− let create_users_table = Migration::new("create_user_table", None).with_action(
171+ test.first_migration(
210− CreateTableBuilder::default()
172+ r#"
173+ name = "create_user_table"
176+ type = "create_table"
211− .name("users")
177+ name = "users"
212− .primary_key(vec!["id".to_string()])
178+ primary_key = ["id"]
213− .columns(vec![
180+ [[actions.columns]]
214− ColumnBuilder::default()
215− .name("id")
181+ name = "id"
216− .data_type("INTEGER")
182+ type = "INTEGER"
218− .unwrap(),
184+ [[actions.columns]]
219− ColumnBuilder::default()
220− .name("name")
185+ name = "name"
221− .data_type("TEXT")
186+ type = "TEXT"
225− .build()
190+ test.second_migration(
192+ name = "set_name_not_null"
195+ type = "alter_column"
228− let rename_to_full_name =
229− Migration::new("rename_to_full_name", None).with_action(AlterColumn {
230− table: "users".to_string(),
231− column: "name".to_string(),
232− up: None, // up and down are not required when only renaming a column
234− changes: ColumnChanges {
237− name: Some("full_name".to_string()),
242− let first_migrations = vec![create_users_table.clone()];
243− let second_migrations = vec![create_users_table.clone(), rename_to_full_name.clone()];
245− // Run first migration, should automatically finish
246− reshape.migrate(first_migrations.clone()).unwrap();
248− // Update search paths
250− .simple_query(&reshape::schema_query_for_migration(
251− &first_migrations.last().unwrap().name,
204+ test.after_first(|db| {
255− // Insert some test data
205+ // Insert some test data
257− .simple_query(
206+ db.simple_query(
259 INSERT INTO users (id, name) VALUES
208 INSERT INTO users (id, name) VALUES
260 (1, 'John Doe'),
209 (1, 'John Doe'),
@@ -262,94 +211,69 @@ fn alter_column_rename() {
264 .unwrap();
213 .unwrap();
266− // Run second migration
216+ test.intermediate(|_, new_db| {
267− reshape.migrate(second_migrations.clone()).unwrap();
217+ // Check that existing values can be queried using new column name
268− new_db
218+ let expected = vec!["John Doe", "Jane Doe"];
269− .simple_query(&reshape::schema_query_for_migration(
219+ assert!(new_db
270− &second_migrations.last().unwrap().name,
220+ .query("SELECT full_name FROM users ORDER BY id", &[],)
272− .unwrap();
222+ .iter()
223+ .map(|row| row.get::<_, String>("full_name"))
274− // Check that existing values can be queried using new column name
227+ test.run();
275− let expected = vec!["John Doe", "Jane Doe"];
277− .query("SELECT full_name FROM users ORDER BY id", &[],)
280− .map(|row| row.get::<_, String>("full_name"))
283− reshape.complete().unwrap();
284− common::assert_cleaned_up(&mut new_db);
288fn alter_column_multiple() {
231fn alter_column_multiple() {
289− let (mut reshape, mut old_db, mut new_db) = common::setup();
232+ let mut test = Test::new("Alter column value multiple times");
291− let create_users_table = Migration::new("create_user_table", None).with_action(
234+ test.first_migration(
292− CreateTableBuilder::default()
235+ r#"
236+ name = "create_user_table"
239+ type = "create_table"
293− .name("users")
240+ name = "users"
294− .primary_key(vec!["id".to_string()])
241+ primary_key = ["id"]
295− .columns(vec![
243+ [[actions.columns]]
296− ColumnBuilder::default()
297− .name("id")
244+ name = "id"
298− .data_type("INTEGER")
245+ type = "INTEGER"
300− .unwrap(),
247+ [[actions.columns]]
301− ColumnBuilder::default()
302− .name("counter")
248+ name = "counter"
303− .data_type("INTEGER")
249+ type = "INTEGER"
304− .nullable(false)
250+ nullable = false
308− .build()
254+ test.second_migration(
256+ name = "increment_counter_twice"
259+ type = "alter_column"
263+ down = "counter - 1"
266+ type = "alter_column"
270+ down = "counter - 1"
311− let increment_counter_twice = Migration::new("increment_counter_twice", None)
312− .with_action(AlterColumn {
313− table: "users".to_string(),
314− column: "counter".to_string(),
315− up: Some("counter + 1".to_string()),
316− down: Some("counter - 1".to_string()),
317− changes: ColumnChanges {
324− .with_action(AlterColumn {
325− table: "users".to_string(),
326− column: "counter".to_string(),
327− up: Some("counter + 1".to_string()),
328− down: Some("counter - 1".to_string()),
329− changes: ColumnChanges {
337− let first_migrations = vec![create_users_table.clone()];
338− let second_migrations = vec![create_users_table.clone(), increment_counter_twice.clone()];
340− // Run first migration, should automatically finish
341− reshape.migrate(first_migrations.clone()).unwrap();
343− // Update search paths
345− .simple_query(&reshape::schema_query_for_migration(
346− &first_migrations.last().unwrap().name,
274+ test.after_first(|db| {
350− // Insert some test data
275+ // Insert some test data
352− .simple_query(
276+ db.simple_query(
354 INSERT INTO users (id, counter) VALUES
278 INSERT INTO users (id, counter) VALUES
@@ -357,239 +281,196 @@ fn alter_column_multiple() {
359 .unwrap();
283 .unwrap();
361− // Run second migration
286+ test.intermediate(|old_db, new_db| {
362− reshape.migrate(second_migrations.clone()).unwrap();
364− .simple_query(&reshape::schema_query_for_migration(
365− &second_migrations.last().unwrap().name,
369− // Check that the existing data has been updated
287+ // Check that the existing data has been updated
370− let expected = vec![2, 102];
288+ let expected = vec![2, 102];
371− let results: Vec<i32> = new_db
289+ let results: Vec<i32> = new_db
372− .query("SELECT counter FROM users ORDER BY id", &[])
290+ .query("SELECT counter FROM users ORDER BY id", &[])
373− .unwrap()
291+ .unwrap()
375− .map(|row| row.get::<_, i32>("counter"))
293+ .map(|row| row.get::<_, i32>("counter"))
376− .collect();
294+ .collect();
377− assert_eq!(expected, results);
295+ assert_eq!(expected, results);
379− // Update data using old schema and make sure it was updated for the new schema
297+ // Update data using old schema and make sure it was updated for the new schema
381− .query("UPDATE users SET counter = 50 WHERE id = 1", &[])
299+ .query("UPDATE users SET counter = 50 WHERE id = 1", &[])
382− .unwrap();
300+ .unwrap();
383− let result: i32 = new_db
301+ let result: i32 = new_db
384− .query("SELECT counter FROM users WHERE id = 1", &[])
302+ .query("SELECT counter FROM users WHERE id = 1", &[])
385− .unwrap()
303+ .unwrap()
387− .map(|row| row.get("counter"))
305+ .map(|row| row.get("counter"))
389− .unwrap();
307+ .unwrap();
390− assert_eq!(52, result);
308+ assert_eq!(52, result);
392− // Update data using new schema and make sure it was updated for the old schema
310+ // Update data using new schema and make sure it was updated for the old schema
394− .query("UPDATE users SET counter = 50 WHERE id = 1", &[])
312+ .query("UPDATE users SET counter = 50 WHERE id = 1", &[])
395− .unwrap();
313+ .unwrap();
396− let result: i32 = old_db
314+ let result: i32 = old_db
397− .query("SELECT counter FROM users WHERE id = 1", &[])
315+ .query("SELECT counter FROM users WHERE id = 1", &[])
398− .unwrap()
316+ .unwrap()
400− .map(|row| row.get("counter"))
318+ .map(|row| row.get("counter"))
402− .unwrap();
320+ .unwrap();
403− assert_eq!(48, result);
321+ assert_eq!(48, result);
405− reshape.complete().unwrap();
324+ test.run();
406− common::assert_cleaned_up(&mut new_db);
410fn alter_column_default() {
328fn alter_column_default() {
411− let (mut reshape, mut old_db, mut new_db) = common::setup();
329+ let mut test = Test::new("Change default value for column");
413− let create_users_table = Migration::new("create_user_table", None).with_action(
331+ test.first_migration(
414− CreateTableBuilder::default()
332+ r#"
333+ name = "create_user_table"
336+ type = "create_table"
415− .name("users")
337+ name = "users"
416− .primary_key(vec!["id".to_string()])
338+ primary_key = ["id"]
417− .columns(vec![
340+ [[actions.columns]]
418− ColumnBuilder::default()
419− .name("id")
341+ name = "id"
420− .data_type("INTEGER")
342+ type = "INTEGER"
422− .unwrap(),
344+ [[actions.columns]]
423− ColumnBuilder::default()
424− .name("name")
345+ name = "name"
425− .data_type("TEXT")
346+ type = "TEXT"
426− .nullable(false)
347+ nullable = false
427− .default_value("'DEFAULT'")
348+ default = "'DEFAULT'"
434− let change_name_default =
435− Migration::new("change_name_default", None).with_action(AlterColumn {
436− table: "users".to_string(),
437− column: "name".to_string(),
440− changes: ColumnChanges {
444− default: Some("'NEW DEFAULT'".to_string()),
448− let first_migrations = vec![create_users_table.clone()];
449− let second_migrations = vec![create_users_table.clone(), change_name_default.clone()];
451− // Run first migration, should automatically finish
452− reshape.migrate(first_migrations.clone()).unwrap();
454− // Update search paths
456− .simple_query(&reshape::schema_query_for_migration(
457− &first_migrations.last().unwrap().name,
352+ test.second_migration(
354+ name = "change_name_default"
357+ type = "alter_column"
362+ default = "'NEW DEFAULT'"
366+ test.after_first(|db| {
461− // Insert a test user
367+ // Insert a test user
463− .simple_query(
368+ db.simple_query(
465 INSERT INTO users (id) VALUES (1)
370 INSERT INTO users (id) VALUES (1)
468 .unwrap();
373 .unwrap();
470− // Run second migration
376+ test.intermediate(|old_db, new_db| {
471− reshape.migrate(second_migrations.clone()).unwrap();
473− .simple_query(&reshape::schema_query_for_migration(
474− &second_migrations.last().unwrap().name,
478− // Check that the existing users has the old default value
377+ // Check that the existing users has the old default value
479− let expected = vec!["DEFAULT"];
378+ let expected = vec!["DEFAULT"];
480− assert!(new_db
379+ assert!(new_db
481− .query("SELECT name FROM users", &[],)
380+ .query("SELECT name FROM users", &[],)
482− .unwrap()
381+ .unwrap()
484− .map(|row| row.get::<_, String>("name"))
383+ .map(|row| row.get::<_, String>("name"))
485− .eq(expected));
384+ .eq(expected));
487− // Insert data using old schema and make those get the old default value
386+ // Insert data using old schema and make those get the old default value
489− .simple_query("INSERT INTO users (id) VALUES (2)")
388+ .simple_query("INSERT INTO users (id) VALUES (2)")
490− .unwrap();
389+ .unwrap();
491− let result = new_db
390+ let result = new_db
492− .query_one("SELECT name from users WHERE id = 2", &[])
391+ .query_one("SELECT name from users WHERE id = 2", &[])
493− .unwrap();
392+ .unwrap();
494− assert_eq!("DEFAULT", result.get::<_, &str>("name"));
393+ assert_eq!("DEFAULT", result.get::<_, &str>("name"));
496− // Insert data using new schema and make sure it gets the new default value
395+ // Insert data using new schema and make sure it gets the new default value
498− .simple_query("INSERT INTO users (id) VALUES (3)")
397+ .simple_query("INSERT INTO users (id) VALUES (3)")
499− .unwrap();
398+ .unwrap();
500− let result = old_db
399+ let result = old_db
501− .query_one("SELECT name from users WHERE id = 3", &[])
400+ .query_one("SELECT name from users WHERE id = 3", &[])
502− .unwrap();
401+ .unwrap();
503− assert_eq!("NEW DEFAULT", result.get::<_, &str>("name"));
402+ assert_eq!("NEW DEFAULT", result.get::<_, &str>("name"));
505− reshape.complete().unwrap();
405+ test.run();
506− common::assert_cleaned_up(&mut new_db);
510fn alter_column_with_index() {
409fn alter_column_with_index() {
511− let (mut reshape, mut db, _) = common::setup();
410+ let mut test = Test::new("Alter column with index");
513− let create_users_table = Migration::new("create_user_table", None)
515− CreateTableBuilder::default()
517− .primary_key(vec!["id".to_string()])
519− ColumnBuilder::default()
521− .data_type("INTEGER")
524− ColumnBuilder::default()
529− ColumnBuilder::default()
538− .with_action(AddIndex {
539− table: "users".to_string(),
541− name: "users_name_idx".to_string(),
542− columns: vec!["first_name".to_string(), "last_name".to_string()],
547− let uppercase_name = Migration::new("uppercase_name", None).with_action(AlterColumn {
548− table: "users".to_string(),
549− column: "last_name".to_string(),
550− up: Some("UPPER(last_name)".to_string()),
551− down: Some("LOWER(last_name)".to_string()),
552− changes: ColumnChanges {
560− let first_migrations = vec![create_users_table.clone()];
412+ test.first_migration(
561− let second_migrations = vec![create_users_table.clone(), uppercase_name.clone()];
413+ r#"
414+ name = "create_user_table"
563− // Run first migration, should automatically finish
416+ [[actions]]
564− reshape.migrate(first_migrations.clone()).unwrap();
417+ type = "create_table"
419+ primary_key = ["id"]
566− // Run second migration
421+ [[actions.columns]]
567− reshape.migrate(second_migrations.clone()).unwrap();
422+ name = "id"
568− db.simple_query(&reshape::schema_query_for_migration(
423+ type = "INTEGER"
569− &second_migrations.last().unwrap().name,
573− // Complete the second migration which should replace the existing column
425+ [[actions.columns]]
574− // with the temporary one
426+ name = "first_name"
575− reshape.complete().unwrap();
427+ type = "TEXT"
438+ name = "users_name_idx"
439+ columns = ["first_name", "last_name"]
443+ test.second_migration(
445+ name = "uppercase_last_name"
448+ type = "alter_column"
450+ column = "last_name"
451+ up = "UPPER(last_name)"
452+ down = "LOWER(last_name)"
456+ test.after_completion(|db| {
577− // Make sure index still exists
457+ // Make sure index still exists
578− let result: i64 = db
458+ let result: i64 = db
581 SELECT COUNT(*)
461 SELECT COUNT(*)
582 FROM pg_catalog.pg_index
462 FROM pg_catalog.pg_index
583 JOIN pg_catalog.pg_class ON pg_index.indexrelid = pg_class.oid
463 JOIN pg_catalog.pg_class ON pg_index.indexrelid = pg_class.oid
584 WHERE pg_class.relname = 'users_name_idx'
464 WHERE pg_class.relname = 'users_name_idx'
588− .unwrap()
468+ .unwrap()
589− .first()
469+ .first()
590− .map(|row| row.get(0))
470+ .map(|row| row.get(0))
591− .unwrap();
471+ .unwrap();
592− assert_eq!(1, result, "expected index to still exist");
472+ assert_eq!(1, result, "expected index to still exist");
594− common::assert_cleaned_up(&mut db);
475+ test.run();