Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the Postgres schema for the migration table to be specified through migrationStorageTableSchema (#265) #635

Merged
merged 9 commits into from
Oct 14, 2018
Merged
5 changes: 4 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ database, using `sequelize`, but want to use a different table, you can change t
"migrationStoragePath": "sequelizeMeta.json",

// Use a different table name. Default: SequelizeMeta
"migrationStorageTableName": "sequelize_meta"
"migrationStorageTableName": "sequelize_meta",

// Use a different schema (Postgres-only). Default: undefined
"migrationStorageTableSchema": "sequelize_schema"
}
}
```
Expand Down
23 changes: 21 additions & 2 deletions src/core/migrator.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@ export function getMigrator (type, args) {

return sequelize
.authenticate()
.then(() => {
// Check if this is a PostgreSQL run and if there is a custom schema specified, and if there is, check if it's
// been created. If not, attempt to create it.
if (helpers.version.getDialectName() === 'pg') {
const customSchemaName = helpers.umzug.getSchema('migration');
if (customSchemaName && customSchemaName !== 'public') {
return sequelize.showAllSchemas().then(schemas => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (!_.includes(schemas, customSchemaName)) {
return sequelize.createSchema(customSchemaName);
} else {
return Bluebird.resolve();
}
});
}
}

return Bluebird.resolve();
})
.then(() => migrator)
.catch(e => helpers.view.error(e));
});
Expand Down Expand Up @@ -127,7 +145,8 @@ export function addTimestampsToSchema (migrator) {
}
}, {
tableName,
timestamps: true
timestamps: true,
schema: helpers.umzug.getSchema()
});

return SequelizeMeta.sync()
Expand All @@ -136,4 +155,4 @@ export function addTimestampsToSchema (migrator) {
});
});
});
}
}
5 changes: 5 additions & 0 deletions src/helpers/umzug-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,18 @@ module.exports = {
return this.getStorageOption(type + 'StorageTableName', storageTableName[type]);
},

getSchema (type) {
return this.getStorageOption(type + 'StorageTableSchema', undefined);
},

getStorageOptions (type, extraOptions) {
const options = {};

if (this.getStorage(type) === 'json') {
options.path = this.getStoragePath(type);
} else if (this.getStorage(type) === 'sequelize') {
options.tableName = this.getTableName(type);
options.schema = this.getSchema(type);
}

_.assign(options, extraOptions);
Expand Down
29 changes: 29 additions & 0 deletions test/db/migrate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,35 @@ const _ = require('lodash');
});
});
});

describe('custom meta schema', () => {
it('correctly uses the defined schema', function (done) {
const self = this;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self = this not required with arrow functions


prepare(() => {
if (Support.dialectIsPostgres()) {
helpers.readSchemas(self.sequelize, schemas => {
expect(schemas.sort()).to.eql(['sequelize_schema']);

// Tables from public should still be the same.
helpers.readTables(self.sequelize, tables => {
expect(tables.sort()).to.eql(['Person', 'Task']);
done();
});
});
} else {
// If not Postgres, the schema option gets prepended to the table name.
helpers.readTables(self.sequelize, tables => {
expect(tables.sort()).to.eql(['Person', 'Task', 'sequelize_schema.SequelizeMeta']);
done();
});
}
}, {
migrationFile: 'new/*createPerson',
config: { migrationStorageTableSchema: 'sequelize_schema' }
});
});
});
});
});

Expand Down
8 changes: 8 additions & 0 deletions test/support/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@ module.exports = {
});
},

readSchemas: function (sequelize, callback) {
return sequelize
.showAllSchemas()
.then(function (schemas) {
return callback(schemas.sort());
});
},

countTable: function (sequelize, table, callback) {
var QueryGenerator = sequelize.getQueryInterface().QueryGenerator;

Expand Down
69 changes: 49 additions & 20 deletions test/support/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var _ = require('lodash');
var Bluebird = require('bluebird');
var DataTypes = Sequelize;
var Config = require(__dirname + '/config/config');
var expect = require('expect.js');
Expand Down Expand Up @@ -90,27 +91,55 @@ var Support = {
},

clearDatabase: function (sequelize, callback) {
sequelize
.getQueryInterface()
.dropAllTables()
.then(function () {
if (sequelize.daoFactoryManager) {
sequelize.daoFactoryManager.daos = [];
} else {
sequelize.modelManager.models = [];
}

return sequelize
.getQueryInterface()
.dropAllEnums()
.then(callback)
.catch(function (err) {
console.log('Error in support.clearDatabase() dropAllEnums() :: ', err);
function dropAllTables() {
return sequelize
.getQueryInterface()
.dropAllTables()
.then(function () {
if (sequelize.daoFactoryManager) {
sequelize.daoFactoryManager.daos = [];
} else {
sequelize.modelManager.models = [];
}

return sequelize
.getQueryInterface()
.dropAllEnums()
.then(callback)
.catch(function (err) {
console.log('Error in support.clearDatabase() dropAllEnums() :: ', err);
});
})
.catch(function (err) {
console.log('Error in support.clearDatabase() dropAllTables() :: ', err);
});
};

// If Postgres, loop through each of the non-public schemas and DROP/re-CREATE them.
if (this.dialectIsPostgres()) {
sequelize
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think tests are failing because of missing return

.showAllSchemas()
.then(function (schemas) {
// showAllSchemas() leaves off the public schema.
let searchPathSchemas = schemas.join(', ');
let promise = Bluebird.resolve();

_.forEach(schemas, function (schema) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Promise.map + Promise.all combination rather than forEach for better readability

promise = promise.then(function () {
return sequelize
.dropSchema(schema)
.then(function() {
return sequelize.createSchema(schema)
});
});
})
.catch(function (err) {
console.log('Error in support.clearDatabase() dropAllTables() :: ', err);
});
});

// Drop the public schema tables.
promise.then(dropAllTables);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return the promise

});
} else {
return dropAllTables();
}
},

getSupportedDialects: function () {
Expand Down