CLI tool to help with postgresql database schema updates, migrations and versioning.
The goal of pgfine is to provide project structure declarative as much as possible: - all database objects have their corresponding create script. - migration scripts should only be needed to update data-full objects - tables.
bash
cargo install pgfine
bash
git clone https://gitlab.com/mrsk/pgfine
cargo install --path ./pgfine
env-local-db-0.sh
(as an example) file like this:```bash
export PGFINECONNECTIONSTRING="..."
export PGFINEADMINCONNECTION_STRING="..."
export PGFINE_DIR="./pgfine"
export PGFINEROLEPREFIX="prod_"
export PGFINEROOTCERT="" ```
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
├── schemas
│ └── public.sql
├── constraints
├── triggers
├── policies
└── views
Modify newly created ./pgfine/create/*.sql
and ./pgfine/drop/*.sql
scripts if needed.
./pgfine/create/*
scripts if needed.bash
pgfine migrate
Two extra tables will be created:
pgfine_objects
: contains a list of managed pgfine objects and their hashes.
sql
create table if not exists pgfine_objects (
po_id text primary key,
po_type text,
po_md5 text,
po_script text,
po_path text,
po_depends_on text[],
po_required_by text[]
);
pgfine_migrations
: contains a list of executed migrations. Selecting the max value should reveal the current state of database. The first migration will be inserted as empty string.
sql
create table if not exists pgfine_migrations (
pm_id text primary key
);
./pgfine/**/*.sql
../pgfine/migrations/*
scripts.Run
bash
pgfine migrate
Test your fresh db maybe.
bash
pgfine migrate
Database objects are: - tables - views - triggers - constraints - policies - functions - roles - schemas
Filenames for database objects must be of specific format :
- tables: ./pgfine/tables/<schema>.<name>.sql
- views: ./pgfine/views/<schema>.<name>.sql
- functions: : ./pgfine/functions/<schema>.<name>.sql
- triggers: ./pgfine/triggers/<schema>.<table>.<name>.sql
- constraints: ./pgfine/constraints/<schema>.<table>.<name>.sql
- policies: ./pgfine/policies/<schema>.<table>.<name>.sql
- roles: ./pgfine/roles/<name>.sql
- schemas: ./pgfine/schemas/<name>.sql
Each file contains script to create that object.
Updates are done by dropping the object and creating a new one.
Drop scripts are generated by object type and object name. Tables will never be dropped automatically - they have to be dropper/updated using migration scripts or manually.
Example ./pgfine/tables/public.table0.sql
:
```sql
create table table0 (
id bigserial primary key
);
-- create indexes -- create constraints -- create rules -- create triggers
```
Table constraints and indeces can be stored along with tables. But to modify them you will have to write migration scripts.
If you have circular foreign key dependencies you should define those constraints in a separate ./pgfine/constraints/
files to break the cycle.
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 ```
Example ./pgfine/constraints/public.table1.t0_id_fk.sql
:
sql
alter table table1
add constraint t0_id_fk foreign key (t0_id) references table1 (id);
pgfine init
PGFINE_DIR
.pgfine migrate
./pgfine/create/
scripts to create role and database (using admin connection).pgfine_objects
table and project contents.pgfine drop --no-joke
./pgfine/drop/
scripts to drop role and database (using admin connection).public
schema../pgfine/migrations/
is assumed to be increasing in alphabetical order.{pgfine_role_prefix}
text should not be used for other porpuses as for database-role prefix in your scripts.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...
PGFINE_ALLOW_DROP
variable to protect production envs./example/
./pgfine/initial/
execute after the database is created ./pgfine/final/
execute after the database objects are created