@@ -44,22 +44,35 @@ And please give some love to our featured sponsors 🤩:
44
44
45
45
## Status
46
46
47
- ** EXPERIMENTAL**
48
-
49
- Tests are in place for many of the APIs, though the API remains undocumented
50
- (deliberately) and thus if you use the API directly (as opposed to using the
51
- CLI) you should expect to have to update your code from time to time. (We advise
52
- using TypeScript to make spotting breaking changes easier.) There are no
53
- automated integration tests of the CLI yet (although mostly all it does is hand
54
- off to the API).
55
-
56
- There are people (including the maintainer) using this software to manage
57
- production databases. It is also used in
58
- [ Graphile Starter] ( https://github.com/graphile/starter ) . However, it is not for
59
- the faint of heart - this software is powerful and requires knowledge of SQL. If
60
- you don't understand what makes Graphile Migrate awesome, or you're concerned
61
- about it continuing to evolve, you may want to consider an alternative migration
62
- framework such as these awesome (and quite diverse) projects:
47
+ ** STABLE**
48
+
49
+ This project is intended to be consumed via the CLI, which is stable and is
50
+ being used in production in many projects. The CLI doesn't have explicit tests
51
+ (PR welcome!), but it's a thin wrapper around the programmatic API which has
52
+ copious tests.
53
+
54
+ The programmatic API is deliberately undocumented; it is not a public interface
55
+ at this time (though it is fully typed in TypeScript). We reserve the right to
56
+ make breaking changes to the programmatic API in patch releases (though this has
57
+ not happened yet and is unlikely to happen without good reason). Should you need
58
+ to use the programmatic API, please get in touch to encourage us to make this a
59
+ supported interface ─ we'd love to know how you're using it!
60
+
61
+ The project as a whole is stable, but the approach is still "experimental", in
62
+ particular:
63
+
64
+ - because committed migrations are hashed you cannot edit old migrations; this
65
+ may cause you issues should you upgrade PostgreSQL and it drops support for a
66
+ syntax or feature you were previously using. We plan to fix this issue _ if and
67
+ when_ it occurs, so if this affects you please open a detailed issue.
68
+ - the approach of up-only and re-runnable migrations is not for the faint of
69
+ heart ─ it requires solid SQL knowledge and if insufficient attention is paid
70
+ it could result in your migrations and your local database state drifting
71
+ apart (see 'Drift' below).
72
+
73
+ If you don't understand what makes Graphile Migrate awesome, you may want to
74
+ consider an alternative migration framework such as these awesome (and quite
75
+ diverse) projects:
63
76
64
77
- [ db-migrate] ( https://db-migrate.readthedocs.io/en/latest/Getting%20Started/commands/ )
65
78
- [ sqitch] ( https://sqitch.org/ )
@@ -130,13 +143,13 @@ PostgreSQL servers have a default database called `postgres` which is a good
130
143
choice for this).
131
144
132
145
> Your database URL is needed for most Graphile Migrate commands. The shadow
133
- > database URL is needed for the development-only commands ` commit ` ,
134
- > ` uncommit ` and ` reset ` . The root database URL is needed to drop and
135
- > recreate databases, i.e. for the ` reset ` command and for commands that call
136
- > it ( ` commit ` and ` uncommit ` , which reset the shadow database).
146
+ > database URL is needed for the development-only commands ` commit ` , ` uncommit `
147
+ > and ` reset ` . The root database URL is needed to drop and recreate databases,
148
+ > i.e. for the ` reset ` command and for commands that call it ( ` commit ` and
149
+ > ` uncommit ` , which reset the shadow database).
137
150
>
138
- > ** NOTE** : you should not need the shadow database URL or root database URL
139
- > in production (you only need the ` graphile-migrate migrate ` command in
151
+ > ** NOTE** : you should not need the shadow database URL or root database URL in
152
+ > production (you only need the ` graphile-migrate migrate ` command in
140
153
> production) unless you have actions that need them.
141
154
142
155
``` bash
@@ -730,6 +743,76 @@ Since "superuser" has a specific meaning and is not strictly required for these
730
743
activities we avoid that term, however you may find that you use a superuser as
731
744
your root user - this is expected.
732
745
746
+ ## Drift
747
+
748
+ > **NOTE**: drift only affects your local development database, it cannot occur
749
+ > in your production database assuming you're only using
750
+ > `graphile-migrate migrate` in production.
751
+
752
+ In development, if you're insufficiently careful with modifications to
753
+ `current.sql` (including when you choose to save the file, and when switching
754
+ branches in `git`) you may end up with a local database state that differs from
755
+ what you'd expect given the committed migrations and contents of `current.sql`.
756
+ We **strongly recommend against auto-save** for this reason; and recommend that
757
+ you keep a dumped `schema.sql` to help you spot unexpected changes.
758
+
759
+ Here's an illustrative example to explain the drift phenomenon, with function
760
+ inspired by [XKCD221](https://xkcd.com/221/). Imagine that you're running
761
+ `graphile-migrate watch` locally and you write the following to `current.sql`:
762
+
763
+ ```sql
764
+ -- Revision 1
765
+ create function rnd() returns int as $$
766
+ select 4;
767
+ $$ language sql stable;
768
+ ```
769
+
770
+ Because `watch` runs the contents of `current.sql` whenever it changes, this
771
+ will create the `rnd()` function in your local database.
772
+
773
+ A couple seconds later you change your mind, and decide to rename the function,
774
+ writing the following to `current.sql`:
775
+
776
+ ```sql
777
+ -- Revision 2
778
+ create function get_random_number() returns int as $$
779
+ select 4;
780
+ $$ language sql stable;
781
+ ```
782
+
783
+ This creates `get_random_number()`, but no-one ever said to delete `rnd()`, so
784
+ now both functions exist. According to the committed migrations and
785
+ `current.sql` only `get_random_number()` should exist. The existence of the
786
+ orphaned `rnd()` function in your local database is what we term "drift" ─ this
787
+ function will never appear in your production database even after you commit
788
+ this latest migration; it also won't be in your shadow database (because we
789
+ reset the shadow database and reapply all the migrations frequently).
790
+
791
+ Since Graphile Migrate doesn't know how to reverse the SQL you've written, it's
792
+ up to you to make the SQL safe so that it can be ran over and over, and adjust
793
+ to your changes. The two to `current.sql` versions above should have been
794
+
795
+ ```sql
796
+ -- Revision 1
797
+ drop function if exists rnd();
798
+
799
+ create function rnd() returns int as $$
800
+ select 4;
801
+ $$ language sql stable;
802
+ ```
803
+
804
+ and
805
+
806
+ ```sql
807
+ -- Revision 2
808
+ drop function if exists rnd();
809
+ drop function if exists get_random_number();
810
+
811
+ create function get_random_number() returns int as $$
812
+ select 4;
813
+ $$ language sql stable;
814
+ ```
815
+
733
816
## TODO:
734
817
735
818
- [ ] Store pgSettings with committed transactions to protect against user edits
0 commit comments