K
Kysely•15mo ago
Luccas

mysql InsertResult always empty

my app is heavy id/transaction user and i need the id of created register to insert another register but InsertResult always is empty
12 Replies
Luccas
Luccas•15mo ago
now i doing an workaround like this
.values({
provider,
user_id: sql<number>`LAST_INSERT_ID()`,
provider_id: sql<string>`LAST_INSERT_ID()`,
})
.values({
provider,
user_id: sql<number>`LAST_INSERT_ID()`,
provider_id: sql<string>`LAST_INSERT_ID()`,
})
koskimas
koskimas•15mo ago
What do you mean by empty? The result object doesn't have the insertId property? If you're just console.logging the result, it always seems like an empty object. The properties are non-enumerable getters. If the insertId is still empty when you do this
const res = await db
.insertInto('person')
.values(person)
.executeTakeFirstOrThrow()
console.log(res.insertId)
const res = await db
.insertInto('person')
.values(person)
.executeTakeFirstOrThrow()
console.log(res.insertId)
please provide more information: * Kysely version * Which dialect are you using * The exact code you're trying to run * How it fails * What are you expecting to happen * Any errors you see
Luccas
Luccas•15mo ago
* Kysely version - "kysely": "^0.23.5" * Which dialect are you using - i tried PlanetScaleDialect and MysqlDialect, same result in both * The exact code you're trying to run
return db.transaction().execute(async (trx) => {
await trx
.insertInto('user')
.values({
first_name: firstName,
last_name: lastName,
public_id: userPublicId,
password: hashPass,
email: email,
})
.executeTakeFirst()
.then(console.log);

const userId = (await sql<{ id: number }>`SELECT LAST_INSERT_ID() AS id`.execute(trx)).rows[0].id;

return trx
.insertInto('user_providers')
.values({
provider,
user_id: userId,
provider_id: userId.toString(),
})
.execute();
});
return db.transaction().execute(async (trx) => {
await trx
.insertInto('user')
.values({
first_name: firstName,
last_name: lastName,
public_id: userPublicId,
password: hashPass,
email: email,
})
.executeTakeFirst()
.then(console.log);

const userId = (await sql<{ id: number }>`SELECT LAST_INSERT_ID() AS id`.execute(trx)).rows[0].id;

return trx
.insertInto('user_providers')
.values({
provider,
user_id: userId,
provider_id: userId.toString(),
})
.execute();
});
* How it fails - the received return from console.log is [ InsertResult {} ] * What are you expecting to happen - return id of insert * Any errors you see - no errors
Igal
Igal•15mo ago
Hey 👋
* How it fails - the received return from console.log is [ InsertResult {} ]
You're trying to print a class instance with non-enumerable getters. Try printing result.insertId instead.
koskimas
koskimas•15mo ago
@Igal We should probably make the properties enumerable somehow. This is not the first time this has been reported.
Igal
Igal•15mo ago
In general, this type of stuff is why I prefer using uuids/cuid2 nowadays.
koskimas
koskimas•15mo ago
I think we can call Object.defineProperty(InsertResult.prototype, 'insertId', {enumerable: true}) Didn't know defineProperty can be used for an existing property
Igal
Igal•15mo ago
Yeah its a thing, I used to do it with Error.message
Luccas
Luccas•15mo ago
worked, thanks Does this not cause performance issues?
Igal
Igal•15mo ago
transactions are arguably worse for performance. any locking in write-heavy workflows is bad
Luccas
Luccas•15mo ago
I agree with you i exaggerated a bit when I said that my app was transaction heavy user haha
Igal
Igal•15mo ago
you could generate a guid, pass the entity to a queue+dlq.. and then deal with the writing in parallel without a transaction and without fear of data loss. reads would still use inner joins and would filter out things that were not written to both tables yet