不要怂,就是干,撸起袖子干!

Commit 0abea9f9 by Sushant Committed by GitHub

fix(indexes): duplicate unique indexes with sync (#9033)

1 parent d92d0d5a
......@@ -55,8 +55,7 @@ const QueryGenerator = {
const query = "IF OBJECT_ID('<%= table %>', 'U') IS NULL CREATE TABLE <%= table %> (<%= attributes %>)",
primaryKeys = [],
foreignKeys = {},
attrStr = [],
self = this;
attrStr = [];
for (const attr in attributes) {
if (attributes.hasOwnProperty(attr)) {
......@@ -93,15 +92,17 @@ const QueryGenerator = {
if (options.uniqueKeys) {
_.each(options.uniqueKeys, (columns, indexName) => {
if (!_.isString(indexName)) {
indexName = 'uniq_' + tableName + '_' + columns.fields.join('_');
if (columns.customIndex) {
if (!_.isString(indexName)) {
indexName = 'uniq_' + tableName + '_' + columns.fields.join('_');
}
values.attributes += `, CONSTRAINT ${this.quoteIdentifier(indexName)} UNIQUE (${columns.fields.map(field => this.quoteIdentifier(field)).join(', ')})`;
}
values.attributes += ', CONSTRAINT ' + self.quoteIdentifier(indexName) + ' UNIQUE (' + _.map(columns.fields, self.quoteIdentifier).join(', ') + ')';
});
}
if (pkString.length > 0) {
values.attributes += ', PRIMARY KEY (' + pkString + ')';
values.attributes += `, PRIMARY KEY (${pkString})`;
}
for (const fkey in foreignKeys) {
......
......@@ -80,17 +80,17 @@ const QueryGenerator = {
if (options.uniqueKeys) {
_.each(options.uniqueKeys, (columns, indexName) => {
if (!columns.singleField) { // If it's a single field it's handled in column def, not as an index
if (columns.customIndex) {
if (!_.isString(indexName)) {
indexName = 'uniq_' + tableName + '_' + columns.fields.join('_');
}
values.attributes += ', UNIQUE ' + this.quoteIdentifier(indexName) + ' (' + _.map(columns.fields, this.quoteIdentifier).join(', ') + ')';
values.attributes += `, UNIQUE ${this.quoteIdentifier(indexName)} (${columns.fields.map(field => this.quoteIdentifier(field)).join(', ')})`;
}
});
}
if (pkString.length > 0) {
values.attributes += ', PRIMARY KEY (' + pkString + ')';
values.attributes += `, PRIMARY KEY (${pkString})`;
}
for (const fkey in foreignKeys) {
......
......@@ -39,9 +39,7 @@ const QueryGenerator = {
},
createTableQuery(tableName, attributes, options) {
options = _.extend({
}, options || {});
options = _.extend({}, options || {});
//Postgres 9.0 does not support CREATE TABLE IF NOT EXISTS, 9.1 and above do
const databaseVersion = _.get(this, 'sequelize.options.databaseVersion', 0);
......@@ -72,8 +70,8 @@ const QueryGenerator = {
if (options.uniqueKeys) {
_.each(options.uniqueKeys, columns => {
if (!columns.singleField) { // If it's a single field it's handled in column def, not as an index
values.attributes += ', UNIQUE (' + columns.fields.map(f => this.quoteIdentifiers(f)).join(', ') + ')';
if (columns.customIndex) {
values.attributes += `, UNIQUE (${columns.fields.map(field => this.quoteIdentifier(field)).join(', ')})`;
}
});
}
......@@ -86,7 +84,7 @@ const QueryGenerator = {
}, []).join(',');
if (pks.length > 0) {
values.attributes += ', PRIMARY KEY (' + pks + ')';
values.attributes += `, PRIMARY KEY (${pks})`;
}
return `CREATE TABLE ${databaseVersion === 0 || semver.gte(databaseVersion, '9.1.0') ? 'IF NOT EXISTS ' : ''}${values.table} (${values.attributes})${values.comments};`;
......
......@@ -61,14 +61,14 @@ const QueryGenerator = {
if (options.uniqueKeys) {
_.each(options.uniqueKeys, columns => {
if (!columns.singleField) { // If it's a single field it's handled in column def, not as an index
attrStr += ', UNIQUE (' + columns.fields.map(field => this.quoteIdentifier(field)).join(', ') + ')';
if (columns.customIndex) {
attrStr += `, UNIQUE (${columns.fields.map(field => this.quoteIdentifier(field)).join(', ')})`;
}
});
}
if (pkString.length > 0) {
attrStr += ', PRIMARY KEY (' + pkString + ')';
attrStr += `, PRIMARY KEY (${pkString})`;
}
const sql = `CREATE TABLE IF NOT EXISTS ${table} (${attrStr});`;
......
......@@ -994,7 +994,10 @@ class Model {
if (definition.hasOwnProperty('unique') && definition.unique) {
let idxName;
if (typeof definition.unique === 'object' && definition.unique.hasOwnProperty('name')) {
if (
typeof definition.unique === 'object' &&
definition.unique.hasOwnProperty('name')
) {
idxName = definition.unique.name;
} else if (typeof definition.unique === 'string') {
idxName = definition.unique;
......@@ -1002,12 +1005,13 @@ class Model {
idxName = this.tableName + '_' + name + '_unique';
}
let idx = this.options.uniqueKeys[idxName] || { fields: [] };
idx = idx || {fields: [], msg: null};
const idx = this.options.uniqueKeys[idxName] || { fields: [] };
idx.fields.push(definition.field);
idx.msg = idx.msg || definition.unique.msg || null;
idx.name = idxName || false;
idx.column = name;
idx.customIndex = definition.unique !== true;
this.options.uniqueKeys[idxName] = idx;
}
......@@ -1025,6 +1029,7 @@ class Model {
delete definition.index;
}
});
// Create a map of field to attribute names
this.fieldAttributeMap = _.reduce(this.fieldRawAttributesMap, (map, value, key) => {
if (key !== value.fieldName) {
......
......@@ -79,7 +79,7 @@ describe(Support.getTestDialectTeaser('InstanceValidator'), () => {
it('should enforce a unique constraint', function() {
const Model = this.sequelize.define('model', {
uniqueName: { type: Sequelize.STRING, unique: true }
uniqueName: { type: Sequelize.STRING, unique: 'uniqueName' }
});
const records = [
{ uniqueName: 'unique name one' },
......
......@@ -3,7 +3,8 @@
const chai = require('chai'),
Sequelize = require('../../../index'),
expect = chai.expect,
Support = require(__dirname + '/../support');
Support = require(__dirname + '/../support'),
dialect = Support.getTestDialect();
describe(Support.getTestDialectTeaser('Model'), () => {
describe('sync', () => {
......@@ -127,5 +128,148 @@ describe(Support.getTestDialectTeaser('Model'), () => {
return this.sequelize.sync({ alter: true })
.then(() => this.sequelize.sync({ alter: true }));
});
describe('indexes', () => {
it('should create only one unique index for unique:true column', function() {
const User = this.sequelize.define('testSync', {
email: {
type: Sequelize.STRING,
unique: true
}
});
return User.sync({ force: true }).then(() => {
return this.sequelize.getQueryInterface().showIndex(User.getTableName());
}).then(results => {
if (dialect === 'sqlite') {
// SQLite doesn't treat primary key as index
expect(results).to.have.length(1);
} else {
expect(results).to.have.length(2);
expect(results.filter(r => r.primary)).to.have.length(1);
}
expect(results.filter(r => r.unique === true && r.primary === false)).to.have.length(1);
});
});
it('should create only one unique index for unique:true columns', function() {
const User = this.sequelize.define('testSync', {
email: {
type: Sequelize.STRING,
unique: true
},
phone: {
type: Sequelize.STRING,
unique: true
}
});
return User.sync({ force: true }).then(() => {
return this.sequelize.getQueryInterface().showIndex(User.getTableName());
}).then(results => {
if (dialect === 'sqlite') {
// SQLite doesn't treat primary key as index
expect(results).to.have.length(2);
} else {
expect(results).to.have.length(3);
expect(results.filter(r => r.primary)).to.have.length(1);
}
expect(results.filter(r => r.unique === true && r.primary === false)).to.have.length(2);
});
});
it('should create only one unique index for unique:true columns taking care of options.indexes', function() {
const User = this.sequelize.define('testSync', {
email: {
type: Sequelize.STRING,
unique: true
},
phone: {
type: Sequelize.STRING,
unique: true
}
}, {
indexes: [
{ name: 'wow_my_index', fields: ['email', 'phone'], unique: true }
]
});
return User.sync({ force: true }).then(() => {
return this.sequelize.getQueryInterface().showIndex(User.getTableName());
}).then(results => {
if (dialect === 'sqlite') {
// SQLite doesn't treat primary key as index
expect(results).to.have.length(3);
} else {
expect(results).to.have.length(4);
expect(results.filter(r => r.primary)).to.have.length(1);
}
expect(results.filter(r => r.unique === true && r.primary === false)).to.have.length(3);
expect(results.filter(r => r.name === 'wow_my_index')).to.have.length(1);
});
});
it('should create only one unique index for unique:name column', function() {
const User = this.sequelize.define('testSync', {
email: {
type: Sequelize.STRING,
unique: 'wow_my_index'
}
});
return User.sync({ force: true }).then(() => {
return this.sequelize.getQueryInterface().showIndex(User.getTableName());
}).then(results => {
if (dialect === 'sqlite') {
// SQLite doesn't treat primary key as index
expect(results).to.have.length(1);
} else {
expect(results).to.have.length(2);
expect(results.filter(r => r.primary)).to.have.length(1);
}
expect(results.filter(r => r.unique === true && r.primary === false)).to.have.length(1);
if (['postgres', 'sqlite'].indexOf(dialect) === -1) {
// Postgres/SQLite doesn't support naming indexes in create table
expect(results.filter(r => r.name === 'wow_my_index')).to.have.length(1);
}
});
});
it('should create only one unique index for unique:name columns', function() {
const User = this.sequelize.define('testSync', {
email: {
type: Sequelize.STRING,
unique: 'wow_my_index'
},
phone: {
type: Sequelize.STRING,
unique: 'wow_my_index'
}
});
return User.sync({ force: true }).then(() => {
return this.sequelize.getQueryInterface().showIndex(User.getTableName());
}).then(results => {
if (dialect === 'sqlite') {
// SQLite doesn't treat primary key as index
expect(results).to.have.length(1);
} else {
expect(results).to.have.length(2);
expect(results.filter(r => r.primary)).to.have.length(1);
}
expect(results.filter(r => r.unique === true && r.primary === false)).to.have.length(1);
if (['postgres', 'sqlite'].indexOf(dialect) === -1) {
// Postgres/SQLite doesn't support naming indexes in create table
expect(results.filter(r => r.name === 'wow_my_index')).to.have.length(1);
}
});
});
});
});
});
......@@ -8,13 +8,6 @@ const dialect = Support.getTestDialect();
const Sequelize = Support.Sequelize;
const current = Support.sequelize;
const _ = require('lodash');
let count = 0;
const log = function() {
// sqlite fires a lot more querys than the other dbs. this is just a simple hack, since i'm lazy
if (dialect !== 'sqlite' || count === 0) {
count++;
}
};
describe(Support.getTestDialectTeaser('QueryInterface'), () => {
beforeEach(function() {
......@@ -451,148 +444,6 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => {
});
});
describe('changeColumn', () => {
it('should support schemas', function() {
return this.sequelize.createSchema('archive').bind(this).then(function() {
return this.queryInterface.createTable({
tableName: 'users',
schema: 'archive'
}, {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
currency: DataTypes.INTEGER
}).bind(this).then(function() {
return this.queryInterface.changeColumn({
tableName: 'users',
schema: 'archive'
}, 'currency', {
type: DataTypes.FLOAT
});
}).then(function() {
return this.queryInterface.describeTable({
tableName: 'users',
schema: 'archive'
});
}).then(table => {
if (dialect === 'postgres' || dialect === 'postgres-native') {
expect(table.currency.type).to.equal('DOUBLE PRECISION');
} else {
expect(table.currency.type).to.equal('FLOAT');
}
});
});
});
it('should change columns', function() {
return this.queryInterface.createTable({
tableName: 'users'
}, {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
currency: DataTypes.INTEGER
}).bind(this).then(function() {
return this.queryInterface.changeColumn('users', 'currency', {
type: DataTypes.FLOAT,
allowNull: true
});
}).then(function() {
return this.queryInterface.describeTable({
tableName: 'users'
});
}).then(table => {
if (dialect === 'postgres' || dialect === 'postgres-native') {
expect(table.currency.type).to.equal('DOUBLE PRECISION');
} else {
expect(table.currency.type).to.equal('FLOAT');
}
});
});
// MSSQL doesn't support using a modified column in a check constraint.
// https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql
if (dialect !== 'mssql') {
it('should work with enums', function() {
return this.queryInterface.createTable({
tableName: 'users'
}, {
firstName: DataTypes.STRING
}).bind(this).then(function() {
return this.queryInterface.changeColumn('users', 'firstName', {
type: DataTypes.ENUM(['value1', 'value2', 'value3'])
});
});
});
it('should work with enums with schemas', function() {
return this.sequelize.createSchema('archive').bind(this).then(function() {
return this.queryInterface.createTable({
tableName: 'users',
schema: 'archive'
}, {
firstName: DataTypes.STRING
});
}).bind(this).then(function() {
return this.queryInterface.changeColumn({
tableName: 'users',
schema: 'archive'
}, 'firstName', {
type: DataTypes.ENUM(['value1', 'value2', 'value3'])
});
});
});
}
});
//SQlite navitely doesnt support ALTER Foreign key
if (dialect !== 'sqlite') {
describe('should support foreign keys', () => {
beforeEach(function() {
return this.queryInterface.createTable('users', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
level_id: {
type: DataTypes.INTEGER,
allowNull: false
}
})
.bind(this).then(function() {
return this.queryInterface.createTable('level', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
}
});
});
});
it('able to change column to foreign key', function() {
return this.queryInterface.changeColumn('users', 'level_id', {
type: DataTypes.INTEGER,
references: {
model: 'level',
key: 'id'
},
onUpdate: 'cascade',
onDelete: 'cascade'
}, {logging: log}).then(() => {
expect(count).to.be.equal(1);
count = 0;
});
});
});
}
describe('addColumn', () => {
beforeEach(function() {
return this.sequelize.createSchema('archive').bind(this).then(function() {
......@@ -669,181 +520,6 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => {
});
});
describe('removeColumn', () => {
describe('(without a schema)', () => {
beforeEach(function() {
return this.queryInterface.createTable('users', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
firstName: {
type: DataTypes.STRING,
defaultValue: 'Someone'
},
lastName: {
type: DataTypes.STRING
},
manager: {
type: DataTypes.INTEGER,
references: {
model: 'users',
key: 'id'
}
},
email: {
type: DataTypes.STRING,
unique: true
}
});
});
it('should be able to remove a column with a default value', function() {
return this.queryInterface.removeColumn('users', 'firstName').bind(this).then(function() {
return this.queryInterface.describeTable('users');
}).then(table => {
expect(table).to.not.have.property('firstName');
});
});
it('should be able to remove a column without default value', function() {
return this.queryInterface.removeColumn('users', 'lastName').bind(this).then(function() {
return this.queryInterface.describeTable('users');
}).then(table => {
expect(table).to.not.have.property('lastName');
});
});
it('should be able to remove a column with a foreign key constraint', function() {
return this.queryInterface.removeColumn('users', 'manager').bind(this).then(function() {
return this.queryInterface.describeTable('users');
}).then(table => {
expect(table).to.not.have.property('manager');
});
});
it('should be able to remove a column with primaryKey', function() {
return this.queryInterface.removeColumn('users', 'manager').bind(this).then(function() {
return this.queryInterface.describeTable('users');
}).then(function(table) {
expect(table).to.not.have.property('manager');
return this.queryInterface.removeColumn('users', 'id');
}).then(function() {
return this.queryInterface.describeTable('users');
}).then(table => {
expect(table).to.not.have.property('id');
});
});
// From MSSQL documentation on ALTER COLUMN:
// The modified column cannot be any one of the following:
// - Used in a CHECK or UNIQUE constraint.
// https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql#arguments
if (dialect !== 'mssql') {
it('should be able to remove a column with unique contraint', function() {
return this.queryInterface.removeColumn('users', 'email').bind(this).then(function() {
return this.queryInterface.describeTable('users');
}).then(table => {
expect(table).to.not.have.property('email');
});
});
}
});
describe('(with a schema)', () => {
beforeEach(function() {
return this.sequelize.createSchema('archive').bind(this).then(function() {
return this.queryInterface.createTable({
tableName: 'users',
schema: 'archive'
}, {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
firstName: {
type: DataTypes.STRING,
defaultValue: 'Someone'
},
lastName: {
type: DataTypes.STRING
},
email: {
type: DataTypes.STRING,
unique: true
}
});
});
});
it('should be able to remove a column with a default value', function() {
return this.queryInterface.removeColumn({
tableName: 'users',
schema: 'archive'
}, 'firstName'
).bind(this).then(function() {
return this.queryInterface.describeTable({
tableName: 'users',
schema: 'archive'
});
}).then(table => {
expect(table).to.not.have.property('firstName');
});
});
it('should be able to remove a column without default value', function() {
return this.queryInterface.removeColumn({
tableName: 'users',
schema: 'archive'
}, 'lastName'
).bind(this).then(function() {
return this.queryInterface.describeTable({
tableName: 'users',
schema: 'archive'
});
}).then(table => {
expect(table).to.not.have.property('lastName');
});
});
it('should be able to remove a column with primaryKey', function() {
return this.queryInterface.removeColumn({
tableName: 'users',
schema: 'archive'
}, 'id').bind(this).then(function() {
return this.queryInterface.describeTable({
tableName: 'users',
schema: 'archive'
});
}).then(table => {
expect(table).to.not.have.property('id');
});
});
// From MSSQL documentation on ALTER COLUMN:
// The modified column cannot be any one of the following:
// - Used in a CHECK or UNIQUE constraint.
// https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql#arguments
if (dialect !== 'mssql') {
it('should be able to remove a column with unique contraint', function() {
return this.queryInterface.removeColumn({
tableName: 'users',
schema: 'archive'
}, 'email').bind(this).then(function() {
return this.queryInterface.describeTable({
tableName: 'users',
schema: 'archive'
});
}).then(table => {
expect(table).to.not.have.property('email');
});
});
}
});
});
describe('describeForeignKeys', () => {
beforeEach(function() {
return this.queryInterface.createTable('users', {
......
'use strict';
const chai = require('chai');
const expect = chai.expect;
const Support = require(__dirname + '/../support');
const DataTypes = require(__dirname + '/../../../lib/data-types');
const dialect = Support.getTestDialect();
let count = 0;
function log() {
// sqlite fires a lot more querys than the other dbs. this is just a simple hack, since i'm lazy
if (dialect !== 'sqlite' || count === 0) {
count++;
}
};
describe(Support.getTestDialectTeaser('QueryInterface'), () => {
beforeEach(function() {
this.sequelize.options.quoteIdenifiers = true;
this.queryInterface = this.sequelize.getQueryInterface();
});
afterEach(function() {
return this.sequelize.dropAllSchemas();
});
describe('changeColumn', () => {
it('should support schemas', function() {
return this.sequelize.createSchema('archive').bind(this).then(function() {
return this.queryInterface.createTable({
tableName: 'users',
schema: 'archive'
}, {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
currency: DataTypes.INTEGER
}).bind(this).then(function() {
return this.queryInterface.changeColumn({
tableName: 'users',
schema: 'archive'
}, 'currency', {
type: DataTypes.FLOAT
});
}).then(function() {
return this.queryInterface.describeTable({
tableName: 'users',
schema: 'archive'
});
}).then(table => {
if (dialect === 'postgres' || dialect === 'postgres-native') {
expect(table.currency.type).to.equal('DOUBLE PRECISION');
} else {
expect(table.currency.type).to.equal('FLOAT');
}
});
});
});
it('should change columns', function() {
return this.queryInterface.createTable({
tableName: 'users'
}, {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
currency: DataTypes.INTEGER
}).bind(this).then(function() {
return this.queryInterface.changeColumn('users', 'currency', {
type: DataTypes.FLOAT,
allowNull: true
});
}).then(function() {
return this.queryInterface.describeTable({
tableName: 'users'
});
}).then(table => {
if (dialect === 'postgres' || dialect === 'postgres-native') {
expect(table.currency.type).to.equal('DOUBLE PRECISION');
} else {
expect(table.currency.type).to.equal('FLOAT');
}
});
});
// MSSQL doesn't support using a modified column in a check constraint.
// https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql
if (dialect !== 'mssql') {
it('should work with enums', function() {
return this.queryInterface.createTable({
tableName: 'users'
}, {
firstName: DataTypes.STRING
}).bind(this).then(function() {
return this.queryInterface.changeColumn('users', 'firstName', {
type: DataTypes.ENUM(['value1', 'value2', 'value3'])
});
});
});
it('should work with enums with schemas', function() {
return this.sequelize.createSchema('archive').bind(this).then(function() {
return this.queryInterface.createTable({
tableName: 'users',
schema: 'archive'
}, {
firstName: DataTypes.STRING
});
}).bind(this).then(function() {
return this.queryInterface.changeColumn({
tableName: 'users',
schema: 'archive'
}, 'firstName', {
type: DataTypes.ENUM(['value1', 'value2', 'value3'])
});
});
});
}
//SQlite navitely doesnt support ALTER Foreign key
if (dialect !== 'sqlite') {
describe('should support foreign keys', () => {
beforeEach(function() {
return this.queryInterface.createTable('users', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
level_id: {
type: DataTypes.INTEGER,
allowNull: false
}
})
.bind(this).then(function() {
return this.queryInterface.createTable('level', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
}
});
});
});
it('able to change column to foreign key', function() {
return this.queryInterface.changeColumn('users', 'level_id', {
type: DataTypes.INTEGER,
references: {
model: 'level',
key: 'id'
},
onUpdate: 'cascade',
onDelete: 'cascade'
}, {logging: log}).then(() => {
expect(count).to.be.equal(1);
count = 0;
});
});
});
}
});
});
\ No newline at end of file
'use strict';
const chai = require('chai');
const expect = chai.expect;
const Support = require(__dirname + '/../support');
const DataTypes = require(__dirname + '/../../../lib/data-types');
const dialect = Support.getTestDialect();
describe(Support.getTestDialectTeaser('QueryInterface'), () => {
beforeEach(function() {
this.sequelize.options.quoteIdenifiers = true;
this.queryInterface = this.sequelize.getQueryInterface();
});
afterEach(function() {
return this.sequelize.dropAllSchemas();
});
describe('removeColumn', () => {
describe('(without a schema)', () => {
beforeEach(function() {
return this.queryInterface.createTable('users', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
firstName: {
type: DataTypes.STRING,
defaultValue: 'Someone'
},
lastName: {
type: DataTypes.STRING
},
manager: {
type: DataTypes.INTEGER,
references: {
model: 'users',
key: 'id'
}
},
email: {
type: DataTypes.STRING,
unique: true
}
});
});
it('should be able to remove a column with a default value', function() {
return this.queryInterface.removeColumn('users', 'firstName').bind(this).then(function() {
return this.queryInterface.describeTable('users');
}).then(table => {
expect(table).to.not.have.property('firstName');
});
});
it('should be able to remove a column without default value', function() {
return this.queryInterface.removeColumn('users', 'lastName').bind(this).then(function() {
return this.queryInterface.describeTable('users');
}).then(table => {
expect(table).to.not.have.property('lastName');
});
});
it('should be able to remove a column with a foreign key constraint', function() {
return this.queryInterface.removeColumn('users', 'manager').bind(this).then(function() {
return this.queryInterface.describeTable('users');
}).then(table => {
expect(table).to.not.have.property('manager');
});
});
it('should be able to remove a column with primaryKey', function() {
return this.queryInterface.removeColumn('users', 'manager').bind(this).then(function() {
return this.queryInterface.describeTable('users');
}).then(function(table) {
expect(table).to.not.have.property('manager');
return this.queryInterface.removeColumn('users', 'id');
}).then(function() {
return this.queryInterface.describeTable('users');
}).then(table => {
expect(table).to.not.have.property('id');
});
});
// From MSSQL documentation on ALTER COLUMN:
// The modified column cannot be any one of the following:
// - Used in a CHECK or UNIQUE constraint.
// https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql#arguments
if (dialect !== 'mssql') {
it('should be able to remove a column with unique contraint', function() {
return this.queryInterface.removeColumn('users', 'email').bind(this).then(function() {
return this.queryInterface.describeTable('users');
}).then(table => {
expect(table).to.not.have.property('email');
});
});
}
});
describe('(with a schema)', () => {
beforeEach(function() {
return this.sequelize.createSchema('archive').then(() => {
return this.queryInterface.createTable({
tableName: 'users',
schema: 'archive'
}, {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
firstName: {
type: DataTypes.STRING,
defaultValue: 'Someone'
},
lastName: {
type: DataTypes.STRING
},
email: {
type: DataTypes.STRING,
unique: true
}
});
});
});
it('should be able to remove a column with a default value', function() {
return this.queryInterface.removeColumn({
tableName: 'users',
schema: 'archive'
}, 'firstName'
).bind(this).then(function() {
return this.queryInterface.describeTable({
tableName: 'users',
schema: 'archive'
});
}).then(table => {
expect(table).to.not.have.property('firstName');
});
});
it('should be able to remove a column without default value', function() {
return this.queryInterface.removeColumn({
tableName: 'users',
schema: 'archive'
}, 'lastName'
).bind(this).then(function() {
return this.queryInterface.describeTable({
tableName: 'users',
schema: 'archive'
});
}).then(table => {
expect(table).to.not.have.property('lastName');
});
});
it('should be able to remove a column with primaryKey', function() {
return this.queryInterface.removeColumn({
tableName: 'users',
schema: 'archive'
}, 'id').bind(this).then(function() {
return this.queryInterface.describeTable({
tableName: 'users',
schema: 'archive'
});
}).then(table => {
expect(table).to.not.have.property('id');
});
});
// From MSSQL documentation on ALTER COLUMN:
// The modified column cannot be any one of the following:
// - Used in a CHECK or UNIQUE constraint.
// https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql#arguments
if (dialect !== 'mssql') {
it('should be able to remove a column with unique contraint', function() {
return this.queryInterface.removeColumn({
tableName: 'users',
schema: 'archive'
}, 'email').bind(this).then(function() {
return this.queryInterface.describeTable({
tableName: 'users',
schema: 'archive'
});
}).then(table => {
expect(table).to.not.have.property('email');
});
});
}
});
});
});
\ No newline at end of file
......@@ -161,7 +161,7 @@ if (dialect === 'mysql') {
expectation: 'CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `otherId` INTEGER, FOREIGN KEY (`otherId`) REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION) ENGINE=InnoDB;'
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}, {uniqueKeys: [{fields: ['title', 'name']}]}],
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}, {uniqueKeys: [{fields: ['title', 'name'], customIndex: true}]}],
expectation: 'CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), UNIQUE `uniq_myTable_title_name` (`title`, `name`)) ENGINE=InnoDB;'
},
{
......
......@@ -142,7 +142,7 @@ if (dialect === 'sqlite') {
expectation: 'CREATE TABLE IF NOT EXISTS `myTable` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` VARCHAR(255));'
},
{
arguments: ['myTable', {id: 'INTEGER PRIMARY KEY AUTOINCREMENT', name: 'VARCHAR(255)', surname: 'VARCHAR(255)'}, {uniqueKeys: {uniqueConstraint: {fields: ['name', 'surname']}}}],
arguments: ['myTable', {id: 'INTEGER PRIMARY KEY AUTOINCREMENT', name: 'VARCHAR(255)', surname: 'VARCHAR(255)'}, {uniqueKeys: {uniqueConstraint: {fields: ['name', 'surname'], customIndex: true }}}],
expectation: 'CREATE TABLE IF NOT EXISTS `myTable` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` VARCHAR(255), `surname` VARCHAR(255), UNIQUE (`name`, `surname`));'
}
],
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!