From 5eed8ce50ce9df1067b95593dde9f4fc526dfc72 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Sat, 22 Nov 2025 09:40:00 +0100 Subject: Add range_minus_multi and multirange_minus_multi functions The existing range_minus function raises an exception when the range is "split", because then the result can't be represented by a single range. For example '[0,10)'::int4range - '[4,5)' would be '[0,4)' and '[5,10)'. This commit adds new set-returning functions so that callers can get results even in the case of splits. There is no risk of an exception for multiranges, but a set-returning function lets us handle them the same way we handle ranges. Both functions return zero results if the subtraction would give an empty range/multirange. The main use-case for these functions is to implement UPDATE/DELETE FOR PORTION OF, which must compute the application-time of "temporal leftovers": the part of history in an updated/deleted row that was not changed. To preserve the untouched history, we will implicitly insert one record for each result returned by range/multirange_minus_multi. Using a set-returning function will also let us support user-defined types for application-time update/delete in the future. Author: Paul A. Jungwirth Reviewed-by: Peter Eisentraut Reviewed-by: Chao Li Discussion: https://www.postgresql.org/message-id/flat/ec498c3d-5f2b-48ec-b989-5561c8aa2024%40illuminatedcomputing.com --- doc/src/sgml/func/func-range.sgml | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'doc/src') diff --git a/doc/src/sgml/func/func-range.sgml b/doc/src/sgml/func/func-range.sgml index 2dc40348a57..3c5a34796a1 100644 --- a/doc/src/sgml/func/func-range.sgml +++ b/doc/src/sgml/func/func-range.sgml @@ -842,6 +842,29 @@ [1,4) + + + + + range_minus_multi + + range_minus_multi ( anyrange, anyrange ) + setof anyrange + + + Returns the non-empty range(s) remaining after subtracting the second range from the first. + One row is returned for each range, so if the second range splits the first into two parts, + there will be two results. If the subtraction yields an empty range, no rows are returned. + + + range_minus_multi('[0,10)'::int4range, '[3,4)'::int4range) + + + [0,3) + [4,10) + + + @@ -1041,6 +1064,25 @@ + + + + + multirange_minus_multi + + multirange_minus_multi ( anymultirange, anymultirange ) + setof anymultirange + + + Returns the non-empty multirange(s) remaining after subtracting the second multirange from the first. + If the subtraction yields an empty multirange, no rows are returned. + Two rows are never returned, because a single multirange can always accommodate any result. + + + multirange_minus_multi('{[0,10)}'::int4multirange, '{[3,4)}'::int4multirange) + {[0,3), [4,10)} + + -- cgit v1.2.3