Keep pgroll
state schema in sync with pgroll
binary version
#876
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background
pgroll
stores its state in thepgroll
schema in the target database. This schema includes the data and SQL functions that it needs to operate. Including:pgroll.migrations
table: tracks all schema changes applied to all schema in the target database.is_active_migration_period
- determines if there is an in-progress migration.read_schema
- returns all tables, constraints, indexes etc in the given schema.raw_migration
- installed by the event trigger to capture inferred migrations.The
pgroll
schema is created when a user runspgroll init
. Internally this runsinit.sql
against the target database.init.sql
is written to be idempotent; a user can runpgroll init
multiple times without fear of corruptingpgroll
's internal state.When a user upgrades their version of
pgroll
, there is no automated mechanism to ensure thatpgroll init
is re-run. This means that the new version ofpgroll
is not in sync with any changes topgroll
's internal state tables/functions required by that new version.This PR keeps the version of
pgroll
and its internalpgroll
schema in sync:The pgroll_version table
pgroll
will track the version number of thepgroll
binary used to initializepgroll
's internal state in a newpgroll_version
table:The table will contain exactly one row. The table is created by
init.sql
as follows:When the user runs
pgroll init
thepgroll_version
table is truncated and the current version of thepgroll
binary is inserted into the table.Automatic upgrades
When a user upgrades their version of
pgroll
,pgroll
will automatically re-initialize its internal state to ensure that there is no version skew between thepgroll
binary and the version ofpgroll
's internal state.For example, a user has
pgroll
0.14.0 installed. Thepgroll_version
table looks ike thisThe user installs
pgroll
0.15.0. The first time the user runs apgroll
command that requires a connection to the target database (technically whenever astate.State
instance is constructed), the version stored in thepgroll_version
table is checked against the currentpgroll
binary version. If the state version is less than the binary version (using a standard semver comparison), then the state is re-initialized and thepgroll_version
table is updated.Disallow downgrades
In the case where a user attempts to use a version of
pgroll
that is older than the version stored in thepgroll_version
table, thepgroll
command will display an error and ask the user to upgrade their version ofpgroll
.Using an older version of
pgroll
against newer internal state is not supported and a downgrade risks permanent data loss so aborting is the correct option here.Edge cases
Missing pgroll_version table
For versions of
pgroll
's internal state that don’t have apgroll_version
table, the version comparison will always report that the internal state version is smaller than the currentpgroll
binary version. This will cause re-initialization and creation of thepgroll_version
table.Development versions
The version number is injected into the
pgroll
CLI using linker flags at build time during our CI process. For local builds that don’t perform this version injection, the version is set to the string“development”
.pgroll
will never cause re-initialization ofpgroll
internal state.pgroll
will re-initialize If the version in thepgroll_version
table is “development”.So
"development"
builds ofpgroll
are isolated from versioned builds in terms of their effects onpgroll
’s internal state.