on main help sign in
reshape/tests/complex.rs
379 lines 11 kB history raw
1mod common;
2use common::Test;
4#[test]
5fn move_column_between_tables() {
6 let mut test = Test::new("Move column between tables");
8 test.first_migration(
9 r#"
10 name = "create_tables"
12 [[actions]]
13 type = "create_table"
14 name = "users"
15 primary_key = ["id"]
17 [[actions.columns]]
18 name = "id"
19 type = "INTEGER"
21 [[actions.columns]]
22 name = "email"
23 type = "TEXT"
25 [[actions]]
26 type = "create_table"
27 name = "profiles"
28 primary_key = ["id"]
30 [[actions.columns]]
31 name = "id"
32 type = "INTEGER"
34 [[actions.columns]]
35 name = "user_id"
36 type = "INTEGER"
37 nullable = false
38 "#,
39 );
41 test.second_migration(
42 r#"
43 name = "move_email_column"
45 [[actions]]
46 type = "add_column"
47 table = "profiles"
49 [actions.column]
50 name = "email"
51 type = "TEXT"
52 nullable = false
54 # When `users` is updated in the old schema, we write the email value to `profiles`
55 # When `profiles` is updated in the old schema, the equivalent `users.email` will also be updated
56 [actions.up]
57 table = "users"
58 value = "users.email"
59 where = "profiles.user_id = users.id"
61 [[actions]]
62 type = "remove_column"
63 table = "users"
64 column = "email"
66 # When `profiles` is changed in the new schema, we write the email address back to the removed column
67 [actions.down]
68 table = "profiles"
69 value = "profiles.email"
70 where = "users.id = profiles.user_id"
71 "#,
72 );
74 test.after_first(|db| {
75 db.simple_query("INSERT INTO users (id, email) VALUES (1, 'test1@test.com')")
76 .unwrap();
77 db.simple_query("INSERT INTO users (id, email) VALUES (2, 'test2@test.com')")
78 .unwrap();
80 db.simple_query("INSERT INTO profiles (id, user_id) VALUES (1, 1)")
81 .unwrap();
82 db.simple_query("INSERT INTO profiles (id, user_id) VALUES (2, 2)")
83 .unwrap();
84 });
86 test.intermediate(|old_db, new_db| {
87 // Ensure emails were backfilled into profiles
88 let profiles_emails: Vec<String> = new_db
89 .query(
90 r#"
91 SELECT email
92 FROM profiles
93 ORDER BY id
94 "#,
95 &[],
96 )
97 .unwrap()
98 .iter()
99 .map(|row| row.get("email"))
100 .collect();
101 assert_eq!(vec!("test1@test.com", "test2@test.com"), profiles_emails);
103 // Ensure insert in old schema updates new
104 old_db
105 .simple_query("INSERT INTO users (id, email) VALUES (3, 'test3@test.com')")
106 .unwrap();
107 old_db
108 .simple_query("INSERT INTO profiles (id, user_id) VALUES (3, 3)")
109 .unwrap();
110 let new_email: String = new_db
111 .query("SELECT email FROM profiles WHERE id = 3", &[])
112 .unwrap()
113 .first()
114 .map(|row| row.get("email"))
115 .unwrap();
116 assert_eq!("test3@test.com", new_email);
118 // Ensure updates in old schema updates new
119 old_db
120 .simple_query("UPDATE users SET email = 'test3+updated@test.com' WHERE id = 3")
121 .unwrap();
122 let new_email: String = new_db
123 .query("SELECT email FROM profiles WHERE id = 3", &[])
124 .unwrap()
125 .first()
126 .map(|row| row.get("email"))
127 .unwrap();
128 assert_eq!("test3+updated@test.com", new_email);
130 // Ensure insert in new schema updates old
131 new_db
132 .simple_query(
133 "INSERT INTO profiles (id, user_id, email) VALUES (4, 4, 'test4@test.com')",
134 )
135 .unwrap();
136 new_db
137 .simple_query("INSERT INTO users (id) VALUES (4)")
138 .unwrap();
139 let old_email: String = old_db
140 .query("SELECT email FROM users WHERE id = 4", &[])
141 .unwrap()
142 .first()
143 .map(|row| row.get("email"))
144 .unwrap();
145 assert_eq!("test4@test.com", old_email);
147 // Ensure update in new schema updates old
148 new_db
149 .simple_query("UPDATE profiles SET email = 'test4+updated@test.com' WHERE id = 4")
150 .unwrap();
151 let old_email: String = old_db
152 .query("SELECT email FROM users WHERE id = 4", &[])
153 .unwrap()
154 .first()
155 .map(|row| row.get("email"))
156 .unwrap();
157 assert_eq!("test4+updated@test.com", old_email);
158 });
160 test.run();
163#[test]
164fn extract_relation_into_new_table() {
165 let mut test = Test::new("Extract relation into new table");
167 test.first_migration(
168 r#"
169 name = "create_tables"
171 [[actions]]
172 type = "create_table"
173 name = "accounts"
174 primary_key = ["id"]
176 [[actions.columns]]
177 name = "id"
178 type = "INTEGER"
180 [[actions]]
181 type = "create_table"
182 name = "users"
183 primary_key = ["id"]
185 [[actions.columns]]
186 name = "id"
187 type = "INTEGER"
189 [[actions.columns]]
190 name = "account_id"
191 type = "INTEGER"
192 nullable = false
194 [[actions.columns]]
195 name = "account_role"
196 type = "TEXT"
197 nullable = false
198 "#,
199 );
201 test.second_migration(
202 r#"
203 name = "add_account_user_connection"
205 [[actions]]
206 type = "create_table"
207 name = "user_account_connections"
208 primary_key = ["account_id", "user_id"]
210 [[actions.columns]]
211 name = "account_id"
212 type = "INTEGER"
214 [[actions.columns]]
215 name = "user_id"
216 type = "INTEGER"
218 [[actions.columns]]
219 name = "role"
220 type = "TEXT"
221 nullable = false
223 [actions.up]
224 table = "users"
225 values = { user_id = "id", account_id = "account_id", role = "UPPER(account_role)" }
226 where = "user_account_connections.user_id = users.id"
228 [[actions]]
229 type = "remove_column"
230 table = "users"
231 column = "account_id"
233 [actions.down]
234 table = "user_account_connections"
235 value = "user_account_connections.account_id"
236 where = "users.id = user_account_connections.user_id"
238 [[actions]]
239 type = "remove_column"
240 table = "users"
241 column = "account_role"
243 [actions.down]
244 table = "user_account_connections"
245 value = "LOWER(user_account_connections.role)"
246 where = "users.id = user_account_connections.user_id"
247 "#,
248 );
250 test.after_first(|db| {
251 db.simple_query("INSERT INTO accounts (id) VALUES (1)")
252 .unwrap();
253 db.simple_query("INSERT INTO users (id, account_id, account_role) VALUES (1, 1, 'admin')")
254 .unwrap();
255 });
257 test.intermediate(|old_db, new_db| {
258 // Ensure connections was backfilled
259 let rows: Vec<(i32, i32, String)> = new_db
260 .query(
261 "
262 SELECT account_id, user_id, role
263 FROM user_account_connections
264 ",
265 &[],
266 )
267 .unwrap()
268 .iter()
269 .map(|row| (row.get("account_id"), row.get("user_id"), row.get("role")))
270 .collect();
271 assert_eq!(1, rows.len());
273 let row = rows.first().unwrap();
274 assert_eq!(1, row.0);
275 assert_eq!(1, row.1);
276 assert_eq!("ADMIN", row.2);
278 // Ensure inserted user in old schema creates a new connection
279 old_db
280 .simple_query(
281 "INSERT INTO users (id, account_id, account_role) VALUES (2, 1, 'developer')",
282 )
283 .unwrap();
284 assert!(
285 new_db
286 .query(
287 "
288 SELECT account_id, user_id, role
289 FROM user_account_connections
290 WHERE account_id = 1 AND user_id = 2 AND role = 'DEVELOPER'
291 ",
292 &[],
293 )
294 .unwrap()
295 .len()
296 == 1
297 );
299 // Ensure NOT NULL constraint still applies to old schema
300 let result = old_db
301 .simple_query(
302 "INSERT INTO users (id, account_id, account_role) VALUES (2, NULL, 'developer')",
303 );
304 assert!(result.is_err());
306 // Ensure updated user role in old schema updates connection in new schema
307 old_db
308 .simple_query("UPDATE users SET account_role = 'admin' WHERE id = 2")
309 .unwrap();
310 assert!(
311 new_db
312 .query(
313 "
314 SELECT account_id, user_id, role
315 FROM user_account_connections
316 WHERE account_id = 1 AND user_id = 2 AND role = 'ADMIN'
317 ",
318 &[],
319 )
320 .unwrap()
321 .len()
322 == 1
323 );
325 // Ensure updated connection in new schema updates old schema user
326 new_db
327 .simple_query(
328 "UPDATE user_account_connections SET role = 'DEVELOPER' WHERE account_id = 1 AND user_id = 2",
329 )
330 .unwrap();
331 assert!(
332 old_db
333 .query(
334 "
335 SELECT id
336 FROM users
337 WHERE id = 2 AND account_id = 1 AND account_role = 'developer'
338 ",
339 &[],
340 )
341 .unwrap()
342 .len()
343 == 1
344 );
346 // Ensure insert of user with connection through new schema updates user in old schema
347 new_db
348 .simple_query(
349 r#"
350 BEGIN;
351 INSERT INTO users (id) VALUES (3);
352 INSERT INTO user_account_connections (user_id, account_id, role) VALUES (3, 1, 'DEVELOPER');
353 COMMIT;
354 "#,
355 )
356 .unwrap();
357 new_db
358 .simple_query(
359 "",
360 )
361 .unwrap();
362 assert!(
363 old_db
364 .query(
365 "
366 SELECT id
367 FROM users
368 WHERE id = 3 AND account_id = 1 AND account_role = 'developer'
369 ",
370 &[],
371 )
372 .unwrap()
373 .len()
374 == 1
375 );
376 });
378 test.run();