Skip to content

isobit/pgt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pgt

⚠️ Currently a work-in-progress.

pgt is a collection of tools for PostgreSQL:

  • bench is a tool for running benchmarks written as SQL Go templates
  • migrate is a simple and production-safe plain SQL migration system
  • mux is a PostgreSQL protocol proxy that can multiplex connections/sessions (useful for debugging in-progress transactions)

Migrations

Features:

  • Version table tracks full history of migrations; updated atomically with transaction but also includes mechanism for detecting partially failed up/down for non-txn migrations
  • Auto transaction wrapping, but can be disabled e.g. for create index concurrently
  • Configurable schema version table
  • Watchdog that looks for other backend processes that are blocked waiting for locks taken by migrations, and cancels if too many are blocked for too long. (sorta inspired by autovacuum's back-off strategy)
  • Convenience for dumping schema SQL (--dump flag that calls pg_dump or custom command, e.g. exec'ing pg_dump in a docker container)
  • Test mode that automatically creates an isolated test database, runs each migration (up+down+up or just up if irreversible)
  • Interactive mode which can prompt for each migration and show SQL
  • Version table bootstrapping is implemented as reviewable, explicitly built-in "zero migration".
  • Migrations are very nearly plain SQL (special directives are just comments)

Possible future features:

  • Export reports on locks acquired by migrations (e.g. detect non-concurrent index creation)
  • Helper for renumbering migrations post-merge
  • Helper prompts for resolving issues like unexpected statement timeouts and previously failed partial migrations.

Caveats:

  • Once created (version 0 applied), specified version table must be exactly the same as the existing version table, or pgt will think the version has be reset to -1. The table can be renamed by manually running alter table ... rename to ....
  • Currently pgt does not know how to force-set the version or otherwise recover from failed partial migrations (no-transaction migrations), but this can be accomplished by manually patching the version table.

Usage:

USAGE:
    pgt migrate [OPTIONS]

OPTIONS:
    -h, --help                                              show usage help
    -d, --database <VALUE>         PGT_DATABASE             database connection string  (required)
    -s, --source <VALUE>           PGT_MIGRATION_SOURCE     path to migrations directory  (required)
    -t, --target <VALUE>           PGT_MIGRATION_TARGET     version to target  (default: latest)
    --version-table <VALUE>        PGT_VERSION_TABLE        use custom version table name  (default: pgt.schema_version)
    -y, --yes                                               bypass all confirmation prompts
    --test                         PGT_TEST                 enable test mode
    --test-database-name <VALUE>                            (default: pgt_migrate_test_1694394525)
    --retain-test-database
    --dump <VALUE>                 PGT_DUMP                 file path to dump schema to
    --dump-command <VALUE>         PGT_DUMP_COMMAND         command used to dump schema  (default: pg_dump --schema-only '{{.Url}}')
    --max-block-duration <VALUE>   PGT_MAX_BLOCK_DURATION   (default: 10s)
    --max-block-processes <VALUE>  PGT_MAX_BLOCK_PROCESSES  (default: 0)

Examples

Basic migration:

001_create_foo.sql

create table foo (
    id int primary key not null generated by default as identity,
    value int
);

Migration with down/rollback:

002_foo_description.sql

alter table foo add column description text;
--pgt:down
alter table foo drop column description;

Disable transaction auto-wrapping:

003_foo_value_index.sql

--pgt:no_transaction
create index concurrently foo_value_idx on foo using btree (value);

--pgt:down
drop index foo_data_idx;