Update lower/upper bound of range type

As far as I know, using CASE WHEN... is the best way to get the bounds. Here are some simple user-defined functions that return the range bounds for all the native range types.

Warning: These functions behave in surprising ways, because the range types behave in sometimes surprising ways.

The built-in range types int4range, int8range, and daterange all use a canonical form that includes the lower bound and excludes the upper bound; that is, [).

And

Although '(]' is specified here, on display the value will be converted to canonical form, since int8range is a discrete range type . . .

(emphasis added)

PostgreSQL canonicalizes the closed range from 1 to 10 as a half open range from 1 to 11.

select int4range('[1,10]');
[1,11)

It does the same thing for ranges that are half open on the left.

select int4range('(1,10]');
[2,11)

range_bounds() returns the bounds for result, not for the input.

select range_bounds(int4range('(1,10]'));
[)

The functions

create or replace function range_bounds(in range int4range)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range int8range)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range numrange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;


create or replace function range_bounds(in range tsrange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range tstzrange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range daterange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

I found function I missed, it's possible to do that like this

UPDATE table
SET
    my_column = tstzrange(
        lower(my_column),
        now(),
        concat(
            CASE WHEN lower_inc(my_column) THEN '[' ELSE '(' END,
            CASE WHEN upper_inc(my_column) THEN ']' ELSE ')' END
        )
    )

It would be better to create function for this probably. Or is there any other (simpler/better) solution?

Tags:

Postgresql