Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 80feb72

Browse files
committed
Add OLD/NEW support to RETURNING in DML queries.
This allows the RETURNING list of INSERT/UPDATE/DELETE/MERGE queries to explicitly return old and new values by using the special aliases "old" and "new", which are automatically added to the query (if not already defined) while parsing its RETURNING list, allowing things like: RETURNING old.colname, new.colname, ... RETURNING old.*, new.* Additionally, a new syntax is supported, allowing the names "old" and "new" to be changed to user-supplied alias names, e.g.: RETURNING WITH (OLD AS o, NEW AS n) o.colname, n.colname, ... This is useful when the names "old" and "new" are already defined, such as inside trigger functions, allowing backwards compatibility to be maintained -- the interpretation of any existing queries that happen to already refer to relations called "old" or "new", or use those as aliases for other relations, is not changed. For an INSERT, old values will generally be NULL, and for a DELETE, new values will generally be NULL, but that may change for an INSERT with an ON CONFLICT ... DO UPDATE clause, or if a query rewrite rule changes the command type. Therefore, we put no restrictions on the use of old and new in any DML queries. Dean Rasheed, reviewed by Jian He and Jeff Davis. Discussion: https://postgr.es/m/CAEZATCWx0J0-v=Qjc6gXzR=KtsdvAE7Ow=D=mu50AgOe+pvisQ@mail.gmail.com
1 parent 7407b2d commit 80feb72

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2910
-390
lines changed

contrib/postgres_fdw/expected/postgres_fdw.out

+118-6
Original file line numberDiff line numberDiff line change
@@ -4975,12 +4975,12 @@ INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
49754975

49764976
INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
49774977
INSERT INTO ft2 (c1,c2,c3)
4978-
VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING *;
4979-
c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4980-
------+-----+-----+----+----+----+------------+----
4981-
1101 | 201 | aaa | | | | ft2 |
4982-
1102 | 202 | bbb | | | | ft2 |
4983-
1103 | 203 | ccc | | | | ft2 |
4978+
VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING old, new, old.*, new.*;
4979+
old | new | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4980+
-----+---------------------------------+----+----+----+----+----+----+----+----+------+-----+-----+----+----+----+------------+----
4981+
| (1101,201,aaa,,,,"ft2 ",) | | | | | | | | | 1101 | 201 | aaa | | | | ft2 |
4982+
| (1102,202,bbb,,,,"ft2 ",) | | | | | | | | | 1102 | 202 | bbb | | | | ft2 |
4983+
| (1103,203,ccc,,,,"ft2 ",) | | | | | | | | | 1103 | 203 | ccc | | | | ft2 |
49844984
(3 rows)
49854985

49864986
INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee');
@@ -5111,6 +5111,31 @@ UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING
51115111
1017 | 507 | 0001700017_update7 | | | | ft2 |
51125112
(102 rows)
51135113

5114+
BEGIN;
5115+
EXPLAIN (verbose, costs off)
5116+
UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7b' WHERE c1 % 10 = 7 AND c1 < 40
5117+
RETURNING old.*, new.*; -- can't be pushed down
5118+
QUERY PLAN
5119+
----------------------------------------------------------------------------------------------------------------------------------------------
5120+
Update on public.ft2
5121+
Output: old.c1, old.c2, old.c3, old.c4, old.c5, old.c6, old.c7, old.c8, new.c1, new.c2, new.c3, new.c4, new.c5, new.c6, new.c7, new.c8
5122+
Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c3 = $3 WHERE ctid = $1 RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8
5123+
-> Foreign Scan on public.ft2
5124+
Output: (c2 + 400), (c3 || '_update7b'::text), ctid, ft2.*
5125+
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" < 40)) AND ((("C 1" % 10) = 7)) FOR UPDATE
5126+
(6 rows)
5127+
5128+
UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7b' WHERE c1 % 10 = 7 AND c1 < 40
5129+
RETURNING old.*, new.*;
5130+
c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
5131+
----+-----+---------------+------------------------------+--------------------------+----+------------+-----+----+-----+------------------------+------------------------------+--------------------------+----+------------+-----
5132+
7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo | 7 | 807 | 00007_update7_update7b | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5133+
17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo | 17 | 807 | 00017_update7_update7b | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5134+
27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo | 27 | 807 | 00027_update7_update7b | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5135+
37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo | 37 | 807 | 00037_update7_update7b | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5136+
(4 rows)
5137+
5138+
ROLLBACK;
51145139
EXPLAIN (verbose, costs off)
51155140
UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
51165141
FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down
@@ -5241,6 +5266,29 @@ DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4;
52415266
1105 |
52425267
(103 rows)
52435268

