if (resultRelInfo->ri_WithCheckOptions != NIL)
ExecWithCheckOptions(WCO_VIEW_CHECK, resultRelInfo, slot, estate);
- /* Process RETURNING if present */
- if (resultRelInfo->ri_projectReturning)
+ /*
+ * Process RETURNING if present.
+ *
+ * If this is an UPDATE/DELETE ... FOR PORTION OF, we do not return the
+ * leftover rows inserted by ExecForPortionOfLeftovers(). Note that we
+ * must check mtstate->operation here, because we *do* want to process the
+ * newly inserted row of a cross-partition UPDATE with a FOR PORTION OF
+ * clause (ExecCrossPartitionUpdate() leaves mtstate->operation set to
+ * CMD_UPDATE, whereas ExecForPortionOfLeftovers() sets it to CMD_INSERT).
+ */
+ if (resultRelInfo->ri_projectReturning &&
+ !(node->forPortionOf && mtstate->operation == CMD_INSERT))
{
TupleTableSlot *oldSlot = NULL;
\set QUIET true
-- UPDATE ... RETURNING returns only the updated values
-- (not the inserted side values, which are added by a separate "statement"):
+CREATE FUNCTION fpo_returning_row(text)
+RETURNS text LANGUAGE plpgsql AS
+$$
+BEGIN
+ RAISE NOTICE 'RETURNING %', $1;
+ RETURN $1;
+END;
+$$;
UPDATE for_portion_of_test
FOR PORTION OF valid_at FROM '2018-02-01' TO '2018-02-15'
SET name = 'three^3'
WHERE id = '[3,4)'
- RETURNING *;
- id | valid_at | name
--------+-------------------------+---------
- [3,4) | [2018-02-01,2018-02-15) | three^3
+ RETURNING *, fpo_returning_row(for_portion_of_test::text);
+NOTICE: RETURNING ("[3,4)","[2018-02-01,2018-02-15)",three^3)
+ id | valid_at | name | fpo_returning_row
+-------+-------------------------+---------+---------------------------------------------
+ [3,4) | [2018-02-01,2018-02-15) | three^3 | ("[3,4)","[2018-02-01,2018-02-15)",three^3)
(1 row)
-- UPDATE ... RETURNING supports NEW and OLD valid_at
DELETE FROM for_portion_of_test
FOR PORTION OF valid_at FROM '2018-02-02' TO '2018-02-03'
WHERE id = '[3,4)'
- RETURNING *;
- id | valid_at | name
--------+-------------------------+---------
- [3,4) | [2018-02-01,2018-02-10) | three^3
+ RETURNING *, fpo_returning_row(for_portion_of_test::text);
+NOTICE: RETURNING ("[3,4)","[2018-02-01,2018-02-10)",three^3)
+ id | valid_at | name | fpo_returning_row
+-------+-------------------------+---------+---------------------------------------------
+ [3,4) | [2018-02-01,2018-02-10) | three^3 | ("[3,4)","[2018-02-01,2018-02-10)",three^3)
(1 row)
-- DELETE FOR PORTION OF in a PL/pgSQL function
UPDATE temporal_partitioned FOR PORTION OF valid_at FROM '2000-06-01' TO '2000-07-01'
SET name = 'one^2',
id = '[4,5)'
- WHERE id = '[1,2)';
+ WHERE id = '[1,2)'
+ RETURNING id, valid_at, name, fpo_returning_row(temporal_partitioned::text);
+NOTICE: RETURNING ("[4,5)","[2000-06-01,2000-07-01)",one^2,30)
+ id | valid_at | name | fpo_returning_row
+-------+-------------------------+-------+----------------------------------------------
+ [4,5) | [2000-06-01,2000-07-01) | one^2 | ("[4,5)","[2000-06-01,2000-07-01)",one^2,30)
+(1 row)
+
-- Move from partition 3 to partition 1
UPDATE temporal_partitioned FOR PORTION OF valid_at FROM '2000-06-01' TO '2000-07-01'
SET name = 'three^2',
five | [2000-07-01,2010-01-01) | [5,6) | 3471
(4 rows)
+DROP FUNCTION fpo_returning_row;
DROP TABLE temporal_partitioned;
-- UPDATE/DELETE FOR PORTION OF with RULEs
CREATE TABLE fpo_rule (f1 bigint, f2 int4range);
-- UPDATE ... RETURNING returns only the updated values
-- (not the inserted side values, which are added by a separate "statement"):
+CREATE FUNCTION fpo_returning_row(text)
+RETURNS text LANGUAGE plpgsql AS
+$$
+BEGIN
+ RAISE NOTICE 'RETURNING %', $1;
+ RETURN $1;
+END;
+$$;
UPDATE for_portion_of_test
FOR PORTION OF valid_at FROM '2018-02-01' TO '2018-02-15'
SET name = 'three^3'
WHERE id = '[3,4)'
- RETURNING *;
+ RETURNING *, fpo_returning_row(for_portion_of_test::text);
-- UPDATE ... RETURNING supports NEW and OLD valid_at
UPDATE for_portion_of_test
DELETE FROM for_portion_of_test
FOR PORTION OF valid_at FROM '2018-02-02' TO '2018-02-03'
WHERE id = '[3,4)'
- RETURNING *;
+ RETURNING *, fpo_returning_row(for_portion_of_test::text);
-- DELETE FOR PORTION OF in a PL/pgSQL function
INSERT INTO for_portion_of_test (id, valid_at, name) VALUES
UPDATE temporal_partitioned FOR PORTION OF valid_at FROM '2000-06-01' TO '2000-07-01'
SET name = 'one^2',
id = '[4,5)'
- WHERE id = '[1,2)';
+ WHERE id = '[1,2)'
+ RETURNING id, valid_at, name, fpo_returning_row(temporal_partitioned::text);
-- Move from partition 3 to partition 1
UPDATE temporal_partitioned FOR PORTION OF valid_at FROM '2000-06-01' TO '2000-07-01'
SELECT * FROM temporal_partitioned_3 ORDER BY id, valid_at;
SELECT * FROM temporal_partitioned_5 ORDER BY id, valid_at;
+DROP FUNCTION fpo_returning_row;
DROP TABLE temporal_partitioned;
-- UPDATE/DELETE FOR PORTION OF with RULEs