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

Commit 82b6c505 by Louis-Rémi Babé Committed by Jan Aagaard Meier

Fix upsert behavior to update all _changed_ fields by default (#7523)

* Fix upsert behavior to update all _changed_ fields by default

* Update changelog
1 parent aa7360aa
......@@ -68,6 +68,7 @@
- [REMOVED] Removes support for `{raw: 'injection goes here'}` for order and group. [#7188](https://github.com/sequelize/sequelize/issues/7188)
- [FIXED] `showIndex` breaks with newline characters [#7492](https://github.com/sequelize/sequelize/pull/7492)
- [FIXED] Update or soft delete breaks when querying on `JSON/JSONB` [#7376](https://github.com/sequelize/sequelize/issues/7376) [#7400](https://github.com/sequelize/sequelize/issues/7400) [#7444](https://github.com/sequelize/sequelize/issues/7444)
- [FIXED] Upsert now updates all changed fields by default
## BC breaks:
- Model.validate instance method now runs validation hooks by default. Previously you needed to pass { hooks: true }. You can override this behavior by passing { hooks: false }
......
......@@ -2170,7 +2170,7 @@ class Model {
* @param {Object} values
* @param {Object} [options]
* @param {Boolean} [options.validate=true] Run validations before the row is inserted
* @param {Array} [options.fields=Object.keys(this.attributes)] The fields to insert / update. Defaults to all fields
* @param {Array} [options.fields=Object.keys(this.attributes)] The fields to insert / update. Defaults to all changed fields
* @param {Boolean} [options.hooks=true] Run before / after upsert hooks?
* @param {Transaction} [options.transaction] Transaction to run query under
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
......@@ -2184,15 +2184,15 @@ class Model {
hooks: true
}, Utils.cloneDeep(options || {}));
if (!options.fields) {
options.fields = Object.keys(values);
}
const createdAtAttr = this._timestampAttributes.createdAt;
const updatedAtAttr = this._timestampAttributes.updatedAt;
const hadPrimary = this.primaryKeyField in values || this.primaryKeyAttribute in values;
const instance = this.build(values);
if (!options.fields) {
options.fields = Object.keys(instance._changed);
}
return instance.validate(options).then(() => {
// Map field names
const updatedDataValues = _.pick(instance.dataValues, Object.keys(instance._changed));
......
......@@ -72,7 +72,7 @@
"mysql2": "^1.2.0",
"pg": "^6.1.0",
"pg-hstore": "^2.3.2",
"pg-native": "^1.8.0",
"pg-native": "^1.10.0",
"pg-types": "^1.11.0",
"rimraf": "^2.5.4",
"sinon": "^1.17.6",
......
......@@ -12,8 +12,19 @@ describe(Support.getTestDialectTeaser('Model'), () => {
if (current.dialect.supports.upserts) {
describe('method upsert', () => {
const self = this;
const User = current.define('User', {
name: DataTypes.STRING,
virtualValue: {
type: DataTypes.VIRTUAL,
set(val) {
return this.value = val;
},
get() {
return this.value;
}
},
value: DataTypes.STRING,
secretValue: {
type: DataTypes.INTEGER,
allowNull: false
......@@ -23,17 +34,40 @@ describe(Support.getTestDialectTeaser('Model'), () => {
before(function() {
this.query = current.query;
current.query = sinon.stub().returns(Promise.resolve());
self.stub = sinon.stub(current.getQueryInterface(), 'upsert', () => {
return User.build({});
});
});
beforeEach(() => {
self.stub.reset();
});
after(function() {
current.query = this.query;
self.stub.restore();
});
it('skip validations for missing fields', () => {
return expect(User.upsert({
name: 'Grumpy Cat'
})).not.to.be.rejectedWith(current.ValidationError);
});
it('updates all changed fields by default', () => {
return User
.upsert({
name: 'Old Cat',
virtualValue: 111
})
.then(() => {
expect(Object.keys(self.stub.getCall(0).args[2])).to.deep.equal([
'name', 'value', 'updatedAt'
]);
});
});
});
}
});
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!