-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Upsert uses a WHERE clause with both primary key and unique indices on Postgres #8552
Description
What are you doing?
I am using upsert to update models that have both a primary key and a composite unique constraint which is DEFERRABLE INITIALLY DEFERRED. When I try to change the members of the unique constraint I get a key uniqueness error.
Model:
module.exports = (sequelize, DataTypes) => {
return sequelize.define(
'rule',
{
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
},
priority: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0,
unique: 'rules_priority_parent_id'
},
parent_id: {
type: DataTypes.UUID,
allowNull: false,
unique: 'rules_priority_parent_id'
}
},
{
tableName: 'rules',
timestamps: true
}
)
}Then do:
models.rule.create({
id: 5,
priority: 0,
parent_id: 20
})
models.rule.create({
id: 10,
priority: 1,
parent_id: 20
})
models.sequelize.transaction(() => (
models.rule.upsert({
id: 5,
priority: 1,
parent_id: 20
})
.then(() => models.rule.upsert({
id: 10,
priority: 0,
parent_id: 20
}))
))What do you expect to happen?
The priority of the two rows to be swapped
What is actually happening?
Uniqueness constraint error
I get a constraint error on the uniqueness of the primary key.
Postgres output:
ERROR: duplicate key value violates unique constraint "rules_pkey"
DETAIL: Key (id)=(5) already exists.
CONTEXT: SQL statement "UPDATE "rules" SET "priority"=1, "parent_id"=20, "id"=5, "updated_at"='2017-10-27 17:37:23.120 +00:00' WHERE ("id" = 5 OR ("priority" = 1 AND "parent_id" = 20))"
PL/pgSQL function pg_temp_3.sequelize_upsert() line 1 at SQL statement
I see a fix for sequelize@3 for the same problem (issue #6240, PR #6243), but it appears to still be a problem in sequelize@4.
Dialect: postgres
Dialect version: pg@6.4.2
Database version: 9.6.3
Sequelize version: 4.19.0
Tested with master branch: Yes
Note : Your issue may be ignored by maintainers if it's not tested against master branch OR does not follow issue template.