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

Commit fba11cef by Sushant Committed by GitHub

fix(UnknownConstraintError): improper handling of error options (#9547)

1 parent d46e2070
......@@ -125,31 +125,6 @@ class AbstractQuery {
return 'insertId';
}
/**
* Iterate over all known tables and search their names inside the sql query.
* This method will also check association aliases ('as' option).
*
* @param {String} attribute An attribute of a SQL query. (?)
* @return {String} The found tableName / alias.
* @private
*/
findTableNameInAttribute(attribute) {
if (!this.options.include) {
return null;
}
if (!this.options.includeNames) {
this.options.includeNames = this.options.include.map(include => include.as);
}
const tableNames = this.options.includeNames.filter(include => attribute.indexOf(include + '.') === 0);
if (tableNames.length === 1) {
return tableNames[0];
} else {
return null;
}
}
getUniqueConstraintErrorMessage(field) {
let message = field + ' must be unique';
......
......@@ -262,6 +262,7 @@ class Query extends AbstractQuery {
formatError(err) {
let match;
match = err.message.match(/Violation of (?:UNIQUE|PRIMARY) KEY constraint '((.|\s)*)'. Cannot insert duplicate key in object '.*'.(:? The duplicate key value is \((.*)\).)?/);
match = match || err.message.match(/Cannot insert duplicate key row in object .* with unique index '(.*)'/);
if (match && match.length > 1) {
......@@ -310,9 +311,18 @@ class Query extends AbstractQuery {
}
match = err.message.match(/Could not drop constraint. See previous errors./);
if (match && match.length > 0) {
return new sequelizeErrors.UnknownConstraintError(match[1]);
let constraint = err.sql.match(/(?:constraint|index) \[(.+?)\]/i);
constraint = constraint ? constraint[1] : undefined;
let table = err.sql.match(/table \[(.+?)\]/i);
table = table ? table[1] : undefined;
return new sequelizeErrors.UnknownConstraintError({
message: match[1],
constraint,
table,
parent: err
});
}
return new sequelizeErrors.DatabaseError(err);
......
......@@ -9,7 +9,7 @@
*/
const _ = require('lodash');
const UnknownConstraintError = require('../../errors').UnknownConstraintError;
const sequelizeErrors = require('../../errors');
/**
A wrapper that fixes MySQL's inability to cleanly remove columns from existing tables if they have a foreign key constraint.
......@@ -67,7 +67,11 @@ function removeConstraint(tableName, constraintName, options) {
query = this.QueryGenerator.removeIndexQuery(constraint.tableName, constraint.constraintName);
}
} else {
throw new UnknownConstraintError(`Constraint ${constraintName} on table ${tableName} does not exist`);
throw new sequelizeErrors.UnknownConstraintError({
message: `Constraint ${constraintName} on table ${tableName} does not exist`,
constraint: constraintName,
table: tableName
});
}
return this.sequelize.query(query, options);
......
......@@ -347,14 +347,18 @@ class Query extends AbstractQuery {
});
case '42704':
if (err.sql && /CONSTRAINT/gi.test(err.sql)) {
if (err.sql && /(CONSTRAINT|INDEX)/gi.test(err.sql)) {
message = 'Unknown constraint error';
index = errMessage.match(/(?:constraint|index) \"(.+?)\"/i);
index = index ? index[1] : undefined;
table = errMessage.match(/relation \"(.+?)\"/i);
table = table ? table[1] : undefined;
throw new sequelizeErrors.UnknownConstraintError({
message,
constraint: err.constraint,
constraint: index,
fields,
table: err.table,
table,
parent: err
});
}
......
......@@ -2,7 +2,7 @@
const _ = require('lodash');
const Promise = require('../../promise');
const UnknownConstraintError = require('../../errors').UnknownConstraintError;
const sequelizeErrors = require('../../errors');
/**
Returns an object that treats SQLite's inabilities to do certain queries.
......@@ -131,7 +131,11 @@ function removeConstraint(tableName, constraintName, options) {
return this.describeTable(tableName, options);
} else {
throw new UnknownConstraintError(`Constraint ${constraintName} on table ${tableName} does not exist`);
throw new sequelizeErrors.UnknownConstraintError({
message: `Constraint ${constraintName} on table ${tableName} does not exist`,
constraint: constraintName,
table: tableName
});
}
})
.then(fields => {
......
......@@ -210,11 +210,17 @@ exports.ExclusionConstraintError = ExclusionConstraintError;
* Thrown when constraint name is not found in the database
*/
class UnknownConstraintError extends DatabaseError {
constructor(message) {
const parent = { message };
super(parent);
constructor(options) {
options = options || {};
options.parent = options.parent || { sql: '' };
super(options.parent);
this.name = 'SequelizeUnknownConstraintError';
this.message = message || 'The specified constraint does not exist';
this.message = options.message || 'The specified constraint does not exist';
this.constraint = options.constraint;
this.fields = options.fields;
this.table = options.table;
Error.captureStackTrace(this, this.constructor);
}
}
......
......@@ -770,11 +770,20 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => {
});
});
describe('error handling', () => {
describe('unknown constraint', () => {
it('should throw non existent constraints as UnknownConstraintError', function() {
return expect(this.queryInterface.removeConstraint('users', 'unknown__contraint__name', {
type: 'unique'
})).to.eventually.be.rejectedWith(Sequelize.UnknownConstraintError);
const promise = this.queryInterface
.removeConstraint('users', 'unknown__constraint__name', {
type: 'unique'
})
.catch(e => {
expect(e.table).to.equal('users');
expect(e.constraint).to.equal('unknown__constraint__name');
throw e;
});
return expect(promise).to.eventually.be.rejectedWith(Sequelize.UnknownConstraintError);
});
});
});
......
......@@ -6,7 +6,7 @@ const expect = require('chai').expect;
describe('errors', () => {
it('should maintain stack trace with message', () => {
const errorsWithMessage = [
'BaseError', 'ValidationError', 'UnknownConstraintError', 'InstanceError',
'BaseError', 'ValidationError', 'InstanceError',
'EmptyResultError', 'EagerLoadingError', 'AssociationError', 'QueryError'
];
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!