ReviewOS

also looking at this

stacks/bun-query-builder

fix(client): whereJsonContains binds the document, not its JSON text (#1091)

#1100
Merged glennmichael123 wants to merge fix/1091-json-contains-double-encode into main
3 files +172 -3
packages/bun-query-builder/src/client.tsmodified+18-3
Changes to packages/bun-query-builder/src/client.ts
@@ -4944,12 +4944,27 @@ export function createQueryBuilder<DB extends DatabaseSchema<any>>(state?: Parti
49444944 const dialect = config.dialect
49454945 const idx = whereParams.length + 1
49464946 if (dialect === 'postgres') {
4947 // Bind the document itself, NOT `JSON.stringify(document)`. Bun's
4948 // driver already JSON-encodes a value bound to a jsonb parameter, so
4949 // stringifying first encoded it twice and Postgres received the jsonb
4950 // *string* `"[\"bun\"]"` where the array `["bun"]` was meant. A jsonb
4951 // string never `@>`-contains anything, so the predicate was vacuously
4952 // false and every call returned zero rows, silently. See #1091.
4953 //
4954 // That encoding covers objects, arrays and strings. Numbers and
4955 // booleans are bound as int4/bool instead, which `@>` has no operator
4956 // for (`operator does not exist: jsonb @> integer`), so those are
4957 // lifted to a jsonb scalar with to_jsonb().
4958 const needsJsonbLift = typeof json === 'number' || typeof json === 'boolean'
4959 const operand = needsJsonbLift
4960 ? `to_jsonb(${getPlaceholder(idx)})`
4961 : getPlaceholder(idx)
49474962 // operator (`@>`, default) or function (`jsonb_contains`) per config.
49484963 if (config.sql?.jsonContainsMode === 'function')
4949 pushWhere('AND', `jsonb_contains(${column}, ${getPlaceholder(idx)})`)
4964 pushWhere('AND', `jsonb_contains(${column}, ${operand})`)
49504965 else
4951 pushWhere('AND', `${column} @> ${getPlaceholder(idx)}`)
4952 whereParams.push(JSON.stringify(json))
4966 pushWhere('AND', `${column} @> ${operand}`)
4967 whereParams.push(json)
49534968 }
49544969 else if (isMysqlLike(dialect)) {
49554970 pushWhere('AND', `JSON_CONTAINS(${column}, ${getPlaceholder(idx)})`)