on main help sign in
Add relationship cardinality change example
9752b1efabianlindfors
README.md+54−2
@@ -2,7 +2,7 @@
2
2
3[![Test status badge](https://github.com/fabianlindfors/Reshape/actions/workflows/test.yaml/badge.svg)](https://github.com/fabianlindfors/reshape/actions/workflows/test.yaml) [![Latest release](https://shields.io/github/v/release/fabianlindfors/reshape?display_name=tag&sort=semver&color=blue)](https://github.com/fabianlindfors/reshape/releases)
3[![Test status badge](https://github.com/fabianlindfors/Reshape/actions/workflows/test.yaml/badge.svg)](https://github.com/fabianlindfors/reshape/actions/workflows/test.yaml) [![Latest release](https://shields.io/github/v/release/fabianlindfors/reshape?display_name=tag&sort=semver&color=blue)](https://github.com/fabianlindfors/reshape/releases)
4
4
5−> Also check out [ReshapeDB](https://reshapedb.com), a new database built from the ground up to make zero-downtime schema and data migrations as simple and safe as possible
5+> Also check out [ReshapeDB](https://reshapedb.com), a new database built from the ground up to make zero-downtime schema and data migrations as simple and safe as possible. If you'd like to chat about it, please [reach out](contact@reshapedb.com)!
6
6
7Reshape is an easy-to-use, zero-downtime schema migration tool for Postgres. It automatically handles complex migrations that would normally require downtime or manual multi-step changes. During a migration, Reshape ensures both the old and new schema are available at the same time, allowing you to gradually roll out your application. It will also perform all changes without excessive locking, avoiding downtime caused by blocking other queries. For a more thorough introduction to Reshape, check out the [introductory blog post](https://fabianlindfors.se/blog/schema-migrations-in-postgres-using-reshape/).
7Reshape is an easy-to-use, zero-downtime schema migration tool for Postgres. It automatically handles complex migrations that would normally require downtime or manual multi-step changes. During a migration, Reshape ensures both the old and new schema are available at the same time, allowing you to gradually roll out your application. It will also perform all changes without excessive locking, avoiding downtime caused by blocking other queries. For a more thorough introduction to Reshape, check out the [introductory blog post](https://fabianlindfors.se/blog/schema-migrations-in-postgres-using-reshape/).
8
8
@@ -243,6 +243,7 @@ primary_key = ["user_id"]
243 type = "TEXT"
243 type = "TEXT"
244
244
245 # Backfill from `users` table and copy `users.email` to `user_email` column
245 # Backfill from `users` table and copy `users.email` to `user_email` column
246+ # This will perform an upsert based on the primary key to avoid duplicate rows
246 [actions.up]
247 [actions.up]
247 table = "users"
248 table = "users"
248 values = { user_id = "id", user_email = "email" }
249 values = { user_id = "id", user_email = "email" }
@@ -621,7 +622,7 @@ abort = """
621
622
622### Complex changes across tables
623### Complex changes across tables
623
624
624−The `up` and `down` options available for many actions can also perform more complex changes that span tables.
625+The `up` and `down` options available when creating tables, adding columns and removing columns can also perform more complex changes that span tables.
625
626
626_Example: move `email` column from `users` to `profiles` table_
627_Example: move `email` column from `users` to `profiles` table_
627
628
@@ -653,6 +654,57 @@ table = "profiles"
653 where = "user_id = id"
654 where = "user_id = id"
654```
655```
655
656
657+_Example: turn a 1:N relationship between `users` and `accounts` into N:M and change the format of the associated `role`_
658+
659+```toml
660+# Add `user_account_connections` as a junction table
661+[[actions]]
662+type = "create_table"
663+name = "user_account_connections"
664+primary_key = ["account_id", "user_id"]
665+
666+ [[actions.columns]]
667+ name = "account_id"
668+ type = "INTEGER"
669+
670+ [[actions.columns]]
671+ name = "user_id"
672+ type = "INTEGER"
673+
674+ # `role` is currently stored directly on the `users` table but is part of the relationship
675+ [[actions.columns]]
676+ name = "role"
677+ type = "TEXT"
678+
679+ # Backfill the new table from `users` and uppercase the `role`
680+ [actions.up]
681+ table = "users"
682+ values = { user_id = "id", account_id = "account_id", role = "UPPER(account_role)" }
683+ where = "user_id = id"
684+
685+[[actions]]
686+type = "remove_column"
687+table = "users"
688+column = "account_id"
689+
690+ # When `user_account_connections` is updated, we write the `account_id` back to `users`
691+ [actions.down]
692+ table = "user_account_connections"
693+ value = "account_id"
694+ where = "id = user_id"
695+
696+[[actions]]
697+type = "remove_column"
698+table = "users"
699+column = "account_role"
700+
701+ # When `user_account_connections` is updated, we write the lowercase role back to `users`
702+ [actions.down]
703+ table = "user_account_connections"
704+ value = "LOWER(role)"
705+ where = "id = user_id"
706+```
707+
656## Commands and options
708## Commands and options
657
709
658### `reshape migration start`
710### `reshape migration start`