1.2.2 • Published 6 years ago

sql-patch v1.2.2

Weekly downloads
2
License
MIT
Repository
github
Last release
6 years ago

sql-patch

Up/down migrations with some arbitrary DSL/ORM are tedious.

This library (and command line script) provides a tool for applying all of the SQL commands in some directory in order, idempotently. I.e., given a database name and directory:

  1. Create the database (if needed)
  2. Create a table to track the patches that have been applied (if needed)
  3. Read the *.sql files from the directory and execute them in order if they haven't been executed before
  4. Record which files have been executed, so that subsequent calls won't execute them again

It's simpler than typical (say, Rails) migrations. Patches are one-way, and SQL only.

CLI example

Create a new database if needed: createdb buyersdb (only PostgreSQL for now; see To-do below)

migrations/01-initial.sql:

CREATE TABLE customer (
  id SERIAL PRIMARY KEY,
  fullname TEXT,
  created TIMESTAMP DEFAULT current_timestamp
);
INSERT INTO customer (fullname) VALUES ('Lance Moore'), ('Phil Lester');

Running sql-patch migrations/ --database buyersdb will create a new table, if needed, to track migration execution. This meta-table will be created in the "buyersdb" database itself, and by default is named "_schema_patches". It will then execute the contents of the migrations/01-initial.sql file as a single query in that database.

Our table now looks like this:

idfullnamecreated
1Lance Moore2015-12-23 21:45:09
2Phil Lester2015-12-23 21:45:09

Running sql-patch migrations/ --database buyersdb again will have no effect, even if you change the contents of 01-initial.sql. Thus you should never change the contents of a migration once it's been used.

Suppose we later decide a single "fullname" field is sloppy.

migrations/02-split-name.sql:

ALTER TABLE customer
  ADD COLUMN firstname TEXT,
  ADD COLUMN lastname TEXT;
UPDATE customer SET firstname = substring(fullname from '(.*) '),
                    lastname  = substring(fullname from ' (.*)');
ALTER TABLE customer DROP COLUMN fullname;

Running sql-patch migrations/ --database buyersdb now will read the "_schema_patches" table, find that 02-split-name.sql has not been applied, and run it.

Our amended table now looks like this:

idcreatedfirstnamelastname
12015-12-23 21:45:09LanceMoore
22015-12-23 21:45:09PhilLester

API example

This example does pretty much the same thing, even creating the database if needed, from a Node.js script.

const path = require('path');
const Connection = require('sqlcmd-pg').Connection;
const sqlPatch = require('sql-patch');

const db = new Connection({
  user: 'postgres',
  database: 'buyersdb',
});

db.createDatabaseIfNotExists(function(err) {
  if (err) throw err;

  var patches_dirpath = path.join(__dirname, 'migrations');
  sqlPatch.executePatches(db, '_schema_patches', patches_dirpath, function(err) {
    if (err) throw err;

    console.log('DONE');
    process.exit();
  });
});

To-do

  • Support engines other than PostgreSQL
  • Run each patch within a transaction (if supported by the engine)

License

Copyright 2015 Christopher Brown. MIT Licensed

1.2.2

6 years ago

1.2.1

6 years ago

1.2.0

6 years ago

1.1.0

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago

0.1.6

8 years ago

0.1.5

8 years ago

0.1.4

8 years ago

0.1.3

8 years ago

0.1.2

8 years ago

0.1.1

8 years ago

0.1.0

8 years ago