Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

postgrator

rickbergfalk99.5kMIT8.0.0TypeScript support: included

A SQL migration tool for SQL people

migrator, migration, postgres, postgresql, mysql, sql server, sql

readme

Postgrator

CircleCI

A Node.js SQL migration library using a directory of plain SQL scripts. Supports Postgres, MySQL, SQL Server, and SQLite.

Available as a CLI tool: https://www.npmjs.com/package/postgrator-cli.

Installation

npm install postgrator

Usage

Create a directory and stick some SQL scripts in there that change your database in some way. It might look like:

migrations/
  |- 001.do.sql
  |- 001.undo.sql
  |- 002.do.optional-description-of-script.sql
  |- 002.undo.optional-description-of-script.sql
  |- 003.do.sql
  |- 003.undo.sql
  |- 004.do.js
  |- 004.undo.js
  |- ... and so on

The files must follow the convention [version].[action].[optional-description].sql or [version].[action].[optional-description].js (or .mjs, .cjs)

Version must be a number, but you may start and increment the numbers in any way you'd like. If you choose to use a purely sequential numbering scheme instead of something based on a timestamp, you will find it helpful to start with 000s or some large number for file organization purposes.

Action must be either "do" or "undo". Do implements the version, and undo undoes it. In other migration tools, this might be "up" and "down". Writing undo scripts is optional if your dev/migration strategy does not require it.

Optional-description can be a label or tag to help keep track of what happens inside the script. Descriptions should not contain periods.

SQL or JS You have a choice of either using a plain SQL file or you can also generate your SQL via a javascript module. The javascript module should export a function called generateSql() that returns a string representing the SQL.

Note: As of version 6.0.0, postgrator is an ES module, and uses import() to load js migrations. .mjs and .cjs should be honored.

For example:

// Assuming commonJS module
module.exports.generateSql = function () {
  return (
    "CREATE USER transaction_user WITH PASSWORD '" +
    process.env.TRANSACTION_USER_PASSWORD +
    "'"
  );
};

You might want to choose the JS file approach, to make use of (secret) environment variables such as the above.

When using JS files, the file content nor the resulting script is checksum validated.

Support for asynchronous functions is provided, in the event you need to retrieve data from an external source, for example:

import axios from "axios";

module.exports.generateSql = async () => {
  const response = await axios({
    method: "get",
    url: "https://api.example.org/person/1",
  });
  return `INSERT INTO person (name, age) VALUES ('${response.data.name}', ${response.data.age});`;
};

To run your SQL migrations with Postgrator, write a Node.js script or integrate Postgrator with your application.

When first run against your database, Postgrator will create the table specified by config.schemaTable. Postgrator relies on this table to track what version the database is at.

Postgrator automatically determines whether it needs to go "up" or "down", and will update the schemaTable accordingly. If the database is already at the version specified to migrate to, Postgrator does nothing.

import Postgrator from "postgrator";
import pg from "pg";
import { dirname } from "path";
import { fileURLToPath } from "url";

const __dirname = dirname(fileURLToPath(import.meta.url));

async function main() {
  // Create a client of your choice
  const client = new pg.Client({
    host: "localhost",
    port: 5432,
    database: "postgrator",
    user: "postgrator",
    password: "postgrator",
  });

  try {
    // Establish a database connection
    await client.connect();

    // Create postgrator instance
    const postgrator = new Postgrator({
      migrationPattern: __dirname + "/some/pattern/*",
      driver: "pg",
      database: "databasename",
      schemaTable: "schemaversion",
      execQuery: (query) => client.query(query),
      execSqlScript: (sqlScript) => client.sqlScript(sqlScript),
    });

    // Migrate to specific version
    const appliedMigrations = await postgrator.migrate("002");
    console.log(appliedMigrations);

    // Or migrate to max version (optionally can provide 'max')
    await postgrator.migrate();
  } catch (error) {
    // If error happened partially through migrations,
    // error object is decorated with appliedMigrations
    console.error(error.appliedMigrations); // array of migration objects
  }

  // Once done migrating, close your connection.
  await client.end();
}
main();

Want more examples for MySQL and MS SQL Server? Check out the examples directory.

Options

