objection.js
objection.js copied to clipboard
onConflict returns wrong values when there is a conflict
Objection.js v3.0.1 Knex v1.0.7 pg v8.7.1. (postgres)
Inserting records via Objection behaves differently than does inserting records via Knex when onConflict().ignore()
is used and a conflict occurs. The Knex behavior seems correct to me.
Table schema:
await knex.schema.createTable('user_platform', table => {
table.integer('user_id')
table.integer('platform_id')
table.unique(['user_id', 'platform_id'])
})
DB class:
const { Model } = require('objection')
class UserPlatform extends Model {
static get tableName() {
return 'userPlatform'
}
static get idColumn() {
return ['userId', 'platformId']
}
static insertWithKnex(userPlatforms = []) {
const knex = this.knex()
return knex('userPlatform').insert(userPlatforms).onConflict(this.idColumn).ignore().returning('*')
}
static insertWithObjection(userPlatforms = []) {
return this.query().insert(userPlatforms).onConflict(this.idColumn).ignore().returning('*')
}
static get relationMappings() {
return {},
}
}
module.exports = UserPlatform
Test Cases:
describe('insert', () => {
const userPlatforms = [
{ userId: 1, platformId: 11 },
{ userId: 1, platformId: 12 },
]
console.log({existing: userPlatforms})
it('Knex version - should NOT raise, but ignore, on insertion of duplicate records, existing or provided, returning only those actually added', async () => {
expect.assertions(1)
await db.UserPlatformDB.insert(userPlatforms)
const inserts = userPlatforms.concat([
{ userId: 1, platformId: 13 },
{ userId: 1, platformId: 13 },
])
console.log({ inserts })
const response = await db.UserPlatformDB.insertWithKnex(inserts)
console.log({ response })
expect(response.map(rs => rs.platformId)).toEqual([13])
})
it('Objection version - should NOT raise, but ignore, on insertion of duplicate records, existing or provided, returning only those actually added', async () => {
expect.assertions(1)
await db.UserPlatformDB.insert(userPlatforms)
const inserts = userPlatforms.concat([
{ userId: 1, platformId: 13 },
{ userId: 1, platformId: 13 },
])
console.log({ inserts })
const response = await db.UserPlatformDB.insertWithObjection(inserts)
console.log({ response })
expect(response.map(rs => rs.platformId)).toEqual([13])
})
Test Output from Knex test:
console.log
{
existing: [
{ userId: 1, platformId: 11 },
{ userId: 1, platformId: 12 },
]
}
console.log
{
inserts: [
{ userId: 1, platformId: 11 },
{ userId: 1, platformId: 12 },
{ userId: 1, platformId: 13 },
{ userId: 1, platformId: 13 }
]
}
console.log
{
response: [
{ userId: 1, platformId: 13 }
]
}
User Platform
insert
✓ Knex version - should NOT raise, but ignore, on insertion of duplicate records, existing or provided, returning only those actually added (957 ms)
Test output from Objection test:
console.log
{
existing: [
{ userId: 1, platformId: 11 },
{ userId: 1, platformId: 12 },
]
}
console.log
{
inserts: [
{ userId: 1, platformId: 11 },
{ userId: 1, platformId: 12 },
{ userId: 1, platformId: 13 },
{ userId: 1, platformId: 13 }
]
}
console.log
{
response: [
extended(UserPlatform) {
userId: 1,
platformId: 13
},
extended(UserPlatform) {
userId: 1,
platformId: 12
},
extended(UserPlatform) {
userId: 1,
platformId: 13
},
extended(UserPlatform) {
userId: 1,
platformId: 13
}
]
}
FAIL tests/db/user-platform.test.js
User Platform
insert
✕ Objection version - should NOT raise, but ignore, on insertion of duplicate records, existing or provided, returning only those actually added (548 ms)
User Platform › insert › Objection version - should NOT raise, bug ignore, on insertion of duplicate records, existing or provided, returning only those actually added
expect(received).toEqual(expected) // deep equality
- Expected - 0
+ Received + 3
Array [
13,
+ 12,
+ 13,
+ 13,
]
155 | const response = await db.UserPlatformDB.insertWithObjection(inserts)
156 | console.log({ added: response })
> 157 | expect(response.map(rs => rs.platformId)).toEqual([13])
|
160 | })