5269+
BEGIN;
5270+
EXPLAIN (verbose, costs off)
5271+
DELETE FROM ft2 WHERE c1 % 10 = 6 AND c1 < 40 RETURNING old.c1, c4; -- can't be pushed down
5272+
QUERY PLAN
5273+
-----------------------------------------------------------------------------------------------------------
5274+
Delete on public.ft2
5275+
Output: old.c1, c4
5276+
Remote SQL: DELETE FROM "S 1"."T 1" WHERE ctid = $1 RETURNING "C 1", c4
5277+
-> Foreign Scan on public.ft2
5278+
Output: ctid
5279+
Remote SQL: SELECT ctid FROM "S 1"."T 1" WHERE (("C 1" < 40)) AND ((("C 1" % 10) = 6)) FOR UPDATE
5280+
(6 rows)
5281+
5282+
DELETE FROM ft2 WHERE c1 % 10 = 6 AND c1 < 40 RETURNING old.c1, c4;
5283+
c1 | c4
5284+
----+------------------------------
5285+
6 | Wed Jan 07 00:00:00 1970 PST
5286+
16 | Sat Jan 17 00:00:00 1970 PST
5287+
26 | Tue Jan 27 00:00:00 1970 PST
5288+
36 | Fri Feb 06 00:00:00 1970 PST
5289+
(4 rows)
5290+
5291+
ROLLBACK;
52445292
EXPLAIN (verbose, costs off)
52455293
DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down
52465294
QUERY PLAN
@@ -6165,6 +6213,70 @@ UPDATE ft2 SET c3 = 'foo'
61656213
(1296,96,foo,,,,"ft2 ",) | 1296 | 96 | foo | | | | ft2 | | (96,97,AAA096) | 96 | 97 | AAA096
61666214
(16 rows)
61676215

