Skip to content

Commit 63b053e

Browse files
committed
fix(postgrest): set columns parameter for single-object insert/upsert
Closes #1653
1 parent ea490dd commit 63b053e

File tree

2 files changed

+63
-19
lines changed

2 files changed

+63
-19
lines changed

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

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,11 @@ export default class PostgrestQueryBuilder<
130130
})
131131
}
132132

133-
// TODO(v3): Make `defaultToNull` consistent for both single & bulk inserts.
134133
insert<Row extends Relation extends { Insert: unknown } ? Relation['Insert'] : never>(
135134
values: Row,
136135
options?: {
137136
count?: 'exact' | 'planned' | 'estimated'
137+
defaultToNull?: boolean
138138
}
139139
): PostgrestFilterBuilder<
140140
ClientOptions,
@@ -183,8 +183,7 @@ export default class PostgrestQueryBuilder<
183183
* numbers.
184184
*
185185
* @param options.defaultToNull - Make missing fields default to `null`.
186-
* Otherwise, use the default value for the column. Only applies for bulk
187-
* inserts.
186+
* Otherwise, use the default value for the column.
188187
*/
189188
insert<Row extends Relation extends { Insert: unknown } ? Relation['Insert'] : never>(
190189
values: Row | Row[],
@@ -213,12 +212,12 @@ export default class PostgrestQueryBuilder<
213212
this.headers.append('Prefer', `missing=default`)
214213
}
215214

216-
if (Array.isArray(values)) {
217-
const columns = values.reduce((acc, x) => acc.concat(Object.keys(x)), [] as string[])
218-
if (columns.length > 0) {
219-
const uniqueColumns = [...new Set(columns)].map((column) => `"${column}"`)
220-
this.url.searchParams.set('columns', uniqueColumns.join(','))
221-
}
215+
const columns = Array.isArray(values)
216+
? values.reduce((acc, x) => acc.concat(Object.keys(x)), [] as string[])
217+
: Object.keys(values)
218+
if (columns.length > 0) {
219+
const uniqueColumns = [...new Set(columns)].map((column) => `"${column}"`)
220+
this.url.searchParams.set('columns', uniqueColumns.join(','))
222221
}
223222

224223
return new PostgrestFilterBuilder({
@@ -231,13 +230,13 @@ export default class PostgrestQueryBuilder<
231230
})
232231
}
233232

234-
// TODO(v3): Make `defaultToNull` consistent for both single & bulk upserts.
235233
upsert<Row extends Relation extends { Insert: unknown } ? Relation['Insert'] : never>(
236234
values: Row,
237235
options?: {
238236
onConflict?: string
239237
ignoreDuplicates?: boolean
240238
count?: 'exact' | 'planned' | 'estimated'
239+
defaultToNull?: boolean
241240
}
242241
): PostgrestFilterBuilder<
243242
ClientOptions,
@@ -265,7 +264,7 @@ export default class PostgrestQueryBuilder<
265264
Relationships,
266265
'POST'
267266
>
268-
/**
267+
/**
269268
* Perform an UPSERT on the table or view. Depending on the column(s) passed
270269
* to `onConflict`, `.upsert()` allows you to perform the equivalent of
271270
* `.insert()` if a row with the corresponding `onConflict` columns doesn't
@@ -301,7 +300,7 @@ export default class PostgrestQueryBuilder<
301300
* @param options.defaultToNull - Make missing fields default to `null`.
302301
* Otherwise, use the default value for the column. This only applies when
303302
* inserting new rows, not when merging with existing rows under
304-
* `ignoreDuplicates: false`. This also only applies when doing bulk upserts.
303+
* `ignoreDuplicates: false`.
305304
*
306305
* @example Upsert a single row using a unique key
307306
* ```ts
@@ -351,7 +350,6 @@ export default class PostgrestQueryBuilder<
351350
* ```
352351
*/
353352

354-
355353
upsert<Row extends Relation extends { Insert: unknown } ? Relation['Insert'] : never>(
356354
values: Row | Row[],
357355
{
@@ -386,12 +384,12 @@ export default class PostgrestQueryBuilder<
386384
this.headers.append('Prefer', 'missing=default')
387385
}
388386

389-
if (Array.isArray(values)) {
390-
const columns = values.reduce((acc, x) => acc.concat(Object.keys(x)), [] as string[])
391-
if (columns.length > 0) {
392-
const uniqueColumns = [...new Set(columns)].map((column) => `"${column}"`)
393-
this.url.searchParams.set('columns', uniqueColumns.join(','))
394-
}
387+
const columns = Array.isArray(values)
388+
? values.reduce((acc, x) => acc.concat(Object.keys(x)), [] as string[])
389+
: Object.keys(values)
390+
if (columns.length > 0) {
391+
const uniqueColumns = [...new Set(columns)].map((column) => `"${column}"`)
392+
this.url.searchParams.set('columns', uniqueColumns.join(','))
395393
}
396394

397395
return new PostgrestFilterBuilder({

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

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,52 @@ describe("insert, update, delete with count: 'exact'", () => {
15691569
`)
15701570
})
15711571

1572+
test('single upsert with column defaults', async () => {
1573+
let res = await postgrest
1574+
.from('channels')
1575+
.upsert({ slug: 'test-single-upsert' }, { defaultToNull: false })
1576+
.select()
1577+
.rollback()
1578+
expect(res).toMatchInlineSnapshot(`
1579+
{
1580+
"count": null,
1581+
"data": [
1582+
{
1583+
"data": null,
1584+
"id": 8,
1585+
"slug": "test-single-upsert",
1586+
},
1587+
],
1588+
"error": null,
1589+
"status": 201,
1590+
"statusText": "Created",
1591+
}
1592+
`)
1593+
})
1594+
1595+
test('single insert with column defaults', async () => {
1596+
let res = await postgrest
1597+
.from('channels')
1598+
.insert({ slug: 'test-single-insert' }, { defaultToNull: false })
1599+
.select()
1600+
.rollback()
1601+
expect(res).toMatchInlineSnapshot(`
1602+
{
1603+
"count": null,
1604+
"data": [
1605+
{
1606+
"data": null,
1607+
"id": 9,
1608+
"slug": "test-single-insert",
1609+
},
1610+
],
1611+
"error": null,
1612+
"status": 201,
1613+
"statusText": "Created",
1614+
}
1615+
`)
1616+
})
1617+
15721618
test("update with count: 'exact'", async () => {
15731619
let res = await postgrest
15741620
.from('messages')

0 commit comments

Comments
 (0)