effect
effect copied to clipboard
Writing instances of Uint8Array using unprepared statements fails
What version of Effect is running?
3.14.1
What steps can reproduce the bug?
Reproduction case available here. The steps can be found in the README. Simple, non-runnable example:
import { SqlClient } from "@effect/sql"
import { DBClientLayer } from "./db-client.ts"
import { Array, Effect, Logger } from "effect"
import { MigratorLayer } from "./migrator.ts"
const badId = new Uint8Array(Array.replicate(0x0, 16))
const anotherBadId = new Uint8Array(Array.replicate(0x1, 16))
const goodId = Buffer.from(new Uint8Array(Array.replicate(0x2, 16)))
const program = Effect.gen(function* () {
const sql = yield* SqlClient.SqlClient
yield* sql`TRUNCATE TABLE examples`
// works
yield* sql`INSERT INTO examples ${sql.insert({ id: goodId })}`.unprepared
// works
yield* sql`INSERT INTO examples ${sql.insert({ id: anotherBadId })}`
// fails with:
// [cause]: Error: Column count doesn't match value count at row 1
// code: 'ER_WRONG_VALUE_COUNT_ON_ROW',
// errno: 1136,
// sqlState: '21S01',
// sqlMessage: "Column count doesn't match value count at row 1",
// sql: 'INSERT INTO examples (`id`) VALUES (`0` = 0, `1` = 0, `2` = 0, `3` = 0, `4` = 0, `5` = 0, `6` = 0, `7` = 0, `8` = 0, `9` = 0, `10` = 0, `11` = 0, `12` = 0, `13` = 0, `14` = 0, `15` = 0)'
yield* sql`INSERT INTO examples ${sql.insert({ id: badId })}`.unprepared
})
program.pipe(
Effect.provide(MigratorLayer),
Effect.provide(DBClientLayer),
Effect.provide(Logger.json),
Effect.runPromise
)
What is the expected behavior?
I expect the write operation to succeed regardless of the actual type of the binary data or the type of the statement used to execute the query.
What do you see instead?
Error: Column count doesn't match value count at row 1
<stacktrace truncated> {
code: 'ER_WRONG_VALUE_COUNT_ON_ROW',
errno: 1136,
sqlState: '21S01',
sqlMessage: "Column count doesn't match value count at row 1",
sql: 'INSERT INTO examples (`id`) VALUES (`0` = 0, `1` = 0, `2` = 0, `3` = 0, `4` = 0, `5` = 0, `6` = 0, `7` = 0, `8` = 0, `9` = 0, `10` = 0, `11` = 0, `12` = 0, `13` = 0, `14` = 0, `15` = 0)'
}
Additional information
No response
@tim-smart ~I think my original PR adding support for binary values isn't quite up to the challenge 😄~
NVM:
import { Array } from "effect"
const u = new Uint8Array(Array.replicate(0x0, 16))
// undefined
typeof u === "object" && "buffer" in u && u.buffer instanceof ArrayBuffer
// true
This is probably an issue in mysql2 itself. I'll try to replicate it using mysql2 directly.