You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit ce5416f
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/queries.md
+82-8Lines changed: 82 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -295,7 +295,7 @@ A write targets exactly one table of its entry's schema.
295
295
296
296
| Statement | Accepted shape |
297
297
| --- | --- |
298
-
|`INSERT`| an explicit column list and a single `VALUES` row, each value a placeholder or an expression that binds none |
298
+
|`INSERT`| an explicit column list and a single `VALUES` row, each value a placeholder or an expression that binds none, with an optional `ON CONFLICT` clause|
299
299
|`UPDATE`|`SET` assignments that each assign one direct column a placeholder or an expression that binds none, with an optional `WHERE` using the read predicate forms |
300
300
|`DELETE`| one target table with an optional `WHERE` using the read predicate forms |
301
301
@@ -356,6 +356,53 @@ the whole value, as in `SET bio = :bio::text`, is typed by its cast as well and
356
356
named after its column. A value that contains an uncast placeholder, such as
357
357
`COALESCE($2, bio)`, stays rejected.
358
358
359
+
### Upsert with `ON CONFLICT`
360
+
361
+
An `INSERT` may end with one conflict clause whose target is a parenthesized
362
+
list of plain column names of the inserted table, followed by one action:
363
+
364
+
| Action | Accepted shape |
365
+
| --- | --- |
366
+
|`DO NOTHING`| no assignment, so the statement binds only its `VALUES` row |
367
+
|`DO UPDATE SET`| assignments analyzed exactly as `UPDATE` assignments are, where a value may also be `EXCLUDED.column`|
368
+
369
+
```sql
370
+
-- name: UpsertAuthor :one
371
+
INSERT INTO authors (id, name, bio)
372
+
VALUES (:id, :name, :bio)
373
+
ON CONFLICT (id) DO UPDATE
374
+
SET name =EXCLUDED.name,
375
+
bio = :bio,
376
+
version =authors.version+1,
377
+
updated_at = now()
378
+
RETURNING *;
379
+
```
380
+
381
+
`UpsertAuthor` generates `upsertAuthor(Long id, String name, String bio)` and
382
+
returns the `AuthorsRow` it inserted or updated.
383
+
384
+
A `DO UPDATE` placeholder is written after the `VALUES` placeholders, so it
385
+
binds after them: on a two-value insert,
386
+
`ON CONFLICT (id) DO UPDATE SET active = $3` binds `$1`, `$2`, and `$3` in that
387
+
order, and the repeated `:bio` above is bound at both of its positions. A
388
+
`DO UPDATE` placeholder is typed by its assigned column, or by its own cast
389
+
wherever a cast appears inside the assigned value.
390
+
391
+
`EXCLUDED.column` reads the proposed row, and that column must exist in the
392
+
inserted table. An `EXCLUDED` reference inside a larger expression is not
393
+
resolved, as no other computed write value is, so PostgreSQL checks it. sqlcj
394
+
does not match the conflict target against a unique index; PostgreSQL does.
395
+
396
+
A `DO NOTHING` action writes no row when a conflict occurs, so
397
+
`DO NOTHING ... RETURNING` returns no row on conflict and suits `:optional` or
398
+
`:many` rather than `:one`. A `DO UPDATE ... RETURNING` always returns the row
399
+
it inserted or updated.
400
+
401
+
Every other conflict form is rejected on every insert, whether `:exec` or
402
+
returning: a missing target, `ON CONFLICT ON CONSTRAINT`, a target element that
403
+
is an expression or carries a collation or an operator class, a conflict-target
404
+
predicate, and `DO UPDATE ... WHERE`.
405
+
359
406
### `RETURNING`
360
407
361
408
A supported `INSERT`, `UPDATE`, or `DELETE` declared `:one`, `:optional`, or
@@ -372,9 +419,10 @@ the target table's shared `<TableName>Row` record, while a `RETURNING` column
372
419
list keeps the query's own `<QueryName>Result` record.
373
420
374
421
An aliased or computed `RETURNING` item, a qualified `table.*`, an unknown
375
-
column, and `RETURNING` on `:exec` are rejected. `ON CONFLICT`, multi-row
376
-
`VALUES`, `INSERT ... SELECT`, `UPDATE ... FROM`, `DELETE ... USING`, and common
377
-
table expressions are rejected in a returning write.
422
+
column, and `RETURNING` on `:exec` are rejected. Multi-row `VALUES`,
423
+
`INSERT ... SELECT`, `UPDATE ... FROM`, `DELETE ... USING`, and common table
424
+
expressions are rejected in a returning write, while an accepted `ON CONFLICT`
425
+
clause is analyzed the same way with and without `RETURNING`.
378
426
379
427
## Parameters
380
428
@@ -721,9 +769,16 @@ name, and its header line.
721
769
or built from a `SELECT`; an `UPDATE` assignment that sets a column list, such
722
770
as `SET (name, active) = ('a', TRUE)`; and a written column that the table does
723
771
not declare.
772
+
- A conflict clause outside the accepted upsert shape, on an `:exec` and on a
773
+
returning insert alike: `ON CONFLICT` without a target, `ON CONFLICT ON
774
+
CONSTRAINT`, a target element that is an expression or carries a collation or
775
+
an operator class, a conflict-target predicate such as
776
+
`ON CONFLICT (id) WHERE active`, and `DO UPDATE ... WHERE`. A `DO UPDATE`
777
+
assignment that sets a column list, and an unknown target, assigned, or
778
+
`EXCLUDED` column, are rejected as the write forms above are.
724
779
- An aliased, computed, qualified-wildcard, or unknown `RETURNING` item;
725
-
`RETURNING` on `:exec`; and `ON CONFLICT`, `UPDATE ... FROM`,
726
-
`DELETE ... USING`, or a common table expression in a returning write.
780
+
`RETURNING` on `:exec`; and `UPDATE ... FROM`, `DELETE ... USING`, or a common
781
+
table expression in a returning write.
727
782
- Any annotation other than `:one`, `:optional`, `:many`, and `:exec`.
728
783
729
784
### Not analyzed
@@ -739,8 +794,9 @@ them:
739
794
literal pattern, a range whose bounds are both literal such as
740
795
`id BETWEEN 1 AND 10`, or `IN` with a subquery,
741
796
- common table expressions, and subqueries outside the `FROM` item,
742
-
-`ON CONFLICT`, `UPDATE ... FROM`, and `DELETE ... USING` on a non-returning
743
-
`:exec` write.
797
+
-`UPDATE ... FROM` and `DELETE ... USING` on a non-returning `:exec` write,
798
+
- the unique index an accepted `ON CONFLICT` target matches, and the column
799
+
references of an `EXCLUDED` value that is not exactly `EXCLUDED.column`.
744
800
745
801
sqlcj itself provides no macros, array operators such as `= ANY`, dynamic `IN`
746
802
expansion, or query-building API. An array parameter is one whole list bound at
@@ -916,6 +972,24 @@ Writes and `RETURNING`:
916
972
`QueryAnalyzerTest.shouldRejectExcludedWriteValueForm` cover the values that
917
973
bind no placeholder, their numbering and binding order, and the nearby
0 commit comments