pg-patcher - A Postgres patch helper for node-postgres.
var pg = require('pg');
var pgpatcher = require('pg-patcher');
var client = new pg.Client({
user : 'mydb',
database : 'mydatabase',
});
client.connect(function(err) {
pgpatcher(client, 2, function(err) {
// database is now patched to level 2
client.end();
});
});
Meanwhile:
$ ls -l db/
total 80
-rw-rw-r-- 1 chilts chilts 124 Nov 18 11:52 patch-0-1.sql
-rw-rw-r-- 1 chilts chilts 21 Nov 18 11:34 patch-1-0.sql
-rw-rw-r-- 1 chilts chilts 405 Nov 18 11:36 patch-1-2.sql
-rw-rw-r-- 1 chilts chilts 110 Nov 18 11:37 patch-2-1.sql
Each patch file needs a prefix, two version (from and to) and should end in .sql
.
The API is pretty simple. Just pass your Pg client, the level you want to patch to (whether forwards or backwards), any options and a callback.
var pgpatcher = require('pg-patcher');
pgpatcher(client, level, [opts], callback);
There are only two options to the module, both of which are optional:
var options = {
dir : 'db',
prefix : 'patch',
};
If you leave out opts
completely, these defaults are set for you. These two examples are equivalent:
pgpatcher(client, 2, function(err) {
// database is now patched to level 2
});
pgpatcher(client, 2, { dir : 'db', prefix : 'patch' }, function(err) {
// database is now patched to level 2
});
I have seen too many times that database patch scripts write the current patch level to the current directory. This is wrong on so many levels.
- what if you release your site to multiple webservers/machines?
- what if your patch file gets out of sync with the database itself
Therefore, the only place the database patch level should be is in the database itself. This module does that.
Patch files are just a set of statements that you'd like to perform on the database. These could be creation, altering, dropping of tables, functions, trigger or whatever else Postgres allows. It could also be adding application data to the database or manipulating various colums. It's entirely up to you.
pg-patcher just makes sure that the property
table is updated to the current patch level you specified, once all
patches have been sucessfully applied.
The first patch patch-0-1.sql
should create a property table and set the patch
key to 1
. The first
reverse patch should drop this table. ie. the first two patches are:
$ cat db/patch-0-1.sql
CREATE TABLE property (
key TEXT PRIMARY KEY,
value TEXT
);
INSERT INTO property(key, value) VALUES('patch', 1);
$ cat db/patch-1-0.sql
DROP TABLE property;
Prior to patching, a new transaction is started. After patching it is committed. Therefore, every patch file you have asked to be performed will either succeed or fail. ie. if your database is currently at patch level 3 and you ask to move to patch level 7, then all of 3, 4, 5, 6 and 7 will succeed or none of them.
Therefore, there is no need for you to add BEGIN
or COMMIT
statements in your patch files. pg-patcher will
also make sure the property table contains the current patch level.
Postgres is most wonderful since that DDL can be performed within transactions, which means it's great for creating or altering tables, functions, triggers, whatever. This is why I love it.
pg-patcher also has a command line tool you can run from your package.json
with npm run
:
"scripts": {
"db-patch": "pg-patcher --host localhost --database mydatabase --user myuser --level 2"
}
This can be invoked with npm db-patch
(or with the name of your choosing). However, you may want to place this in
a separate script if you need to pass a password.
You may pass any or all of these to the executable: database, user, password, port, host, ssl.
Written by:
For:
(Ends)