Skip to content

Commit cce7555

Browse files
authored
fix(orm): "array_contains" filter fixes (#480)
* fix(orm): "array_contains" filter fixes * update
1 parent 293cf0d commit cce7555

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed

packages/orm/src/client/crud/dialects/postgresql.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,10 @@ export class PostgresCrudDialect<Schema extends SchemaDef> extends BaseCrudDiale
468468
value: unknown,
469469
) {
470470
return match(operation)
471-
.with('array_contains', () => sql<SqlBool>`${lhs} @> ${sql.val(JSON.stringify([value]))}::jsonb`)
471+
.with('array_contains', () => {
472+
const v = Array.isArray(value) ? value : [value];
473+
return sql<SqlBool>`${lhs} @> ${sql.val(JSON.stringify(v))}::jsonb`;
474+
})
472475
.with('array_starts_with', () =>
473476
this.eb(
474477
this.eb.fn('jsonb_extract_path', [lhs, this.eb.val('0')]),

packages/orm/src/client/crud/dialects/sqlite.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { AnyNullClass, DbNullClass, JsonNullClass } from '../../../common-types'
1414
import type { BuiltinType, FieldDef, GetModels, SchemaDef } from '../../../schema';
1515
import { DELEGATE_JOINED_FIELD_PREFIX } from '../../constants';
1616
import type { FindArgs } from '../../crud-types';
17-
import { createInternalError } from '../../errors';
17+
import { createInternalError, createNotSupportedError } from '../../errors';
1818
import {
1919
getDelegateDescendantModels,
2020
getManyToManyRelation,
@@ -374,7 +374,15 @@ export class SqliteCrudDialect<Schema extends SchemaDef> extends BaseCrudDialect
374374
value: unknown,
375375
) {
376376
return match(operation)
377-
.with('array_contains', () => sql<any>`EXISTS (SELECT 1 FROM jsonb_each(${lhs}) WHERE value = ${value})`)
377+
.with('array_contains', () => {
378+
if (Array.isArray(value)) {
379+
throw createNotSupportedError(
380+
'SQLite "array_contains" only supports checking for a single value, not an array of values',
381+
);
382+
} else {
383+
return sql<any>`EXISTS (SELECT 1 FROM jsonb_each(${lhs}) WHERE value = ${value})`;
384+
}
385+
})
378386
.with('array_starts_with', () =>
379387
this.eb(this.eb.fn('json_extract', [lhs, this.eb.val('$[0]')]), '=', value),
380388
)
@@ -390,7 +398,7 @@ export class SqliteCrudDialect<Schema extends SchemaDef> extends BaseCrudDialect
390398
) {
391399
return this.eb.exists(
392400
this.eb
393-
.selectFrom(this.eb.fn('json_each', [receiver]).as('$items'))
401+
.selectFrom(this.eb.fn('jsonb_each', [receiver]).as('$items'))
394402
.select(this.eb.lit(1).as('$t'))
395403
.where(buildFilter(this.eb.ref('$items.value'))),
396404
);

tests/e2e/orm/client-api/json-filter.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,19 @@ describe('Json filter tests', () => {
759759
}),
760760
).resolves.toMatchObject({ data: { tags: ['typescript', 'react', 'node'] } });
761761

762+
if ((db.$schema.provider.type as any) === 'postgresql') {
763+
await expect(
764+
db.foo.findFirst({
765+
where: {
766+
data: {
767+
path: '$.tags',
768+
array_contains: ['react'],
769+
},
770+
},
771+
}),
772+
).resolves.toMatchObject({ data: { tags: ['typescript', 'react', 'node'] } });
773+
}
774+
762775
await expect(
763776
db.foo.findFirst({
764777
where: {

0 commit comments

Comments
 (0)