|
| 1 | +# Idempotent Examples |
| 2 | + |
| 3 | +Idempotency is an important concept in Graphile Migrate, if a migration is |
| 4 | +idempotent it means that you can run the migration multiple times and the end |
| 5 | +state of the database structure will always be the same. (NOTE: though the |
| 6 | +structure may be the same, some idempotent commands may result in |
| 7 | +deleting/dropping data, so extreme care must be exercised.) |
| 8 | + |
| 9 | +Many of PostgreSQL's commands have built in support for idempotency; you will |
| 10 | +see this commonly with `IF EXISTS` or `IF NOT EXISTS` clauses, |
| 11 | +`CREATE OR REPLACE`, and similar constructs: |
| 12 | + |
| 13 | +```sql |
| 14 | +-- Create a schema |
| 15 | +DROP SCHEMA IF EXISTS app CASCADE; |
| 16 | +CREATE SCHEMA app; |
| 17 | + |
| 18 | +-- Create a table |
| 19 | +DROP TABLE IF EXISTS foo CASCADE; |
| 20 | +CREATE TABLE foo ...; |
| 21 | + |
| 22 | +-- Add a column to the end of the table |
| 23 | +ALTER TABLE foo DROP COLUMN IF EXISTS bar CASCADE; |
| 24 | +ALTER TABLE foo ADD COLUMN foo ...; |
| 25 | + |
| 26 | +-- Make a column NOT NULL |
| 27 | +ALTER TABLE foo ALTER COLUMN foo SET NOT NULL; |
| 28 | + |
| 29 | +-- Alter a column type |
| 30 | +ALTER TABLE foo ALTER COLUMN foo TYPE int USING foo::int; |
| 31 | + |
| 32 | +-- Change the body or flags of a function |
| 33 | +CREATE OR REPLACE FUNCTION ...; |
| 34 | + |
| 35 | +-- Change a function signature (arguments, return type, etc) |
| 36 | +DROP FUNCTION IF EXISTS ... CASCADE; |
| 37 | +CREATE OR REPLACE FUNCTION ... |
| 38 | +``` |
| 39 | + |
| 40 | +Sometimes idempotency is a little more difficult to achieve. For instance, some |
| 41 | +commands do not have the `if exists` parameter. One such example is `rename`. In |
| 42 | +this case, we can implement the `if exists` logic ourselves using an anonymous |
| 43 | +code block: |
| 44 | + |
| 45 | +```sql |
| 46 | +do $$ |
| 47 | +begin |
| 48 | + /* if column `username` exists on users table */ |
| 49 | + if exists( |
| 50 | + select 1 |
| 51 | + from information_schema.columns |
| 52 | + where table_schema = 'public' |
| 53 | + and table_name = 'users' |
| 54 | + and column_name = 'username' |
| 55 | + ) then |
| 56 | + /* rename the column to `name` */ |
| 57 | + alter table users |
| 58 | + rename column username to name; |
| 59 | + end if; |
| 60 | +end$$; |
| 61 | +``` |
0 commit comments