6216+
BEGIN;
6217+
EXPLAIN (verbose, costs off)
6218+
UPDATE ft2 SET c3 = 'bar'
6219+
FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
6220+
WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
6221+
RETURNING old, new, ft2, ft2.*, ft4, ft4.*; -- can't be pushed down
6222+
QUERY PLAN
6223+
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6224+
Update on public.ft2
6225+
Output: old.*, new.*, ft2.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.*, ft4.c1, ft4.c2, ft4.c3
6226+
Remote SQL: UPDATE "S 1"."T 1" SET c3 = $2 WHERE ctid = $1 RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8
6227+
-> Foreign Scan
6228+
Output: 'bar'::text, ft2.ctid, ft2.*, ft4.*, ft5.*, ft4.c1, ft4.c2, ft4.c3
6229+
Relations: ((public.ft2) INNER JOIN (public.ft4)) INNER JOIN (public.ft5)
6230+
Remote SQL: SELECT r1.ctid, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2.c1, r2.c2, r2.c3) END, CASE WHEN (r3.*)::text IS NOT NULL THEN ROW(r3.c1, r3.c2, r3.c3) END, r2.c1, r2.c2, r2.c3 FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 3" r2 ON (((r1.c2 = r2.c1)) AND ((r1."C 1" > 1200)))) INNER JOIN "S 1"."T 4" r3 ON (((r2.c1 = r3.c1)))) FOR UPDATE OF r1
6231+
-> Nested Loop
6232+
Output: ft2.ctid, ft2.*, ft4.*, ft5.*, ft4.c1, ft4.c2, ft4.c3
6233+
Join Filter: (ft4.c1 = ft5.c1)
6234+
-> Sort
6235+
Output: ft2.ctid, ft2.*, ft2.c2, ft4.*, ft4.c1, ft4.c2, ft4.c3
6236+
Sort Key: ft2.c2
6237+
-> Hash Join
6238+
Output: ft2.ctid, ft2.*, ft2.c2, ft4.*, ft4.c1, ft4.c2, ft4.c3
6239+
Hash Cond: (ft2.c2 = ft4.c1)
6240+
-> Foreign Scan on public.ft2
6241+
Output: ft2.ctid, ft2.*, ft2.c2
6242+
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 1200)) FOR UPDATE
6243+
-> Hash
6244+
Output: ft4.*, ft4.c1, ft4.c2, ft4.c3
6245+
-> Foreign Scan on public.ft4
6246+
Output: ft4.*, ft4.c1, ft4.c2, ft4.c3
6247+
Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
6248+
-> Materialize
6249+
Output: ft5.*, ft5.c1
6250+
-> Foreign Scan on public.ft5
6251+
Output: ft5.*, ft5.c1
6252+
Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4"
6253+
(29 rows)
6254+
6255+
UPDATE ft2 SET c3 = 'bar'
6256+
FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
6257+
WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
6258+
RETURNING old, new, ft2, ft2.*, ft4, ft4.*;
6259+
old | new | ft2 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | ft4 | c1 | c2 | c3
6260+
--------------------------------+--------------------------------+--------------------------------+------+----+-----+----+----+----+------------+----+----------------+----+----+--------
6261+
(1206,6,foo,,,,"ft2 ",) | (1206,6,bar,,,,"ft2 ",) | (1206,6,bar,,,,"ft2 ",) | 1206 | 6 | bar | | | | ft2 | | (6,7,AAA006) | 6 | 7 | AAA006
6262+
(1212,12,foo,,,,"ft2 ",) | (1212,12,bar,,,,"ft2 ",) | (1212,12,bar,,,,"ft2 ",) | 1212 | 12 | bar | | | | ft2 | | (12,13,AAA012) | 12 | 13 | AAA012
6263+
(1224,24,foo,,,,"ft2 ",) | (1224,24,bar,,,,"ft2 ",) | (1224,24,bar,,,,"ft2 ",) | 1224 | 24 | bar | | | | ft2 | | (24,25,AAA024) | 24 | 25 | AAA024
6264+
(1230,30,foo,,,,"ft2 ",) | (1230,30,bar,,,,"ft2 ",) | (1230,30,bar,,,,"ft2 ",) | 1230 | 30 | bar | | | | ft2 | | (30,31,AAA030) | 30 | 31 | AAA030
6265+
(1242,42,foo,,,,"ft2 ",) | (1242,42,bar,,,,"ft2 ",) | (1242,42,bar,,,,"ft2 ",) | 1242 | 42 | bar | | | | ft2 | | (42,43,AAA042) | 42 | 43 | AAA042
6266+
(1248,48,foo,,,,"ft2 ",) | (1248,48,bar,,,,"ft2 ",) | (1248,48,bar,,,,"ft2 ",) | 1248 | 48 | bar | | | | ft2 | | (48,49,AAA048) | 48 | 49 | AAA048
6267+
(1260,60,foo,,,,"ft2 ",) | (1260,60,bar,,,,"ft2 ",) | (1260,60,bar,,,,"ft2 ",) | 1260 | 60 | bar | | | | ft2 | | (60,61,AAA060) | 60 | 61 | AAA060
6268+
(1266,66,foo,,,,"ft2 ",) | (1266,66,bar,,,,"ft2 ",) | (1266,66,bar,,,,"ft2 ",) | 1266 | 66 | bar | | | | ft2 | | (66,67,AAA066) | 66 | 67 | AAA066
6269+
(1278,78,foo,,,,"ft2 ",) | (1278,78,bar,,,,"ft2 ",) | (1278,78,bar,,,,"ft2 ",) | 1278 | 78 | bar | | | | ft2 | | (78,79,AAA078) | 78 | 79 | AAA078
6270+
(1284,84,foo,,,,"ft2 ",) | (1284,84,bar,,,,"ft2 ",) | (1284,84,bar,,,,"ft2 ",) | 1284 | 84 | bar | | | | ft2 | | (84,85,AAA084) | 84 | 85 | AAA084
6271+
(1296,96,foo,,,,"ft2 ",) | (1296,96,bar,,,,"ft2 ",) | (1296,96,bar,,,,"ft2 ",) | 1296 | 96 | bar | | | | ft2 | | (96,97,AAA096) | 96 | 97 | AAA096
6272+
(1218,18,foo,,,,"ft2 ",) | (1218,18,bar,,,,"ft2 ",) | (1218,18,bar,,,,"ft2 ",) | 1218 | 18 | bar | | | | ft2 | | (18,19,AAA018) | 18 | 19 | AAA018
6273+
(1236,36,foo,,,,"ft2 ",) | (1236,36,bar,,,,"ft2 ",) | (1236,36,bar,,,,"ft2 ",) | 1236 | 36 | bar | | | | ft2 | | (36,37,AAA036) | 36 | 37 | AAA036
6274+
(1254,54,foo,,,,"ft2 ",) | (1254,54,bar,,,,"ft2 ",) | (1254,54,bar,,,,"ft2 ",) | 1254 | 54 | bar | | | | ft2 | | (54,55,AAA054) | 54 | 55 | AAA054
6275+
(1272,72,foo,,,,"ft2 ",) | (1272,72,bar,,,,"ft2 ",) | (1272,72,bar,,,,"ft2 ",) | 1272 | 72 | bar | | | | ft2 | | (72,73,AAA072) | 72 | 73 | AAA072
6276+
(1290,90,foo,,,,"ft2 ",) | (1290,90,bar,,,,"ft2 ",) | (1290,90,bar,,,,"ft2 ",) | 1290 | 90 | bar | | | | ft2 | | (90,91,AAA090) | 90 | 91 | AAA090
6277+
(16 rows)
6278+
6279+
ROLLBACK;
61686280
EXPLAIN (verbose, costs off)
61696281
DELETE FROM ft2
61706282
USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1)

