From 0c060b271250f2a1ffd62fafa7c75e5a708d581d Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Fri, 12 Dec 2025 22:45:33 +0800 Subject: [PATCH 1/2] fix(orm): "array_contains" filter fixes --- packages/orm/src/client/crud/dialects/postgresql.ts | 5 ++++- packages/orm/src/client/crud/dialects/sqlite.ts | 12 +++++++++--- tests/e2e/orm/client-api/json-filter.test.ts | 13 +++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/packages/orm/src/client/crud/dialects/postgresql.ts b/packages/orm/src/client/crud/dialects/postgresql.ts index 5b0c64510..733af920c 100644 --- a/packages/orm/src/client/crud/dialects/postgresql.ts +++ b/packages/orm/src/client/crud/dialects/postgresql.ts @@ -468,7 +468,10 @@ export class PostgresCrudDialect extends BaseCrudDiale value: unknown, ) { return match(operation) - .with('array_contains', () => sql`${lhs} @> ${sql.val(JSON.stringify([value]))}::jsonb`) + .with('array_contains', () => { + const v = Array.isArray(value) ? value : [value]; + return sql`${lhs} @> ${sql.val(JSON.stringify(v))}::jsonb`; + }) .with('array_starts_with', () => this.eb( this.eb.fn('jsonb_extract_path', [lhs, this.eb.val('0')]), diff --git a/packages/orm/src/client/crud/dialects/sqlite.ts b/packages/orm/src/client/crud/dialects/sqlite.ts index 677261983..9930ec838 100644 --- a/packages/orm/src/client/crud/dialects/sqlite.ts +++ b/packages/orm/src/client/crud/dialects/sqlite.ts @@ -14,7 +14,7 @@ import { AnyNullClass, DbNullClass, JsonNullClass } from '../../../common-types' import type { BuiltinType, FieldDef, GetModels, SchemaDef } from '../../../schema'; import { DELEGATE_JOINED_FIELD_PREFIX } from '../../constants'; import type { FindArgs } from '../../crud-types'; -import { createInternalError } from '../../errors'; +import { createInternalError, createNotSupportedError } from '../../errors'; import { getDelegateDescendantModels, getManyToManyRelation, @@ -374,7 +374,13 @@ export class SqliteCrudDialect extends BaseCrudDialect value: unknown, ) { return match(operation) - .with('array_contains', () => sql`EXISTS (SELECT 1 FROM jsonb_each(${lhs}) WHERE value = ${value})`) + .with('array_contains', () => { + if (Array.isArray(value)) { + throw createNotSupportedError('Sqlite "array_contains" must be used with a single value'); + } else { + return sql`EXISTS (SELECT 1 FROM jsonb_each(${lhs}) WHERE value = ${value})`; + } + }) .with('array_starts_with', () => this.eb(this.eb.fn('json_extract', [lhs, this.eb.val('$[0]')]), '=', value), ) @@ -390,7 +396,7 @@ export class SqliteCrudDialect extends BaseCrudDialect ) { return this.eb.exists( this.eb - .selectFrom(this.eb.fn('json_each', [receiver]).as('$items')) + .selectFrom(this.eb.fn('jsonb_each', [receiver]).as('$items')) .select(this.eb.lit(1).as('$t')) .where(buildFilter(this.eb.ref('$items.value'))), ); diff --git a/tests/e2e/orm/client-api/json-filter.test.ts b/tests/e2e/orm/client-api/json-filter.test.ts index acb03b04f..4260d439b 100644 --- a/tests/e2e/orm/client-api/json-filter.test.ts +++ b/tests/e2e/orm/client-api/json-filter.test.ts @@ -759,6 +759,19 @@ describe('Json filter tests', () => { }), ).resolves.toMatchObject({ data: { tags: ['typescript', 'react', 'node'] } }); + if ((db.$schema.provider.type as any) === 'postgresql') { + await expect( + db.foo.findFirst({ + where: { + data: { + path: '$.tags', + array_contains: ['react'], + }, + }, + }), + ).resolves.toMatchObject({ data: { tags: ['typescript', 'react', 'node'] } }); + } + await expect( db.foo.findFirst({ where: { From b827139e48c399a310b69929d282a3bad1e57b12 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Fri, 12 Dec 2025 22:51:51 +0800 Subject: [PATCH 2/2] update --- packages/orm/src/client/crud/dialects/sqlite.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/orm/src/client/crud/dialects/sqlite.ts b/packages/orm/src/client/crud/dialects/sqlite.ts index 9930ec838..102d57252 100644 --- a/packages/orm/src/client/crud/dialects/sqlite.ts +++ b/packages/orm/src/client/crud/dialects/sqlite.ts @@ -376,7 +376,9 @@ export class SqliteCrudDialect extends BaseCrudDialect return match(operation) .with('array_contains', () => { if (Array.isArray(value)) { - throw createNotSupportedError('Sqlite "array_contains" must be used with a single value'); + throw createNotSupportedError( + 'SQLite "array_contains" only supports checking for a single value, not an array of values', + ); } else { return sql`EXISTS (SELECT 1 FROM jsonb_each(${lhs}) WHERE value = ${value})`; }