Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ To create and then execute migration, use:

`runmigration`
* To select a revision, use `--rev <x>`
* If migration fails, you can continue, use `--pos <x>`
* To prevent execution next migrations, use `--one`

Each migration runs in a transaction, so it will be rolled back if part of it fails. To disable, use `--no-transaction`. Then, if it fails, you can continue by using `--pos <x>`.


For more information, use `makemigration --help`, `runmigration --help`

Expand Down
2 changes: 1 addition & 1 deletion bin/makemigration.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ console.log(`New migration to revision ${currentState.revision} has been saved t

if (options.execute)
{
migrate.executeMigration(sequelize.getQueryInterface(), info.filename, 0, (err) => {
migrate.executeMigration(sequelize.getQueryInterface(), info.filename, true, 0, (err) => {
if (!err)
console.log("Migration has been executed successfully");
else
Expand Down
4 changes: 3 additions & 1 deletion bin/runmigration.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const pathConfig = require('../lib/pathconfig');
const optionDefinitions = [
{ name: 'rev', alias: 'r', type: Number, description: 'Set migration revision (default: 0)', defaultValue: 0 },
{ name: 'pos', alias: 'p', type: Number, description: 'Run first migration at pos (default: 0)', defaultValue: 0 },
{ name: 'no-transaction', type: Boolean, description: 'Run each change separately instead of all in a transaction (allows it to fail and continue)', defaultValue: false },
{ name: 'one', type: Boolean, description: 'Do not run next migrations', defaultValue: false },
{ name: 'list', alias: 'l', type: Boolean, description: 'Show migration file list (without execution)', defaultValue: false },
{ name: 'migrations-path', type: String, description: 'The path to the migrations folder' },
Expand Down Expand Up @@ -57,6 +58,7 @@ const queryInterface = sequelize.getQueryInterface();
let fromRevision = options.rev;
let fromPos = parseInt(options.pos);
let stop = options.one;
let noTransaction = options['no-transaction'];

let migrationFiles = fs.readdirSync(migrationsDir)
// filter JS files
Expand Down Expand Up @@ -89,7 +91,7 @@ if (options.list)
Async.eachSeries(migrationFiles,
function (file, cb) {
console.log("Execute migration from file: "+file);
migrate.executeMigration(queryInterface, path.join(migrationsDir, file), fromPos, (err) => {
migrate.executeMigration(queryInterface, path.join(migrationsDir, file), !noTransaction, fromPos, (err) => {
if (stop)
return cb("Stopped");

Expand Down
98 changes: 61 additions & 37 deletions lib/migrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -654,42 +654,49 @@ const getMigration = function(actions)
return " { \n" + ret.join(", \n") + "\n }";
};

let addTransactionToOptions = (options) => {
let ret = JSON.stringify({...options, transaction: '###TRANSACTION###'});
ret = ret.replace('"###TRANSACTION###"', 'transaction');
return ret;
};

let commandsUp = [];
let consoleOut = [];

for (let _i in actions)
{
let action = actions[_i];
switch (action.actionType)
switch (action.actionType)
{
case 'createTable':
{
let resUp =`{ fn: "createTable", params: [
"${action.tableName}",
${getAttributes(action.attributes)},
${JSON.stringify(action.options)}
${addTransactionToOptions(action.options)}
] }`;
commandsUp.push(resUp);

consoleOut.push(`createTable "${action.tableName}", deps: [${action.depends.join(', ')}]`);
}
break;

case 'dropTable':
{
let res = `{ fn: "dropTable", params: ["${action.tableName}"] }`;
let res = `{ fn: "dropTable", params: ["${action.tableName}", {transaction: transaction}] }`;
commandsUp.push(res);

consoleOut.push(`dropTable "${action.tableName}"`);
}
break;

case 'addColumn':
{
let resUp = `{ fn: "addColumn", params: [
"${action.tableName}",
"${(action.options && action.options.field) ? action.options.field : action.attributeName}",
${propertyToStr(action.options)}
${propertyToStr(action.options)},
{transaction: transaction}
] }`;

commandsUp.push(resUp);
Expand All @@ -700,54 +707,61 @@ let resUp = `{ fn: "addColumn", params: [

case 'removeColumn':
{
let res = `{ fn: "removeColumn", params: ["${action.tableName}", "${(action.options && action.options.field) ? action.options.field : action.columnName}"] }`;
let res = `{ fn: "removeColumn", params: [
"${action.tableName}",
"${(action.options && action.options.field) ? action.options.field : action.columnName}",
{transaction: transaction}
]
}`;
commandsUp.push(res);

consoleOut.push(`removeColumn "${(action.options && action.options.field) ? action.options.field : action.columnName}" from table "${action.tableName}"`);
}
break;

case 'changeColumn':
{
let res = `{ fn: "changeColumn", params: [
"${action.tableName}",
"${(action.options && action.options.field) ? action.options.field : action.attributeName}",
${propertyToStr(action.options)}
${propertyToStr(action.options)},
{transaction: transaction}
] }`;
commandsUp.push(res);

consoleOut.push(`changeColumn "${action.attributeName}" on table "${action.tableName}"`);
}
break;

case 'addIndex':
{
let res = `{ fn: "addIndex", params: [
"${action.tableName}",
${JSON.stringify(action.fields)},
${JSON.stringify(action.options)}
${addTransactionToOptions(action.options)}
] }`;
commandsUp.push(res);

let nameOrAttrs = (action.options && action.options.indexName && action.options.indexName != '') ? `"${action.options.indexName}"` : JSON.stringify(action.fields);
consoleOut.push(`addIndex ${nameOrAttrs} to table "${action.tableName}"`);
}
break;

case 'removeIndex':
{
// log(action)
let nameOrAttrs = (action.options && action.options.indexName && action.options.indexName != '') ? `"${action.options.indexName}"` : JSON.stringify(action.fields);

let res = `{ fn: "removeIndex", params: [
"${action.tableName}",
${nameOrAttrs}
${nameOrAttrs},
{transaction: transaction}
] }`;
commandsUp.push(res);

consoleOut.push(`removeIndex ${nameOrAttrs} from table "${action.tableName}"`);
}

default:
// code
}
Expand All @@ -759,9 +773,9 @@ let res = `{ fn: "removeIndex", params: [

const writeMigration = function(revision, migration, migrationsDir, name = '', comment = '')
{
let _commands = "var migrationCommands = [ \n" + migration.commandsUp.join(", \n") +' \n];\n';
let _commands = "var migrationCommands = function(transaction) {return [ \n" + migration.commandsUp.join(", \n") +' \n];};\n';
let _actions = ' * ' + migration.consoleOut.join("\n * ");

_commands = beautify(_commands);
let info = {
revision,
Expand All @@ -787,23 +801,32 @@ ${_commands}

module.exports = {
pos: 0,
useTransaction: true,
up: function(queryInterface, Sequelize)
{
var index = this.pos;
return new Promise(function(resolve, reject) {
function next() {
if (index < migrationCommands.length)
{
let command = migrationCommands[index];
console.log("[#"+index+"] execute: " + command.fn);
index++;
queryInterface[command.fn].apply(queryInterface, command.params).then(next, reject);
function run(transaction) {
const commands = migrationCommands(transaction);
return new Promise(function(resolve, reject) {
function next() {
if (index < commands.length)
{
let command = commands[index];
console.log("[#"+index+"] execute: " + command.fn);
index++;
queryInterface[command.fn].apply(queryInterface, command.params).then(next, reject);
}
else
resolve();
}
else
resolve();
}
next();
});
next();
});
}
if (this.useTransaction) {
return queryInterface.sequelize.transaction(run);
} else {
return run(null);
}
},
info: info
};
Expand All @@ -817,7 +840,7 @@ module.exports = {
return {filename, info};
};

const executeMigration = function(queryInterface, filename, pos, cb)
const executeMigration = function(queryInterface, filename, useTransaction, pos, cb)
{
let mig = require(filename);

Expand All @@ -829,6 +852,7 @@ const executeMigration = function(queryInterface, filename, pos, cb)
console.log("Set position to "+pos);
mig.pos = pos;
}
mig.useTransaction = useTransaction;

mig.up(queryInterface, Sequelize).then(
() => {
Expand Down