contrib/postgres_fdw/sql/postgres_fdw.sql

+24-1
Original file line numberDiff line numberDiff line change
@@ -1469,14 +1469,21 @@ EXPLAIN (verbose, costs off)
14691469
INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
14701470
INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
14711471
INSERT INTO ft2 (c1,c2,c3)
1472-
VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING *;
1472+
VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING old, new, old.*, new.*;
14731473
INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee');
14741474
EXPLAIN (verbose, costs off)
14751475
UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; -- can be pushed down
14761476
UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3;
14771477
EXPLAIN (verbose, costs off)
14781478
UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *; -- can be pushed down
14791479
UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *;
1480+
BEGIN;
1481+
EXPLAIN (verbose, costs off)
1482+
UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7b' WHERE c1 % 10 = 7 AND c1 < 40
1483+
RETURNING old.*, new.*; -- can't be pushed down
1484+
UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7b' WHERE c1 % 10 = 7 AND c1 < 40
1485+
RETURNING old.*, new.*;
1486+
ROLLBACK;
14801487
EXPLAIN (verbose, costs off)
14811488
UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
14821489
FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down
@@ -1485,6 +1492,11 @@ UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
14851492
EXPLAIN (verbose, costs off)
14861493
DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4; -- can be pushed down
14871494
DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4;
1495+
BEGIN;
1496+
EXPLAIN (verbose, costs off)
1497+
DELETE FROM ft2 WHERE c1 % 10 = 6 AND c1 < 40 RETURNING old.c1, c4; -- can't be pushed down
1498+
DELETE FROM ft2 WHERE c1 % 10 = 6 AND c1 < 40 RETURNING old.c1, c4;
1499+
ROLLBACK;
14881500
EXPLAIN (verbose, costs off)
14891501
DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down
14901502
DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;
@@ -1511,6 +1523,17 @@ UPDATE ft2 SET c3 = 'foo'
15111523
FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
15121524
WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
15131525
RETURNING ft2, ft2.*, ft4, ft4.*;
1526+
BEGIN;
1527+
EXPLAIN (verbose, costs off)
1528+
UPDATE ft2 SET c3 = 'bar'
1529+
FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
1530+
WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
1531+
RETURNING old, new, ft2, ft2.*, ft4, ft4.*; -- can't be pushed down
1532+
UPDATE ft2 SET c3 = 'bar'
1533+
FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
1534+
WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
1535+
RETURNING old, new, ft2, ft2.*, ft4, ft4.*;
1536+
ROLLBACK;
15141537
EXPLAIN (verbose, costs off)
15151538
DELETE FROM ft2
15161539
USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1)

