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

Commit 8a95e421 by Carlos Weckesser Committed by Sushant

fix(findOrCreate): error with unique constraint when complex where is used (#8093)

1 parent 8de0231f
......@@ -19,3 +19,4 @@ coverage
*.sublime*
esdoc
package-lock.json
yarn.lock
......@@ -829,7 +829,7 @@ class Model {
}
this._hasReadOnlyAttributes = this._readOnlyAttributes && this._readOnlyAttributes.length;
this._isReadOnlyAttribute = Utils._.memoize(key => this._hasReadOnlyAttributes && this._readOnlyAttributes.indexOf(key) !== -1);
this._addDefaultAttributes();
this.refreshAttributes();
this._findAutoIncrementAttribute();
......@@ -847,7 +847,7 @@ class Model {
});
this.options.indexes = this.options.indexes.map(this._conformIndex);
this.sequelize.modelManager.addModel(this);
this.sequelize.runHooks('afterDefine', this);
......@@ -2076,7 +2076,9 @@ class Model {
return [instance, true];
}).catch(this.sequelize.UniqueConstraintError, err => {
const whereFields = Object.keys(options.where).map(name => this.rawAttributes[name].field || name);
const flattenedWhere = Utils.flattenObjectDeep(options.where);
const flattenedWhereKeys = _.map(_.keys(flattenedWhere), name => _.last(_.split(name, '.')));
const whereFields = flattenedWhereKeys.map(name => _.get(this.rawAttributes, `${name}.field`, name));
const defaultFields = options.defaults && Object.keys(options.defaults).map(name => this.rawAttributes[name].field || name);
if (defaultFields) {
......
......@@ -418,6 +418,53 @@ function removeTicks(s, tickChar) {
exports.removeTicks = removeTicks;
/**
* Receives a tree-like object and returns a plain object which depth is 1.
*
* - Input:
*
* {
* name: 'John',
* address: {
* street: 'Fake St. 123',
* coordinates: {
* longitude: 55.6779627,
* latitude: 12.5964313
* }
* }
* }
*
* - Output:
*
* {
* name: 'John',
* address.street: 'Fake St. 123',
* address.coordinates.latitude: 55.6779627,
* address.coordinates.longitude: 12.5964313
* }
*
* @param {object} value Object to be deeply flattened
*/
function flattenObjectDeep(value) {
if (!_.isPlainObject(value)) return value;
const flattenedObj = {};
function flattenObject(obj, subPath) {
Object.keys(obj).forEach(key => {
const pathToProperty = subPath ? `${subPath}.${key}` : `${key}`;
if (typeof obj[key] === 'object') {
flattenObject(obj[key], flattenedObj, pathToProperty);
} else {
flattenedObj[pathToProperty] = _.get(obj, key);
}
});
return flattenedObj;
}
return flattenObject(value, undefined);
}
exports.flattenObjectDeep = flattenObjectDeep;
/**
* Utility functions for representing SQL functions, and columns that should be escaped.
* Please do not use these functions directly, use Sequelize.fn and Sequelize.col instead.
* @private
......@@ -515,4 +562,4 @@ exports.mapIsolationLevelStringToTedious = (isolationLevel, tedious) => {
case 'SNAPSHOT':
return tediousIsolationLevel.SNAPSHOT;
}
};
\ No newline at end of file
};
......@@ -104,6 +104,37 @@ describe(Support.getTestDialectTeaser('Model'), () => {
});
});
it('should error correctly when defaults contain a unique key and the where clause is complex', function() {
const User = this.sequelize.define('user', {
objectId: {
type: DataTypes.STRING,
unique: true
},
username: {
type: DataTypes.STRING,
unique: true
}
});
return User.sync({force: true})
.then(() => User.create({ username: 'gottlieb' }))
.then(() => User.findOrCreate({
where: {
$or: [{
objectId: 'asdasdasd1'
}, {
objectId: 'asdasdasd2'
}]
},
defaults: {
username: 'gottlieb'
}
}).catch(error => {
expect(error).to.be.instanceof(Sequelize.UniqueConstraintError);
expect(error.errors[0].path).to.be.a('string', 'username');
}));
});
it('should work with undefined uuid primary key in where', function() {
const User = this.sequelize.define('User', {
id: {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!