BulkCreate with composite unique constraint does not work
See original GitHub issueIssue Description
What are you doing?
I am trying to use bulkCreate
to updateOnDuplicate
when a duplicate is detected. Duplicate should be detected by a “multi column unique index”.
"use strict";
const Sequelize = require("./index");
const sequelize = require("./test/support").createSequelizeInstance();
const chai = require("chai"),
expect = chai.expect;
class Bar extends Sequelize.Model {}
Bar.init(
{
value: Sequelize.DataTypes.STRING,
timestamp: {
type: Sequelize.DataTypes.DATE,
allowNull: false
}
},
{
indexes: [
{
name: "unique_timestamp_per_foo",
unique: true,
fields: ["timestamp", "FooId"]
}
],
sequelize
}
);
class Foo extends Sequelize.Model {}
Foo.init({}, { sequelize });
Bar.belongsTo(Foo, {
foreignKey: { allowNull: false },
onDelete: "CASCADE"
});
Foo.hasMany(Bar, { foreignKey: { allowNull: false }, onDelete: "CASCADE" });
(async () => {
await sequelize.sync({ force: true });
// Create a _parent_ `Foo` model
const foo = await Foo.create();
// Create a `Bar` object
const originalBar = await Bar.create({
value: "original",
timestamp: new Date(Date.UTC(2016, 0, 1)),
FooId: foo.id
});
// We obviously expect a `Bar` object to exist with the unique constraints of `timestamp` and `FooId`
expect(
await Bar.count({
where: { FooId: foo.id, timestamp: new Date(Date.UTC(2016, 0, 1)) }
})
).to.equal(1);
// We create a modified `Bar` object that has an overlapping `timestamp` and `FooId`
// This should be detected as duplicate by the `uniqueTimestampPerFoo` unique constraint/index,
// during the next `bulkCreate` operation with `updateOnDuplicate` set.
const modifiedBar = Bar.build({
value: "modified",
timestamp: new Date(Date.UTC(2016, 0, 1)),
FooId: foo.id
});
// "Bulk" create to "upsert" a modified `existingBar` when conflict detected.
// We only want `value` and `updatedAt` to be updated on conflict.
await expect(
Bar.bulkCreate([modifiedBar.toJSON()], {
updateOnDuplicate: ["value", "updatedAt"],
logging: console.log
})
).not.to.be.rejectedWith(Sequelize.SequelizeUniqueConstraintError);
// *** The above function should not have been rejected with a `SequelizeUniqueConstraintError` ***
// *** The below is what should have been expected ***
// Reload the modified original `Bar` object by `id`
const refreshedOriginalBar = await Bar.findByPk(originalBar.id);
// The value should have been updated
expect(refreshedOriginalBar.value).to.equal("modified");
// The refreshed updatedAt should be greater than the original updatedAt
expect(refreshedOriginalBar.updatedAt > originalBar.updatedAt).be.true;
})();
What do you expect to happen?
See the expected assertions from my SSCCE:
// *** The below is what should have been expected ***
// Reload the modified original `Bar` object by `id`
const refreshedOriginalBar = await Bar.findByPk(originalBar.id);
// The value should have been updated
expect(refreshedOriginalBar.value).to.equal("modified");
// The refreshed updatedAt should be greater than the original updatedAt
expect(refreshedOriginalBar.updatedAt > originalBar.updatedAt).be.true;
I wanted a duplicate to be detected by the unique_timestamp_per_foo
unique key when calling the bulkCreate
method with updateOnDuplicate
array set.
Furthermore, I wanted the insert SQL to be ON CONFLICT ("timestamp", "FooId")
instead of ON CONFLICT ("id")
What is actually happening?
A SequelizeUniqueConstraintError
is thrown because the expected multi-field index does not get added to upsertKeys
here (https://github.com/sequelize/sequelize/blob/3517eb7e7bf5ce07cd33ad61fec291d0e8892d49/lib/model.js#L2705) because it is filtered out.
Environment
- Sequelize version: sequelize@0.0.0-development
- Node.js v10.16.3
- Operating System: Windows 10
Issue Template Checklist
How does this problem relate to dialects?
- I think this problem happens regardless of the dialect.
- I think this problem happens only for the following dialect(s): Postgres
Would you be willing to resolve this issue by submitting a Pull Request?
- Yes, I have the time and I know how to start.
- Yes, I have the time but I don’t know how to start, I would need guidance.
- No, I don’t have the time, although I believe I could do it if I had the time…
- No, I don’t have the time and I wouldn’t even know how to start.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:4
- Comments:14 (4 by maintainers)
Top Results From Across the Web
Enforce composite unique constraint that depends on parent ...
My first approach to the problem is to get rid of the table seat , other than being able to enumerate all the...
Read more >Unique Constraints and Check Constraints - SQL Server
A CHECK constraint returns TRUE when the condition it is checking is not FALSE for any row in the table. A CHECK constraint...
Read more >Defining Constraints and Indexes
This approach can't work when two or more foreign key constraints are involved in a ... Column("col3", Integer), # explicit/composite unique constraint.
Read more >Documentation: 15: 11.6. Unique Indexes - PostgreSQL
When an index is declared unique, multiple table rows with equal indexed values are not allowed. Null values are not considered equal. A...
Read more >SQL UNIQUE Constraint - W3Schools
The UNIQUE constraint ensures that all values in a column are different. ... SQL UNIQUE Constraint on CREATE TABLE ... ID int NOT...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@Rochet2 I’ve created a patch for my fix: https://gist.github.com/fnimick/5dd3c6855cea6e000c86d1bc38876958
PR coming shortly.
Do we have an ETA on when this PR might get looked at? Or how we can get it merged in? Is there any work required on contributors end to get this pushed through?