🐘 pgfine

CLI tool to help with postgresql database schema updates, migrations and versioning.

Install

From crates.io

bash cargo install pgfine

From repository

bash git clone https://gitlab.com/mrsk/pgfine cargo install --path ./pgfine

Create a new project

```bash

Connection strings: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING

credentials to connect to target db to perform updates and migrations

export PGFINECONNECTIONSTRING="..."

credentials for creating a new database refereced in the above connection string (usually postgres db with user postgres).

export PGFINEADMINCONNECTION_STRING="..."

path pointing to pgfine project, a good choice would be "./pgfine"

export PGFINE_DIR="./pgfine" ```

Environment variables need to be activated when using pgfine. You can do this by running: bash source env-local-db-0.sh

To initialize pgfine project run: bash pgfine init

This will create directory for storing all pgfine project data:

./pgfine/ ├── create │   ├── 00-create-role.sql │   └── 01-create-database.sql ├── drop │   ├── 00-drop-database.sql │   └── 01-drop-role.sql ├── functions ├── migrations ├── roles ├── tables ├── constraints └── views

Modify newly created ./pgfine/create/*.sql and ./pgfine/drop/*.sql scripts if needed.

Create a database

bash pgfine migrate

Two extra tables will be created additionaly to the tables defined in the pgfine project:

Making changes to database

Table constraints should be stored along with tables. You will have a problem if constraints form circular dependencies.

Rollbacks

Database objects

Database objects are: - tables - views - indexes - constraints - functions - ...

Each database object has coresponding create/alter script in pgfine project directory (see bellow for details). Filenames must consist of schema name and object name and .sql extension (example: ./pgfine/tables/public.some_table_0.sql).

Database object scripts are executed when pgfine attempts to create or alter database object; except for tables - pgfine won't attempt to alter or drop tables, these changes have to be implemented using migration scripts.

Sometimes object needs to be dropped and created instead of updating it in place (one such case is when argument is removed from function definition). Drop script is generated using object id.

Tables

Example ./pgfine/tables/public.table0.sql: ```sql create table table0 ( id bigserial primary key );

-- create indexes -- create constraints -- create rules -- create triggers

```

Views

Example ./pgfine/views/public.view0.sql: ```sql -- it is recommended to include "or replace", otherwise it will be dropped and created again each time changes are made. create or replace view view0 as select t0.id from table0 t0 join table1 t1 on t1.id = t0.id

-- create indexes maybe ```

Constraints

In the constraint identifier the schema part should represent the schema of associated table. (Constraints do not dirrectly belong to particular schema of database, but they are associated with tables.)

When constraint is modified it will always be dropped and created again.

Example ./pgfine/constraints/public.table1_t0_id_fk.sql: sql alter table table1 add constraint table1_t0_id_fk foreign key (t0_id) references table1 (id);

Commands

pgfine init

pgfine migrate

If database is missing:

Creates an up to date fresh databaes using PGFINE_ADMIN_CONNECTION_STRING and skips all migration scripts

If database exists:

pgfine drop --no-joke

Assumptions

Timeouts

If your database is huge it will probably take some time to execute migrations if those are involved in moving the data. Timeouts should be disabled in pgfine. If you find that it hangs in the middle of transaction you might check what is holding the locks, or just kill the pgfine process manually and retry again.

Configured on server side

statement_timeout (integer)

    Abort any statement that takes more than the specified number of milliseconds, starting from the time the command arrives at the server from the client. If log_min_error_statement is set to ERROR or lower, the statement that timed out will also be logged. A value of zero (the default) turns this off.

    Setting statement_timeout in postgresql.conf is not recommended because it would affect all sessions.

idle_in_transaction_session_timeout (integer)

    Terminate any session with an open transaction that has been idle for longer than the specified duration in milliseconds. This allows any locks held by that session to be released and the connection slot to be reused; it also allows tuples visible only to this transaction to be vacuumed. See Section 24.1 for more details about this.

    The default value of 0 disables this feature.

Alternatives

At the current stage pgfine is not the best thing in the world. You might also want to check these alternatives: - refinery - flyway - diesel.rs - dbmigrate - and more...

Plan for 1.0.0

Post 1.0.0 plan