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

Commit fba11cef by Sushant Committed by GitHub

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

1 parent d46e2070
...@@ -125,31 +125,6 @@ class AbstractQuery { ...@@ -125,31 +125,6 @@ class AbstractQuery {
return 'insertId'; 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) { getUniqueConstraintErrorMessage(field) {
let message = field + ' must be unique'; let message = field + ' must be unique';
......
...@@ -262,6 +262,7 @@ class Query extends AbstractQuery { ...@@ -262,6 +262,7 @@ class Query extends AbstractQuery {
formatError(err) { formatError(err) {
let match; 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 = 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 '(.*)'/); match = match || err.message.match(/Cannot insert duplicate key row in object .* with unique index '(.*)'/);
if (match && match.length > 1) { if (match && match.length > 1) {
...@@ -310,9 +311,18 @@ class Query extends AbstractQuery { ...@@ -310,9 +311,18 @@ class Query extends AbstractQuery {
} }
match = err.message.match(/Could not drop constraint. See previous errors./); match = err.message.match(/Could not drop constraint. See previous errors./);
if (match && match.length > 0) { 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); return new sequelizeErrors.DatabaseError(err);
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
*/ */
const _ = require('lodash'); 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. 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) { ...@@ -67,7 +67,11 @@ function removeConstraint(tableName, constraintName, options) {
query = this.QueryGenerator.removeIndexQuery(constraint.tableName, constraint.constraintName); query = this.QueryGenerator.removeIndexQuery(constraint.tableName, constraint.constraintName);
} }
} else { } 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); return this.sequelize.query(query, options);
......
...@@ -347,14 +347,18 @@ class Query extends AbstractQuery { ...@@ -347,14 +347,18 @@ class Query extends AbstractQuery {
}); });
case '42704': case '42704':
if (err.sql && /CONSTRAINT/gi.test(err.sql)) { if (err.sql && /(CONSTRAINT|INDEX)/gi.test(err.sql)) {
message = 'Unknown constraint error'; 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({ throw new sequelizeErrors.UnknownConstraintError({
message, message,
constraint: err.constraint, constraint: index,
fields, fields,
table: err.table, table,
parent: err parent: err
}); });
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
const _ = require('lodash'); const _ = require('lodash');
const Promise = require('../../promise'); 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. Returns an object that treats SQLite's inabilities to do certain queries.
...@@ -131,7 +131,11 @@ function removeConstraint(tableName, constraintName, options) { ...@@ -131,7 +131,11 @@ function removeConstraint(tableName, constraintName, options) {
return this.describeTable(tableName, options); return this.describeTable(tableName, options);
} else { } 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 => { .then(fields => {
......
...@@ -210,11 +210,17 @@ exports.ExclusionConstraintError = ExclusionConstraintError; ...@@ -210,11 +210,17 @@ exports.ExclusionConstraintError = ExclusionConstraintError;
* Thrown when constraint name is not found in the database * Thrown when constraint name is not found in the database
*/ */
class UnknownConstraintError extends DatabaseError { class UnknownConstraintError extends DatabaseError {
constructor(message) { constructor(options) {
const parent = { message }; options = options || {};
super(parent); options.parent = options.parent || { sql: '' };
super(options.parent);
this.name = 'SequelizeUnknownConstraintError'; 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); Error.captureStackTrace(this, this.constructor);
} }
} }
......
...@@ -770,11 +770,20 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { ...@@ -770,11 +770,20 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => {
}); });
}); });
describe('error handling', () => { describe('unknown constraint', () => {
it('should throw non existent constraints as UnknownConstraintError', function() { it('should throw non existent constraints as UnknownConstraintError', function() {
return expect(this.queryInterface.removeConstraint('users', 'unknown__contraint__name', { const promise = this.queryInterface
.removeConstraint('users', 'unknown__constraint__name', {
type: 'unique' type: 'unique'
})).to.eventually.be.rejectedWith(Sequelize.UnknownConstraintError); })
.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; ...@@ -6,7 +6,7 @@ const expect = require('chai').expect;
describe('errors', () => { describe('errors', () => {
it('should maintain stack trace with message', () => { it('should maintain stack trace with message', () => {
const errorsWithMessage = [ const errorsWithMessage = [
'BaseError', 'ValidationError', 'UnknownConstraintError', 'InstanceError', 'BaseError', 'ValidationError', 'InstanceError',
'EmptyResultError', 'EagerLoadingError', 'AssociationError', 'QueryError' '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!