Given the following table:
| user_id | year | roles (array) |
|---|---|---|
| 0 | 2024 | [defender] |
| 0 | 2023 | [attacker] |
| 1 | 2024 | [defender] |
You can observe that we should have a unique entry for each user and year. So this table is correct, but inserting | 0 | 2024 | attacker | should replace update the first row instead.
To my knowledge, this means i should create a unique index for these, which I've done in drizzle as follows:
export const pianiExtra = pgTable(
'players',
{
userId: uuid('user_id')
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),
year: bigint('year', { mode: 'number' }).notNull(),
roles: roles('roles').array().notNull(),
},
(t) => ({
playersUniqueIndex: unique('players_unique_index').on(t.userId, t.year),
}),
);
Which brings me to the insert query:
const input = {
userId: 0,
year: 2024,
roles: [defender, attacker]
}
const result = await ctx.db
.insert(players)
.values(input)
.onConflictDoUpdate({
target: [players.userId, players.year],
set: input,
})
.returning({ id: pianiExtra.id });
There are two things that don;t quite make sense to me here:
- I would expect to pass the newly created index instead of the properties array in
onConflictDoUpdate -> target. - if I run this, I get a
there is no unique or exclusion constraint matching the ON CONFLICT specification, which I suspect is related to the target as well.