Support +/- infinity in the interval data type.
This adds support for infinity to the interval data type, using the same input/output representation as the other date/time data types that support infinity. This allows various arithmetic operations on infinite dates, timestamps and intervals. The new values are represented by setting all fields of the interval to INT32/64_MIN for -infinity, and INT32/64_MAX for +infinity. This ensures that they compare as less/greater than all other interval values, without the need for any special-case comparison code. Note that, since those 2 values were formerly accepted as legal finite intervals, pg_upgrade and dump/restore from an old database will turn them from finite to infinite intervals. That seems OK, since those exact values should be extremely rare in practice, and they are outside the documented range supported by the interval type, which gives us a certain amount of leeway. Bump catalog version. Joseph Koshakow, Jian He, and Ashutosh Bapat, reviewed by me. Discussion: https://postgr.es/m/CAAvxfHea4%2BsPybKK7agDYOMo9N-Z3J6ZXf3BOM79pFsFNcRjwA%40mail.gmail.com
This commit is contained in:
parent
b41b1a7f49
commit
519fc1bd9e
|
@ -306,9 +306,8 @@ leftmostvalue_interval(void)
|
|||
{
|
||||
Interval *v = palloc(sizeof(Interval));
|
||||
|
||||
v->time = PG_INT64_MIN;
|
||||
v->day = PG_INT32_MIN;
|
||||
v->month = PG_INT32_MIN;
|
||||
INTERVAL_NOBEGIN(v);
|
||||
|
||||
return IntervalPGetDatum(v);
|
||||
}
|
||||
|
||||
|
|
|
@ -2328,12 +2328,12 @@ TIMESTAMP WITH TIME ZONE '2004-10-19 10:23:54+02'
|
|||
</row>
|
||||
<row>
|
||||
<entry><literal>infinity</literal></entry>
|
||||
<entry><type>date</type>, <type>timestamp</type></entry>
|
||||
<entry><type>date</type>, <type>timestamp</type>, <type>interval</type></entry>
|
||||
<entry>later than all other time stamps</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>-infinity</literal></entry>
|
||||
<entry><type>date</type>, <type>timestamp</type></entry>
|
||||
<entry><type>date</type>, <type>timestamp</type>, <type>interval</type></entry>
|
||||
<entry>earlier than all other time stamps</entry>
|
||||
</row>
|
||||
<row>
|
||||
|
|
|
@ -9565,7 +9565,7 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
|
|||
<returnvalue>boolean</returnvalue>
|
||||
</para>
|
||||
<para>
|
||||
Test for finite interval (currently always true)
|
||||
Test for finite interval (not +/-infinity)
|
||||
</para>
|
||||
<para>
|
||||
<literal>isfinite(interval '4 hours')</literal>
|
||||
|
@ -10462,7 +10462,11 @@ SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
|
|||
When the input value is +/-Infinity, <function>extract</function> returns
|
||||
+/-Infinity for monotonically-increasing fields (<literal>epoch</literal>,
|
||||
<literal>julian</literal>, <literal>year</literal>, <literal>isoyear</literal>,
|
||||
<literal>decade</literal>, <literal>century</literal>, and <literal>millennium</literal>).
|
||||
<literal>decade</literal>, <literal>century</literal>, and <literal>millennium</literal>
|
||||
for <type>timestamp</type> inputs; <literal>epoch</literal>, <literal>hour</literal>,
|
||||
<literal>day</literal>, <literal>year</literal>, <literal>decade</literal>,
|
||||
<literal>century</literal>, and <literal>millennium</literal> for
|
||||
<type>interval</type> inputs).
|
||||
For other fields, NULL is returned. <productname>PostgreSQL</productname>
|
||||
versions before 9.6 returned zero for all cases of infinite input.
|
||||
</para>
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "access/xact.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "common/hashfn.h"
|
||||
#include "common/int.h"
|
||||
#include "libpq/pqformat.h"
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/supportnodes.h"
|
||||
|
@ -2013,6 +2014,11 @@ interval_time(PG_FUNCTION_ARGS)
|
|||
Interval *span = PG_GETARG_INTERVAL_P(0);
|
||||
TimeADT result;
|
||||
|
||||
if (INTERVAL_NOT_FINITE(span))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("cannot convert infinite interval to time")));
|
||||
|
||||
result = span->time % USECS_PER_DAY;
|
||||
if (result < 0)
|
||||
result += USECS_PER_DAY;
|
||||
|
@ -2049,6 +2055,11 @@ time_pl_interval(PG_FUNCTION_ARGS)
|
|||
Interval *span = PG_GETARG_INTERVAL_P(1);
|
||||
TimeADT result;
|
||||
|
||||
if (INTERVAL_NOT_FINITE(span))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("cannot add infinite interval to time")));
|
||||
|
||||
result = time + span->time;
|
||||
result -= result / USECS_PER_DAY * USECS_PER_DAY;
|
||||
if (result < INT64CONST(0))
|
||||
|
@ -2067,6 +2078,11 @@ time_mi_interval(PG_FUNCTION_ARGS)
|
|||
Interval *span = PG_GETARG_INTERVAL_P(1);
|
||||
TimeADT result;
|
||||
|
||||
if (INTERVAL_NOT_FINITE(span))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("cannot subtract infinite interval from time")));
|
||||
|
||||
result = time - span->time;
|
||||
result -= result / USECS_PER_DAY * USECS_PER_DAY;
|
||||
if (result < INT64CONST(0))
|
||||
|
@ -2090,7 +2106,8 @@ in_range_time_interval(PG_FUNCTION_ARGS)
|
|||
|
||||
/*
|
||||
* Like time_pl_interval/time_mi_interval, we disregard the month and day
|
||||
* fields of the offset. So our test for negative should too.
|
||||
* fields of the offset. So our test for negative should too. This also
|
||||
* catches -infinity, so we only need worry about +infinity below.
|
||||
*/
|
||||
if (offset->time < 0)
|
||||
ereport(ERROR,
|
||||
|
@ -2100,13 +2117,14 @@ in_range_time_interval(PG_FUNCTION_ARGS)
|
|||
/*
|
||||
* We can't use time_pl_interval/time_mi_interval here, because their
|
||||
* wraparound behavior would give wrong (or at least undesirable) answers.
|
||||
* Fortunately the equivalent non-wrapping behavior is trivial, especially
|
||||
* since we don't worry about integer overflow.
|
||||
* Fortunately the equivalent non-wrapping behavior is trivial, except
|
||||
* that adding an infinite (or very large) interval might cause integer
|
||||
* overflow. Subtraction cannot overflow here.
|
||||
*/
|
||||
if (sub)
|
||||
sum = base - offset->time;
|
||||
else
|
||||
sum = base + offset->time;
|
||||
else if (pg_add_s64_overflow(base, offset->time, &sum))
|
||||
PG_RETURN_BOOL(less);
|
||||
|
||||
if (less)
|
||||
PG_RETURN_BOOL(val <= sum);
|
||||
|
@ -2581,6 +2599,11 @@ timetz_pl_interval(PG_FUNCTION_ARGS)
|
|||
Interval *span = PG_GETARG_INTERVAL_P(1);
|
||||
TimeTzADT *result;
|
||||
|
||||
if (INTERVAL_NOT_FINITE(span))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("cannot add infinite interval to time")));
|
||||
|
||||
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
||||
|
||||
result->time = time->time + span->time;
|
||||
|
@ -2603,6 +2626,11 @@ timetz_mi_interval(PG_FUNCTION_ARGS)
|
|||
Interval *span = PG_GETARG_INTERVAL_P(1);
|
||||
TimeTzADT *result;
|
||||
|
||||
if (INTERVAL_NOT_FINITE(span))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("cannot subtract infinite interval from time")));
|
||||
|
||||
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
||||
|
||||
result->time = time->time - span->time;
|
||||
|
@ -2630,7 +2658,8 @@ in_range_timetz_interval(PG_FUNCTION_ARGS)
|
|||
|
||||
/*
|
||||
* Like timetz_pl_interval/timetz_mi_interval, we disregard the month and
|
||||
* day fields of the offset. So our test for negative should too.
|
||||
* day fields of the offset. So our test for negative should too. This
|
||||
* also catches -infinity, so we only need worry about +infinity below.
|
||||
*/
|
||||
if (offset->time < 0)
|
||||
ereport(ERROR,
|
||||
|
@ -2640,13 +2669,14 @@ in_range_timetz_interval(PG_FUNCTION_ARGS)
|
|||
/*
|
||||
* We can't use timetz_pl_interval/timetz_mi_interval here, because their
|
||||
* wraparound behavior would give wrong (or at least undesirable) answers.
|
||||
* Fortunately the equivalent non-wrapping behavior is trivial, especially
|
||||
* since we don't worry about integer overflow.
|
||||
* Fortunately the equivalent non-wrapping behavior is trivial, except
|
||||
* that adding an infinite (or very large) interval might cause integer
|
||||
* overflow. Subtraction cannot overflow here.
|
||||
*/
|
||||
if (sub)
|
||||
sum.time = base->time - offset->time;
|
||||
else
|
||||
sum.time = base->time + offset->time;
|
||||
else if (pg_add_s64_overflow(base->time, offset->time, &sum.time))
|
||||
PG_RETURN_BOOL(less);
|
||||
sum.zone = base->zone;
|
||||
|
||||
if (less)
|
||||
|
@ -3096,6 +3126,13 @@ timetz_izone(PG_FUNCTION_ARGS)
|
|||
TimeTzADT *result;
|
||||
int tz;
|
||||
|
||||
if (INTERVAL_NOT_FINITE(zone))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("interval time zone \"%s\" must be finite",
|
||||
DatumGetCString(DirectFunctionCall1(interval_out,
|
||||
PointerGetDatum(zone))))));
|
||||
|
||||
if (zone->month != 0 || zone->day != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
|
|
|
@ -3271,6 +3271,9 @@ ClearPgItmIn(struct pg_itm_in *itm_in)
|
|||
*
|
||||
* Allow ISO-style time span, with implicit units on number of days
|
||||
* preceding an hh:mm:ss field. - thomas 1998-04-30
|
||||
*
|
||||
* itm_in remains undefined for infinite interval values for which dtype alone
|
||||
* suffices.
|
||||
*/
|
||||
int
|
||||
DecodeInterval(char **field, int *ftype, int nf, int range,
|
||||
|
@ -3574,6 +3577,8 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
|
|||
if (parsing_unit_val)
|
||||
return DTERR_BAD_FORMAT;
|
||||
type = DecodeUnits(i, field[i], &uval);
|
||||
if (type == UNKNOWN_FIELD)
|
||||
type = DecodeSpecial(i, field[i], &uval);
|
||||
if (type == IGNORE_DTF)
|
||||
continue;
|
||||
|
||||
|
@ -3597,6 +3602,27 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
|
|||
type = uval;
|
||||
break;
|
||||
|
||||
case RESERV:
|
||||
tmask = (DTK_DATE_M | DTK_TIME_M);
|
||||
|
||||
/*
|
||||
* Only reserved words corresponding to infinite
|
||||
* intervals are accepted.
|
||||
*/
|
||||
if (uval != DTK_LATE && uval != DTK_EARLY)
|
||||
return DTERR_BAD_FORMAT;
|
||||
|
||||
/*
|
||||
* Infinity cannot be followed by anything else. We
|
||||
* could allow "ago" to reverse the sign of infinity
|
||||
* but using signed infinity is more intuitive.
|
||||
*/
|
||||
if (i != nf - 1)
|
||||
return DTERR_BAD_FORMAT;
|
||||
|
||||
*dtype = uval;
|
||||
break;
|
||||
|
||||
default:
|
||||
return DTERR_BAD_FORMAT;
|
||||
}
|
||||
|
|
|
@ -4127,7 +4127,7 @@ interval_to_char(PG_FUNCTION_ARGS)
|
|||
struct pg_itm tt,
|
||||
*itm = &tt;
|
||||
|
||||
if (VARSIZE_ANY_EXHDR(fmt) <= 0)
|
||||
if (VARSIZE_ANY_EXHDR(fmt) <= 0 || INTERVAL_NOT_FINITE(it))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
ZERO_tmtc(&tmtc);
|
||||
|
|
|
@ -4802,6 +4802,10 @@ convert_timevalue_to_scalar(Datum value, Oid typid, bool *failure)
|
|||
* Convert the month part of Interval to days using assumed
|
||||
* average month length of 365.25/12.0 days. Not too
|
||||
* accurate, but plenty good enough for our purposes.
|
||||
*
|
||||
* This also works for infinite intervals, which just have all
|
||||
* fields set to INT_MIN/INT_MAX, and so will produce a result
|
||||
* smaller/larger than any finite interval.
|
||||
*/
|
||||
return interval->time + interval->day * (double) USECS_PER_DAY +
|
||||
interval->month * ((DAYS_PER_YEAR / (double) MONTHS_PER_YEAR) * USECS_PER_DAY);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -57,6 +57,6 @@
|
|||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 202311141
|
||||
#define CATALOG_VERSION_NO 202311142
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,12 +43,13 @@
|
|||
{ aggfnoid => 'avg(float8)', aggtransfn => 'float8_accum',
|
||||
aggfinalfn => 'float8_avg', aggcombinefn => 'float8_combine',
|
||||
aggtranstype => '_float8', agginitval => '{0,0,0}' },
|
||||
{ aggfnoid => 'avg(interval)', aggtransfn => 'interval_accum',
|
||||
aggfinalfn => 'interval_avg', aggcombinefn => 'interval_combine',
|
||||
aggmtransfn => 'interval_accum', aggminvtransfn => 'interval_accum_inv',
|
||||
aggmfinalfn => 'interval_avg', aggtranstype => '_interval',
|
||||
aggmtranstype => '_interval', agginitval => '{0 second,0 second}',
|
||||
aggminitval => '{0 second,0 second}' },
|
||||
{ aggfnoid => 'avg(interval)', aggtransfn => 'interval_avg_accum',
|
||||
aggfinalfn => 'interval_avg', aggcombinefn => 'interval_avg_combine',
|
||||
aggserialfn => 'interval_avg_serialize',
|
||||
aggdeserialfn => 'interval_avg_deserialize',
|
||||
aggmtransfn => 'interval_avg_accum', aggminvtransfn => 'interval_avg_accum_inv',
|
||||
aggmfinalfn => 'interval_avg', aggtranstype => 'internal',
|
||||
aggtransspace => '40', aggmtranstype => 'internal', aggmtransspace => '40' },
|
||||
|
||||
# sum
|
||||
{ aggfnoid => 'sum(int8)', aggtransfn => 'int8_avg_accum',
|
||||
|
@ -72,10 +73,13 @@
|
|||
{ aggfnoid => 'sum(money)', aggtransfn => 'cash_pl', aggcombinefn => 'cash_pl',
|
||||
aggmtransfn => 'cash_pl', aggminvtransfn => 'cash_mi',
|
||||
aggtranstype => 'money', aggmtranstype => 'money' },
|
||||
{ aggfnoid => 'sum(interval)', aggtransfn => 'interval_pl',
|
||||
aggcombinefn => 'interval_pl', aggmtransfn => 'interval_pl',
|
||||
aggminvtransfn => 'interval_mi', aggtranstype => 'interval',
|
||||
aggmtranstype => 'interval' },
|
||||
{ aggfnoid => 'sum(interval)', aggtransfn => 'interval_avg_accum',
|
||||
aggfinalfn => 'interval_sum', aggcombinefn => 'interval_avg_combine',
|
||||
aggserialfn => 'interval_avg_serialize',
|
||||
aggdeserialfn => 'interval_avg_deserialize',
|
||||
aggmtransfn => 'interval_avg_accum', aggminvtransfn => 'interval_avg_accum_inv',
|
||||
aggmfinalfn => 'interval_sum', aggtranstype => 'internal',
|
||||
aggtransspace => '40', aggmtranstype => 'internal', aggmtransspace => '40'},
|
||||
{ aggfnoid => 'sum(numeric)', aggtransfn => 'numeric_avg_accum',
|
||||
aggfinalfn => 'numeric_sum', aggcombinefn => 'numeric_avg_combine',
|
||||
aggserialfn => 'numeric_avg_serialize',
|
||||
|
|
|
@ -4917,17 +4917,29 @@
|
|||
prosrc => 'numeric_poly_stddev_samp' },
|
||||
|
||||
{ oid => '1843', descr => 'aggregate transition function',
|
||||
proname => 'interval_accum', prorettype => '_interval',
|
||||
proargtypes => '_interval interval', prosrc => 'interval_accum' },
|
||||
proname => 'interval_avg_accum', proisstrict => 'f',
|
||||
prorettype => 'internal', proargtypes => 'internal interval',
|
||||
prosrc => 'interval_avg_accum' },
|
||||
{ oid => '3325', descr => 'aggregate combine function',
|
||||
proname => 'interval_combine', prorettype => '_interval',
|
||||
proargtypes => '_interval _interval', prosrc => 'interval_combine' },
|
||||
proname => 'interval_avg_combine', proisstrict => 'f',
|
||||
prorettype => 'internal', proargtypes => 'internal internal',
|
||||
prosrc => 'interval_avg_combine' },
|
||||
{ oid => '3549', descr => 'aggregate transition function',
|
||||
proname => 'interval_accum_inv', prorettype => '_interval',
|
||||
proargtypes => '_interval interval', prosrc => 'interval_accum_inv' },
|
||||
proname => 'interval_avg_accum_inv', proisstrict => 'f',
|
||||
prorettype => 'internal', proargtypes => 'internal interval',
|
||||
prosrc => 'interval_avg_accum_inv' },
|
||||
{ oid => '8505', descr => 'aggregate serial function',
|
||||
proname => 'interval_avg_serialize', prorettype => 'bytea',
|
||||
proargtypes => 'internal', prosrc => 'interval_avg_serialize' },
|
||||
{ oid => '8506', descr => 'aggregate deserial function',
|
||||
proname => 'interval_avg_deserialize', prorettype => 'internal',
|
||||
proargtypes => 'bytea internal', prosrc => 'interval_avg_deserialize' },
|
||||
{ oid => '1844', descr => 'aggregate final function',
|
||||
proname => 'interval_avg', prorettype => 'interval',
|
||||
proargtypes => '_interval', prosrc => 'interval_avg' },
|
||||
proname => 'interval_avg', proisstrict => 'f', prorettype => 'interval',
|
||||
proargtypes => 'internal', prosrc => 'interval_avg' },
|
||||
{ oid => '8507', descr => 'aggregate final function',
|
||||
proname => 'interval_sum', proisstrict => 'f', prorettype => 'interval',
|
||||
proargtypes => 'internal', prosrc => 'interval_sum' },
|
||||
{ oid => '1962', descr => 'aggregate transition function',
|
||||
proname => 'int2_avg_accum', prorettype => '_int8',
|
||||
proargtypes => '_int8 int2', prosrc => 'int2_avg_accum' },
|
||||
|
|
|
@ -151,7 +151,7 @@ struct pg_itm_in
|
|||
#define TIMESTAMP_INFINITY PG_INT64_MAX
|
||||
|
||||
/*
|
||||
* Historically these alias for infinity have been used.
|
||||
* Historically these aliases for infinity have been used.
|
||||
*/
|
||||
#define DT_NOBEGIN TIMESTAMP_MINUS_INFINITY
|
||||
#define DT_NOEND TIMESTAMP_INFINITY
|
||||
|
@ -168,6 +168,31 @@ struct pg_itm_in
|
|||
|
||||
#define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
|
||||
|
||||
/*
|
||||
* Infinite intervals are represented by setting all fields to the minimum or
|
||||
* maximum integer values.
|
||||
*/
|
||||
#define INTERVAL_NOBEGIN(i) \
|
||||
do { \
|
||||
(i)->time = PG_INT64_MIN; \
|
||||
(i)->day = PG_INT32_MIN; \
|
||||
(i)->month = PG_INT32_MIN; \
|
||||
} while (0)
|
||||
|
||||
#define INTERVAL_IS_NOBEGIN(i) \
|
||||
((i)->month == PG_INT32_MIN && (i)->day == PG_INT32_MIN && (i)->time == PG_INT64_MIN)
|
||||
|
||||
#define INTERVAL_NOEND(i) \
|
||||
do { \
|
||||
(i)->time = PG_INT64_MAX; \
|
||||
(i)->day = PG_INT32_MAX; \
|
||||
(i)->month = PG_INT32_MAX; \
|
||||
} while (0)
|
||||
|
||||
#define INTERVAL_IS_NOEND(i) \
|
||||
((i)->month == PG_INT32_MAX && (i)->day == PG_INT32_MAX && (i)->time == PG_INT64_MAX)
|
||||
|
||||
#define INTERVAL_NOT_FINITE(i) (INTERVAL_IS_NOBEGIN(i) || INTERVAL_IS_NOEND(i))
|
||||
|
||||
/*
|
||||
* Julian date support.
|
||||
|
|
|
@ -941,6 +941,34 @@ SELECT * FROM brin_interval_test WHERE a = '30 years'::interval;
|
|||
Index Cond: (a = '@ 30 years'::interval)
|
||||
(4 rows)
|
||||
|
||||
DROP TABLE brin_interval_test;
|
||||
RESET enable_seqscan;
|
||||
-- test handling of infinite interval values
|
||||
CREATE TABLE brin_interval_test(a INTERVAL);
|
||||
INSERT INTO brin_interval_test VALUES ('-infinity'), ('infinity');
|
||||
INSERT INTO brin_interval_test SELECT (i || ' days')::interval FROM generate_series(100, 140) s(i);
|
||||
CREATE INDEX ON brin_interval_test USING brin (a interval_minmax_multi_ops) WITH (pages_per_range=1);
|
||||
SET enable_seqscan = off;
|
||||
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF)
|
||||
SELECT * FROM brin_interval_test WHERE a = '-30 years'::interval;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------
|
||||
Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1)
|
||||
Recheck Cond: (a = '@ 30 years ago'::interval)
|
||||
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1)
|
||||
Index Cond: (a = '@ 30 years ago'::interval)
|
||||
(4 rows)
|
||||
|
||||
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF)
|
||||
SELECT * FROM brin_interval_test WHERE a = '30 years'::interval;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------
|
||||
Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1)
|
||||
Recheck Cond: (a = '@ 30 years'::interval)
|
||||
-> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1)
|
||||
Index Cond: (a = '@ 30 years'::interval)
|
||||
(4 rows)
|
||||
|
||||
DROP TABLE brin_interval_test;
|
||||
RESET enable_seqscan;
|
||||
RESET datestyle;
|
||||
|
|
|
@ -1171,6 +1171,7 @@ SELECT t.d1 AS t, i.f1 AS i, t.d1 + i.f1 AS "add", t.d1 - i.f1 AS "subtract"
|
|||
|
||||
SELECT t.f1 AS t, i.f1 AS i, t.f1 + i.f1 AS "add", t.f1 - i.f1 AS "subtract"
|
||||
FROM TIME_TBL t, INTERVAL_TBL i
|
||||
WHERE isfinite(i.f1)
|
||||
ORDER BY 1,2;
|
||||
t | i | add | subtract
|
||||
-------------+-------------------------------+-------------+-------------
|
||||
|
@ -1278,6 +1279,7 @@ SELECT t.f1 AS t, i.f1 AS i, t.f1 + i.f1 AS "add", t.f1 - i.f1 AS "subtract"
|
|||
|
||||
SELECT t.f1 AS t, i.f1 AS i, t.f1 + i.f1 AS "add", t.f1 - i.f1 AS "subtract"
|
||||
FROM TIMETZ_TBL t, INTERVAL_TBL i
|
||||
WHERE isfinite(i.f1)
|
||||
ORDER BY 1,2;
|
||||
t | i | add | subtract
|
||||
----------------+-------------------------------+----------------+----------------
|
||||
|
@ -1556,6 +1558,22 @@ SELECT d.f1 AS "timestamp", t.f1 AS "interval", d.f1 + t.f1 AS plus
|
|||
ORDER BY plus, "timestamp", "interval";
|
||||
timestamp | interval | plus
|
||||
------------------------------+-------------------------------+------------------------------
|
||||
Thu Jan 01 00:00:00 1970 PST | -infinity | -infinity
|
||||
Wed Feb 28 17:32:01 1996 PST | -infinity | -infinity
|
||||
Thu Feb 29 17:32:01 1996 PST | -infinity | -infinity
|
||||
Fri Mar 01 17:32:01 1996 PST | -infinity | -infinity
|
||||
Mon Dec 30 17:32:01 1996 PST | -infinity | -infinity
|
||||
Tue Dec 31 17:32:01 1996 PST | -infinity | -infinity
|
||||
Fri Dec 31 17:32:01 1999 PST | -infinity | -infinity
|
||||
Sat Jan 01 17:32:01 2000 PST | -infinity | -infinity
|
||||
Wed Mar 15 02:14:05 2000 PST | -infinity | -infinity
|
||||
Wed Mar 15 03:14:04 2000 PST | -infinity | -infinity
|
||||
Wed Mar 15 08:14:01 2000 PST | -infinity | -infinity
|
||||
Wed Mar 15 12:14:03 2000 PST | -infinity | -infinity
|
||||
Wed Mar 15 13:14:02 2000 PST | -infinity | -infinity
|
||||
Sun Dec 31 17:32:01 2000 PST | -infinity | -infinity
|
||||
Mon Jan 01 17:32:01 2001 PST | -infinity | -infinity
|
||||
Sat Sep 22 18:19:20 2001 PDT | -infinity | -infinity
|
||||
Thu Jan 01 00:00:00 1970 PST | @ 14 secs ago | Wed Dec 31 23:59:46 1969 PST
|
||||
Thu Jan 01 00:00:00 1970 PST | @ 1 min | Thu Jan 01 00:01:00 1970 PST
|
||||
Thu Jan 01 00:00:00 1970 PST | @ 5 hours | Thu Jan 01 05:00:00 1970 PST
|
||||
|
@ -1716,14 +1734,45 @@ SELECT d.f1 AS "timestamp", t.f1 AS "interval", d.f1 + t.f1 AS plus
|
|||
Sun Dec 31 17:32:01 2000 PST | @ 34 years | Sun Dec 31 17:32:01 2034 PST
|
||||
Mon Jan 01 17:32:01 2001 PST | @ 34 years | Mon Jan 01 17:32:01 2035 PST
|
||||
Sat Sep 22 18:19:20 2001 PDT | @ 34 years | Sat Sep 22 18:19:20 2035 PDT
|
||||
(160 rows)
|
||||
Thu Jan 01 00:00:00 1970 PST | infinity | infinity
|
||||
Wed Feb 28 17:32:01 1996 PST | infinity | infinity
|
||||
Thu Feb 29 17:32:01 1996 PST | infinity | infinity
|
||||
Fri Mar 01 17:32:01 1996 PST | infinity | infinity
|
||||
Mon Dec 30 17:32:01 1996 PST | infinity | infinity
|
||||
Tue Dec 31 17:32:01 1996 PST | infinity | infinity
|
||||
Fri Dec 31 17:32:01 1999 PST | infinity | infinity
|
||||
Sat Jan 01 17:32:01 2000 PST | infinity | infinity
|
||||
Wed Mar 15 02:14:05 2000 PST | infinity | infinity
|
||||
Wed Mar 15 03:14:04 2000 PST | infinity | infinity
|
||||
Wed Mar 15 08:14:01 2000 PST | infinity | infinity
|
||||
Wed Mar 15 12:14:03 2000 PST | infinity | infinity
|
||||
Wed Mar 15 13:14:02 2000 PST | infinity | infinity
|
||||
Sun Dec 31 17:32:01 2000 PST | infinity | infinity
|
||||
Mon Jan 01 17:32:01 2001 PST | infinity | infinity
|
||||
Sat Sep 22 18:19:20 2001 PDT | infinity | infinity
|
||||
(192 rows)
|
||||
|
||||
SELECT d.f1 AS "timestamp", t.f1 AS "interval", d.f1 - t.f1 AS minus
|
||||
FROM TEMP_TIMESTAMP d, INTERVAL_TBL t
|
||||
WHERE isfinite(d.f1)
|
||||
ORDER BY minus, "timestamp", "interval";
|
||||
timestamp | interval | minus
|
||||
------------------------------+-------------------------------+------------------------------
|
||||
Thu Jan 01 00:00:00 1970 PST | infinity | -infinity
|
||||
Wed Feb 28 17:32:01 1996 PST | infinity | -infinity
|
||||
Thu Feb 29 17:32:01 1996 PST | infinity | -infinity
|
||||
Fri Mar 01 17:32:01 1996 PST | infinity | -infinity
|
||||
Mon Dec 30 17:32:01 1996 PST | infinity | -infinity
|
||||
Tue Dec 31 17:32:01 1996 PST | infinity | -infinity
|
||||
Fri Dec 31 17:32:01 1999 PST | infinity | -infinity
|
||||
Sat Jan 01 17:32:01 2000 PST | infinity | -infinity
|
||||
Wed Mar 15 02:14:05 2000 PST | infinity | -infinity
|
||||
Wed Mar 15 03:14:04 2000 PST | infinity | -infinity
|
||||
Wed Mar 15 08:14:01 2000 PST | infinity | -infinity
|
||||
Wed Mar 15 12:14:03 2000 PST | infinity | -infinity
|
||||
Wed Mar 15 13:14:02 2000 PST | infinity | -infinity
|
||||
Sun Dec 31 17:32:01 2000 PST | infinity | -infinity
|
||||
Mon Jan 01 17:32:01 2001 PST | infinity | -infinity
|
||||
Sat Sep 22 18:19:20 2001 PDT | infinity | -infinity
|
||||
Thu Jan 01 00:00:00 1970 PST | @ 34 years | Wed Jan 01 00:00:00 1936 PST
|
||||
Wed Feb 28 17:32:01 1996 PST | @ 34 years | Wed Feb 28 17:32:01 1962 PST
|
||||
Thu Feb 29 17:32:01 1996 PST | @ 34 years | Wed Feb 28 17:32:01 1962 PST
|
||||
|
@ -1884,7 +1933,23 @@ SELECT d.f1 AS "timestamp", t.f1 AS "interval", d.f1 - t.f1 AS minus
|
|||
Sat Sep 22 18:19:20 2001 PDT | @ 5 hours | Sat Sep 22 13:19:20 2001 PDT
|
||||
Sat Sep 22 18:19:20 2001 PDT | @ 1 min | Sat Sep 22 18:18:20 2001 PDT
|
||||
Sat Sep 22 18:19:20 2001 PDT | @ 14 secs ago | Sat Sep 22 18:19:34 2001 PDT
|
||||
(160 rows)
|
||||
Thu Jan 01 00:00:00 1970 PST | -infinity | infinity
|
||||
Wed Feb 28 17:32:01 1996 PST | -infinity | infinity
|
||||
Thu Feb 29 17:32:01 1996 PST | -infinity | infinity
|
||||
Fri Mar 01 17:32:01 1996 PST | -infinity | infinity
|
||||
Mon Dec 30 17:32:01 1996 PST | -infinity | infinity
|
||||
Tue Dec 31 17:32:01 1996 PST | -infinity | infinity
|
||||
Fri Dec 31 17:32:01 1999 PST | -infinity | infinity
|
||||
Sat Jan 01 17:32:01 2000 PST | -infinity | infinity
|
||||
Wed Mar 15 02:14:05 2000 PST | -infinity | infinity
|
||||
Wed Mar 15 03:14:04 2000 PST | -infinity | infinity
|
||||
Wed Mar 15 08:14:01 2000 PST | -infinity | infinity
|
||||
Wed Mar 15 12:14:03 2000 PST | -infinity | infinity
|
||||
Wed Mar 15 13:14:02 2000 PST | -infinity | infinity
|
||||
Sun Dec 31 17:32:01 2000 PST | -infinity | infinity
|
||||
Mon Jan 01 17:32:01 2001 PST | -infinity | infinity
|
||||
Sat Sep 22 18:19:20 2001 PDT | -infinity | infinity
|
||||
(192 rows)
|
||||
|
||||
SELECT d.f1 AS "timestamp",
|
||||
timestamp with time zone '1980-01-06 00:00 GMT' AS gpstime_zero,
|
||||
|
|
|
@ -52,6 +52,18 @@ SELECT INTERVAL '10 years -11 month -12 days +13:14' AS "9 years...";
|
|||
9 years 1 mon -12 days +13:14:00
|
||||
(1 row)
|
||||
|
||||
SELECT INTERVAL 'infinity' AS "eternity";
|
||||
eternity
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
SELECT INTERVAL '-infinity' AS "beginning of time";
|
||||
beginning of time
|
||||
-------------------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
CREATE TABLE INTERVAL_TBL (f1 interval);
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 1 minute');
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 5 hour');
|
||||
|
@ -63,6 +75,8 @@ INSERT INTO INTERVAL_TBL (f1) VALUES ('1 day 2 hours 3 minutes 4 seconds');
|
|||
INSERT INTO INTERVAL_TBL (f1) VALUES ('6 years');
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('5 months');
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('5 months 12 hours');
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('infinity');
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('-infinity');
|
||||
-- badly formatted interval
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('badly formatted interval');
|
||||
ERROR: invalid input syntax for type interval: "badly formatted interval"
|
||||
|
@ -117,7 +131,9 @@ SELECT * FROM INTERVAL_TBL;
|
|||
6 years
|
||||
5 mons
|
||||
5 mons 12:00:00
|
||||
(10 rows)
|
||||
infinity
|
||||
-infinity
|
||||
(12 rows)
|
||||
|
||||
SELECT * FROM INTERVAL_TBL
|
||||
WHERE INTERVAL_TBL.f1 <> interval '@ 10 days';
|
||||
|
@ -132,7 +148,9 @@ SELECT * FROM INTERVAL_TBL
|
|||
6 years
|
||||
5 mons
|
||||
5 mons 12:00:00
|
||||
(9 rows)
|
||||
infinity
|
||||
-infinity
|
||||
(11 rows)
|
||||
|
||||
SELECT * FROM INTERVAL_TBL
|
||||
WHERE INTERVAL_TBL.f1 <= interval '@ 5 hours';
|
||||
|
@ -141,7 +159,8 @@ SELECT * FROM INTERVAL_TBL
|
|||
00:01:00
|
||||
05:00:00
|
||||
-00:00:14
|
||||
(3 rows)
|
||||
-infinity
|
||||
(4 rows)
|
||||
|
||||
SELECT * FROM INTERVAL_TBL
|
||||
WHERE INTERVAL_TBL.f1 < interval '@ 1 day';
|
||||
|
@ -150,7 +169,8 @@ SELECT * FROM INTERVAL_TBL
|
|||
00:01:00
|
||||
05:00:00
|
||||
-00:00:14
|
||||
(3 rows)
|
||||
-infinity
|
||||
(4 rows)
|
||||
|
||||
SELECT * FROM INTERVAL_TBL
|
||||
WHERE INTERVAL_TBL.f1 = interval '@ 34 years';
|
||||
|
@ -168,7 +188,8 @@ SELECT * FROM INTERVAL_TBL
|
|||
6 years
|
||||
5 mons
|
||||
5 mons 12:00:00
|
||||
(5 rows)
|
||||
infinity
|
||||
(6 rows)
|
||||
|
||||
SELECT * FROM INTERVAL_TBL
|
||||
WHERE INTERVAL_TBL.f1 > interval '@ 3 seconds ago';
|
||||
|
@ -183,7 +204,8 @@ SELECT * FROM INTERVAL_TBL
|
|||
6 years
|
||||
5 mons
|
||||
5 mons 12:00:00
|
||||
(9 rows)
|
||||
infinity
|
||||
(10 rows)
|
||||
|
||||
SELECT r1.*, r2.*
|
||||
FROM INTERVAL_TBL r1, INTERVAL_TBL r2
|
||||
|
@ -191,27 +213,35 @@ SELECT r1.*, r2.*
|
|||
ORDER BY r1.f1, r2.f1;
|
||||
f1 | f1
|
||||
-----------------+-----------------
|
||||
-00:00:14 | -infinity
|
||||
00:01:00 | -infinity
|
||||
00:01:00 | -00:00:14
|
||||
05:00:00 | -infinity
|
||||
05:00:00 | -00:00:14
|
||||
05:00:00 | 00:01:00
|
||||
1 day 02:03:04 | -infinity
|
||||
1 day 02:03:04 | -00:00:14
|
||||
1 day 02:03:04 | 00:01:00
|
||||
1 day 02:03:04 | 05:00:00
|
||||
10 days | -infinity
|
||||
10 days | -00:00:14
|
||||
10 days | 00:01:00
|
||||
10 days | 05:00:00
|
||||
10 days | 1 day 02:03:04
|
||||
3 mons | -infinity
|
||||
3 mons | -00:00:14
|
||||
3 mons | 00:01:00
|
||||
3 mons | 05:00:00
|
||||
3 mons | 1 day 02:03:04
|
||||
3 mons | 10 days
|
||||
5 mons | -infinity
|
||||
5 mons | -00:00:14
|
||||
5 mons | 00:01:00
|
||||
5 mons | 05:00:00
|
||||
5 mons | 1 day 02:03:04
|
||||
5 mons | 10 days
|
||||
5 mons | 3 mons
|
||||
5 mons 12:00:00 | -infinity
|
||||
5 mons 12:00:00 | -00:00:14
|
||||
5 mons 12:00:00 | 00:01:00
|
||||
5 mons 12:00:00 | 05:00:00
|
||||
|
@ -219,6 +249,7 @@ SELECT r1.*, r2.*
|
|||
5 mons 12:00:00 | 10 days
|
||||
5 mons 12:00:00 | 3 mons
|
||||
5 mons 12:00:00 | 5 mons
|
||||
6 years | -infinity
|
||||
6 years | -00:00:14
|
||||
6 years | 00:01:00
|
||||
6 years | 05:00:00
|
||||
|
@ -227,6 +258,7 @@ SELECT r1.*, r2.*
|
|||
6 years | 3 mons
|
||||
6 years | 5 mons
|
||||
6 years | 5 mons 12:00:00
|
||||
34 years | -infinity
|
||||
34 years | -00:00:14
|
||||
34 years | 00:01:00
|
||||
34 years | 05:00:00
|
||||
|
@ -236,8 +268,63 @@ SELECT r1.*, r2.*
|
|||
34 years | 5 mons
|
||||
34 years | 5 mons 12:00:00
|
||||
34 years | 6 years
|
||||
(45 rows)
|
||||
infinity | -infinity
|
||||
infinity | -00:00:14
|
||||
infinity | 00:01:00
|
||||
infinity | 05:00:00
|
||||
infinity | 1 day 02:03:04
|
||||
infinity | 10 days
|
||||
infinity | 3 mons
|
||||
infinity | 5 mons
|
||||
infinity | 5 mons 12:00:00
|
||||
infinity | 6 years
|
||||
infinity | 34 years
|
||||
(66 rows)
|
||||
|
||||
-- test unary minus
|
||||
SELECT f1, -f1 FROM INTERVAL_TBL;
|
||||
f1 | ?column?
|
||||
-----------------+-------------------
|
||||
00:01:00 | -00:01:00
|
||||
05:00:00 | -05:00:00
|
||||
10 days | -10 days
|
||||
34 years | -34 years
|
||||
3 mons | -3 mons
|
||||
-00:00:14 | 00:00:14
|
||||
1 day 02:03:04 | -1 days -02:03:04
|
||||
6 years | -6 years
|
||||
5 mons | -5 mons
|
||||
5 mons 12:00:00 | -5 mons -12:00:00
|
||||
infinity | -infinity
|
||||
-infinity | infinity
|
||||
(12 rows)
|
||||
|
||||
SELECT -('-2147483648 months'::interval); -- should fail
|
||||
ERROR: interval out of range
|
||||
SELECT -('-2147483647 months'::interval); -- ok
|
||||
?column?
|
||||
------------------------
|
||||
178956970 years 7 mons
|
||||
(1 row)
|
||||
|
||||
SELECT -('-2147483648 days'::interval); -- should fail
|
||||
ERROR: interval out of range
|
||||
SELECT -('-2147483647 days'::interval); -- ok
|
||||
?column?
|
||||
-----------------
|
||||
2147483647 days
|
||||
(1 row)
|
||||
|
||||
SELECT -('-9223372036854775808 us'::interval); -- should fail
|
||||
ERROR: interval out of range
|
||||
SELECT -('-9223372036854775807 us'::interval); -- ok
|
||||
?column?
|
||||
-------------------------
|
||||
2562047788:00:54.775807
|
||||
(1 row)
|
||||
|
||||
SELECT -('-2147483647 months -2147483647 days -9223372036854775807 us'::interval); -- should fail
|
||||
ERROR: interval out of range
|
||||
-- Test intervals that are large enough to overflow 64 bits in comparisons
|
||||
CREATE TEMP TABLE INTERVAL_TBL_OF (f1 interval);
|
||||
INSERT INTO INTERVAL_TBL_OF (f1) VALUES
|
||||
|
@ -304,6 +391,17 @@ SELECT f1 FROM INTERVAL_TBL_OF r1 ORDER BY f1;
|
|||
(5 rows)
|
||||
|
||||
RESET enable_seqscan;
|
||||
-- subtracting about-to-overflow values should result in 0
|
||||
SELECT f1 - f1 FROM INTERVAL_TBL_OF;
|
||||
?column?
|
||||
----------
|
||||
00:00:00
|
||||
00:00:00
|
||||
00:00:00
|
||||
00:00:00
|
||||
00:00:00
|
||||
(5 rows)
|
||||
|
||||
DROP TABLE INTERVAL_TBL_OF;
|
||||
-- Test multiplication and division with intervals.
|
||||
-- Floating point arithmetic rounding errors can lead to unexpected results,
|
||||
|
@ -386,12 +484,14 @@ SELECT * FROM INTERVAL_TBL;
|
|||
@ 6 years
|
||||
@ 5 mons
|
||||
@ 5 mons 12 hours
|
||||
(10 rows)
|
||||
infinity
|
||||
-infinity
|
||||
(12 rows)
|
||||
|
||||
-- test avg(interval), which is somewhat fragile since people have been
|
||||
-- known to change the allowed input syntax for type interval without
|
||||
-- updating pg_aggregate.agginitval
|
||||
select avg(f1) from interval_tbl;
|
||||
select avg(f1) from interval_tbl where isfinite(f1);
|
||||
avg
|
||||
-------------------------------------------------
|
||||
@ 4 years 1 mon 10 days 4 hours 18 mins 23 secs
|
||||
|
@ -820,8 +920,8 @@ SELECT interval '1 2:03:04.5678' minute to second(2);
|
|||
SELECT f1, f1::INTERVAL DAY TO MINUTE AS "minutes",
|
||||
(f1 + INTERVAL '1 month')::INTERVAL MONTH::INTERVAL YEAR AS "years"
|
||||
FROM interval_tbl;
|
||||
f1 | minutes | years
|
||||
-----------------+-----------------+----------
|
||||
f1 | minutes | years
|
||||
-----------------+-----------------+-----------
|
||||
00:01:00 | 00:01:00 | 00:00:00
|
||||
05:00:00 | 05:00:00 | 00:00:00
|
||||
10 days | 10 days | 00:00:00
|
||||
|
@ -832,7 +932,9 @@ SELECT f1, f1::INTERVAL DAY TO MINUTE AS "minutes",
|
|||
6 years | 6 years | 6 years
|
||||
5 mons | 5 mons | 00:00:00
|
||||
5 mons 12:00:00 | 5 mons 12:00:00 | 00:00:00
|
||||
(10 rows)
|
||||
infinity | infinity | infinity
|
||||
-infinity | -infinity | -infinity
|
||||
(12 rows)
|
||||
|
||||
-- test inputting and outputting SQL standard interval literals
|
||||
SET IntervalStyle TO sql_standard;
|
||||
|
@ -1616,31 +1718,31 @@ select make_interval(mins := -1, secs := -9223372036800.0);
|
|||
ERROR: interval out of range
|
||||
-- test that INT_MIN number is formatted properly
|
||||
SET IntervalStyle to postgres;
|
||||
select interval '-2147483648 months -2147483648 days -9223372036854775808 us';
|
||||
select interval '-2147483647 months -2147483648 days -9223372036854775808 us';
|
||||
interval
|
||||
--------------------------------------------------------------------
|
||||
-178956970 years -8 mons -2147483648 days -2562047788:00:54.775808
|
||||
-178956970 years -7 mons -2147483648 days -2562047788:00:54.775808
|
||||
(1 row)
|
||||
|
||||
SET IntervalStyle to sql_standard;
|
||||
select interval '-2147483648 months -2147483648 days -9223372036854775808 us';
|
||||
select interval '-2147483647 months -2147483648 days -9223372036854775808 us';
|
||||
interval
|
||||
---------------------------------------------------
|
||||
-178956970-8 -2147483648 -2562047788:00:54.775808
|
||||
-178956970-7 -2147483648 -2562047788:00:54.775808
|
||||
(1 row)
|
||||
|
||||
SET IntervalStyle to iso_8601;
|
||||
select interval '-2147483648 months -2147483648 days -9223372036854775808 us';
|
||||
select interval '-2147483647 months -2147483648 days -9223372036854775808 us';
|
||||
interval
|
||||
-----------------------------------------------------
|
||||
P-178956970Y-8M-2147483648DT-2562047788H-54.775808S
|
||||
P-178956970Y-7M-2147483648DT-2562047788H-54.775808S
|
||||
(1 row)
|
||||
|
||||
SET IntervalStyle to postgres_verbose;
|
||||
select interval '-2147483648 months -2147483648 days -9223372036854775808 us';
|
||||
select interval '-2147483647 months -2147483648 days -9223372036854775808 us';
|
||||
interval
|
||||
------------------------------------------------------------------------------
|
||||
@ 178956970 years 8 mons 2147483648 days 2562047788 hours 54.775808 secs ago
|
||||
@ 178956970 years 7 mons 2147483648 days 2562047788 hours 54.775808 secs ago
|
||||
(1 row)
|
||||
|
||||
-- check that '30 days' equals '1 month' according to the hash function
|
||||
|
@ -1719,19 +1821,21 @@ SELECT f1,
|
|||
EXTRACT(MILLENNIUM FROM f1) AS MILLENNIUM,
|
||||
EXTRACT(EPOCH FROM f1) AS EPOCH
|
||||
FROM INTERVAL_TBL;
|
||||
f1 | microsecond | millisecond | second | minute | hour | day | month | quarter | year | decade | century | millennium | epoch
|
||||
-------------------------------+-------------+-------------+------------+--------+------+-----+-------+---------+------+--------+---------+------------+-------------------
|
||||
@ 1 min | 0 | 0.000 | 0.000000 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 60.000000
|
||||
@ 5 hours | 0 | 0.000 | 0.000000 | 0 | 5 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 18000.000000
|
||||
@ 10 days | 0 | 0.000 | 0.000000 | 0 | 0 | 10 | 0 | 1 | 0 | 0 | 0 | 0 | 864000.000000
|
||||
@ 34 years | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 1 | 34 | 3 | 0 | 0 | 1072958400.000000
|
||||
@ 3 mons | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 3 | 2 | 0 | 0 | 0 | 0 | 7776000.000000
|
||||
@ 14 secs ago | -14000000 | -14000.000 | -14.000000 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | -14.000000
|
||||
@ 1 day 2 hours 3 mins 4 secs | 4000000 | 4000.000 | 4.000000 | 3 | 2 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 93784.000000
|
||||
@ 6 years | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 1 | 6 | 0 | 0 | 0 | 189345600.000000
|
||||
@ 5 mons | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 5 | 2 | 0 | 0 | 0 | 0 | 12960000.000000
|
||||
@ 5 mons 12 hours | 0 | 0.000 | 0.000000 | 0 | 12 | 0 | 5 | 2 | 0 | 0 | 0 | 0 | 13003200.000000
|
||||
(10 rows)
|
||||
f1 | microsecond | millisecond | second | minute | hour | day | month | quarter | year | decade | century | millennium | epoch
|
||||
-------------------------------+-------------+-------------+------------+--------+-----------+-----------+-------+---------+-----------+-----------+-----------+------------+-------------------
|
||||
@ 1 min | 0 | 0.000 | 0.000000 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 60.000000
|
||||
@ 5 hours | 0 | 0.000 | 0.000000 | 0 | 5 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 18000.000000
|
||||
@ 10 days | 0 | 0.000 | 0.000000 | 0 | 0 | 10 | 0 | 1 | 0 | 0 | 0 | 0 | 864000.000000
|
||||
@ 34 years | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 1 | 34 | 3 | 0 | 0 | 1072958400.000000
|
||||
@ 3 mons | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 3 | 2 | 0 | 0 | 0 | 0 | 7776000.000000
|
||||
@ 14 secs ago | -14000000 | -14000.000 | -14.000000 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | -14.000000
|
||||
@ 1 day 2 hours 3 mins 4 secs | 4000000 | 4000.000 | 4.000000 | 3 | 2 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 93784.000000
|
||||
@ 6 years | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 1 | 6 | 0 | 0 | 0 | 189345600.000000
|
||||
@ 5 mons | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 5 | 2 | 0 | 0 | 0 | 0 | 12960000.000000
|
||||
@ 5 mons 12 hours | 0 | 0.000 | 0.000000 | 0 | 12 | 0 | 5 | 2 | 0 | 0 | 0 | 0 | 13003200.000000
|
||||
infinity | | | | | Infinity | Infinity | | | Infinity | Infinity | Infinity | Infinity | Infinity
|
||||
-infinity | | | | | -Infinity | -Infinity | | | -Infinity | -Infinity | -Infinity | -Infinity | -Infinity
|
||||
(12 rows)
|
||||
|
||||
SELECT EXTRACT(FORTNIGHT FROM INTERVAL '2 days'); -- error
|
||||
ERROR: unit "fortnight" not recognized for type interval
|
||||
|
@ -1805,7 +1909,9 @@ SELECT f1,
|
|||
@ 6 years | 0 | 0 | 0 | 189345600
|
||||
@ 5 mons | 0 | 0 | 0 | 12960000
|
||||
@ 5 mons 12 hours | 0 | 0 | 0 | 13003200
|
||||
(10 rows)
|
||||
infinity | | | | Infinity
|
||||
-infinity | | | | -Infinity
|
||||
(12 rows)
|
||||
|
||||
-- internal overflow test case
|
||||
SELECT extract(epoch from interval '1000000000 days');
|
||||
|
@ -1814,6 +1920,292 @@ SELECT extract(epoch from interval '1000000000 days');
|
|||
86400000000000.000000
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- test infinite intervals
|
||||
--
|
||||
-- largest finite intervals
|
||||
SELECT interval '-2147483648 months -2147483648 days -9223372036854775807 us';
|
||||
interval
|
||||
------------------------------------------------------------------------------
|
||||
@ 178956970 years 8 mons 2147483648 days 2562047788 hours 54.775807 secs ago
|
||||
(1 row)
|
||||
|
||||
SELECT interval '2147483647 months 2147483647 days 9223372036854775806 us';
|
||||
interval
|
||||
--------------------------------------------------------------------------
|
||||
@ 178956970 years 7 mons 2147483647 days 2562047788 hours 54.775806 secs
|
||||
(1 row)
|
||||
|
||||
-- infinite intervals
|
||||
SELECT interval '-2147483648 months -2147483648 days -9223372036854775808 us';
|
||||
interval
|
||||
-----------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
SELECT interval '2147483647 months 2147483647 days 9223372036854775807 us';
|
||||
interval
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
CREATE TABLE INFINITE_INTERVAL_TBL (i interval);
|
||||
INSERT INTO INFINITE_INTERVAL_TBL VALUES ('infinity'), ('-infinity'), ('1 year 2 days 3 hours');
|
||||
SELECT i, isfinite(i) FROM INFINITE_INTERVAL_TBL;
|
||||
i | isfinite
|
||||
-------------------------+----------
|
||||
infinity | f
|
||||
-infinity | f
|
||||
@ 1 year 2 days 3 hours | t
|
||||
(3 rows)
|
||||
|
||||
-- test basic arithmetic
|
||||
CREATE FUNCTION eval(expr text)
|
||||
RETURNS text AS
|
||||
$$
|
||||
DECLARE
|
||||
result text;
|
||||
BEGIN
|
||||
EXECUTE 'select '||expr INTO result;
|
||||
RETURN result;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RETURN SQLERRM;
|
||||
END
|
||||
$$
|
||||
LANGUAGE plpgsql;
|
||||
SELECT d AS date, i AS interval,
|
||||
eval(format('date %L + interval %L', d, i)) AS plus,
|
||||
eval(format('date %L - interval %L', d, i)) AS minus
|
||||
FROM (VALUES (date '-infinity'),
|
||||
(date '1995-08-06'),
|
||||
(date 'infinity')) AS t1(d),
|
||||
(VALUES (interval '-infinity'),
|
||||
(interval 'infinity')) AS t2(i);
|
||||
date | interval | plus | minus
|
||||
------------+-----------+------------------------+------------------------
|
||||
-infinity | -infinity | -infinity | timestamp out of range
|
||||
-infinity | infinity | timestamp out of range | -infinity
|
||||
1995-08-06 | -infinity | -infinity | infinity
|
||||
1995-08-06 | infinity | infinity | -infinity
|
||||
infinity | -infinity | timestamp out of range | infinity
|
||||
infinity | infinity | infinity | timestamp out of range
|
||||
(6 rows)
|
||||
|
||||
SELECT i1 AS interval1, i2 AS interval2,
|
||||
eval(format('interval %L + interval %L', i1, i2)) AS plus,
|
||||
eval(format('interval %L - interval %L', i1, i2)) AS minus
|
||||
FROM (VALUES (interval '-infinity'),
|
||||
(interval '2 months'),
|
||||
(interval 'infinity')) AS t1(i1),
|
||||
(VALUES (interval '-infinity'),
|
||||
(interval '10 days'),
|
||||
(interval 'infinity')) AS t2(i2);
|
||||
interval1 | interval2 | plus | minus
|
||||
-----------+-----------+-----------------------+-----------------------
|
||||
-infinity | -infinity | -infinity | interval out of range
|
||||
-infinity | @ 10 days | -infinity | -infinity
|
||||
-infinity | infinity | interval out of range | -infinity
|
||||
@ 2 mons | -infinity | -infinity | infinity
|
||||
@ 2 mons | @ 10 days | @ 2 mons 10 days | @ 2 mons -10 days
|
||||
@ 2 mons | infinity | infinity | -infinity
|
||||
infinity | -infinity | interval out of range | infinity
|
||||
infinity | @ 10 days | infinity | infinity
|
||||
infinity | infinity | infinity | interval out of range
|
||||
(9 rows)
|
||||
|
||||
SELECT interval '2147483646 months 2147483646 days 9223372036854775806 us' + interval '1 month 1 day 1 us';
|
||||
ERROR: interval out of range
|
||||
SELECT interval '-2147483647 months -2147483647 days -9223372036854775807 us' + interval '-1 month -1 day -1 us';
|
||||
ERROR: interval out of range
|
||||
SELECT interval '2147483646 months 2147483646 days 9223372036854775806 us' - interval '-1 month -1 day -1 us';
|
||||
ERROR: interval out of range
|
||||
SELECT interval '-2147483647 months -2147483647 days -9223372036854775807 us' - interval '1 month 1 day 1 us';
|
||||
ERROR: interval out of range
|
||||
SELECT t AS timestamp, i AS interval,
|
||||
eval(format('timestamp %L + interval %L', t, i)) AS plus,
|
||||
eval(format('timestamp %L - interval %L', t, i)) AS minus
|
||||
FROM (VALUES (timestamp '-infinity'),
|
||||
(timestamp '1995-08-06 12:30:15'),
|
||||
(timestamp 'infinity')) AS t1(t),
|
||||
(VALUES (interval '-infinity'),
|
||||
(interval 'infinity')) AS t2(i);
|
||||
timestamp | interval | plus | minus
|
||||
---------------------+-----------+------------------------+------------------------
|
||||
-infinity | -infinity | -infinity | timestamp out of range
|
||||
-infinity | infinity | timestamp out of range | -infinity
|
||||
1995-08-06 12:30:15 | -infinity | -infinity | infinity
|
||||
1995-08-06 12:30:15 | infinity | infinity | -infinity
|
||||
infinity | -infinity | timestamp out of range | infinity
|
||||
infinity | infinity | infinity | timestamp out of range
|
||||
(6 rows)
|
||||
|
||||
SELECT t AT TIME ZONE 'GMT' AS timestamptz, i AS interval,
|
||||
eval(format('timestamptz %L + interval %L', t, i)) AS plus,
|
||||
eval(format('timestamptz %L - interval %L', t, i)) AS minus
|
||||
FROM (VALUES (timestamptz '-infinity'),
|
||||
(timestamptz '1995-08-06 12:30:15 GMT'),
|
||||
(timestamptz 'infinity')) AS t1(t),
|
||||
(VALUES (interval '-infinity'),
|
||||
(interval 'infinity')) AS t2(i);
|
||||
timestamptz | interval | plus | minus
|
||||
---------------------+-----------+------------------------+------------------------
|
||||
-infinity | -infinity | -infinity | timestamp out of range
|
||||
-infinity | infinity | timestamp out of range | -infinity
|
||||
1995-08-06 12:30:15 | -infinity | -infinity | infinity
|
||||
1995-08-06 12:30:15 | infinity | infinity | -infinity
|
||||
infinity | -infinity | timestamp out of range | infinity
|
||||
infinity | infinity | infinity | timestamp out of range
|
||||
(6 rows)
|
||||
|
||||
-- time +/- infinite interval not supported
|
||||
SELECT time '11:27:42' + interval 'infinity';
|
||||
ERROR: cannot add infinite interval to time
|
||||
SELECT time '11:27:42' + interval '-infinity';
|
||||
ERROR: cannot add infinite interval to time
|
||||
SELECT time '11:27:42' - interval 'infinity';
|
||||
ERROR: cannot subtract infinite interval from time
|
||||
SELECT time '11:27:42' - interval '-infinity';
|
||||
ERROR: cannot subtract infinite interval from time
|
||||
SELECT timetz '11:27:42' + interval 'infinity';
|
||||
ERROR: cannot add infinite interval to time
|
||||
SELECT timetz '11:27:42' + interval '-infinity';
|
||||
ERROR: cannot add infinite interval to time
|
||||
SELECT timetz '11:27:42' - interval 'infinity';
|
||||
ERROR: cannot subtract infinite interval from time
|
||||
SELECT timetz '11:27:42' - interval '-infinity';
|
||||
ERROR: cannot subtract infinite interval from time
|
||||
SELECT lhst.i lhs,
|
||||
rhst.i rhs,
|
||||
lhst.i < rhst.i AS lt,
|
||||
lhst.i <= rhst.i AS le,
|
||||
lhst.i = rhst.i AS eq,
|
||||
lhst.i > rhst.i AS gt,
|
||||
lhst.i >= rhst.i AS ge,
|
||||
lhst.i <> rhst.i AS ne
|
||||
FROM INFINITE_INTERVAL_TBL lhst CROSS JOIN INFINITE_INTERVAL_TBL rhst
|
||||
WHERE NOT isfinite(lhst.i);
|
||||
lhs | rhs | lt | le | eq | gt | ge | ne
|
||||
-----------+-------------------------+----+----+----+----+----+----
|
||||
infinity | infinity | f | t | t | f | t | f
|
||||
-infinity | infinity | t | t | f | f | f | t
|
||||
infinity | -infinity | f | f | f | t | t | t
|
||||
-infinity | -infinity | f | t | t | f | t | f
|
||||
infinity | @ 1 year 2 days 3 hours | f | f | f | t | t | t
|
||||
-infinity | @ 1 year 2 days 3 hours | t | t | f | f | f | t
|
||||
(6 rows)
|
||||
|
||||
SELECT i AS interval,
|
||||
-i AS um,
|
||||
i * 2.0 AS mul,
|
||||
i * -2.0 AS mul_neg,
|
||||
i * 'infinity' AS mul_inf,
|
||||
i * '-infinity' AS mul_inf_neg,
|
||||
i / 3.0 AS div,
|
||||
i / -3.0 AS div_neg
|
||||
FROM INFINITE_INTERVAL_TBL
|
||||
WHERE NOT isfinite(i);
|
||||
interval | um | mul | mul_neg | mul_inf | mul_inf_neg | div | div_neg
|
||||
-----------+-----------+-----------+-----------+-----------+-------------+-----------+-----------
|
||||
infinity | -infinity | infinity | -infinity | infinity | -infinity | infinity | -infinity
|
||||
-infinity | infinity | -infinity | infinity | -infinity | infinity | -infinity | infinity
|
||||
(2 rows)
|
||||
|
||||
SELECT -interval '-2147483647 months -2147483647 days -9223372036854775807 us';
|
||||
ERROR: interval out of range
|
||||
SELECT interval 'infinity' * 'nan';
|
||||
ERROR: interval out of range
|
||||
SELECT interval '-infinity' * 'nan';
|
||||
ERROR: interval out of range
|
||||
SELECT interval '-1073741824 months -1073741824 days -4611686018427387904 us' * 2;
|
||||
ERROR: interval out of range
|
||||
SELECT interval 'infinity' * 0;
|
||||
ERROR: interval out of range
|
||||
SELECT interval '-infinity' * 0;
|
||||
ERROR: interval out of range
|
||||
SELECT interval '0 days' * 'infinity'::float;
|
||||
ERROR: interval out of range
|
||||
SELECT interval '0 days' * '-infinity'::float;
|
||||
ERROR: interval out of range
|
||||
SELECT interval '5 days' * 'infinity'::float;
|
||||
?column?
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
SELECT interval '5 days' * '-infinity'::float;
|
||||
?column?
|
||||
-----------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
SELECT interval 'infinity' / 'infinity';
|
||||
ERROR: interval out of range
|
||||
SELECT interval 'infinity' / '-infinity';
|
||||
ERROR: interval out of range
|
||||
SELECT interval 'infinity' / 'nan';
|
||||
ERROR: interval out of range
|
||||
SELECT interval '-infinity' / 'infinity';
|
||||
ERROR: interval out of range
|
||||
SELECT interval '-infinity' / '-infinity';
|
||||
ERROR: interval out of range
|
||||
SELECT interval '-infinity' / 'nan';
|
||||
ERROR: interval out of range
|
||||
SELECT interval '-1073741824 months -1073741824 days -4611686018427387904 us' / 0.5;
|
||||
ERROR: interval out of range
|
||||
SELECT date_bin('infinity', timestamp '2001-02-16 20:38:40', timestamp '2001-02-16 20:05:00');
|
||||
ERROR: timestamps cannot be binned into infinite intervals
|
||||
SELECT date_bin('-infinity', timestamp '2001-02-16 20:38:40', timestamp '2001-02-16 20:05:00');
|
||||
ERROR: timestamps cannot be binned into infinite intervals
|
||||
SELECT i AS interval, date_trunc('hour', i)
|
||||
FROM INFINITE_INTERVAL_TBL
|
||||
WHERE NOT isfinite(i);
|
||||
interval | date_trunc
|
||||
-----------+------------
|
||||
infinity | infinity
|
||||
-infinity | -infinity
|
||||
(2 rows)
|
||||
|
||||
SELECT i AS interval, justify_days(i), justify_hours(i), justify_interval(i)
|
||||
FROM INFINITE_INTERVAL_TBL
|
||||
WHERE NOT isfinite(i);
|
||||
interval | justify_days | justify_hours | justify_interval
|
||||
-----------+--------------+---------------+------------------
|
||||
infinity | infinity | infinity | infinity
|
||||
-infinity | -infinity | -infinity | -infinity
|
||||
(2 rows)
|
||||
|
||||
SELECT timezone('infinity'::interval, '1995-08-06 12:12:12'::timestamp);
|
||||
ERROR: interval time zone "infinity" must be finite
|
||||
SELECT timezone('-infinity'::interval, '1995-08-06 12:12:12'::timestamp);
|
||||
ERROR: interval time zone "-infinity" must be finite
|
||||
SELECT timezone('infinity'::interval, '1995-08-06 12:12:12'::timestamptz);
|
||||
ERROR: interval time zone "infinity" must be finite
|
||||
SELECT timezone('-infinity'::interval, '1995-08-06 12:12:12'::timestamptz);
|
||||
ERROR: interval time zone "-infinity" must be finite
|
||||
SELECT timezone('infinity'::interval, '12:12:12'::time);
|
||||
ERROR: interval time zone "infinity" must be finite
|
||||
SELECT timezone('-infinity'::interval, '12:12:12'::time);
|
||||
ERROR: interval time zone "-infinity" must be finite
|
||||
SELECT timezone('infinity'::interval, '12:12:12'::timetz);
|
||||
ERROR: interval time zone "infinity" must be finite
|
||||
SELECT timezone('-infinity'::interval, '12:12:12'::timetz);
|
||||
ERROR: interval time zone "-infinity" must be finite
|
||||
SELECT 'infinity'::interval::time;
|
||||
ERROR: cannot convert infinite interval to time
|
||||
SELECT '-infinity'::interval::time;
|
||||
ERROR: cannot convert infinite interval to time
|
||||
SELECT to_char('infinity'::interval, 'YYYY');
|
||||
to_char
|
||||
---------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT to_char('-infinity'::interval, 'YYYY');
|
||||
to_char
|
||||
---------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- "ago" can only appear once at the end of an interval.
|
||||
SELECT INTERVAL '42 days 2 seconds ago ago';
|
||||
ERROR: invalid input syntax for type interval: "42 days 2 seconds ago ago"
|
||||
|
@ -1832,3 +2224,42 @@ SELECT INTERVAL '1 year months days 5 hours';
|
|||
ERROR: invalid input syntax for type interval: "1 year months days 5 hours"
|
||||
LINE 1: SELECT INTERVAL '1 year months days 5 hours';
|
||||
^
|
||||
-- unacceptable reserved words in interval. Only "infinity", "+infinity" and
|
||||
-- "-infinity" are allowed.
|
||||
SELECT INTERVAL 'now';
|
||||
ERROR: invalid input syntax for type interval: "now"
|
||||
LINE 1: SELECT INTERVAL 'now';
|
||||
^
|
||||
SELECT INTERVAL 'today';
|
||||
ERROR: invalid input syntax for type interval: "today"
|
||||
LINE 1: SELECT INTERVAL 'today';
|
||||
^
|
||||
SELECT INTERVAL 'tomorrow';
|
||||
ERROR: invalid input syntax for type interval: "tomorrow"
|
||||
LINE 1: SELECT INTERVAL 'tomorrow';
|
||||
^
|
||||
SELECT INTERVAL 'allballs';
|
||||
ERROR: invalid input syntax for type interval: "allballs"
|
||||
LINE 1: SELECT INTERVAL 'allballs';
|
||||
^
|
||||
SELECT INTERVAL 'epoch';
|
||||
ERROR: invalid input syntax for type interval: "epoch"
|
||||
LINE 1: SELECT INTERVAL 'epoch';
|
||||
^
|
||||
SELECT INTERVAL 'yesterday';
|
||||
ERROR: invalid input syntax for type interval: "yesterday"
|
||||
LINE 1: SELECT INTERVAL 'yesterday';
|
||||
^
|
||||
-- infinity specification should be the only thing
|
||||
SELECT INTERVAL 'infinity years';
|
||||
ERROR: invalid input syntax for type interval: "infinity years"
|
||||
LINE 1: SELECT INTERVAL 'infinity years';
|
||||
^
|
||||
SELECT INTERVAL 'infinity ago';
|
||||
ERROR: invalid input syntax for type interval: "infinity ago"
|
||||
LINE 1: SELECT INTERVAL 'infinity ago';
|
||||
^
|
||||
SELECT INTERVAL '+infinity -infinity';
|
||||
ERROR: invalid input syntax for type interval: "+infinity -infinity"
|
||||
LINE 1: SELECT INTERVAL '+infinity -infinity';
|
||||
^
|
||||
|
|
|
@ -2125,3 +2125,65 @@ select * from generate_series('2020-01-01 00:00'::timestamp,
|
|||
'2020-01-02 03:00'::timestamp,
|
||||
'0 hour'::interval);
|
||||
ERROR: step size cannot equal zero
|
||||
select generate_series(timestamp '1995-08-06 12:12:12', timestamp '1996-08-06 12:12:12', interval 'infinity');
|
||||
ERROR: step size cannot be infinite
|
||||
select generate_series(timestamp '1995-08-06 12:12:12', timestamp '1996-08-06 12:12:12', interval '-infinity');
|
||||
ERROR: step size cannot be infinite
|
||||
-- test arithmetic with infinite timestamps
|
||||
select timestamp 'infinity' - timestamp 'infinity';
|
||||
ERROR: interval out of range
|
||||
select timestamp 'infinity' - timestamp '-infinity';
|
||||
?column?
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
select timestamp '-infinity' - timestamp 'infinity';
|
||||
?column?
|
||||
-----------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
select timestamp '-infinity' - timestamp '-infinity';
|
||||
ERROR: interval out of range
|
||||
select timestamp 'infinity' - timestamp '1995-08-06 12:12:12';
|
||||
?column?
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
select timestamp '-infinity' - timestamp '1995-08-06 12:12:12';
|
||||
?column?
|
||||
-----------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
-- test age() with infinite timestamps
|
||||
select age(timestamp 'infinity');
|
||||
age
|
||||
-----------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
select age(timestamp '-infinity');
|
||||
age
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
select age(timestamp 'infinity', timestamp 'infinity');
|
||||
ERROR: interval out of range
|
||||
select age(timestamp 'infinity', timestamp '-infinity');
|
||||
age
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
select age(timestamp '-infinity', timestamp 'infinity');
|
||||
age
|
||||
-----------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
select age(timestamp '-infinity', timestamp '-infinity');
|
||||
ERROR: interval out of range
|
||||
|
|
|
@ -2468,6 +2468,10 @@ select * from generate_series('2020-01-01 00:00'::timestamptz,
|
|||
'2020-01-02 03:00'::timestamptz,
|
||||
'0 hour'::interval);
|
||||
ERROR: step size cannot equal zero
|
||||
select generate_series(timestamptz '1995-08-06 12:12:12', timestamptz '1996-08-06 12:12:12', interval 'infinity');
|
||||
ERROR: step size cannot be infinite
|
||||
select generate_series(timestamptz '1995-08-06 12:12:12', timestamptz '1996-08-06 12:12:12', interval '-infinity');
|
||||
ERROR: step size cannot be infinite
|
||||
-- Interval crossing time shift for Europe/Warsaw timezone (with DST)
|
||||
SET TimeZone to 'UTC';
|
||||
SELECT date_add('2022-10-30 00:00:00+01'::timestamptz,
|
||||
|
@ -3210,3 +3214,61 @@ select * from tmptz where f1 at time zone 'utc' = '2017-01-18 00:00';
|
|||
Tue Jan 17 16:00:00 2017 PST
|
||||
(1 row)
|
||||
|
||||
-- test arithmetic with infinite timestamps
|
||||
SELECT timestamptz 'infinity' - timestamptz 'infinity';
|
||||
ERROR: interval out of range
|
||||
SELECT timestamptz 'infinity' - timestamptz '-infinity';
|
||||
?column?
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
SELECT timestamptz '-infinity' - timestamptz 'infinity';
|
||||
?column?
|
||||
-----------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
SELECT timestamptz '-infinity' - timestamptz '-infinity';
|
||||
ERROR: interval out of range
|
||||
SELECT timestamptz 'infinity' - timestamptz '1995-08-06 12:12:12';
|
||||
?column?
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
SELECT timestamptz '-infinity' - timestamptz '1995-08-06 12:12:12';
|
||||
?column?
|
||||
-----------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
-- test age() with infinite timestamps
|
||||
SELECT age(timestamptz 'infinity');
|
||||
age
|
||||
-----------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
SELECT age(timestamptz '-infinity');
|
||||
age
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
SELECT age(timestamptz 'infinity', timestamptz 'infinity');
|
||||
ERROR: interval out of range
|
||||
SELECT age(timestamptz 'infinity', timestamptz '-infinity');
|
||||
age
|
||||
----------
|
||||
infinity
|
||||
(1 row)
|
||||
|
||||
SELECT age(timestamptz '-infinity', timestamptz 'infinity');
|
||||
age
|
||||
-----------
|
||||
-infinity
|
||||
(1 row)
|
||||
|
||||
SELECT age(timestamptz '-infinity', timestamptz '-infinity');
|
||||
ERROR: interval out of range
|
||||
|
|
|
@ -2372,6 +2372,7 @@ create temp table datetimes(
|
|||
f_timestamp timestamp
|
||||
);
|
||||
insert into datetimes values
|
||||
(0, '10:00', '10:00 BST', '-infinity', '-infinity', '-infinity'),
|
||||
(1, '11:00', '11:00 BST', '1 year', '2000-10-19 10:23:54+01', '2000-10-19 10:23:54'),
|
||||
(2, '12:00', '12:00 BST', '2 years', '2001-10-19 10:23:54+01', '2001-10-19 10:23:54'),
|
||||
(3, '13:00', '13:00 BST', '3 years', '2001-10-19 10:23:54+01', '2001-10-19 10:23:54'),
|
||||
|
@ -2381,14 +2382,16 @@ insert into datetimes values
|
|||
(7, '17:00', '17:00 BST', '7 years', '2005-10-19 10:23:54+01', '2005-10-19 10:23:54'),
|
||||
(8, '18:00', '18:00 BST', '8 years', '2006-10-19 10:23:54+01', '2006-10-19 10:23:54'),
|
||||
(9, '19:00', '19:00 BST', '9 years', '2007-10-19 10:23:54+01', '2007-10-19 10:23:54'),
|
||||
(10, '20:00', '20:00 BST', '10 years', '2008-10-19 10:23:54+01', '2008-10-19 10:23:54');
|
||||
(10, '20:00', '20:00 BST', '10 years', '2008-10-19 10:23:54+01', '2008-10-19 10:23:54'),
|
||||
(11, '21:00', '21:00 BST', 'infinity', 'infinity', 'infinity');
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time range between
|
||||
'70 min'::interval preceding and '2 hours'::interval following);
|
||||
id | f_time | first_value | last_value
|
||||
----+----------+-------------+------------
|
||||
1 | 11:00:00 | 1 | 3
|
||||
0 | 10:00:00 | 0 | 2
|
||||
1 | 11:00:00 | 0 | 3
|
||||
2 | 12:00:00 | 1 | 4
|
||||
3 | 13:00:00 | 2 | 6
|
||||
4 | 14:00:00 | 3 | 6
|
||||
|
@ -2396,9 +2399,10 @@ window w as (order by f_time range between
|
|||
6 | 15:00:00 | 4 | 7
|
||||
7 | 17:00:00 | 7 | 9
|
||||
8 | 18:00:00 | 7 | 10
|
||||
9 | 19:00:00 | 8 | 10
|
||||
10 | 20:00:00 | 9 | 10
|
||||
(10 rows)
|
||||
9 | 19:00:00 | 8 | 11
|
||||
10 | 20:00:00 | 9 | 11
|
||||
11 | 21:00:00 | 10 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
|
@ -2406,7 +2410,8 @@ window w as (order by f_time desc range between
|
|||
'70 min' preceding and '2 hours' following);
|
||||
id | f_time | first_value | last_value
|
||||
----+----------+-------------+------------
|
||||
10 | 20:00:00 | 10 | 8
|
||||
11 | 21:00:00 | 11 | 9
|
||||
10 | 20:00:00 | 11 | 8
|
||||
9 | 19:00:00 | 10 | 7
|
||||
8 | 18:00:00 | 9 | 7
|
||||
7 | 17:00:00 | 8 | 5
|
||||
|
@ -2414,17 +2419,90 @@ window w as (order by f_time desc range between
|
|||
5 | 15:00:00 | 6 | 3
|
||||
4 | 14:00:00 | 6 | 2
|
||||
3 | 13:00:00 | 4 | 1
|
||||
2 | 12:00:00 | 3 | 1
|
||||
1 | 11:00:00 | 2 | 1
|
||||
(10 rows)
|
||||
2 | 12:00:00 | 3 | 0
|
||||
1 | 11:00:00 | 2 | 0
|
||||
0 | 10:00:00 | 1 | 0
|
||||
(12 rows)
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time desc range between
|
||||
'-70 min' preceding and '2 hours' following); -- error, negative offset disallowed
|
||||
ERROR: invalid preceding or following size in window function
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time range between
|
||||
'infinity'::interval preceding and 'infinity'::interval following);
|
||||
id | f_time | first_value | last_value
|
||||
----+----------+-------------+------------
|
||||
0 | 10:00:00 | 0 | 11
|
||||
1 | 11:00:00 | 0 | 11
|
||||
2 | 12:00:00 | 0 | 11
|
||||
3 | 13:00:00 | 0 | 11
|
||||
4 | 14:00:00 | 0 | 11
|
||||
5 | 15:00:00 | 0 | 11
|
||||
6 | 15:00:00 | 0 | 11
|
||||
7 | 17:00:00 | 0 | 11
|
||||
8 | 18:00:00 | 0 | 11
|
||||
9 | 19:00:00 | 0 | 11
|
||||
10 | 20:00:00 | 0 | 11
|
||||
11 | 21:00:00 | 0 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time range between
|
||||
'infinity'::interval preceding and 'infinity'::interval preceding);
|
||||
id | f_time | first_value | last_value
|
||||
----+----------+-------------+------------
|
||||
0 | 10:00:00 | |
|
||||
1 | 11:00:00 | |
|
||||
2 | 12:00:00 | |
|
||||
3 | 13:00:00 | |
|
||||
4 | 14:00:00 | |
|
||||
5 | 15:00:00 | |
|
||||
6 | 15:00:00 | |
|
||||
7 | 17:00:00 | |
|
||||
8 | 18:00:00 | |
|
||||
9 | 19:00:00 | |
|
||||
10 | 20:00:00 | |
|
||||
11 | 21:00:00 | |
|
||||
(12 rows)
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time range between
|
||||
'infinity'::interval following and 'infinity'::interval following);
|
||||
id | f_time | first_value | last_value
|
||||
----+----------+-------------+------------
|
||||
0 | 10:00:00 | |
|
||||
1 | 11:00:00 | |
|
||||
2 | 12:00:00 | |
|
||||
3 | 13:00:00 | |
|
||||
4 | 14:00:00 | |
|
||||
5 | 15:00:00 | |
|
||||
6 | 15:00:00 | |
|
||||
7 | 17:00:00 | |
|
||||
8 | 18:00:00 | |
|
||||
9 | 19:00:00 | |
|
||||
10 | 20:00:00 | |
|
||||
11 | 21:00:00 | |
|
||||
(12 rows)
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time range between
|
||||
'-infinity'::interval following and
|
||||
'infinity'::interval following); -- error, negative offset disallowed
|
||||
ERROR: invalid preceding or following size in window function
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz range between
|
||||
'70 min'::interval preceding and '2 hours'::interval following);
|
||||
id | f_timetz | first_value | last_value
|
||||
----+-------------+-------------+------------
|
||||
1 | 11:00:00+01 | 1 | 3
|
||||
0 | 10:00:00+01 | 0 | 2
|
||||
1 | 11:00:00+01 | 0 | 3
|
||||
2 | 12:00:00+01 | 1 | 4
|
||||
3 | 13:00:00+01 | 2 | 6
|
||||
4 | 14:00:00+01 | 3 | 6
|
||||
|
@ -2432,9 +2510,10 @@ window w as (order by f_timetz range between
|
|||
6 | 15:00:00+01 | 4 | 7
|
||||
7 | 17:00:00+01 | 7 | 9
|
||||
8 | 18:00:00+01 | 7 | 10
|
||||
9 | 19:00:00+01 | 8 | 10
|
||||
10 | 20:00:00+01 | 9 | 10
|
||||
(10 rows)
|
||||
9 | 19:00:00+01 | 8 | 11
|
||||
10 | 20:00:00+01 | 9 | 11
|
||||
11 | 21:00:00+01 | 10 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
|
@ -2442,7 +2521,8 @@ window w as (order by f_timetz desc range between
|
|||
'70 min' preceding and '2 hours' following);
|
||||
id | f_timetz | first_value | last_value
|
||||
----+-------------+-------------+------------
|
||||
10 | 20:00:00+01 | 10 | 8
|
||||
11 | 21:00:00+01 | 11 | 9
|
||||
10 | 20:00:00+01 | 11 | 8
|
||||
9 | 19:00:00+01 | 10 | 7
|
||||
8 | 18:00:00+01 | 9 | 7
|
||||
7 | 17:00:00+01 | 8 | 5
|
||||
|
@ -2450,16 +2530,89 @@ window w as (order by f_timetz desc range between
|
|||
5 | 15:00:00+01 | 6 | 3
|
||||
4 | 14:00:00+01 | 6 | 2
|
||||
3 | 13:00:00+01 | 4 | 1
|
||||
2 | 12:00:00+01 | 3 | 1
|
||||
1 | 11:00:00+01 | 2 | 1
|
||||
(10 rows)
|
||||
2 | 12:00:00+01 | 3 | 0
|
||||
1 | 11:00:00+01 | 2 | 0
|
||||
0 | 10:00:00+01 | 1 | 0
|
||||
(12 rows)
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz desc range between
|
||||
'70 min' preceding and '-2 hours' following); -- error, negative offset disallowed
|
||||
ERROR: invalid preceding or following size in window function
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz range between
|
||||
'infinity'::interval preceding and 'infinity'::interval following);
|
||||
id | f_timetz | first_value | last_value
|
||||
----+-------------+-------------+------------
|
||||
0 | 10:00:00+01 | 0 | 11
|
||||
1 | 11:00:00+01 | 0 | 11
|
||||
2 | 12:00:00+01 | 0 | 11
|
||||
3 | 13:00:00+01 | 0 | 11
|
||||
4 | 14:00:00+01 | 0 | 11
|
||||
5 | 15:00:00+01 | 0 | 11
|
||||
6 | 15:00:00+01 | 0 | 11
|
||||
7 | 17:00:00+01 | 0 | 11
|
||||
8 | 18:00:00+01 | 0 | 11
|
||||
9 | 19:00:00+01 | 0 | 11
|
||||
10 | 20:00:00+01 | 0 | 11
|
||||
11 | 21:00:00+01 | 0 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz range between
|
||||
'infinity'::interval preceding and 'infinity'::interval preceding);
|
||||
id | f_timetz | first_value | last_value
|
||||
----+-------------+-------------+------------
|
||||
0 | 10:00:00+01 | |
|
||||
1 | 11:00:00+01 | |
|
||||
2 | 12:00:00+01 | |
|
||||
3 | 13:00:00+01 | |
|
||||
4 | 14:00:00+01 | |
|
||||
5 | 15:00:00+01 | |
|
||||
6 | 15:00:00+01 | |
|
||||
7 | 17:00:00+01 | |
|
||||
8 | 18:00:00+01 | |
|
||||
9 | 19:00:00+01 | |
|
||||
10 | 20:00:00+01 | |
|
||||
11 | 21:00:00+01 | |
|
||||
(12 rows)
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz range between
|
||||
'infinity'::interval following and 'infinity'::interval following);
|
||||
id | f_timetz | first_value | last_value
|
||||
----+-------------+-------------+------------
|
||||
0 | 10:00:00+01 | |
|
||||
1 | 11:00:00+01 | |
|
||||
2 | 12:00:00+01 | |
|
||||
3 | 13:00:00+01 | |
|
||||
4 | 14:00:00+01 | |
|
||||
5 | 15:00:00+01 | |
|
||||
6 | 15:00:00+01 | |
|
||||
7 | 17:00:00+01 | |
|
||||
8 | 18:00:00+01 | |
|
||||
9 | 19:00:00+01 | |
|
||||
10 | 20:00:00+01 | |
|
||||
11 | 21:00:00+01 | |
|
||||
(12 rows)
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz range between
|
||||
'infinity'::interval following and
|
||||
'-infinity'::interval following); -- error, negative offset disallowed
|
||||
ERROR: invalid preceding or following size in window function
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval range between
|
||||
'1 year'::interval preceding and '1 year'::interval following);
|
||||
id | f_interval | first_value | last_value
|
||||
----+------------+-------------+------------
|
||||
0 | -infinity | 0 | 0
|
||||
1 | @ 1 year | 1 | 2
|
||||
2 | @ 2 years | 1 | 3
|
||||
3 | @ 3 years | 2 | 4
|
||||
|
@ -2470,7 +2623,8 @@ window w as (order by f_interval range between
|
|||
8 | @ 8 years | 7 | 9
|
||||
9 | @ 9 years | 8 | 10
|
||||
10 | @ 10 years | 9 | 10
|
||||
(10 rows)
|
||||
11 | infinity | 11 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
|
@ -2478,6 +2632,7 @@ window w as (order by f_interval desc range between
|
|||
'1 year' preceding and '1 year' following);
|
||||
id | f_interval | first_value | last_value
|
||||
----+------------+-------------+------------
|
||||
11 | infinity | 11 | 11
|
||||
10 | @ 10 years | 10 | 9
|
||||
9 | @ 9 years | 10 | 8
|
||||
8 | @ 8 years | 9 | 7
|
||||
|
@ -2488,14 +2643,87 @@ window w as (order by f_interval desc range between
|
|||
3 | @ 3 years | 4 | 2
|
||||
2 | @ 2 years | 3 | 1
|
||||
1 | @ 1 year | 2 | 1
|
||||
(10 rows)
|
||||
0 | -infinity | 0 | 0
|
||||
(12 rows)
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval desc range between
|
||||
'-1 year' preceding and '1 year' following); -- error, negative offset disallowed
|
||||
ERROR: invalid preceding or following size in window function
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval range between
|
||||
'infinity'::interval preceding and 'infinity'::interval following);
|
||||
id | f_interval | first_value | last_value
|
||||
----+------------+-------------+------------
|
||||
0 | -infinity | 0 | 11
|
||||
1 | @ 1 year | 0 | 11
|
||||
2 | @ 2 years | 0 | 11
|
||||
3 | @ 3 years | 0 | 11
|
||||
4 | @ 4 years | 0 | 11
|
||||
5 | @ 5 years | 0 | 11
|
||||
6 | @ 5 years | 0 | 11
|
||||
7 | @ 7 years | 0 | 11
|
||||
8 | @ 8 years | 0 | 11
|
||||
9 | @ 9 years | 0 | 11
|
||||
10 | @ 10 years | 0 | 11
|
||||
11 | infinity | 0 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval range between
|
||||
'infinity'::interval preceding and 'infinity'::interval preceding);
|
||||
id | f_interval | first_value | last_value
|
||||
----+------------+-------------+------------
|
||||
0 | -infinity | 0 | 0
|
||||
1 | @ 1 year | 0 | 0
|
||||
2 | @ 2 years | 0 | 0
|
||||
3 | @ 3 years | 0 | 0
|
||||
4 | @ 4 years | 0 | 0
|
||||
5 | @ 5 years | 0 | 0
|
||||
6 | @ 5 years | 0 | 0
|
||||
7 | @ 7 years | 0 | 0
|
||||
8 | @ 8 years | 0 | 0
|
||||
9 | @ 9 years | 0 | 0
|
||||
10 | @ 10 years | 0 | 0
|
||||
11 | infinity | 0 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval range between
|
||||
'infinity'::interval following and 'infinity'::interval following);
|
||||
id | f_interval | first_value | last_value
|
||||
----+------------+-------------+------------
|
||||
0 | -infinity | 0 | 11
|
||||
1 | @ 1 year | 11 | 11
|
||||
2 | @ 2 years | 11 | 11
|
||||
3 | @ 3 years | 11 | 11
|
||||
4 | @ 4 years | 11 | 11
|
||||
5 | @ 5 years | 11 | 11
|
||||
6 | @ 5 years | 11 | 11
|
||||
7 | @ 7 years | 11 | 11
|
||||
8 | @ 8 years | 11 | 11
|
||||
9 | @ 9 years | 11 | 11
|
||||
10 | @ 10 years | 11 | 11
|
||||
11 | infinity | 11 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval range between
|
||||
'-infinity'::interval following and
|
||||
'infinity'::interval following); -- error, negative offset disallowed
|
||||
ERROR: invalid preceding or following size in window function
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz range between
|
||||
'1 year'::interval preceding and '1 year'::interval following);
|
||||
id | f_timestamptz | first_value | last_value
|
||||
----+------------------------------+-------------+------------
|
||||
0 | -infinity | 0 | 0
|
||||
1 | Thu Oct 19 02:23:54 2000 PDT | 1 | 3
|
||||
2 | Fri Oct 19 02:23:54 2001 PDT | 1 | 4
|
||||
3 | Fri Oct 19 02:23:54 2001 PDT | 1 | 4
|
||||
|
@ -2506,7 +2734,8 @@ window w as (order by f_timestamptz range between
|
|||
8 | Thu Oct 19 02:23:54 2006 PDT | 7 | 9
|
||||
9 | Fri Oct 19 02:23:54 2007 PDT | 8 | 10
|
||||
10 | Sun Oct 19 02:23:54 2008 PDT | 9 | 10
|
||||
(10 rows)
|
||||
11 | infinity | 11 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
|
@ -2514,6 +2743,7 @@ window w as (order by f_timestamptz desc range between
|
|||
'1 year' preceding and '1 year' following);
|
||||
id | f_timestamptz | first_value | last_value
|
||||
----+------------------------------+-------------+------------
|
||||
11 | infinity | 11 | 11
|
||||
10 | Sun Oct 19 02:23:54 2008 PDT | 10 | 9
|
||||
9 | Fri Oct 19 02:23:54 2007 PDT | 10 | 8
|
||||
8 | Thu Oct 19 02:23:54 2006 PDT | 9 | 7
|
||||
|
@ -2524,14 +2754,87 @@ window w as (order by f_timestamptz desc range between
|
|||
3 | Fri Oct 19 02:23:54 2001 PDT | 4 | 1
|
||||
2 | Fri Oct 19 02:23:54 2001 PDT | 4 | 1
|
||||
1 | Thu Oct 19 02:23:54 2000 PDT | 3 | 1
|
||||
(10 rows)
|
||||
0 | -infinity | 0 | 0
|
||||
(12 rows)
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz desc range between
|
||||
'1 year' preceding and '-1 year' following); -- error, negative offset disallowed
|
||||
ERROR: invalid preceding or following size in window function
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz range between
|
||||
'infinity'::interval preceding and 'infinity'::interval following);
|
||||
id | f_timestamptz | first_value | last_value
|
||||
----+------------------------------+-------------+------------
|
||||
0 | -infinity | 0 | 11
|
||||
1 | Thu Oct 19 02:23:54 2000 PDT | 0 | 11
|
||||
2 | Fri Oct 19 02:23:54 2001 PDT | 0 | 11
|
||||
3 | Fri Oct 19 02:23:54 2001 PDT | 0 | 11
|
||||
4 | Sat Oct 19 02:23:54 2002 PDT | 0 | 11
|
||||
5 | Sun Oct 19 02:23:54 2003 PDT | 0 | 11
|
||||
6 | Tue Oct 19 02:23:54 2004 PDT | 0 | 11
|
||||
7 | Wed Oct 19 02:23:54 2005 PDT | 0 | 11
|
||||
8 | Thu Oct 19 02:23:54 2006 PDT | 0 | 11
|
||||
9 | Fri Oct 19 02:23:54 2007 PDT | 0 | 11
|
||||
10 | Sun Oct 19 02:23:54 2008 PDT | 0 | 11
|
||||
11 | infinity | 0 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz range between
|
||||
'infinity'::interval preceding and 'infinity'::interval preceding);
|
||||
id | f_timestamptz | first_value | last_value
|
||||
----+------------------------------+-------------+------------
|
||||
0 | -infinity | 0 | 0
|
||||
1 | Thu Oct 19 02:23:54 2000 PDT | 0 | 0
|
||||
2 | Fri Oct 19 02:23:54 2001 PDT | 0 | 0
|
||||
3 | Fri Oct 19 02:23:54 2001 PDT | 0 | 0
|
||||
4 | Sat Oct 19 02:23:54 2002 PDT | 0 | 0
|
||||
5 | Sun Oct 19 02:23:54 2003 PDT | 0 | 0
|
||||
6 | Tue Oct 19 02:23:54 2004 PDT | 0 | 0
|
||||
7 | Wed Oct 19 02:23:54 2005 PDT | 0 | 0
|
||||
8 | Thu Oct 19 02:23:54 2006 PDT | 0 | 0
|
||||
9 | Fri Oct 19 02:23:54 2007 PDT | 0 | 0
|
||||
10 | Sun Oct 19 02:23:54 2008 PDT | 0 | 0
|
||||
11 | infinity | 0 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz range between
|
||||
'infinity'::interval following and 'infinity'::interval following);
|
||||
id | f_timestamptz | first_value | last_value
|
||||
----+------------------------------+-------------+------------
|
||||
0 | -infinity | 0 | 11
|
||||
1 | Thu Oct 19 02:23:54 2000 PDT | 11 | 11
|
||||
2 | Fri Oct 19 02:23:54 2001 PDT | 11 | 11
|
||||
3 | Fri Oct 19 02:23:54 2001 PDT | 11 | 11
|
||||
4 | Sat Oct 19 02:23:54 2002 PDT | 11 | 11
|
||||
5 | Sun Oct 19 02:23:54 2003 PDT | 11 | 11
|
||||
6 | Tue Oct 19 02:23:54 2004 PDT | 11 | 11
|
||||
7 | Wed Oct 19 02:23:54 2005 PDT | 11 | 11
|
||||
8 | Thu Oct 19 02:23:54 2006 PDT | 11 | 11
|
||||
9 | Fri Oct 19 02:23:54 2007 PDT | 11 | 11
|
||||
10 | Sun Oct 19 02:23:54 2008 PDT | 11 | 11
|
||||
11 | infinity | 11 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz range between
|
||||
'-infinity'::interval following and
|
||||
'infinity'::interval following); -- error, negative offset disallowed
|
||||
ERROR: invalid preceding or following size in window function
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp range between
|
||||
'1 year'::interval preceding and '1 year'::interval following);
|
||||
id | f_timestamp | first_value | last_value
|
||||
----+--------------------------+-------------+------------
|
||||
0 | -infinity | 0 | 0
|
||||
1 | Thu Oct 19 10:23:54 2000 | 1 | 3
|
||||
2 | Fri Oct 19 10:23:54 2001 | 1 | 4
|
||||
3 | Fri Oct 19 10:23:54 2001 | 1 | 4
|
||||
|
@ -2542,7 +2845,8 @@ window w as (order by f_timestamp range between
|
|||
8 | Thu Oct 19 10:23:54 2006 | 7 | 9
|
||||
9 | Fri Oct 19 10:23:54 2007 | 8 | 10
|
||||
10 | Sun Oct 19 10:23:54 2008 | 9 | 10
|
||||
(10 rows)
|
||||
11 | infinity | 11 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
|
@ -2550,6 +2854,7 @@ window w as (order by f_timestamp desc range between
|
|||
'1 year' preceding and '1 year' following);
|
||||
id | f_timestamp | first_value | last_value
|
||||
----+--------------------------+-------------+------------
|
||||
11 | infinity | 11 | 11
|
||||
10 | Sun Oct 19 10:23:54 2008 | 10 | 9
|
||||
9 | Fri Oct 19 10:23:54 2007 | 10 | 8
|
||||
8 | Thu Oct 19 10:23:54 2006 | 9 | 7
|
||||
|
@ -2560,8 +2865,80 @@ window w as (order by f_timestamp desc range between
|
|||
3 | Fri Oct 19 10:23:54 2001 | 4 | 1
|
||||
2 | Fri Oct 19 10:23:54 2001 | 4 | 1
|
||||
1 | Thu Oct 19 10:23:54 2000 | 3 | 1
|
||||
(10 rows)
|
||||
0 | -infinity | 0 | 0
|
||||
(12 rows)
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp desc range between
|
||||
'-1 year' preceding and '1 year' following); -- error, negative offset disallowed
|
||||
ERROR: invalid preceding or following size in window function
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp range between
|
||||
'infinity'::interval preceding and 'infinity'::interval following);
|
||||
id | f_timestamp | first_value | last_value
|
||||
----+--------------------------+-------------+------------
|
||||
0 | -infinity | 0 | 11
|
||||
1 | Thu Oct 19 10:23:54 2000 | 0 | 11
|
||||
2 | Fri Oct 19 10:23:54 2001 | 0 | 11
|
||||
3 | Fri Oct 19 10:23:54 2001 | 0 | 11
|
||||
4 | Sat Oct 19 10:23:54 2002 | 0 | 11
|
||||
5 | Sun Oct 19 10:23:54 2003 | 0 | 11
|
||||
6 | Tue Oct 19 10:23:54 2004 | 0 | 11
|
||||
7 | Wed Oct 19 10:23:54 2005 | 0 | 11
|
||||
8 | Thu Oct 19 10:23:54 2006 | 0 | 11
|
||||
9 | Fri Oct 19 10:23:54 2007 | 0 | 11
|
||||
10 | Sun Oct 19 10:23:54 2008 | 0 | 11
|
||||
11 | infinity | 0 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp range between
|
||||
'infinity'::interval preceding and 'infinity'::interval preceding);
|
||||
id | f_timestamp | first_value | last_value
|
||||
----+--------------------------+-------------+------------
|
||||
0 | -infinity | 0 | 0
|
||||
1 | Thu Oct 19 10:23:54 2000 | 0 | 0
|
||||
2 | Fri Oct 19 10:23:54 2001 | 0 | 0
|
||||
3 | Fri Oct 19 10:23:54 2001 | 0 | 0
|
||||
4 | Sat Oct 19 10:23:54 2002 | 0 | 0
|
||||
5 | Sun Oct 19 10:23:54 2003 | 0 | 0
|
||||
6 | Tue Oct 19 10:23:54 2004 | 0 | 0
|
||||
7 | Wed Oct 19 10:23:54 2005 | 0 | 0
|
||||
8 | Thu Oct 19 10:23:54 2006 | 0 | 0
|
||||
9 | Fri Oct 19 10:23:54 2007 | 0 | 0
|
||||
10 | Sun Oct 19 10:23:54 2008 | 0 | 0
|
||||
11 | infinity | 0 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp range between
|
||||
'infinity'::interval following and 'infinity'::interval following);
|
||||
id | f_timestamp | first_value | last_value
|
||||
----+--------------------------+-------------+------------
|
||||
0 | -infinity | 0 | 11
|
||||
1 | Thu Oct 19 10:23:54 2000 | 11 | 11
|
||||
2 | Fri Oct 19 10:23:54 2001 | 11 | 11
|
||||
3 | Fri Oct 19 10:23:54 2001 | 11 | 11
|
||||
4 | Sat Oct 19 10:23:54 2002 | 11 | 11
|
||||
5 | Sun Oct 19 10:23:54 2003 | 11 | 11
|
||||
6 | Tue Oct 19 10:23:54 2004 | 11 | 11
|
||||
7 | Wed Oct 19 10:23:54 2005 | 11 | 11
|
||||
8 | Thu Oct 19 10:23:54 2006 | 11 | 11
|
||||
9 | Fri Oct 19 10:23:54 2007 | 11 | 11
|
||||
10 | Sun Oct 19 10:23:54 2008 | 11 | 11
|
||||
11 | infinity | 11 | 11
|
||||
(12 rows)
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp range between
|
||||
'-infinity'::interval following and
|
||||
'infinity'::interval following); -- error, negative offset disallowed
|
||||
ERROR: invalid preceding or following size in window function
|
||||
-- RANGE offset PRECEDING/FOLLOWING error cases
|
||||
select sum(salary) over (order by enroll_date, salary range between '1 year'::interval preceding and '2 years'::interval following
|
||||
exclude ties), salary, enroll_date from empsalary;
|
||||
|
@ -4375,6 +4752,52 @@ SELECT i,AVG(v::interval) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDE
|
|||
4 |
|
||||
(4 rows)
|
||||
|
||||
-- moving aggregates over infinite intervals
|
||||
SELECT x
|
||||
,avg(x) OVER(ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING ) as curr_next_avg
|
||||
,avg(x) OVER(ROWS BETWEEN 1 PRECEDING AND CURRENT ROW ) as prev_curr_avg
|
||||
,sum(x) OVER(ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING ) as curr_next_sum
|
||||
,sum(x) OVER(ROWS BETWEEN 1 PRECEDING AND CURRENT ROW ) as prev_curr_sum
|
||||
FROM (VALUES (NULL::interval),
|
||||
('infinity'::interval),
|
||||
('-2147483648 days -2147483648 months -9223372036854775807 usecs'), -- extreme interval value
|
||||
('-infinity'::interval),
|
||||
('2147483647 days 2147483647 months 9223372036854775806 usecs'), -- extreme interval value
|
||||
('infinity'::interval),
|
||||
('6 days'::interval),
|
||||
('7 days'::interval),
|
||||
(NULL::interval),
|
||||
('-infinity'::interval)) v(x);
|
||||
x | curr_next_avg | prev_curr_avg | curr_next_sum | prev_curr_sum
|
||||
------------------------------------------------------------------------------+-------------------+-------------------+---------------+---------------
|
||||
| infinity | | infinity |
|
||||
infinity | infinity | infinity | infinity | infinity
|
||||
@ 178956970 years 8 mons 2147483648 days 2562047788 hours 54.775807 secs ago | -infinity | infinity | -infinity | infinity
|
||||
-infinity | -infinity | -infinity | -infinity | -infinity
|
||||
@ 178956970 years 7 mons 2147483647 days 2562047788 hours 54.775806 secs | infinity | -infinity | infinity | -infinity
|
||||
infinity | infinity | infinity | infinity | infinity
|
||||
@ 6 days | @ 6 days 12 hours | infinity | @ 13 days | infinity
|
||||
@ 7 days | @ 7 days | @ 6 days 12 hours | @ 7 days | @ 13 days
|
||||
| -infinity | @ 7 days | -infinity | @ 7 days
|
||||
-infinity | -infinity | -infinity | -infinity | -infinity
|
||||
(10 rows)
|
||||
|
||||
--should fail.
|
||||
SELECT x, avg(x) OVER(ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
|
||||
FROM (VALUES (NULL::interval),
|
||||
('3 days'::interval),
|
||||
('infinity'::timestamptz - now()),
|
||||
('6 days'::interval),
|
||||
('-infinity'::interval)) v(x);
|
||||
ERROR: interval out of range.
|
||||
--should fail.
|
||||
SELECT x, sum(x) OVER(ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
|
||||
FROM (VALUES (NULL::interval),
|
||||
('3 days'::interval),
|
||||
('infinity'::timestamptz - now()),
|
||||
('6 days'::interval),
|
||||
('-infinity'::interval)) v(x);
|
||||
ERROR: interval out of range.
|
||||
SELECT i,SUM(v::smallint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
||||
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
||||
i | sum
|
||||
|
|
|
@ -682,6 +682,25 @@ SELECT * FROM brin_interval_test WHERE a = '-30 years'::interval;
|
|||
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF)
|
||||
SELECT * FROM brin_interval_test WHERE a = '30 years'::interval;
|
||||
|
||||
DROP TABLE brin_interval_test;
|
||||
RESET enable_seqscan;
|
||||
|
||||
-- test handling of infinite interval values
|
||||
CREATE TABLE brin_interval_test(a INTERVAL);
|
||||
|
||||
INSERT INTO brin_interval_test VALUES ('-infinity'), ('infinity');
|
||||
INSERT INTO brin_interval_test SELECT (i || ' days')::interval FROM generate_series(100, 140) s(i);
|
||||
|
||||
CREATE INDEX ON brin_interval_test USING brin (a interval_minmax_multi_ops) WITH (pages_per_range=1);
|
||||
|
||||
SET enable_seqscan = off;
|
||||
|
||||
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF)
|
||||
SELECT * FROM brin_interval_test WHERE a = '-30 years'::interval;
|
||||
|
||||
EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF)
|
||||
SELECT * FROM brin_interval_test WHERE a = '30 years'::interval;
|
||||
|
||||
DROP TABLE brin_interval_test;
|
||||
RESET enable_seqscan;
|
||||
RESET datestyle;
|
||||
|
|
|
@ -213,10 +213,12 @@ SELECT t.d1 AS t, i.f1 AS i, t.d1 + i.f1 AS "add", t.d1 - i.f1 AS "subtract"
|
|||
|
||||
SELECT t.f1 AS t, i.f1 AS i, t.f1 + i.f1 AS "add", t.f1 - i.f1 AS "subtract"
|
||||
FROM TIME_TBL t, INTERVAL_TBL i
|
||||
WHERE isfinite(i.f1)
|
||||
ORDER BY 1,2;
|
||||
|
||||
SELECT t.f1 AS t, i.f1 AS i, t.f1 + i.f1 AS "add", t.f1 - i.f1 AS "subtract"
|
||||
FROM TIMETZ_TBL t, INTERVAL_TBL i
|
||||
WHERE isfinite(i.f1)
|
||||
ORDER BY 1,2;
|
||||
|
||||
-- SQL9x OVERLAPS operator
|
||||
|
@ -293,7 +295,6 @@ SELECT d.f1 AS "timestamp", t.f1 AS "interval", d.f1 + t.f1 AS plus
|
|||
|
||||
SELECT d.f1 AS "timestamp", t.f1 AS "interval", d.f1 - t.f1 AS minus
|
||||
FROM TEMP_TIMESTAMP d, INTERVAL_TBL t
|
||||
WHERE isfinite(d.f1)
|
||||
ORDER BY minus, "timestamp", "interval";
|
||||
|
||||
SELECT d.f1 AS "timestamp",
|
||||
|
|
|
@ -14,6 +14,8 @@ SELECT INTERVAL '-1 days +02:03' AS "22 hours ago...";
|
|||
SELECT INTERVAL '1.5 weeks' AS "Ten days twelve hours";
|
||||
SELECT INTERVAL '1.5 months' AS "One month 15 days";
|
||||
SELECT INTERVAL '10 years -11 month -12 days +13:14' AS "9 years...";
|
||||
SELECT INTERVAL 'infinity' AS "eternity";
|
||||
SELECT INTERVAL '-infinity' AS "beginning of time";
|
||||
|
||||
CREATE TABLE INTERVAL_TBL (f1 interval);
|
||||
|
||||
|
@ -27,6 +29,8 @@ INSERT INTO INTERVAL_TBL (f1) VALUES ('1 day 2 hours 3 minutes 4 seconds');
|
|||
INSERT INTO INTERVAL_TBL (f1) VALUES ('6 years');
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('5 months');
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('5 months 12 hours');
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('infinity');
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('-infinity');
|
||||
|
||||
-- badly formatted interval
|
||||
INSERT INTO INTERVAL_TBL (f1) VALUES ('badly formatted interval');
|
||||
|
@ -66,6 +70,17 @@ SELECT r1.*, r2.*
|
|||
WHERE r1.f1 > r2.f1
|
||||
ORDER BY r1.f1, r2.f1;
|
||||
|
||||
-- test unary minus
|
||||
|
||||
SELECT f1, -f1 FROM INTERVAL_TBL;
|
||||
SELECT -('-2147483648 months'::interval); -- should fail
|
||||
SELECT -('-2147483647 months'::interval); -- ok
|
||||
SELECT -('-2147483648 days'::interval); -- should fail
|
||||
SELECT -('-2147483647 days'::interval); -- ok
|
||||
SELECT -('-9223372036854775808 us'::interval); -- should fail
|
||||
SELECT -('-9223372036854775807 us'::interval); -- ok
|
||||
SELECT -('-2147483647 months -2147483647 days -9223372036854775807 us'::interval); -- should fail
|
||||
|
||||
-- Test intervals that are large enough to overflow 64 bits in comparisons
|
||||
CREATE TEMP TABLE INTERVAL_TBL_OF (f1 interval);
|
||||
INSERT INTO INTERVAL_TBL_OF (f1) VALUES
|
||||
|
@ -95,6 +110,9 @@ SELECT f1 FROM INTERVAL_TBL_OF r1 ORDER BY f1;
|
|||
SELECT f1 FROM INTERVAL_TBL_OF r1 ORDER BY f1;
|
||||
RESET enable_seqscan;
|
||||
|
||||
-- subtracting about-to-overflow values should result in 0
|
||||
SELECT f1 - f1 FROM INTERVAL_TBL_OF;
|
||||
|
||||
DROP TABLE INTERVAL_TBL_OF;
|
||||
|
||||
-- Test multiplication and division with intervals.
|
||||
|
@ -140,7 +158,7 @@ SELECT * FROM INTERVAL_TBL;
|
|||
-- known to change the allowed input syntax for type interval without
|
||||
-- updating pg_aggregate.agginitval
|
||||
|
||||
select avg(f1) from interval_tbl;
|
||||
select avg(f1) from interval_tbl where isfinite(f1);
|
||||
|
||||
-- test long interval input
|
||||
select '4 millenniums 5 centuries 4 decades 1 year 4 months 4 days 17 minutes 31 seconds'::interval;
|
||||
|
@ -528,13 +546,13 @@ select make_interval(mins := -1, secs := -9223372036800.0);
|
|||
|
||||
-- test that INT_MIN number is formatted properly
|
||||
SET IntervalStyle to postgres;
|
||||
select interval '-2147483648 months -2147483648 days -9223372036854775808 us';
|
||||
select interval '-2147483647 months -2147483648 days -9223372036854775808 us';
|
||||
SET IntervalStyle to sql_standard;
|
||||
select interval '-2147483648 months -2147483648 days -9223372036854775808 us';
|
||||
select interval '-2147483647 months -2147483648 days -9223372036854775808 us';
|
||||
SET IntervalStyle to iso_8601;
|
||||
select interval '-2147483648 months -2147483648 days -9223372036854775808 us';
|
||||
select interval '-2147483647 months -2147483648 days -9223372036854775808 us';
|
||||
SET IntervalStyle to postgres_verbose;
|
||||
select interval '-2147483648 months -2147483648 days -9223372036854775808 us';
|
||||
select interval '-2147483647 months -2147483648 days -9223372036854775808 us';
|
||||
|
||||
-- check that '30 days' equals '1 month' according to the hash function
|
||||
select '30 days'::interval = '1 month'::interval as t;
|
||||
|
@ -598,6 +616,157 @@ SELECT f1,
|
|||
-- internal overflow test case
|
||||
SELECT extract(epoch from interval '1000000000 days');
|
||||
|
||||
--
|
||||
-- test infinite intervals
|
||||
--
|
||||
|
||||
-- largest finite intervals
|
||||
SELECT interval '-2147483648 months -2147483648 days -9223372036854775807 us';
|
||||
SELECT interval '2147483647 months 2147483647 days 9223372036854775806 us';
|
||||
|
||||
-- infinite intervals
|
||||
SELECT interval '-2147483648 months -2147483648 days -9223372036854775808 us';
|
||||
SELECT interval '2147483647 months 2147483647 days 9223372036854775807 us';
|
||||
|
||||
CREATE TABLE INFINITE_INTERVAL_TBL (i interval);
|
||||
INSERT INTO INFINITE_INTERVAL_TBL VALUES ('infinity'), ('-infinity'), ('1 year 2 days 3 hours');
|
||||
|
||||
SELECT i, isfinite(i) FROM INFINITE_INTERVAL_TBL;
|
||||
|
||||
-- test basic arithmetic
|
||||
CREATE FUNCTION eval(expr text)
|
||||
RETURNS text AS
|
||||
$$
|
||||
DECLARE
|
||||
result text;
|
||||
BEGIN
|
||||
EXECUTE 'select '||expr INTO result;
|
||||
RETURN result;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RETURN SQLERRM;
|
||||
END
|
||||
$$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
SELECT d AS date, i AS interval,
|
||||
eval(format('date %L + interval %L', d, i)) AS plus,
|
||||
eval(format('date %L - interval %L', d, i)) AS minus
|
||||
FROM (VALUES (date '-infinity'),
|
||||
(date '1995-08-06'),
|
||||
(date 'infinity')) AS t1(d),
|
||||
(VALUES (interval '-infinity'),
|
||||
(interval 'infinity')) AS t2(i);
|
||||
|
||||
SELECT i1 AS interval1, i2 AS interval2,
|
||||
eval(format('interval %L + interval %L', i1, i2)) AS plus,
|
||||
eval(format('interval %L - interval %L', i1, i2)) AS minus
|
||||
FROM (VALUES (interval '-infinity'),
|
||||
(interval '2 months'),
|
||||
(interval 'infinity')) AS t1(i1),
|
||||
(VALUES (interval '-infinity'),
|
||||
(interval '10 days'),
|
||||
(interval 'infinity')) AS t2(i2);
|
||||
|
||||
SELECT interval '2147483646 months 2147483646 days 9223372036854775806 us' + interval '1 month 1 day 1 us';
|
||||
SELECT interval '-2147483647 months -2147483647 days -9223372036854775807 us' + interval '-1 month -1 day -1 us';
|
||||
SELECT interval '2147483646 months 2147483646 days 9223372036854775806 us' - interval '-1 month -1 day -1 us';
|
||||
SELECT interval '-2147483647 months -2147483647 days -9223372036854775807 us' - interval '1 month 1 day 1 us';
|
||||
|
||||
SELECT t AS timestamp, i AS interval,
|
||||
eval(format('timestamp %L + interval %L', t, i)) AS plus,
|
||||
eval(format('timestamp %L - interval %L', t, i)) AS minus
|
||||
FROM (VALUES (timestamp '-infinity'),
|
||||
(timestamp '1995-08-06 12:30:15'),
|
||||
(timestamp 'infinity')) AS t1(t),
|
||||
(VALUES (interval '-infinity'),
|
||||
(interval 'infinity')) AS t2(i);
|
||||
|
||||
SELECT t AT TIME ZONE 'GMT' AS timestamptz, i AS interval,
|
||||
eval(format('timestamptz %L + interval %L', t, i)) AS plus,
|
||||
eval(format('timestamptz %L - interval %L', t, i)) AS minus
|
||||
FROM (VALUES (timestamptz '-infinity'),
|
||||
(timestamptz '1995-08-06 12:30:15 GMT'),
|
||||
(timestamptz 'infinity')) AS t1(t),
|
||||
(VALUES (interval '-infinity'),
|
||||
(interval 'infinity')) AS t2(i);
|
||||
|
||||
-- time +/- infinite interval not supported
|
||||
SELECT time '11:27:42' + interval 'infinity';
|
||||
SELECT time '11:27:42' + interval '-infinity';
|
||||
SELECT time '11:27:42' - interval 'infinity';
|
||||
SELECT time '11:27:42' - interval '-infinity';
|
||||
SELECT timetz '11:27:42' + interval 'infinity';
|
||||
SELECT timetz '11:27:42' + interval '-infinity';
|
||||
SELECT timetz '11:27:42' - interval 'infinity';
|
||||
SELECT timetz '11:27:42' - interval '-infinity';
|
||||
|
||||
SELECT lhst.i lhs,
|
||||
rhst.i rhs,
|
||||
lhst.i < rhst.i AS lt,
|
||||
lhst.i <= rhst.i AS le,
|
||||
lhst.i = rhst.i AS eq,
|
||||
lhst.i > rhst.i AS gt,
|
||||
lhst.i >= rhst.i AS ge,
|
||||
lhst.i <> rhst.i AS ne
|
||||
FROM INFINITE_INTERVAL_TBL lhst CROSS JOIN INFINITE_INTERVAL_TBL rhst
|
||||
WHERE NOT isfinite(lhst.i);
|
||||
|
||||
SELECT i AS interval,
|
||||
-i AS um,
|
||||
i * 2.0 AS mul,
|
||||
i * -2.0 AS mul_neg,
|
||||
i * 'infinity' AS mul_inf,
|
||||
i * '-infinity' AS mul_inf_neg,
|
||||
i / 3.0 AS div,
|
||||
i / -3.0 AS div_neg
|
||||
FROM INFINITE_INTERVAL_TBL
|
||||
WHERE NOT isfinite(i);
|
||||
|
||||
SELECT -interval '-2147483647 months -2147483647 days -9223372036854775807 us';
|
||||
SELECT interval 'infinity' * 'nan';
|
||||
SELECT interval '-infinity' * 'nan';
|
||||
SELECT interval '-1073741824 months -1073741824 days -4611686018427387904 us' * 2;
|
||||
SELECT interval 'infinity' * 0;
|
||||
SELECT interval '-infinity' * 0;
|
||||
SELECT interval '0 days' * 'infinity'::float;
|
||||
SELECT interval '0 days' * '-infinity'::float;
|
||||
SELECT interval '5 days' * 'infinity'::float;
|
||||
SELECT interval '5 days' * '-infinity'::float;
|
||||
|
||||
SELECT interval 'infinity' / 'infinity';
|
||||
SELECT interval 'infinity' / '-infinity';
|
||||
SELECT interval 'infinity' / 'nan';
|
||||
SELECT interval '-infinity' / 'infinity';
|
||||
SELECT interval '-infinity' / '-infinity';
|
||||
SELECT interval '-infinity' / 'nan';
|
||||
SELECT interval '-1073741824 months -1073741824 days -4611686018427387904 us' / 0.5;
|
||||
|
||||
SELECT date_bin('infinity', timestamp '2001-02-16 20:38:40', timestamp '2001-02-16 20:05:00');
|
||||
SELECT date_bin('-infinity', timestamp '2001-02-16 20:38:40', timestamp '2001-02-16 20:05:00');
|
||||
|
||||
SELECT i AS interval, date_trunc('hour', i)
|
||||
FROM INFINITE_INTERVAL_TBL
|
||||
WHERE NOT isfinite(i);
|
||||
|
||||
SELECT i AS interval, justify_days(i), justify_hours(i), justify_interval(i)
|
||||
FROM INFINITE_INTERVAL_TBL
|
||||
WHERE NOT isfinite(i);
|
||||
|
||||
SELECT timezone('infinity'::interval, '1995-08-06 12:12:12'::timestamp);
|
||||
SELECT timezone('-infinity'::interval, '1995-08-06 12:12:12'::timestamp);
|
||||
SELECT timezone('infinity'::interval, '1995-08-06 12:12:12'::timestamptz);
|
||||
SELECT timezone('-infinity'::interval, '1995-08-06 12:12:12'::timestamptz);
|
||||
SELECT timezone('infinity'::interval, '12:12:12'::time);
|
||||
SELECT timezone('-infinity'::interval, '12:12:12'::time);
|
||||
SELECT timezone('infinity'::interval, '12:12:12'::timetz);
|
||||
SELECT timezone('-infinity'::interval, '12:12:12'::timetz);
|
||||
|
||||
SELECT 'infinity'::interval::time;
|
||||
SELECT '-infinity'::interval::time;
|
||||
|
||||
SELECT to_char('infinity'::interval, 'YYYY');
|
||||
SELECT to_char('-infinity'::interval, 'YYYY');
|
||||
|
||||
-- "ago" can only appear once at the end of an interval.
|
||||
SELECT INTERVAL '42 days 2 seconds ago ago';
|
||||
SELECT INTERVAL '2 minutes ago 5 days';
|
||||
|
@ -605,3 +774,17 @@ SELECT INTERVAL '2 minutes ago 5 days';
|
|||
-- consecutive and dangling units are not allowed.
|
||||
SELECT INTERVAL 'hour 5 months';
|
||||
SELECT INTERVAL '1 year months days 5 hours';
|
||||
|
||||
-- unacceptable reserved words in interval. Only "infinity", "+infinity" and
|
||||
-- "-infinity" are allowed.
|
||||
SELECT INTERVAL 'now';
|
||||
SELECT INTERVAL 'today';
|
||||
SELECT INTERVAL 'tomorrow';
|
||||
SELECT INTERVAL 'allballs';
|
||||
SELECT INTERVAL 'epoch';
|
||||
SELECT INTERVAL 'yesterday';
|
||||
|
||||
-- infinity specification should be the only thing
|
||||
SELECT INTERVAL 'infinity years';
|
||||
SELECT INTERVAL 'infinity ago';
|
||||
SELECT INTERVAL '+infinity -infinity';
|
||||
|
|
|
@ -397,3 +397,22 @@ select generate_series('2022-01-01 00:00'::timestamp,
|
|||
select * from generate_series('2020-01-01 00:00'::timestamp,
|
||||
'2020-01-02 03:00'::timestamp,
|
||||
'0 hour'::interval);
|
||||
select generate_series(timestamp '1995-08-06 12:12:12', timestamp '1996-08-06 12:12:12', interval 'infinity');
|
||||
select generate_series(timestamp '1995-08-06 12:12:12', timestamp '1996-08-06 12:12:12', interval '-infinity');
|
||||
|
||||
|
||||
-- test arithmetic with infinite timestamps
|
||||
select timestamp 'infinity' - timestamp 'infinity';
|
||||
select timestamp 'infinity' - timestamp '-infinity';
|
||||
select timestamp '-infinity' - timestamp 'infinity';
|
||||
select timestamp '-infinity' - timestamp '-infinity';
|
||||
select timestamp 'infinity' - timestamp '1995-08-06 12:12:12';
|
||||
select timestamp '-infinity' - timestamp '1995-08-06 12:12:12';
|
||||
|
||||
-- test age() with infinite timestamps
|
||||
select age(timestamp 'infinity');
|
||||
select age(timestamp '-infinity');
|
||||
select age(timestamp 'infinity', timestamp 'infinity');
|
||||
select age(timestamp 'infinity', timestamp '-infinity');
|
||||
select age(timestamp '-infinity', timestamp 'infinity');
|
||||
select age(timestamp '-infinity', timestamp '-infinity');
|
||||
|
|
|
@ -458,6 +458,8 @@ select generate_series('2022-01-01 00:00'::timestamptz,
|
|||
select * from generate_series('2020-01-01 00:00'::timestamptz,
|
||||
'2020-01-02 03:00'::timestamptz,
|
||||
'0 hour'::interval);
|
||||
select generate_series(timestamptz '1995-08-06 12:12:12', timestamptz '1996-08-06 12:12:12', interval 'infinity');
|
||||
select generate_series(timestamptz '1995-08-06 12:12:12', timestamptz '1996-08-06 12:12:12', interval '-infinity');
|
||||
|
||||
-- Interval crossing time shift for Europe/Warsaw timezone (with DST)
|
||||
SET TimeZone to 'UTC';
|
||||
|
@ -642,3 +644,19 @@ insert into tmptz values ('2017-01-18 00:00+00');
|
|||
explain (costs off)
|
||||
select * from tmptz where f1 at time zone 'utc' = '2017-01-18 00:00';
|
||||
select * from tmptz where f1 at time zone 'utc' = '2017-01-18 00:00';
|
||||
|
||||
-- test arithmetic with infinite timestamps
|
||||
SELECT timestamptz 'infinity' - timestamptz 'infinity';
|
||||
SELECT timestamptz 'infinity' - timestamptz '-infinity';
|
||||
SELECT timestamptz '-infinity' - timestamptz 'infinity';
|
||||
SELECT timestamptz '-infinity' - timestamptz '-infinity';
|
||||
SELECT timestamptz 'infinity' - timestamptz '1995-08-06 12:12:12';
|
||||
SELECT timestamptz '-infinity' - timestamptz '1995-08-06 12:12:12';
|
||||
|
||||
-- test age() with infinite timestamps
|
||||
SELECT age(timestamptz 'infinity');
|
||||
SELECT age(timestamptz '-infinity');
|
||||
SELECT age(timestamptz 'infinity', timestamptz 'infinity');
|
||||
SELECT age(timestamptz 'infinity', timestamptz '-infinity');
|
||||
SELECT age(timestamptz '-infinity', timestamptz 'infinity');
|
||||
SELECT age(timestamptz '-infinity', timestamptz '-infinity');
|
||||
|
|
|
@ -673,6 +673,7 @@ create temp table datetimes(
|
|||
);
|
||||
|
||||
insert into datetimes values
|
||||
(0, '10:00', '10:00 BST', '-infinity', '-infinity', '-infinity'),
|
||||
(1, '11:00', '11:00 BST', '1 year', '2000-10-19 10:23:54+01', '2000-10-19 10:23:54'),
|
||||
(2, '12:00', '12:00 BST', '2 years', '2001-10-19 10:23:54+01', '2001-10-19 10:23:54'),
|
||||
(3, '13:00', '13:00 BST', '3 years', '2001-10-19 10:23:54+01', '2001-10-19 10:23:54'),
|
||||
|
@ -682,7 +683,8 @@ insert into datetimes values
|
|||
(7, '17:00', '17:00 BST', '7 years', '2005-10-19 10:23:54+01', '2005-10-19 10:23:54'),
|
||||
(8, '18:00', '18:00 BST', '8 years', '2006-10-19 10:23:54+01', '2006-10-19 10:23:54'),
|
||||
(9, '19:00', '19:00 BST', '9 years', '2007-10-19 10:23:54+01', '2007-10-19 10:23:54'),
|
||||
(10, '20:00', '20:00 BST', '10 years', '2008-10-19 10:23:54+01', '2008-10-19 10:23:54');
|
||||
(10, '20:00', '20:00 BST', '10 years', '2008-10-19 10:23:54+01', '2008-10-19 10:23:54'),
|
||||
(11, '21:00', '21:00 BST', 'infinity', 'infinity', 'infinity');
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
|
@ -694,6 +696,32 @@ from datetimes
|
|||
window w as (order by f_time desc range between
|
||||
'70 min' preceding and '2 hours' following);
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time desc range between
|
||||
'-70 min' preceding and '2 hours' following); -- error, negative offset disallowed
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time range between
|
||||
'infinity'::interval preceding and 'infinity'::interval following);
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time range between
|
||||
'infinity'::interval preceding and 'infinity'::interval preceding);
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time range between
|
||||
'infinity'::interval following and 'infinity'::interval following);
|
||||
|
||||
select id, f_time, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_time range between
|
||||
'-infinity'::interval following and
|
||||
'infinity'::interval following); -- error, negative offset disallowed
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz range between
|
||||
|
@ -704,6 +732,32 @@ from datetimes
|
|||
window w as (order by f_timetz desc range between
|
||||
'70 min' preceding and '2 hours' following);
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz desc range between
|
||||
'70 min' preceding and '-2 hours' following); -- error, negative offset disallowed
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz range between
|
||||
'infinity'::interval preceding and 'infinity'::interval following);
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz range between
|
||||
'infinity'::interval preceding and 'infinity'::interval preceding);
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz range between
|
||||
'infinity'::interval following and 'infinity'::interval following);
|
||||
|
||||
select id, f_timetz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timetz range between
|
||||
'infinity'::interval following and
|
||||
'-infinity'::interval following); -- error, negative offset disallowed
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval range between
|
||||
|
@ -714,6 +768,32 @@ from datetimes
|
|||
window w as (order by f_interval desc range between
|
||||
'1 year' preceding and '1 year' following);
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval desc range between
|
||||
'-1 year' preceding and '1 year' following); -- error, negative offset disallowed
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval range between
|
||||
'infinity'::interval preceding and 'infinity'::interval following);
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval range between
|
||||
'infinity'::interval preceding and 'infinity'::interval preceding);
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval range between
|
||||
'infinity'::interval following and 'infinity'::interval following);
|
||||
|
||||
select id, f_interval, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_interval range between
|
||||
'-infinity'::interval following and
|
||||
'infinity'::interval following); -- error, negative offset disallowed
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz range between
|
||||
|
@ -724,6 +804,32 @@ from datetimes
|
|||
window w as (order by f_timestamptz desc range between
|
||||
'1 year' preceding and '1 year' following);
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz desc range between
|
||||
'1 year' preceding and '-1 year' following); -- error, negative offset disallowed
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz range between
|
||||
'infinity'::interval preceding and 'infinity'::interval following);
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz range between
|
||||
'infinity'::interval preceding and 'infinity'::interval preceding);
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz range between
|
||||
'infinity'::interval following and 'infinity'::interval following);
|
||||
|
||||
select id, f_timestamptz, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamptz range between
|
||||
'-infinity'::interval following and
|
||||
'infinity'::interval following); -- error, negative offset disallowed
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp range between
|
||||
|
@ -734,6 +840,32 @@ from datetimes
|
|||
window w as (order by f_timestamp desc range between
|
||||
'1 year' preceding and '1 year' following);
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp desc range between
|
||||
'-1 year' preceding and '1 year' following); -- error, negative offset disallowed
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp range between
|
||||
'infinity'::interval preceding and 'infinity'::interval following);
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp range between
|
||||
'infinity'::interval preceding and 'infinity'::interval preceding);
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp range between
|
||||
'infinity'::interval following and 'infinity'::interval following);
|
||||
|
||||
select id, f_timestamp, first_value(id) over w, last_value(id) over w
|
||||
from datetimes
|
||||
window w as (order by f_timestamp range between
|
||||
'-infinity'::interval following and
|
||||
'infinity'::interval following); -- error, negative offset disallowed
|
||||
|
||||
-- RANGE offset PRECEDING/FOLLOWING error cases
|
||||
select sum(salary) over (order by enroll_date, salary range between '1 year'::interval preceding and '2 years'::interval following
|
||||
exclude ties), salary, enroll_date from empsalary;
|
||||
|
@ -1591,6 +1723,39 @@ SELECT i,AVG(v::numeric) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED
|
|||
SELECT i,AVG(v::interval) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
||||
FROM (VALUES(1,'1 sec'),(2,'2 sec'),(3,NULL),(4,NULL)) t(i,v);
|
||||
|
||||
-- moving aggregates over infinite intervals
|
||||
SELECT x
|
||||
,avg(x) OVER(ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING ) as curr_next_avg
|
||||
,avg(x) OVER(ROWS BETWEEN 1 PRECEDING AND CURRENT ROW ) as prev_curr_avg
|
||||
,sum(x) OVER(ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING ) as curr_next_sum
|
||||
,sum(x) OVER(ROWS BETWEEN 1 PRECEDING AND CURRENT ROW ) as prev_curr_sum
|
||||
FROM (VALUES (NULL::interval),
|
||||
('infinity'::interval),
|
||||
('-2147483648 days -2147483648 months -9223372036854775807 usecs'), -- extreme interval value
|
||||
('-infinity'::interval),
|
||||
('2147483647 days 2147483647 months 9223372036854775806 usecs'), -- extreme interval value
|
||||
('infinity'::interval),
|
||||
('6 days'::interval),
|
||||
('7 days'::interval),
|
||||
(NULL::interval),
|
||||
('-infinity'::interval)) v(x);
|
||||
|
||||
--should fail.
|
||||
SELECT x, avg(x) OVER(ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
|
||||
FROM (VALUES (NULL::interval),
|
||||
('3 days'::interval),
|
||||
('infinity'::timestamptz - now()),
|
||||
('6 days'::interval),
|
||||
('-infinity'::interval)) v(x);
|
||||
|
||||
--should fail.
|
||||
SELECT x, sum(x) OVER(ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
|
||||
FROM (VALUES (NULL::interval),
|
||||
('3 days'::interval),
|
||||
('infinity'::timestamptz - now()),
|
||||
('6 days'::interval),
|
||||
('-infinity'::interval)) v(x);
|
||||
|
||||
SELECT i,SUM(v::smallint) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
||||
FROM (VALUES(1,1),(2,2),(3,NULL),(4,NULL)) t(i,v);
|
||||
|
||||
|
|
|
@ -1205,6 +1205,7 @@ IntegerSet
|
|||
InternalDefaultACL
|
||||
InternalGrant
|
||||
Interval
|
||||
IntervalAggState
|
||||
IntoClause
|
||||
InvalMessageArray
|
||||
InvalidationMsgsGroup
|
||||
|
|
Loading…
Reference in New Issue