fix compare of foreign keys for autoupdate (#272)

* fix compare of foreign keys for autoupdate

use mysql table name in case it is not equal model name

* fix column name lookup for fk definition

* fix ADD CONSTRAINT for multiple fk

if more the one foreign key added ADD CONSTRAINT
must be separated with comma but not with space as applySqlChanges do.

* fix duplicate foreign key creation on autoupdate

* fix entity name selection

* change join to toString as requested

* fix removing dropped keys

* fix linter issues

* add test case with columnName in foreign key

and isActual check after autoupdate

* uncommit accitenally commited test case
This commit is contained in:
Sergey Nosenko 2017-05-06 02:13:23 +03:00 committed by Sakib Hasan
parent 204242663e
commit 72abcb8e9f
2 changed files with 342 additions and 326 deletions

View File

@ -73,7 +73,12 @@ function mixinMigration(MySQL, mysql) {
//if we already have a definition, update this table
self.alterTable(model, fields, indexes, foreignKeys, function(err, result) {
if (!err) {
self.addForeignKeys(model, function(err, result) {
//foreignKeys is a list of EXISTING fkeys here, so you don't need to recreate them again
//prepare fkSQL for new foreign keys
var fkSQL = self.getForeignKeySQL(model,
self.getModelDefinition(model).settings.foreignKeys,
foreignKeys);
self.addForeignKeys(model, fkSQL, function(err, result) {
done(err);
});
} else {
@ -390,14 +395,20 @@ function mixinMigration(MySQL, mysql) {
return sql;
};
MySQL.prototype.getForeignKeySQL = function(model, actualFks) {
MySQL.prototype.getForeignKeySQL = function(model, actualFks, existingFks) {
var self = this;
var m = this.getModelDefinition(model);
var addFksSql = [];
existingFks = existingFks || [];
if (actualFks) {
var keys = Object.keys(actualFks);
for (var i = 0; i < keys.length; i++) {
//all existing fks are already checked in MySQL.prototype.dropForeignKeys
//so we need check only names - skip if found
if (existingFks.filter(function(fk) {
return fk.fkName === keys[i];
}).length > 0) continue;
var constraint = self.buildForeignKeyDefinition(model, keys[i]);
if (constraint) {
@ -423,7 +434,7 @@ function mixinMigration(MySQL, mysql) {
fkSQL = self.getForeignKeySQL(model, newFks);
}
if (fkSQL && fkSQL.length) {
self.applySqlChanges(model, fkSQL, function(err, result) {
self.applySqlChanges(model, [fkSQL.toString()], function(err, result) {
if (err) cb(err);
else
cb(null, result);
@ -449,7 +460,8 @@ function mixinMigration(MySQL, mysql) {
var fkCol = expectedColNameForModel(newFk.foreignKey, m);
var fkEntity = self.getModelDefinition(newFk.entity);
var fkRefKey = expectedColNameForModel(newFk.entityKey, fkEntity);
var fkRefTable = newFk.entity.name; //TODO check for mysql name
var fkEntityName = (typeof newFk.entity === 'object') ? newFk.entity.name : newFk.entity;
var fkRefTable = self.table(fkEntityName);
needsToDrop = fkCol != fk.fkColumnName ||
fkRefKey != fk.pkColumnName ||
fkRefTable != fk.pkTableName;
@ -464,8 +476,9 @@ function mixinMigration(MySQL, mysql) {
});
//update out list of existing keys by removing dropped keys
fks = actualFks.filter(function(k) {
return removedFks.indexOf(k) == -1;
removedFks.forEach(function(k) {
var index = actualFks.indexOf(k);
if (index !== -1) actualFks.splice(index, 1);
});
}
return sql;
@ -547,7 +560,7 @@ function mixinMigration(MySQL, mysql) {
//verify that the other model in the same DB
if (this._models[fkEntityName]) {
return ' CONSTRAINT ' + this.client.escapeId(fk.name) +
' FOREIGN KEY (' + fk.foreignKey + ')' +
' FOREIGN KEY (`' + expectedColNameForModel(fk.foreignKey, definition) + '`)' +
' REFERENCES ' + this.tableEscaped(fkEntityName) +
'(' + this.client.escapeId(fk.entityKey) + ')';
}

View File

@ -18,8 +18,7 @@ describe('MySQL connector', function() {
});
it('should auto migrate/update tables', function(done) {
var schema_v1 =
{
var schema_v1 = {
'name': 'CustomerTest',
'options': {
'idInjection': false,
@ -74,8 +73,7 @@ describe('MySQL connector', function() {
},
};
var schema_v2 =
{
var schema_v2 = {
'name': 'CustomerTest',
'options': {
'idInjection': false,
@ -229,8 +227,7 @@ describe('MySQL connector', function() {
});
it('should auto migrate/update foreign keys in tables', function(done) {
var customer2_schema =
{
var customer2_schema = {
'name': 'CustomerTest2',
'options': {
'idInjection': false,
@ -261,8 +258,7 @@ describe('MySQL connector', function() {
},
},
};
var customer3_schema =
{
var customer3_schema = {
'name': 'CustomerTest3',
'options': {
'idInjection': false,
@ -294,8 +290,7 @@ describe('MySQL connector', function() {
},
};
var schema_v1 =
{
var schema_v1 = {
'name': 'OrderTest',
'options': {
'idInjection': false,
@ -321,7 +316,6 @@ describe('MySQL connector', function() {
'customerId': {
'type': 'String',
'length': 20,
'id': 1,
},
'description': {
'type': 'String',
@ -331,8 +325,7 @@ describe('MySQL connector', function() {
},
};
var schema_v2 =
{
var schema_v2 = {
'name': 'OrderTest',
'options': {
'idInjection': false,
@ -358,7 +351,9 @@ describe('MySQL connector', function() {
'customerId': {
'type': 'String',
'length': 20,
'id': 1,
'mysql': {
'columnName': 'customer_id',
},
},
'description': {
'type': 'String',
@ -368,8 +363,7 @@ describe('MySQL connector', function() {
},
};
var schema_v3 =
{
var schema_v3 = {
'name': 'OrderTest',
'options': {
'idInjection': false,
@ -387,7 +381,9 @@ describe('MySQL connector', function() {
'customerId': {
'type': 'String',
'length': 20,
'id': 1,
'mysql': {
'columnName': 'customer_id',
},
},
'description': {
'type': 'String',
@ -408,7 +404,8 @@ describe('MySQL connector', function() {
ds.createModel(schema_v1.name, schema_v1.properties, schema_v1.options);
//do initial update/creation of table
ds.autoupdate(function() {
ds.autoupdate(function(err) {
assert(!err, err);
ds.discoverModelProperties('order_test', function(err, props) {
//validate that we have the correct number of properties
assert.equal(props.length, 3);
@ -429,6 +426,11 @@ describe('MySQL connector', function() {
ds.autoupdate(function(err, result) {
if (err) return done(err);
//should be actual after autoupdate
ds.isActual(function(err, isEqual) {
if (err) return done(err);
assert(!isEqual);
//get and validate the properties on this model
ds.discoverModelProperties('order_test', function(err, props) {
if (err) return done(err);
@ -442,7 +444,7 @@ describe('MySQL connector', function() {
assert(updatedForeignKeys);
assert(updatedForeignKeys.length.should.be.equal(1));
assert.equal(updatedForeignKeys[0].REFERENCED_TABLE_NAME, 'customer_test2');
assert.equal(updatedForeignKeys[0].COLUMN_NAME, 'customerId');
assert.equal(updatedForeignKeys[0].COLUMN_NAME, 'customer_id');
assert.equal(updatedForeignKeys[0].CONSTRAINT_NAME, 'fk_ordertest_customerId');
assert.equal(updatedForeignKeys[0].REFERENCED_COLUMN_NAME, 'id');
@ -473,6 +475,7 @@ describe('MySQL connector', function() {
});
});
});
});
function setupAltColNameData() {
var schema = {