also looking at this
fix(client): whereJsonContains binds the document, not its JSON text (#1091)
#1100
3 files
+172
-3
| @@ -4944,12 +4944,27 @@ export function createQueryBuilder<DB extends DatabaseSchema<any>>(state?: Parti | ||
| 4944 | 4944 | const dialect = config.dialect |
| 4945 | 4945 | const idx = whereParams.length + 1 |
| 4946 | 4946 | 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) | |
| 4947 | 4962 | // operator (`@>`, default) or function (`jsonb_contains`) per config. |
| 4948 | 4963 | if (config.sql?.jsonContainsMode === 'function') |
| 4949 | pushWhere('AND', `jsonb_contains(${column}, ${getPlaceholder(idx)})`) | |
| 4964 | pushWhere('AND', `jsonb_contains(${column}, ${operand})`) | |
| 4950 | 4965 | else |
| 4951 | pushWhere('AND', `${column} @> ${getPlaceholder(idx)}`) | |
| 4952 | whereParams.push(JSON.stringify(json)) | |
| 4966 | pushWhere('AND', `${column} @> ${operand}`) | |
| 4967 | whereParams.push(json) | |
| 4953 | 4968 | } |
| 4954 | 4969 | else if (isMysqlLike(dialect)) { |
| 4955 | 4970 | pushWhere('AND', `JSON_CONTAINS(${column}, ${getPlaceholder(idx)})`) |