Skip to content

Commit 02c3224

Browse files
authored
feat(postgrest): add notin filter (#1957)
1 parent 4d9f71c commit 02c3224

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

packages/core/postgrest-js/src/PostgrestFilterBuilder.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,34 @@ export default class PostgrestFilterBuilder<
379379
return this
380380
}
381381

382+
/**
383+
* Match only rows where `column` is NOT included in the `values` array.
384+
*
385+
* @param column - The column to filter on
386+
* @param values - The values array to filter with
387+
*/
388+
notIn<ColumnName extends string>(
389+
column: ColumnName,
390+
values: ReadonlyArray<
391+
ResolveFilterValue<Schema, Row, ColumnName> extends never
392+
? unknown
393+
: ResolveFilterValue<Schema, Row, ColumnName> extends infer ResolvedFilterValue
394+
? ResolvedFilterValue
395+
: never
396+
>
397+
): this {
398+
const cleanedValues = Array.from(new Set(values))
399+
.map((s) => {
400+
// handle postgrest reserved characters
401+
// https://postgrest.org/en/v7.0.0/api.html#reserved-characters
402+
if (typeof s === 'string' && PostgrestReservedCharsRegexp.test(s)) return `"${s}"`
403+
else return `${s}`
404+
})
405+
.join(',')
406+
this.url.searchParams.append(column, `not.in.(${cleanedValues})`)
407+
return this
408+
}
409+
382410
contains<ColumnName extends string & keyof Row>(
383411
column: ColumnName,
384412
value: string | ReadonlyArray<Row[ColumnName]> | Record<string, unknown>

packages/core/postgrest-js/test/filters.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,20 @@ test('in', async () => {
353353
`)
354354
})
355355

356+
test('notIn', async () => {
357+
const statuses = ['ONLINE', 'OFFLINE'] as const
358+
const res = await postgrest.from('users').select('status').notIn('status', statuses)
359+
expect(res).toMatchInlineSnapshot(`
360+
{
361+
"count": null,
362+
"data": [],
363+
"error": null,
364+
"status": 200,
365+
"statusText": "OK",
366+
}
367+
`)
368+
})
369+
356370
test('contains', async () => {
357371
const res = await postgrest.from('users').select('age_range').contains('age_range', '[1,2)')
358372
expect(res).toMatchInlineSnapshot(`

0 commit comments

Comments
 (0)