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

Commit a0635e3c by Evan Committed by GitHub

fix(model): updateOnDuplicate handles composite keys (#11984)

1 parent f98c59c1
......@@ -858,7 +858,7 @@ class Model {
*
* @see
* <a href="/master/manual/model-basics.html">Model Basics</a> guide
*
*
* @see
* <a href="/master/manual/model-basics.html">Hooks</a> guide
*
......@@ -2708,7 +2708,7 @@ class Model {
// Get primary keys for postgres to enable updateOnDuplicate
options.upsertKeys = _.chain(model.primaryKeys).values().map('field').value();
if (Object.keys(model.uniqueKeys).length > 0) {
options.upsertKeys = _.chain(model.uniqueKeys).values().filter(c => c.fields.length === 1).map(c => c.fields[0]).value();
options.upsertKeys = _.chain(model.uniqueKeys).values().filter(c => c.fields.length >= 1).map(c => c.fields).reduce(c => c[0]).value();
}
}
......@@ -3842,13 +3842,13 @@ class Model {
/**
* Validates this instance, and if the validation passes, persists it to the database.
*
*
* Returns a Promise that resolves to the saved instance (or rejects with a `Sequelize.ValidationError`, which will have a property for each of the fields for which the validation failed, with the error message for that field).
*
*
* This method is optimized to perform an UPDATE only into the fields that changed. If nothing has changed, no SQL query will be performed.
*
*
* This method is not aware of eager loaded associations. In other words, if some other model instance (child) was eager loaded with this instance (parent), and you change something in the child, calling `save()` will simply ignore the change that happened on the child.
*
*
* @param {object} [options] save options
* @param {string[]} [options.fields] An optional array of strings, representing database columns. If fields is provided, only those columns will be validated and saved.
* @param {boolean} [options.silent=false] If true, the updatedAt timestamp will not be updated.
......
......@@ -586,6 +586,117 @@ describe(Support.getTestDialectTeaser('Model'), () => {
expect(people[1].name).to.equal('Bob');
});
});
it('when the composite primary key column names and model field names are different', function() {
const Person = this.sequelize.define('Person', {
systemId: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
field: 'system_id'
},
system: {
type: DataTypes.STRING,
allowNull: false,
primaryKey: true,
field: 'system'
},
name: {
type: DataTypes.STRING,
allowNull: false,
field: 'name'
}
}, {});
return Person.sync({ force: true })
.then(() => {
const inserts = [
{ systemId: 1, system: 'system1', name: 'Alice' }
];
return Person.bulkCreate(inserts);
})
.then(people => {
expect(people.length).to.equal(1);
expect(people[0].systemId).to.equal(1);
expect(people[0].system).to.equal('system1');
expect(people[0].name).to.equal('Alice');
const updates = [
{ systemId: 1, system: 'system1', name: 'CHANGED NAME' },
{ systemId: 1, system: 'system2', name: 'Bob' }
];
return Person.bulkCreate(updates, { updateOnDuplicate: ['systemId', 'system', 'name'] });
})
.then(people => {
expect(people.length).to.equal(2);
expect(people[0].systemId).to.equal(1);
expect(people[0].system).to.equal('system1');
expect(people[0].name).to.equal('CHANGED NAME');
expect(people[1].systemId).to.equal(1);
expect(people[1].system).to.equal('system2');
expect(people[1].name).to.equal('Bob');
});
});
it('when the primary key column names and model field names are different and have composite unique constraints', function() {
const Person = this.sequelize.define('Person', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
field: 'id'
},
systemId: {
type: DataTypes.INTEGER,
allowNull: false,
unique: 'system_id_system_unique',
field: 'system_id'
},
system: {
type: DataTypes.STRING,
allowNull: false,
unique: 'system_id_system_unique',
field: 'system'
},
name: {
type: DataTypes.STRING,
allowNull: false,
field: 'name'
}
}, {});
return Person.sync({ force: true })
.then(() => {
const inserts = [
{ id: 1, systemId: 1, system: 'system1', name: 'Alice' }
];
return Person.bulkCreate(inserts);
})
.then(people => {
expect(people.length).to.equal(1);
expect(people[0].systemId).to.equal(1);
expect(people[0].system).to.equal('system1');
expect(people[0].name).to.equal('Alice');
const updates = [
{ id: 1, systemId: 1, system: 'system1', name: 'CHANGED NAME' },
{ id: 2, systemId: 1, system: 'system2', name: 'Bob' }
];
return Person.bulkCreate(updates, { updateOnDuplicate: ['systemId', 'system', 'name'] });
})
.then(people => {
expect(people.length).to.equal(2);
expect(people[0].systemId).to.equal(1);
expect(people[0].system).to.equal('system1');
expect(people[0].name).to.equal('CHANGED NAME');
expect(people[1].systemId).to.equal(1);
expect(people[1].system).to.equal('system2');
expect(people[1].name).to.equal('Bob');
});
});
});
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!