doc/src/sgml/dml.sgml

+37-4
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ DELETE FROM products;
308308
</para>
309309

310310
<para>
311-
In an <command>INSERT</command>, the data available to <literal>RETURNING</literal> is
311+
In an <command>INSERT</command>, the default data available to
312+
<literal>RETURNING</literal> is
312313
the row as it was inserted. This is not so useful in trivial inserts,
313314
since it would just repeat the data provided by the client. But it can
314315
be very handy when relying on computed default values. For example,
@@ -325,7 +326,8 @@ INSERT INTO users (firstname, lastname) VALUES ('Joe', 'Cool') RETURNING id;
325326
</para>
326327

327328
<para>
328-
In an <command>UPDATE</command>, the data available to <literal>RETURNING</literal> is
329+
In an <command>UPDATE</command>, the default data available to
330+
<literal>RETURNING</literal> is
329331
the new content of the modified row. For example:
330332
<programlisting>
331333
UPDATE products SET price = price * 1.10
@@ -335,7 +337,8 @@ UPDATE products SET price = price * 1.10
335337
</para>
336338

337339
<para>
338-
In a <command>DELETE</command>, the data available to <literal>RETURNING</literal> is
340+
In a <command>DELETE</command>, the default data available to
341+
<literal>RETURNING</literal> is
339342
the content of the deleted row. For example:
340343
<programlisting>
341344
DELETE FROM products
@@ -345,7 +348,8 @@ DELETE FROM products
345348
</para>
346349

347350
<para>
348-
In a <command>MERGE</command>, the data available to <literal>RETURNING</literal> is
351+
In a <command>MERGE</command>, the default data available to
352+
<literal>RETURNING</literal> is
349353
the content of the source row plus the content of the inserted, updated, or
350354
deleted target row. Since it is quite common for the source and target to
351355
have many of the same columns, specifying <literal>RETURNING *</literal>
@@ -359,6 +363,35 @@ MERGE INTO products p USING new_products n ON p.product_no = n.product_no
359363
</programlisting>
360364
</para>
361365

366+
<para>
367+
In each of these commands, it is also possible to explicitly return the
368+
old and new content of the modified row. For example:
369+
<programlisting>
370+
UPDATE products SET price = price * 1.10
371+
WHERE price &lt;= 99.99
372+
RETURNING name, old.price AS old_price, new.price AS new_price,
373+
new.price - old.price AS price_change;
374+
</programlisting>
375+
In this example, writing <literal>new.price</literal> is the same as
376+
just writing <literal>price</literal>, but it makes the meaning clearer.
377+
</para>
378+
379+
<para>
380+
This syntax for returning old and new values is available in
381+
<command>INSERT</command>, <command>UPDATE</command>,
382+
<command>DELETE</command>, and <command>MERGE</command> commands, but
383+
typically old values will be <literal>NULL</literal> for an
384+
<command>INSERT</command>, and new values will be <literal>NULL</literal>
385+
for a <command>DELETE</command>. However, there are situations where it
386+
can still be useful for those commands. For example, in an
387+
<command>INSERT</command> with an
388+
<link linkend="sql-on-conflict"><literal>ON CONFLICT DO UPDATE</literal></link>
389+
clause, the old values will be non-<literal>NULL</literal> for conflicting
390+
rows. Similarly, if a <command>DELETE</command> is turned into an
391+
<command>UPDATE</command> by a <link linkend="sql-createrule">rewrite rule</link>,
392+
the new values may be non-<literal>NULL</literal>.
393+
</para>
394+
362395
<para>
363396
If there are triggers (<xref linkend="triggers"/>) on the target table,
364397
the data available to <literal>RETURNING</literal> is the row as modified by

0 commit comments

Comments
 (0)