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

Commit 6b116691 by Jochem Maas Committed by Sushant

feat(mysql/errors): foreign key errors with more useful information (#8379)

1 parent ccb99dae
......@@ -174,7 +174,9 @@ class Query extends AbstractQuery {
}
formatError(err) {
switch (err.errno || err.code) {
const errCode = err.errno || err.code;
switch (errCode) {
case 1062: {
const match = err.message.match(/Duplicate entry '(.*)' for key '?((.|\s)*?)'?$/);
......@@ -200,24 +202,23 @@ class Query extends AbstractQuery {
return new sequelizeErrors.UniqueConstraintError({message, errors, parent: err, fields});
}
case 1451: {
const match = err.message.match(/FOREIGN KEY \(`(.*)`\) REFERENCES `(.*)` \(`(.*)`\)(?: ON .*)?\)$/);
return new sequelizeErrors.ForeignKeyConstraintError({
fields: null,
index: match ? match[3] : undefined,
parent: err
});
}
case 1451:
case 1452: {
const match = err.message.match(/FOREIGN KEY \(`(.*)`\) REFERENCES `(.*)` \(`(.*)`\)(.*)\)$/);
// e.g. CONSTRAINT `example_constraint_name` FOREIGN KEY (`example_id`) REFERENCES `examples` (`id`)
const match = err.message.match(/CONSTRAINT `(.*)` FOREIGN KEY \(`(.*)`\) REFERENCES `(.*)` \(`(.*)`\)/);
const fields = match ? match[2].split(/`, *`/) : undefined;
return new sequelizeErrors.ForeignKeyConstraintError({
fields: null,
reltype: String(errCode) === '1451' ? 'parent' : 'child',
table: match ? match[3] : undefined,
fields,
value: fields.length && this.instance && this.instance[fields[0]] || undefined,
index: match ? match[1] : undefined,
parent: err
});
}
default:
return new sequelizeErrors.DatabaseError(err);
}
......
......@@ -183,6 +183,7 @@ class ForeignKeyConstraintError extends DatabaseError {
this.table = options.table;
this.value = options.value;
this.index = options.index;
this.reltype = options.reltype;
Error.captureStackTrace(this, this.constructor);
}
}
......
'use strict';
const chai = require('chai');
const expect = chai.expect;
const Support = require(__dirname + '/../../support');
const dialect = Support.getTestDialect();
const DataTypes = require(__dirname + '/../../../../lib/data-types');
if (dialect === 'mysql') {
describe('[MYSQL Specific] Errors', () => {
const validateError = (promise, errClass, errValues) => {
const wanted = Object.assign({}, errValues);
return expect(promise).to.have.been.rejectedWith(errClass).then(() =>
promise.catch(err => Object.keys(wanted).forEach(k => expect(err[k]).to.eql(wanted[k]))));
};
describe('ForeignKeyConstraintError', () => {
beforeEach(function() {
this.Task = this.sequelize.define('task', { title: DataTypes.STRING });
this.User = this.sequelize.define('user', { username: DataTypes.STRING });
this.UserTasks = this.sequelize.define('tasksusers', { userId: DataTypes.INTEGER, taskId: DataTypes.INTEGER });
this.User.belongsToMany(this.Task, { onDelete: 'RESTRICT', through: 'tasksusers' });
this.Task.belongsToMany(this.User, { onDelete: 'RESTRICT', through: 'tasksusers' });
this.Task.belongsTo(this.User, { foreignKey: 'primaryUserId', as: 'primaryUsers' });
});
it('in context of DELETE restriction', function() {
const self = this,
ForeignKeyConstraintError = this.sequelize.ForeignKeyConstraintError;
return this.sequelize.sync({ force: true }).bind({}).then(() => {
return Promise.all([
self.User.create({ id: 67, username: 'foo' }),
self.Task.create({ id: 52, title: 'task' })
]);
}).spread(function(user1, task1) {
this.user1 = user1;
this.task1 = task1;
return user1.setTasks([task1]);
}).then(function() {
return Promise.all([
validateError(this.user1.destroy(), ForeignKeyConstraintError, {
fields: [ 'userId' ],
table: 'users',
value: undefined,
index: 'tasksusers_ibfk_1',
reltype: 'parent'
}),
validateError(this.task1.destroy(), ForeignKeyConstraintError, {
fields: [ 'taskId' ],
table: 'tasks',
value: undefined,
index: 'tasksusers_ibfk_2',
reltype: 'parent'
})
]);
});
});
it('in context of missing relation', function() {
const self = this,
ForeignKeyConstraintError = this.sequelize.ForeignKeyConstraintError;
return this.sequelize.sync({ force: true }).then(() =>
validateError(self.Task.create({ title: 'task', primaryUserId: 5 }), ForeignKeyConstraintError, {
fields: [ 'primaryUserId' ],
table: 'users',
value: 5,
index: 'tasks_ibfk_1',
reltype: 'child'
}));
});
});
});
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!