Commit fc0d9b8c authored by John Naylor's avatar John Naylor

Disallow negative strides in date_bin()

It's not clear what the semantics of negative strides would be, so throw
an error instead.

Per report from Bauyrzhan Sakhariyev

Reviewed-by: Tom Lane, Michael Paquier
Discussion: https://www.postgresql.org/message-id/CAKpL73vZmLuFVuwF26FJ%2BNk11PVHhAnQRoREFcA03x7znRoFvA%40mail.gmail.com
Backpatch to v14
parent 5a8a9be0
...@@ -10008,12 +10008,8 @@ SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-0 ...@@ -10008,12 +10008,8 @@ SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-0
</para> </para>
<para> <para>
Negative intervals are allowed and are treated the same as positive intervals. The <parameter>stride</parameter> interval must be greater than zero and
</para> cannot contain units of month or larger.
<para>
The <parameter>stride</parameter> interval cannot contain units of month
or larger.
</para> </para>
</sect2> </sect2>
......
...@@ -3843,10 +3843,10 @@ timestamp_bin(PG_FUNCTION_ARGS) ...@@ -3843,10 +3843,10 @@ timestamp_bin(PG_FUNCTION_ARGS)
stride_usecs = stride->day * USECS_PER_DAY + stride->time; stride_usecs = stride->day * USECS_PER_DAY + stride->time;
if (stride_usecs == 0) if (stride_usecs <= 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("stride cannot equal zero"))); errmsg("stride must be greater than zero")));
tm_diff = timestamp - origin; tm_diff = timestamp - origin;
tm_delta = tm_diff - tm_diff % stride_usecs; tm_delta = tm_diff - tm_diff % stride_usecs;
...@@ -4026,10 +4026,10 @@ timestamptz_bin(PG_FUNCTION_ARGS) ...@@ -4026,10 +4026,10 @@ timestamptz_bin(PG_FUNCTION_ARGS)
stride_usecs = stride->day * USECS_PER_DAY + stride->time; stride_usecs = stride->day * USECS_PER_DAY + stride->time;
if (stride_usecs == 0) if (stride_usecs <= 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("stride cannot equal zero"))); errmsg("stride must be greater than zero")));
tm_diff = timestamp - origin; tm_diff = timestamp - origin;
tm_delta = tm_diff - tm_diff % stride_usecs; tm_delta = tm_diff - tm_diff % stride_usecs;
......
...@@ -706,7 +706,10 @@ SELECT date_bin('5 years'::interval, timestamp '2020-02-01 01:01:01', timestamp ...@@ -706,7 +706,10 @@ SELECT date_bin('5 years'::interval, timestamp '2020-02-01 01:01:01', timestamp
ERROR: timestamps cannot be binned into intervals containing months or years ERROR: timestamps cannot be binned into intervals containing months or years
-- disallow zero intervals -- disallow zero intervals
SELECT date_bin('0 days'::interval, timestamp '1970-01-01 01:00:00' , timestamp '1970-01-01 00:00:00'); SELECT date_bin('0 days'::interval, timestamp '1970-01-01 01:00:00' , timestamp '1970-01-01 00:00:00');
ERROR: stride cannot equal zero ERROR: stride must be greater than zero
-- disallow negative intervals
SELECT date_bin('-2 days'::interval, timestamp '1970-01-01 01:00:00' , timestamp '1970-01-01 00:00:00');
ERROR: stride must be greater than zero
-- Test casting within a BETWEEN qualifier -- Test casting within a BETWEEN qualifier
SELECT d1 - timestamp without time zone '1997-01-02' AS diff SELECT d1 - timestamp without time zone '1997-01-02' AS diff
FROM TIMESTAMP_TBL FROM TIMESTAMP_TBL
......
...@@ -750,7 +750,10 @@ SELECT date_bin('5 years'::interval, timestamp with time zone '2020-02-01 01:01 ...@@ -750,7 +750,10 @@ SELECT date_bin('5 years'::interval, timestamp with time zone '2020-02-01 01:01
ERROR: timestamps cannot be binned into intervals containing months or years ERROR: timestamps cannot be binned into intervals containing months or years
-- disallow zero intervals -- disallow zero intervals
SELECT date_bin('0 days'::interval, timestamp with time zone '1970-01-01 01:00:00+00' , timestamp with time zone '1970-01-01 00:00:00+00'); SELECT date_bin('0 days'::interval, timestamp with time zone '1970-01-01 01:00:00+00' , timestamp with time zone '1970-01-01 00:00:00+00');
ERROR: stride cannot equal zero ERROR: stride must be greater than zero
-- disallow negative intervals
SELECT date_bin('-2 days'::interval, timestamp with time zone '1970-01-01 01:00:00+00' , timestamp with time zone '1970-01-01 00:00:00+00');
ERROR: stride must be greater than zero
-- Test casting within a BETWEEN qualifier -- Test casting within a BETWEEN qualifier
SELECT d1 - timestamp with time zone '1997-01-02' AS diff SELECT d1 - timestamp with time zone '1997-01-02' AS diff
FROM TIMESTAMPTZ_TBL FROM TIMESTAMPTZ_TBL
......
...@@ -266,6 +266,9 @@ SELECT date_bin('5 years'::interval, timestamp '2020-02-01 01:01:01', timestamp ...@@ -266,6 +266,9 @@ SELECT date_bin('5 years'::interval, timestamp '2020-02-01 01:01:01', timestamp
-- disallow zero intervals -- disallow zero intervals
SELECT date_bin('0 days'::interval, timestamp '1970-01-01 01:00:00' , timestamp '1970-01-01 00:00:00'); SELECT date_bin('0 days'::interval, timestamp '1970-01-01 01:00:00' , timestamp '1970-01-01 00:00:00');
-- disallow negative intervals
SELECT date_bin('-2 days'::interval, timestamp '1970-01-01 01:00:00' , timestamp '1970-01-01 00:00:00');
-- Test casting within a BETWEEN qualifier -- Test casting within a BETWEEN qualifier
SELECT d1 - timestamp without time zone '1997-01-02' AS diff SELECT d1 - timestamp without time zone '1997-01-02' AS diff
FROM TIMESTAMP_TBL FROM TIMESTAMP_TBL
......
...@@ -241,6 +241,9 @@ SELECT date_bin('5 years'::interval, timestamp with time zone '2020-02-01 01:01 ...@@ -241,6 +241,9 @@ SELECT date_bin('5 years'::interval, timestamp with time zone '2020-02-01 01:01
-- disallow zero intervals -- disallow zero intervals
SELECT date_bin('0 days'::interval, timestamp with time zone '1970-01-01 01:00:00+00' , timestamp with time zone '1970-01-01 00:00:00+00'); SELECT date_bin('0 days'::interval, timestamp with time zone '1970-01-01 01:00:00+00' , timestamp with time zone '1970-01-01 00:00:00+00');
-- disallow negative intervals
SELECT date_bin('-2 days'::interval, timestamp with time zone '1970-01-01 01:00:00+00' , timestamp with time zone '1970-01-01 00:00:00+00');
-- Test casting within a BETWEEN qualifier -- Test casting within a BETWEEN qualifier
SELECT d1 - timestamp with time zone '1997-01-02' AS diff SELECT d1 - timestamp with time zone '1997-01-02' AS diff
FROM TIMESTAMPTZ_TBL FROM TIMESTAMPTZ_TBL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment