mirror of
https://github.com/postgres/postgres.git
synced 2025-12-19 17:02:53 +03:00
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 <pj@illuminatedcomputing.com> Reviewed-by: Peter Eisentraut <peter@eisentraut.org> Reviewed-by: Chao Li <li.evan.chao@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/ec498c3d-5f2b-48ec-b989-5561c8aa2024%40illuminatedcomputing.com
This commit is contained in:
@@ -2200,6 +2200,122 @@ SELECT nummultirange(numrange(1,2), numrange(4,5)) - nummultirange(numrange(-2,0
|
||||
{[1,2),[4,5)}
|
||||
(1 row)
|
||||
|
||||
-- multirange_minus_multi
|
||||
SELECT multirange_minus_multi(nummultirange(), nummultirange());
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
(0 rows)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(), nummultirange(numrange(1,2)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
(0 rows)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2)), nummultirange());
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(3,4)), nummultirange());
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2),[3,4)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2)), nummultirange(numrange(1,2)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
(0 rows)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2)), nummultirange(numrange(2,4)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2)), nummultirange(numrange(3,4)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,4)), nummultirange(numrange(1,2)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[2,4)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,4)), nummultirange(numrange(2,3)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2),[3,4)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,4)), nummultirange(numrange(0,8)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
(0 rows)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,4)), nummultirange(numrange(0,2)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[2,4)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,8)), nummultirange(numrange(0,2), numrange(3,4)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[2,3),[4,8)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,8)), nummultirange(numrange(2,3), numrange(5,null)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2),[3,5)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(-2,0)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2),[4,5)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(2,4)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2),[4,5)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(3,5)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(0,9)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
(0 rows)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,3), numrange(4,5)), nummultirange(numrange(2,9)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(8,9)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2),[4,5)}
|
||||
(1 row)
|
||||
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(-2,0), numrange(8,9)));
|
||||
multirange_minus_multi
|
||||
------------------------
|
||||
{[1,2),[4,5)}
|
||||
(1 row)
|
||||
|
||||
-- intersection
|
||||
SELECT nummultirange() * nummultirange();
|
||||
?column?
|
||||
|
||||
@@ -481,6 +481,60 @@ select range_minus(numrange(10.1,12.2,'[]'), numrange(0.0,120.2,'(]'));
|
||||
empty
|
||||
(1 row)
|
||||
|
||||
select range_minus_multi('empty'::numrange, numrange(2.0, 3.0));
|
||||
range_minus_multi
|
||||
-------------------
|
||||
(0 rows)
|
||||
|
||||
select range_minus_multi(numrange(1.1, 2.2), 'empty'::numrange);
|
||||
range_minus_multi
|
||||
-------------------
|
||||
[1.1,2.2)
|
||||
(1 row)
|
||||
|
||||
select range_minus_multi(numrange(1.1, 2.2), numrange(2.0, 3.0));
|
||||
range_minus_multi
|
||||
-------------------
|
||||
[1.1,2.0)
|
||||
(1 row)
|
||||
|
||||
select range_minus_multi(numrange(1.1, 2.2), numrange(2.2, 3.0));
|
||||
range_minus_multi
|
||||
-------------------
|
||||
[1.1,2.2)
|
||||
(1 row)
|
||||
|
||||
select range_minus_multi(numrange(1.1, 2.2,'[]'), numrange(2.0, 3.0));
|
||||
range_minus_multi
|
||||
-------------------
|
||||
[1.1,2.0)
|
||||
(1 row)
|
||||
|
||||
select range_minus_multi(numrange(1.0, 3.0), numrange(1.5, 2.0));
|
||||
range_minus_multi
|
||||
-------------------
|
||||
[1.0,1.5)
|
||||
[2.0,3.0)
|
||||
(2 rows)
|
||||
|
||||
select range_minus_multi(numrange(10.1,12.2,'[]'), numrange(110.0,120.2,'(]'));
|
||||
range_minus_multi
|
||||
-------------------
|
||||
[10.1,12.2]
|
||||
(1 row)
|
||||
|
||||
select range_minus_multi(numrange(10.1,12.2,'[]'), numrange(0.0,120.2,'(]'));
|
||||
range_minus_multi
|
||||
-------------------
|
||||
(0 rows)
|
||||
|
||||
select range_minus_multi(numrange(1.0,3.0,'[]'), numrange(1.5,2.0,'(]'));
|
||||
range_minus_multi
|
||||
-------------------
|
||||
[1.0,1.5]
|
||||
(2.0,3.0]
|
||||
(2 rows)
|
||||
|
||||
select numrange(4.5, 5.5, '[]') && numrange(5.5, 6.5);
|
||||
?column?
|
||||
----------
|
||||
|
||||
@@ -414,6 +414,28 @@ SELECT nummultirange(numrange(1,3), numrange(4,5)) - nummultirange(numrange(2,9)
|
||||
SELECT nummultirange(numrange(1,2), numrange(4,5)) - nummultirange(numrange(8,9));
|
||||
SELECT nummultirange(numrange(1,2), numrange(4,5)) - nummultirange(numrange(-2,0), numrange(8,9));
|
||||
|
||||
-- multirange_minus_multi
|
||||
SELECT multirange_minus_multi(nummultirange(), nummultirange());
|
||||
SELECT multirange_minus_multi(nummultirange(), nummultirange(numrange(1,2)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2)), nummultirange());
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(3,4)), nummultirange());
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2)), nummultirange(numrange(1,2)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2)), nummultirange(numrange(2,4)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2)), nummultirange(numrange(3,4)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,4)), nummultirange(numrange(1,2)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,4)), nummultirange(numrange(2,3)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,4)), nummultirange(numrange(0,8)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,4)), nummultirange(numrange(0,2)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,8)), nummultirange(numrange(0,2), numrange(3,4)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,8)), nummultirange(numrange(2,3), numrange(5,null)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(-2,0)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(2,4)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(3,5)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(0,9)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,3), numrange(4,5)), nummultirange(numrange(2,9)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(8,9)));
|
||||
SELECT multirange_minus_multi(nummultirange(numrange(1,2), numrange(4,5)), nummultirange(numrange(-2,0), numrange(8,9)));
|
||||
|
||||
-- intersection
|
||||
SELECT nummultirange() * nummultirange();
|
||||
SELECT nummultirange() * nummultirange(numrange(1,2));
|
||||
|
||||
@@ -107,6 +107,16 @@ select numrange(1.1, 2.2,'[]') - numrange(2.0, 3.0);
|
||||
select range_minus(numrange(10.1,12.2,'[]'), numrange(110.0,120.2,'(]'));
|
||||
select range_minus(numrange(10.1,12.2,'[]'), numrange(0.0,120.2,'(]'));
|
||||
|
||||
select range_minus_multi('empty'::numrange, numrange(2.0, 3.0));
|
||||
select range_minus_multi(numrange(1.1, 2.2), 'empty'::numrange);
|
||||
select range_minus_multi(numrange(1.1, 2.2), numrange(2.0, 3.0));
|
||||
select range_minus_multi(numrange(1.1, 2.2), numrange(2.2, 3.0));
|
||||
select range_minus_multi(numrange(1.1, 2.2,'[]'), numrange(2.0, 3.0));
|
||||
select range_minus_multi(numrange(1.0, 3.0), numrange(1.5, 2.0));
|
||||
select range_minus_multi(numrange(10.1,12.2,'[]'), numrange(110.0,120.2,'(]'));
|
||||
select range_minus_multi(numrange(10.1,12.2,'[]'), numrange(0.0,120.2,'(]'));
|
||||
select range_minus_multi(numrange(1.0,3.0,'[]'), numrange(1.5,2.0,'(]'));
|
||||
|
||||
select numrange(4.5, 5.5, '[]') && numrange(5.5, 6.5);
|
||||
select numrange(1.0, 2.0) << numrange(3.0, 4.0);
|
||||
select numrange(1.0, 3.0,'[]') << numrange(3.0, 4.0,'[]');
|
||||
|
||||
Reference in New Issue
Block a user