如何在Postgres中创建包含上限的新日期范围类型?

dth*_*dor 4 postgresql date-range

Postgres附带了一个名为Range Types的很好的功能,它提供了有用的范围功能(重叠,包含等).

我希望使用该daterange类型,但我认为类型是用一个尴尬的选择实现的:排除了日期范围的上限.这意味着如果我将我的值定义为2014/01/01 - 2014/01/31,则显示为,[2014/01/01, 2014/01/31)并且1月31日被排除在范围之外!

我认为这是错误的默认选择.我不能想到现实生活中的任何应用或参考,假设排除了日期范围的结束日期.至少不是我的经验.

我想为包含下限和上限的日期实现范围类型,但是我正在使用Postgres文档墙:关于如何创建新的离散范围类型的参考是神秘的,缺少任何示例(取自文档:创建一个规范函数有点棘手,因为必须在声明范围类型之前定义它.

有人可以提供一些帮助吗?甚至直接实施本身; 它应该是5-10行代码,但将这5-10行放在一起是一项严肃的研究工作.

编辑:澄清:我正在寻找有关如何创建正确类型的信息,以便插入[2014/01/01, 2014/01/31]结果upper(daterange) = '2014/01/31'.使用现有的日期范围类型,此值将"转换"为a [2014/01/01, 2014/02/01)并给出aupper(daterange) = '2014/02/01'

Clo*_*eto 7

注意第三个构造函数参数:

select daterange('2014/01/01', '2014/01/31', '[]');
        daterange        
-------------------------
 [2014-01-01,2014-02-01)
Run Code Online (Sandbox Code Playgroud)

或者包含上限的直接演员:

select '[2014/01/01, 2014/01/31]'::daterange;
        daterange        
-------------------------
 [2014-01-01,2014-02-01)
Run Code Online (Sandbox Code Playgroud)

编辑

不是一种新的类型(错误的方法恕我直言),但一个适当的功能:

create function inclusive_upper_daterange(dtr daterange)
returns date as $$

    select upper(dtr) - 1;

$$ language sql immutable;

select inclusive_upper_daterange('[2014/01/01, 2014/01/31]'::daterange);
 inclusive_upper_daterange 
---------------------------
 2014-01-31
Run Code Online (Sandbox Code Playgroud)


dth*_*dor 0

按照 Postgres 文档上的说明,我想出了以下代码来创建我需要的类型。然而它不会工作(继续阅读)。

CREATE TYPE daterange_;

CREATE FUNCTION date_minus(date1 date, date2 date) RETURNS float AS $$
    SELECT cast(date1 - date2 as float);
$$ LANGUAGE sql immutable;

CREATE FUNCTION dr_canonical(dr daterange_) RETURNS daterange_ AS $$
BEGIN
    IF NOT lower_inc(dr) THEN
        dr := daterange_(lower(dr) + 1, upper(dr), '[]');
    END IF;
    IF NOT upper_inc(dr) THEN
        dr := daterange_(lower(dr), upper(dr) - 1, '[]');
    END IF;
    RETURN dr;
END;
$$ LANGUAGE plpgsql;

CREATE TYPE daterange_ AS RANGE (
    SUBTYPE = date,
    SUBTYPE_DIFF = date_minus,
    CANONICAL = dr_canonical    
);
Run Code Online (Sandbox Code Playgroud)

据我所知,这个定义完全符合规范。但是,它无法使用 声明该dr_canonical函数ERROR: SQL function cannot accept shell type daterange_

看起来 (也包括代码)不可能使用 C 以外的任何语言来声明规范函数!因此,声明新的离散范围类型实际上是不可能的,特别是如果您使用无法访问运行它的计算机的 Postgres 云服务。Postgres 发挥得很好。