const postgrator = new Postgrator(options);
Option Required Description default
migrationPattern Required Glob pattern to migration files. e.g. path.join(__dirname, '/migrations/*')
driver Required Must be pg, mysql, mssql, or sqlite3
database Required Target database name. Optional for sqlite3.
execQuery Required Function to execute SQL. MUST return a promise containing an object with a rows array of objects. For example { rows: [{ column_name: 'column_value' }] }
execSqlScript Optional Function to execute db migration script consisting of multiple SQL statements. MUST return a void promise. If not supplied, execQuery will be used. `
schemaTable Optional Table created to track schema version. When using Postgres, you may specify schema as well, e.g. schema_name.table_name schemaversion
validateChecksum Optional Validates checksum of existing SQL migration files already run prior to executing migrations. Set to false to disable. Unused for JS migrations. true
newline Optional Force line ending on file when generating checksum. Value should be either CRLF (windows) or LF (unix/mac).
currentSchema Optional For Postgres and MS SQL Server. Specifies schema to look to when validating schemaversion table columns. For Postgres, run's SET search_path = currentSchema prior to running queries against db

Checksum validation

By default, Postgrator will generate an md5 checksum for each migration file and save the value to the schema table after a successful migration.

Before applying migrations to a database, Postgrator will validate the md5 checksum to ensure the scripts have not changed for any already run existing migrations in the migration directory. If a change is detected, migration will stop, reporting an error.

Because line endings may differ between environments/editors, an option is available to force a specific line ending prior to generating the checksum.

Migration object

Postgrator will often return a migration object or array of migrations. The format of a migration object is:

{
  version: versionNumber,
  action: 'do',
  name: 'first-table',
  filename: 'path/to/0001.up.first-table.sql',
  md5: 'checksumvalue',
  getSql: () => {} // function to get sql from file
}

Logging

Postgrator is an event emitter, allowing you to log however you want to log. There are no events for error or finish.

const postgrator = new Postgrator(options);
postgrator.on("validation-started", (migration) => console.log(migration));
postgrator.on("validation-finished", (migration) => console.log(migration));
postgrator.on("migration-started", (migration) => console.log(migration));
postgrator.on("migration-finished", (migration) => console.log(migration));

Migration errors

If postgrator.migrate() fails to run multiple migrations, Postgrator will stop running any further migrations. Migrations successfully run prior to the migration with the error will remain implemented.

If you need to migrate back to the version the database was at prior to running migrate(), that is up to you to implement. Instead of doing this consider writing your application in a way that is compatible with any version of a future release.

In the event of an error during migration, the error object will be decorated with an array of migrations that run successfully (error.appliedMigrations).

Keep in mind how you write your SQL - You may (or may not) want to write your SQL defensively (ie, check for pre-existing objects before you create new ones).

Preventing partial migrations

Depending on your database and database configuration, consider wrapping each migration in a transaction or BEGIN/END block. By default, Postgres and SQL Server consider multiple statements run in one execution part of one implicit transaction. MySQL however will implement up to the failure.

If using SQL Server, do not write a migration containing multiple statements using the GO keyword. Instead, break statements between the GO keyword into multiple migration files, ensuring that you do not end up with partial migrations implemented but no record of that happening.

Utility methods

Some of postgrator's methods may come in useful performing other migration tasks

// Get max version available from filesystem, as number, not string
const maxVersionAvailable = await postgrator.getMaxVersion();
console.log(maxVersionAvailable);

// "current" database schema version as number, not string
const version = await postgrator.getDatabaseVersion();
console.log(version);

// To get all migrations from directory and parse metadata
const migrations = await postgrator.getMigrations();
console.log(migrations);

Tests

A docker-compose file is provided with containers configured for tests.

To run Postgrator tests locally, you'll need Docker and Docker Compose installed.

# In one terminal window
docker-compose up
# In another terminal once databases are up
npm test
# After tests, in docker session
# control/command-c to quit docker-compose and remove containers
docker-compose rm --force

License

MIT

changelog

CHANGELOG

8.0.0

November 11, 2024

  • Update glob to latest dependency, which technically only supports Node v20 or later. Which technically, makes this a breaking change?

7.3.0

September 3, 2024

  • Support sqlite3 and better-sqlite3 migrations with ; in statements.

  • Add execSqlScript option to execute migrations consisting of multiple statements. If not supplied, Postgrator will fallback to using execQuery.

7.2.0

July 9, 2023

  • Support better-sqlite3

7.1.1

September 21, 2022

  • Fix migration method code comment
  • Use INTEGER for sqlite3 version type

7.1.0

March 31, 2022

  • Add sqlite3 support

7.0.0

February 23, 2022

  • getDatabaseVersion returns 0 when schema version table does not exist instead of undefined. This is technically breaking if you rely on the undefined returned in version 5.0.1.
  • Fix DEP0151 warning about ext resolution

6.0.0

February 21, 2022

Breaking

Postgrator is now an ES module and requires Node 14 or later. .cjs and .mjs migration files are now supported.

No other changes have been made.

5.0.1

February 18, 2022

  • Fix getDatabaseVersion error when schemaversion table does not exist. undefined is returned instead.

5.0.0

October 14, 2021

Version 5 represents an effort to simplify things, allow more flexibility, and reduce the maintenance of this package.

This is made possible by requiring the database query execution function be injected to postgrator. Postgrator no longer manages the database connection, and as a result no longer needs to maintain a mapping to specific database driver implementations.

Despite all the breaking changes below, nothing has changed in the overall migration file approach. Migrations that worked for previous versions of postgrator will still work in v5.

See examples/ directory for quick overview of how v5 is used.

Features

  • md5 validation may be skipped for specific migrations by deleting the md5 value from your DB's schemaversion table.

Fixes

  • Honors uppercase characters in postgres schema table name (#98)
  • JS migrations no longer run during validation, preventing unwanted migration failures (#124)

BREAKING

  • Nodejs 12 or later required.
  • Removed host, port, username, password, ssl, options. Manage connections with execQuery instead.
  • Driver value mysql2 unsupported. (You can still use the mysql2 package for your execQuery implementation, but set driver to mysql)
  • RemovedmigrationDirectory option. Use migrationPattern instead. In most cases it will be path/to/migrations/*. Any glob syntax supported.
  • Removed GO keyword splitting for mssql. Using GO could leave your system in a partially migrated state on failure and is not recommended.
  • filename in migration result is full file path
  • Removed md5 checksum validation for JS migrations. JS migrations are dynamic, and JS style trends could vary over time if a tool like Prettier is applied.
  • JS migrations do not generate SQL until immediately prior to being applied. Previously, JS migrations generated SQL prior to any migrations running. This was problematic for cases where JS migrations no longer successfullly generated SQL.

4.3.1

October 9, 2021

  • Undeprecate currentSchema config. It'll stay for v5.

4.3.0

October 8, 2021

  • Add execQuery function option to allow maximum flexibility in database connection management. Postgrator-owned database connections (the connections established using host, username, password, etc.) are deprecated, and will be removed in Postgrator 5.
  • Deprecate host, port, username, password, ssl, options, currentSchema config.
  • Deprecate runQuery utility function (use your db driver directly).
  • Deprecate migrationDirectory in favor of migrationPattern glob.

4.2.0

July 25, 2021

  • Add support for mssql 7

4.1.1

October 29, 2020

  • Fix pg SSL config when using connectionString

4.1.0

October 9, 2020

  • Add async function migration support
  • Update dependencies

4.0.1

June 15, 2020

  • Fix Postgres SSL typings

4.0.0

April 10, 2020

  • BREAKING: Node.js 10 or later required
  • Add support for pg 8.x.x

3.11.1

April 10, 2020

  • Fix to avoid running migrations with same number
  • Update dependencies
  • Fix Windows compat

3.11.0

December 2, 2019

  • Add support for driver mysql2@2
  • Add support for driver mssql@6
  • Fix non-default schema use for mssql (#94)

3.10.2

June 4, 2019

  • Fix MySQL option typings for mysql2

3.10.1

March 21, 2019

  • Fix TypeScript type for currentSchema postgres option

3.10.0

March 20, 2019

  • Add support for mssql 5.x

3.9.0

March 14, 2019

  • Add mssql domain option
  • Filter out non-migration files to avoid filename parsing errors

3.8.0

Feb 17 2019

  • Add currentSchema option for Postgres

3.7.0

October 14 2018

  • Add support for mysql2
  • Add support for ssl config for mysql
  • Fix: close db connection on migration error
  • Fix: support schema detection for MySQL 8.0
  • Fix: Don't wait for postgres connection end response

3.6.0

April 26 2018

  • Allow schema to be specified for schemaTable (Postgres only) If schema does not exist it will be created.

3.5.0

Feb 17 2018

  • Add connectionTimeout config for mssql

3.4.0

Jan 21 2018

  • Adds support for managing multiple databases/schemas on single cluster/database

3.3.0

Jan 16 2018

  • Adds incompatible version warnings for installed db drivers

3.2.0

Jan 15 2018

  • Add support for pg@6

3.1.0

Dec 24 2017

  • Fix: allow filenames longer than 32 char for mssql
  • Add option to specify glob pattern for migration files

3.0.0

Nov 18 2017

Features / Improvements

  • run_at timestamp column added to schema table
  • md5 and name columns added for all implementations
  • Checksum validation now implemented for all drivers
  • Checksum validation may be skipped using config validateChecksums: false
  • Callback API replaced with Promises
  • Connections opened/closed automatically (no more .endConnection())
  • Lots of tests

Breaking changes

  • Node 6 or greater now required
  • DB drivers must be installed prior to use (pg, mysql, mssql)
  • pg.js and tedious no longer valid driver config option
  • None of the API is the same
  • Checksums now validated by default for all drivers
  • Calling .migrate() without input migrates to latest/max
  • Logging to console removed

2.10.0

May 6 2017

  • Allow migration SQL to be generated via js function

2.9.0

Apr 6 2017

  • Added postgres ssl support

2.8.0

Apr 26 2016

  • Allow port configuration

2.6.0

Jan 20 2016

  • Added config to toggle logging progress
  • Added config for requestTimeout
  • Added support for mssql batches using GO keyword

2.5.0

Aug 25 2015

  • Exposed functions to get current/max migration versions

2.4.0

Aug 19 2015

  • Added config for schematable name
  • Added config for checksum newline ending normalization

2.3.0

June 15 2015

  • Version column increased to BIGINT

2.2.0

Apr 30 2015

  • SQL Server connections closed with endConnection()
  • Update db driver modules

2.1.0

Feb 7 2015

  • Update mssql config: timeout set to 1 hour
  • Add version as PK on schemaversion table

2.0.0

Nov 20 2014

  • Checksum validation added for postgres
  • postgrator.migrate('max', cb) added to migrate to latest version

1.x

Nov 6 2014

Initial version released

0.x

Dec 12 2012

Initial development