PostgreSQL Source Code git master
timestamp.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * timestamp.c
4 * Functions for the built-in SQL types "timestamp" and "interval".
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/adt/timestamp.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres.h"
17
18#include <ctype.h>
19#include <math.h>
20#include <limits.h>
21#include <sys/time.h>
22
23#include "access/xact.h"
24#include "catalog/pg_type.h"
25#include "common/int.h"
26#include "common/int128.h"
27#include "funcapi.h"
28#include "libpq/pqformat.h"
29#include "miscadmin.h"
30#include "nodes/nodeFuncs.h"
31#include "nodes/supportnodes.h"
32#include "optimizer/optimizer.h"
33#include "parser/scansup.h"
34#include "utils/array.h"
35#include "utils/builtins.h"
36#include "utils/date.h"
37#include "utils/datetime.h"
38#include "utils/float.h"
39#include "utils/numeric.h"
40#include "utils/sortsupport.h"
41
42/*
43 * gcc's -ffast-math switch breaks routines that expect exact results from
44 * expressions like timeval / SECS_PER_HOUR, where timeval is double.
45 */
46#ifdef __FAST_MATH__
47#error -ffast-math is known to break this code
48#endif
49
50#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
51
52/* Set at postmaster start */
54
55/* Set at configuration reload */
57
58typedef struct
59{
65
66typedef struct
67{
74
75/*
76 * The transition datatype for interval aggregates is declared as internal.
77 * It's a pointer to an IntervalAggState allocated in the aggregate context.
78 */
79typedef struct IntervalAggState
80{
81 int64 N; /* count of finite intervals processed */
82 Interval sumX; /* sum of finite intervals processed */
83 /* These counts are *not* included in N! Use IA_TOTAL_COUNT() as needed */
84 int64 pInfcount; /* count of +infinity intervals */
85 int64 nInfcount; /* count of -infinity intervals */
87
88#define IA_TOTAL_COUNT(ia) \
89 ((ia)->N + (ia)->pInfcount + (ia)->nInfcount)
90
91static TimeOffset time2t(const int hour, const int min, const int sec, const fsec_t fsec);
92static Timestamp dt2local(Timestamp dt, int timezone);
94 Node *escontext);
97
98static void EncodeSpecialInterval(const Interval *interval, char *str);
99static void interval_um_internal(const Interval *interval, Interval *result);
100
101/* common code for timestamptypmodin and timestamptztypmodin */
102static int32
104{
105 int32 *tl;
106 int n;
107
108 tl = ArrayGetIntegerTypmods(ta, &n);
109
110 /*
111 * we're not too tense about good error message here because grammar
112 * shouldn't allow wrong number of modifiers for TIMESTAMP
113 */
114 if (n != 1)
116 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
117 errmsg("invalid type modifier")));
118
119 return anytimestamp_typmod_check(istz, tl[0]);
120}
121
122/* exported so parse_expr.c can use it */
123int32
125{
126 if (typmod < 0)
128 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
129 errmsg("TIMESTAMP(%d)%s precision must not be negative",
130 typmod, (istz ? " WITH TIME ZONE" : ""))));
131 if (typmod > MAX_TIMESTAMP_PRECISION)
132 {
134 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
135 errmsg("TIMESTAMP(%d)%s precision reduced to maximum allowed, %d",
136 typmod, (istz ? " WITH TIME ZONE" : ""),
139 }
140
141 return typmod;
142}
143
144/* common code for timestamptypmodout and timestamptztypmodout */
145static char *
147{
148 const char *tz = istz ? " with time zone" : " without time zone";
149
150 if (typmod >= 0)
151 return psprintf("(%d)%s", (int) typmod, tz);
152 else
153 return pstrdup(tz);
154}
155
156
157/*****************************************************************************
158 * USER I/O ROUTINES *
159 *****************************************************************************/
160
161/* timestamp_in()
162 * Convert a string to internal form.
163 */
164Datum
166{
167 char *str = PG_GETARG_CSTRING(0);
168#ifdef NOT_USED
169 Oid typelem = PG_GETARG_OID(1);
170#endif
171 int32 typmod = PG_GETARG_INT32(2);
172 Node *escontext = fcinfo->context;
173 Timestamp result;
174 fsec_t fsec;
175 struct pg_tm tt,
176 *tm = &tt;
177 int tz;
178 int dtype;
179 int nf;
180 int dterr;
181 char *field[MAXDATEFIELDS];
182 int ftype[MAXDATEFIELDS];
183 char workbuf[MAXDATELEN + MAXDATEFIELDS];
184 DateTimeErrorExtra extra;
185
186 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
187 field, ftype, MAXDATEFIELDS, &nf);
188 if (dterr == 0)
189 dterr = DecodeDateTime(field, ftype, nf,
190 &dtype, tm, &fsec, &tz, &extra);
191 if (dterr != 0)
192 {
193 DateTimeParseError(dterr, &extra, str, "timestamp", escontext);
195 }
196
197 switch (dtype)
198 {
199 case DTK_DATE:
200 if (tm2timestamp(tm, fsec, NULL, &result) != 0)
201 ereturn(escontext, (Datum) 0,
202 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
203 errmsg("timestamp out of range: \"%s\"", str)));
204 break;
205
206 case DTK_EPOCH:
207 result = SetEpochTimestamp();
208 break;
209
210 case DTK_LATE:
211 TIMESTAMP_NOEND(result);
212 break;
213
214 case DTK_EARLY:
215 TIMESTAMP_NOBEGIN(result);
216 break;
217
218 default:
219 elog(ERROR, "unexpected dtype %d while parsing timestamp \"%s\"",
220 dtype, str);
221 TIMESTAMP_NOEND(result);
222 }
223
224 AdjustTimestampForTypmod(&result, typmod, escontext);
225
226 PG_RETURN_TIMESTAMP(result);
227}
228
229/* timestamp_out()
230 * Convert a timestamp to external form.
231 */
232Datum
234{
236 char *result;
237 struct pg_tm tt,
238 *tm = &tt;
239 fsec_t fsec;
240 char buf[MAXDATELEN + 1];
241
244 else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
245 EncodeDateTime(tm, fsec, false, 0, NULL, DateStyle, buf);
246 else
248 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
249 errmsg("timestamp out of range")));
250
251 result = pstrdup(buf);
252 PG_RETURN_CSTRING(result);
253}
254
255/*
256 * timestamp_recv - converts external binary format to timestamp
257 */
258Datum
260{
262
263#ifdef NOT_USED
264 Oid typelem = PG_GETARG_OID(1);
265#endif
266 int32 typmod = PG_GETARG_INT32(2);
268 struct pg_tm tt,
269 *tm = &tt;
270 fsec_t fsec;
271
273
274 /* range check: see if timestamp_out would like it */
276 /* ok */ ;
277 else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0 ||
280 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
281 errmsg("timestamp out of range")));
282
283 AdjustTimestampForTypmod(&timestamp, typmod, NULL);
284
286}
287
288/*
289 * timestamp_send - converts timestamp to binary format
290 */
291Datum
293{
296
300}
301
302Datum
304{
306
308}
309
310Datum
312{
313 int32 typmod = PG_GETARG_INT32(0);
314
316}
317
318
319/*
320 * timestamp_support()
321 *
322 * Planner support function for the timestamp_scale() and timestamptz_scale()
323 * length coercion functions (we need not distinguish them here).
324 */
325Datum
327{
328 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
329 Node *ret = NULL;
330
331 if (IsA(rawreq, SupportRequestSimplify))
332 {
334
336 }
337
339}
340
341/* timestamp_scale()
342 * Adjust time type for specified scale factor.
343 * Used by PostgreSQL type system to stuff columns.
344 */
345Datum
347{
349 int32 typmod = PG_GETARG_INT32(1);
350 Timestamp result;
351
352 result = timestamp;
353
354 AdjustTimestampForTypmod(&result, typmod, NULL);
355
356 PG_RETURN_TIMESTAMP(result);
357}
358
359/*
360 * AdjustTimestampForTypmod --- round off a timestamp to suit given typmod
361 * Works for either timestamp or timestamptz.
362 *
363 * Returns true on success, false on failure (if escontext points to an
364 * ErrorSaveContext; otherwise errors are thrown).
365 */
366bool
368{
369 static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
370 INT64CONST(1000000),
371 INT64CONST(100000),
372 INT64CONST(10000),
373 INT64CONST(1000),
374 INT64CONST(100),
375 INT64CONST(10),
376 INT64CONST(1)
377 };
378
379 static const int64 TimestampOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
380 INT64CONST(500000),
381 INT64CONST(50000),
382 INT64CONST(5000),
383 INT64CONST(500),
384 INT64CONST(50),
385 INT64CONST(5),
386 INT64CONST(0)
387 };
388
389 if (!TIMESTAMP_NOT_FINITE(*time)
390 && (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
391 {
392 if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)
393 ereturn(escontext, false,
394 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
395 errmsg("timestamp(%d) precision must be between %d and %d",
396 typmod, 0, MAX_TIMESTAMP_PRECISION)));
397
398 if (*time >= INT64CONST(0))
399 {
400 *time = ((*time + TimestampOffsets[typmod]) / TimestampScales[typmod]) *
401 TimestampScales[typmod];
402 }
403 else
404 {
405 *time = -((((-*time) + TimestampOffsets[typmod]) / TimestampScales[typmod])
406 * TimestampScales[typmod]);
407 }
408 }
409
410 return true;
411}
412
413/* timestamptz_in()
414 * Convert a string to internal form.
415 */
416Datum
418{
419 char *str = PG_GETARG_CSTRING(0);
420#ifdef NOT_USED
421 Oid typelem = PG_GETARG_OID(1);
422#endif
423 int32 typmod = PG_GETARG_INT32(2);
424 Node *escontext = fcinfo->context;
425 TimestampTz result;
426 fsec_t fsec;
427 struct pg_tm tt,
428 *tm = &tt;
429 int tz;
430 int dtype;
431 int nf;
432 int dterr;
433 char *field[MAXDATEFIELDS];
434 int ftype[MAXDATEFIELDS];
435 char workbuf[MAXDATELEN + MAXDATEFIELDS];
436 DateTimeErrorExtra extra;
437
438 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
439 field, ftype, MAXDATEFIELDS, &nf);
440 if (dterr == 0)
441 dterr = DecodeDateTime(field, ftype, nf,
442 &dtype, tm, &fsec, &tz, &extra);
443 if (dterr != 0)
444 {
445 DateTimeParseError(dterr, &extra, str, "timestamp with time zone",
446 escontext);
448 }
449
450 switch (dtype)
451 {
452 case DTK_DATE:
453 if (tm2timestamp(tm, fsec, &tz, &result) != 0)
454 ereturn(escontext, (Datum) 0,
455 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
456 errmsg("timestamp out of range: \"%s\"", str)));
457 break;
458
459 case DTK_EPOCH:
460 result = SetEpochTimestamp();
461 break;
462
463 case DTK_LATE:
464 TIMESTAMP_NOEND(result);
465 break;
466
467 case DTK_EARLY:
468 TIMESTAMP_NOBEGIN(result);
469 break;
470
471 default:
472 elog(ERROR, "unexpected dtype %d while parsing timestamptz \"%s\"",
473 dtype, str);
474 TIMESTAMP_NOEND(result);
475 }
476
477 AdjustTimestampForTypmod(&result, typmod, escontext);
478
479 PG_RETURN_TIMESTAMPTZ(result);
480}
481
482/*
483 * Try to parse a timezone specification, and return its timezone offset value
484 * if it's acceptable. Otherwise, an error is thrown.
485 *
486 * Note: some code paths update tm->tm_isdst, and some don't; current callers
487 * don't care, so we don't bother being consistent.
488 */
489static int
491{
492 char tzname[TZ_STRLEN_MAX + 1];
493 int dterr;
494 int tz;
495
496 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
497
498 /*
499 * Look up the requested timezone. First we try to interpret it as a
500 * numeric timezone specification; if DecodeTimezone decides it doesn't
501 * like the format, we try timezone abbreviations and names.
502 *
503 * Note pg_tzset happily parses numeric input that DecodeTimezone would
504 * reject. To avoid having it accept input that would otherwise be seen
505 * as invalid, it's enough to disallow having a digit in the first
506 * position of our input string.
507 */
508 if (isdigit((unsigned char) *tzname))
510 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
511 errmsg("invalid input syntax for type %s: \"%s\"",
512 "numeric time zone", tzname),
513 errhint("Numeric time zones must have \"-\" or \"+\" as first character.")));
514
515 dterr = DecodeTimezone(tzname, &tz);
516 if (dterr != 0)
517 {
518 int type,
519 val;
520 pg_tz *tzp;
521
522 if (dterr == DTERR_TZDISP_OVERFLOW)
524 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
525 errmsg("numeric time zone \"%s\" out of range", tzname)));
526 else if (dterr != DTERR_BAD_FORMAT)
528 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
529 errmsg("time zone \"%s\" not recognized", tzname)));
530
531 type = DecodeTimezoneName(tzname, &val, &tzp);
532
534 {
535 /* fixed-offset abbreviation */
536 tz = -val;
537 }
538 else if (type == TZNAME_DYNTZ)
539 {
540 /* dynamic-offset abbreviation, resolve using specified time */
541 tz = DetermineTimeZoneAbbrevOffset(tm, tzname, tzp);
542 }
543 else
544 {
545 /* full zone name */
546 tz = DetermineTimeZoneOffset(tm, tzp);
547 }
548 }
549
550 return tz;
551}
552
553/*
554 * Look up the requested timezone, returning a pg_tz struct.
555 *
556 * This is the same as DecodeTimezoneNameToTz, but starting with a text Datum.
557 */
558static pg_tz *
560{
561 char tzname[TZ_STRLEN_MAX + 1];
562
563 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
564
565 return DecodeTimezoneNameToTz(tzname);
566}
567
568/*
569 * make_timestamp_internal
570 * workhorse for make_timestamp and make_timestamptz
571 */
572static Timestamp
573make_timestamp_internal(int year, int month, int day,
574 int hour, int min, double sec)
575{
576 struct pg_tm tm;
578 TimeOffset time;
579 int dterr;
580 bool bc = false;
581 Timestamp result;
582
583 tm.tm_year = year;
584 tm.tm_mon = month;
585 tm.tm_mday = day;
586
587 /* Handle negative years as BC */
588 if (tm.tm_year < 0)
589 {
590 bc = true;
591 tm.tm_year = -tm.tm_year;
592 }
593
594 dterr = ValidateDate(DTK_DATE_M, false, false, bc, &tm);
595
596 if (dterr != 0)
598 (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
599 errmsg("date field value out of range: %d-%02d-%02d",
600 year, month, day)));
601
604 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
605 errmsg("date out of range: %d-%02d-%02d",
606 year, month, day)));
607
609
610 /* Check for time overflow */
611 if (float_time_overflows(hour, min, sec))
613 (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
614 errmsg("time field value out of range: %d:%02d:%02g",
615 hour, min, sec)));
616
617 /* This should match tm2time */
618 time = (((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
619 * USECS_PER_SEC) + (int64) rint(sec * USECS_PER_SEC);
620
622 pg_add_s64_overflow(result, time, &result)))
624 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
625 errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
626 year, month, day,
627 hour, min, sec)));
628
629 /* final range check catches just-out-of-range timestamps */
630 if (!IS_VALID_TIMESTAMP(result))
632 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
633 errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
634 year, month, day,
635 hour, min, sec)));
636
637 return result;
638}
639
640/*
641 * make_timestamp() - timestamp constructor
642 */
643Datum
645{
646 int32 year = PG_GETARG_INT32(0);
647 int32 month = PG_GETARG_INT32(1);
648 int32 mday = PG_GETARG_INT32(2);
649 int32 hour = PG_GETARG_INT32(3);
650 int32 min = PG_GETARG_INT32(4);
651 float8 sec = PG_GETARG_FLOAT8(5);
652 Timestamp result;
653
654 result = make_timestamp_internal(year, month, mday,
655 hour, min, sec);
656
657 PG_RETURN_TIMESTAMP(result);
658}
659
660/*
661 * make_timestamptz() - timestamp with time zone constructor
662 */
663Datum
665{
666 int32 year = PG_GETARG_INT32(0);
667 int32 month = PG_GETARG_INT32(1);
668 int32 mday = PG_GETARG_INT32(2);
669 int32 hour = PG_GETARG_INT32(3);
670 int32 min = PG_GETARG_INT32(4);
671 float8 sec = PG_GETARG_FLOAT8(5);
672 Timestamp result;
673
674 result = make_timestamp_internal(year, month, mday,
675 hour, min, sec);
676
678}
679
680/*
681 * Construct a timestamp with time zone.
682 * As above, but the time zone is specified as seventh argument.
683 */
684Datum
686{
687 int32 year = PG_GETARG_INT32(0);
688 int32 month = PG_GETARG_INT32(1);
689 int32 mday = PG_GETARG_INT32(2);
690 int32 hour = PG_GETARG_INT32(3);
691 int32 min = PG_GETARG_INT32(4);
692 float8 sec = PG_GETARG_FLOAT8(5);
694 TimestampTz result;
696 struct pg_tm tt;
697 int tz;
698 fsec_t fsec;
699
700 timestamp = make_timestamp_internal(year, month, mday,
701 hour, min, sec);
702
703 if (timestamp2tm(timestamp, NULL, &tt, &fsec, NULL, NULL) != 0)
705 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
706 errmsg("timestamp out of range")));
707
708 tz = parse_sane_timezone(&tt, zone);
709
710 result = dt2local(timestamp, -tz);
711
712 if (!IS_VALID_TIMESTAMP(result))
714 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
715 errmsg("timestamp out of range")));
716
717 PG_RETURN_TIMESTAMPTZ(result);
718}
719
720/*
721 * to_timestamp(double precision)
722 * Convert UNIX epoch to timestamptz.
723 */
724Datum
726{
727 float8 seconds = PG_GETARG_FLOAT8(0);
728 TimestampTz result;
729
730 /* Deal with NaN and infinite inputs ... */
731 if (isnan(seconds))
733 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
734 errmsg("timestamp cannot be NaN")));
735
736 if (isinf(seconds))
737 {
738 if (seconds < 0)
739 TIMESTAMP_NOBEGIN(result);
740 else
741 TIMESTAMP_NOEND(result);
742 }
743 else
744 {
745 /* Out of range? */
746 if (seconds <
748 || seconds >=
751 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
752 errmsg("timestamp out of range: \"%g\"", seconds)));
753
754 /* Convert UNIX epoch to Postgres epoch */
756
757 seconds = rint(seconds * USECS_PER_SEC);
758 result = (int64) seconds;
759
760 /* Recheck in case roundoff produces something just out of range */
761 if (!IS_VALID_TIMESTAMP(result))
763 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
764 errmsg("timestamp out of range: \"%g\"",
765 PG_GETARG_FLOAT8(0))));
766 }
767
768 PG_RETURN_TIMESTAMP(result);
769}
770
771/* timestamptz_out()
772 * Convert a timestamp to external form.
773 */
774Datum
776{
778 char *result;
779 int tz;
780 struct pg_tm tt,
781 *tm = &tt;
782 fsec_t fsec;
783 const char *tzn;
784 char buf[MAXDATELEN + 1];
785
786 if (TIMESTAMP_NOT_FINITE(dt))
788 else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn, NULL) == 0)
789 EncodeDateTime(tm, fsec, true, tz, tzn, DateStyle, buf);
790 else
792 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
793 errmsg("timestamp out of range")));
794
795 result = pstrdup(buf);
796 PG_RETURN_CSTRING(result);
797}
798
799/*
800 * timestamptz_recv - converts external binary format to timestamptz
801 */
802Datum
804{
806
807#ifdef NOT_USED
808 Oid typelem = PG_GETARG_OID(1);
809#endif
810 int32 typmod = PG_GETARG_INT32(2);
812 int tz;
813 struct pg_tm tt,
814 *tm = &tt;
815 fsec_t fsec;
816
818
819 /* range check: see if timestamptz_out would like it */
821 /* ok */ ;
822 else if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0 ||
825 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
826 errmsg("timestamp out of range")));
827
828 AdjustTimestampForTypmod(&timestamp, typmod, NULL);
829
831}
832
833/*
834 * timestamptz_send - converts timestamptz to binary format
835 */
836Datum
838{
841
845}
846
847Datum
849{
851
853}
854
855Datum
857{
858 int32 typmod = PG_GETARG_INT32(0);
859
861}
862
863
864/* timestamptz_scale()
865 * Adjust time type for specified scale factor.
866 * Used by PostgreSQL type system to stuff columns.
867 */
868Datum
870{
872 int32 typmod = PG_GETARG_INT32(1);
873 TimestampTz result;
874
875 result = timestamp;
876
877 AdjustTimestampForTypmod(&result, typmod, NULL);
878
879 PG_RETURN_TIMESTAMPTZ(result);
880}
881
882
883/* interval_in()
884 * Convert a string to internal form.
885 *
886 * External format(s):
887 * Uses the generic date/time parsing and decoding routines.
888 */
889Datum
891{
892 char *str = PG_GETARG_CSTRING(0);
893#ifdef NOT_USED
894 Oid typelem = PG_GETARG_OID(1);
895#endif
896 int32 typmod = PG_GETARG_INT32(2);
897 Node *escontext = fcinfo->context;
898 Interval *result;
899 struct pg_itm_in tt,
900 *itm_in = &tt;
901 int dtype;
902 int nf;
903 int range;
904 int dterr;
905 char *field[MAXDATEFIELDS];
906 int ftype[MAXDATEFIELDS];
907 char workbuf[256];
908 DateTimeErrorExtra extra;
909
910 itm_in->tm_year = 0;
911 itm_in->tm_mon = 0;
912 itm_in->tm_mday = 0;
913 itm_in->tm_usec = 0;
914
915 if (typmod >= 0)
916 range = INTERVAL_RANGE(typmod);
917 else
919
920 dterr = ParseDateTime(str, workbuf, sizeof(workbuf), field,
921 ftype, MAXDATEFIELDS, &nf);
922 if (dterr == 0)
923 dterr = DecodeInterval(field, ftype, nf, range,
924 &dtype, itm_in);
925
926 /* if those functions think it's a bad format, try ISO8601 style */
927 if (dterr == DTERR_BAD_FORMAT)
929 &dtype, itm_in);
930
931 if (dterr != 0)
932 {
933 if (dterr == DTERR_FIELD_OVERFLOW)
935 DateTimeParseError(dterr, &extra, str, "interval", escontext);
937 }
938
939 result = (Interval *) palloc(sizeof(Interval));
940
941 switch (dtype)
942 {
943 case DTK_DELTA:
944 if (itmin2interval(itm_in, result) != 0)
945 ereturn(escontext, (Datum) 0,
946 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
947 errmsg("interval out of range")));
948 break;
949
950 case DTK_LATE:
951 INTERVAL_NOEND(result);
952 break;
953
954 case DTK_EARLY:
955 INTERVAL_NOBEGIN(result);
956 break;
957
958 default:
959 elog(ERROR, "unexpected dtype %d while parsing interval \"%s\"",
960 dtype, str);
961 }
962
963 AdjustIntervalForTypmod(result, typmod, escontext);
964
965 PG_RETURN_INTERVAL_P(result);
966}
967
968/* interval_out()
969 * Convert a time span to external form.
970 */
971Datum
973{
975 char *result;
976 struct pg_itm tt,
977 *itm = &tt;
978 char buf[MAXDATELEN + 1];
979
980 if (INTERVAL_NOT_FINITE(span))
982 else
983 {
984 interval2itm(*span, itm);
986 }
987
988 result = pstrdup(buf);
989 PG_RETURN_CSTRING(result);
990}
991
992/*
993 * interval_recv - converts external binary format to interval
994 */
995Datum
997{
999
1000#ifdef NOT_USED
1001 Oid typelem = PG_GETARG_OID(1);
1002#endif
1003 int32 typmod = PG_GETARG_INT32(2);
1005
1006 interval = (Interval *) palloc(sizeof(Interval));
1007
1009 interval->day = pq_getmsgint(buf, sizeof(interval->day));
1011
1012 AdjustIntervalForTypmod(interval, typmod, NULL);
1013
1015}
1016
1017/*
1018 * interval_send - converts interval to binary format
1019 */
1020Datum
1022{
1025
1028 pq_sendint32(&buf, interval->day);
1031}
1032
1033/*
1034 * The interval typmod stores a "range" in its high 16 bits and a "precision"
1035 * in its low 16 bits. Both contribute to defining the resolution of the
1036 * type. Range addresses resolution granules larger than one second, and
1037 * precision specifies resolution below one second. This representation can
1038 * express all SQL standard resolutions, but we implement them all in terms of
1039 * truncating rightward from some position. Range is a bitmap of permitted
1040 * fields, but only the temporally-smallest such field is significant to our
1041 * calculations. Precision is a count of sub-second decimal places to retain.
1042 * Setting all bits (INTERVAL_FULL_PRECISION) gives the same truncation
1043 * semantics as choosing MAX_INTERVAL_PRECISION.
1044 */
1045Datum
1047{
1049 int32 *tl;
1050 int n;
1051 int32 typmod;
1052
1053 tl = ArrayGetIntegerTypmods(ta, &n);
1054
1055 /*
1056 * tl[0] - interval range (fields bitmask) tl[1] - precision (optional)
1057 *
1058 * Note we must validate tl[0] even though it's normally guaranteed
1059 * correct by the grammar --- consider SELECT 'foo'::"interval"(1000).
1060 */
1061 if (n > 0)
1062 {
1063 switch (tl[0])
1064 {
1065 case INTERVAL_MASK(YEAR):
1066 case INTERVAL_MASK(MONTH):
1067 case INTERVAL_MASK(DAY):
1068 case INTERVAL_MASK(HOUR):
1069 case INTERVAL_MASK(MINUTE):
1070 case INTERVAL_MASK(SECOND):
1079 /* all OK */
1080 break;
1081 default:
1082 ereport(ERROR,
1083 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1084 errmsg("invalid INTERVAL type modifier")));
1085 }
1086 }
1087
1088 if (n == 1)
1089 {
1090 if (tl[0] != INTERVAL_FULL_RANGE)
1092 else
1093 typmod = -1;
1094 }
1095 else if (n == 2)
1096 {
1097 if (tl[1] < 0)
1098 ereport(ERROR,
1099 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1100 errmsg("INTERVAL(%d) precision must not be negative",
1101 tl[1])));
1102 if (tl[1] > MAX_INTERVAL_PRECISION)
1103 {
1105 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1106 errmsg("INTERVAL(%d) precision reduced to maximum allowed, %d",
1107 tl[1], MAX_INTERVAL_PRECISION)));
1108 typmod = INTERVAL_TYPMOD(MAX_INTERVAL_PRECISION, tl[0]);
1109 }
1110 else
1111 typmod = INTERVAL_TYPMOD(tl[1], tl[0]);
1112 }
1113 else
1114 {
1115 ereport(ERROR,
1116 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1117 errmsg("invalid INTERVAL type modifier")));
1118 typmod = 0; /* keep compiler quiet */
1119 }
1120
1121 PG_RETURN_INT32(typmod);
1122}
1123
1124Datum
1126{
1127 int32 typmod = PG_GETARG_INT32(0);
1128 char *res = (char *) palloc(64);
1129 int fields;
1130 int precision;
1131 const char *fieldstr;
1132
1133 if (typmod < 0)
1134 {
1135 *res = '\0';
1136 PG_RETURN_CSTRING(res);
1137 }
1138
1139 fields = INTERVAL_RANGE(typmod);
1140 precision = INTERVAL_PRECISION(typmod);
1141
1142 switch (fields)
1143 {
1144 case INTERVAL_MASK(YEAR):
1145 fieldstr = " year";
1146 break;
1147 case INTERVAL_MASK(MONTH):
1148 fieldstr = " month";
1149 break;
1150 case INTERVAL_MASK(DAY):
1151 fieldstr = " day";
1152 break;
1153 case INTERVAL_MASK(HOUR):
1154 fieldstr = " hour";
1155 break;
1156 case INTERVAL_MASK(MINUTE):
1157 fieldstr = " minute";
1158 break;
1159 case INTERVAL_MASK(SECOND):
1160 fieldstr = " second";
1161 break;
1163 fieldstr = " year to month";
1164 break;
1166 fieldstr = " day to hour";
1167 break;
1169 fieldstr = " day to minute";
1170 break;
1172 fieldstr = " day to second";
1173 break;
1175 fieldstr = " hour to minute";
1176 break;
1178 fieldstr = " hour to second";
1179 break;
1181 fieldstr = " minute to second";
1182 break;
1184 fieldstr = "";
1185 break;
1186 default:
1187 elog(ERROR, "invalid INTERVAL typmod: 0x%x", typmod);
1188 fieldstr = "";
1189 break;
1190 }
1191
1192 if (precision != INTERVAL_FULL_PRECISION)
1193 snprintf(res, 64, "%s(%d)", fieldstr, precision);
1194 else
1195 snprintf(res, 64, "%s", fieldstr);
1196
1197 PG_RETURN_CSTRING(res);
1198}
1199
1200/*
1201 * Given an interval typmod value, return a code for the least-significant
1202 * field that the typmod allows to be nonzero, for instance given
1203 * INTERVAL DAY TO HOUR we want to identify "hour".
1204 *
1205 * The results should be ordered by field significance, which means
1206 * we can't use the dt.h macros YEAR etc, because for some odd reason
1207 * they aren't ordered that way. Instead, arbitrarily represent
1208 * SECOND = 0, MINUTE = 1, HOUR = 2, DAY = 3, MONTH = 4, YEAR = 5.
1209 */
1210static int
1212{
1213 if (typmod < 0)
1214 return 0; /* SECOND */
1215
1216 switch (INTERVAL_RANGE(typmod))
1217 {
1218 case INTERVAL_MASK(YEAR):
1219 return 5; /* YEAR */
1220 case INTERVAL_MASK(MONTH):
1221 return 4; /* MONTH */
1222 case INTERVAL_MASK(DAY):
1223 return 3; /* DAY */
1224 case INTERVAL_MASK(HOUR):
1225 return 2; /* HOUR */
1226 case INTERVAL_MASK(MINUTE):
1227 return 1; /* MINUTE */
1228 case INTERVAL_MASK(SECOND):
1229 return 0; /* SECOND */
1231 return 4; /* MONTH */
1233 return 2; /* HOUR */
1235 return 1; /* MINUTE */
1237 return 0; /* SECOND */
1239 return 1; /* MINUTE */
1241 return 0; /* SECOND */
1243 return 0; /* SECOND */
1245 return 0; /* SECOND */
1246 default:
1247 elog(ERROR, "invalid INTERVAL typmod: 0x%x", typmod);
1248 break;
1249 }
1250 return 0; /* can't get here, but keep compiler quiet */
1251}
1252
1253
1254/*
1255 * interval_support()
1256 *
1257 * Planner support function for interval_scale().
1258 *
1259 * Flatten superfluous calls to interval_scale(). The interval typmod is
1260 * complex to permit accepting and regurgitating all SQL standard variations.
1261 * For truncation purposes, it boils down to a single, simple granularity.
1262 */
1263Datum
1265{
1266 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1267 Node *ret = NULL;
1268
1269 if (IsA(rawreq, SupportRequestSimplify))
1270 {
1272 FuncExpr *expr = req->fcall;
1273 Node *typmod;
1274
1275 Assert(list_length(expr->args) >= 2);
1276
1277 typmod = (Node *) lsecond(expr->args);
1278
1279 if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
1280 {
1281 Node *source = (Node *) linitial(expr->args);
1282 int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
1283 bool noop;
1284
1285 if (new_typmod < 0)
1286 noop = true;
1287 else
1288 {
1289 int32 old_typmod = exprTypmod(source);
1290 int old_least_field;
1291 int new_least_field;
1292 int old_precis;
1293 int new_precis;
1294
1295 old_least_field = intervaltypmodleastfield(old_typmod);
1296 new_least_field = intervaltypmodleastfield(new_typmod);
1297 if (old_typmod < 0)
1298 old_precis = INTERVAL_FULL_PRECISION;
1299 else
1300 old_precis = INTERVAL_PRECISION(old_typmod);
1301 new_precis = INTERVAL_PRECISION(new_typmod);
1302
1303 /*
1304 * Cast is a no-op if least field stays the same or decreases
1305 * while precision stays the same or increases. But
1306 * precision, which is to say, sub-second precision, only
1307 * affects ranges that include SECOND.
1308 */
1309 noop = (new_least_field <= old_least_field) &&
1310 (old_least_field > 0 /* SECOND */ ||
1311 new_precis >= MAX_INTERVAL_PRECISION ||
1312 new_precis >= old_precis);
1313 }
1314 if (noop)
1315 ret = relabel_to_typmod(source, new_typmod);
1316 }
1317 }
1318
1319 PG_RETURN_POINTER(ret);
1320}
1321
1322/* interval_scale()
1323 * Adjust interval type for specified fields.
1324 * Used by PostgreSQL type system to stuff columns.
1325 */
1326Datum
1328{
1330 int32 typmod = PG_GETARG_INT32(1);
1331 Interval *result;
1332
1333 result = palloc(sizeof(Interval));
1334 *result = *interval;
1335
1336 AdjustIntervalForTypmod(result, typmod, NULL);
1337
1338 PG_RETURN_INTERVAL_P(result);
1339}
1340
1341/*
1342 * Adjust interval for specified precision, in both YEAR to SECOND
1343 * range and sub-second precision.
1344 *
1345 * Returns true on success, false on failure (if escontext points to an
1346 * ErrorSaveContext; otherwise errors are thrown).
1347 */
1348static bool
1350 Node *escontext)
1351{
1352 static const int64 IntervalScales[MAX_INTERVAL_PRECISION + 1] = {
1353 INT64CONST(1000000),
1354 INT64CONST(100000),
1355 INT64CONST(10000),
1356 INT64CONST(1000),
1357 INT64CONST(100),
1358 INT64CONST(10),
1359 INT64CONST(1)
1360 };
1361
1362 static const int64 IntervalOffsets[MAX_INTERVAL_PRECISION + 1] = {
1363 INT64CONST(500000),
1364 INT64CONST(50000),
1365 INT64CONST(5000),
1366 INT64CONST(500),
1367 INT64CONST(50),
1368 INT64CONST(5),
1369 INT64CONST(0)
1370 };
1371
1372 /* Typmod has no effect on infinite intervals */
1374 return true;
1375
1376 /*
1377 * Unspecified range and precision? Then not necessary to adjust. Setting
1378 * typmod to -1 is the convention for all data types.
1379 */
1380 if (typmod >= 0)
1381 {
1382 int range = INTERVAL_RANGE(typmod);
1383 int precision = INTERVAL_PRECISION(typmod);
1384
1385 /*
1386 * Our interpretation of intervals with a limited set of fields is
1387 * that fields to the right of the last one specified are zeroed out,
1388 * but those to the left of it remain valid. Thus for example there
1389 * is no operational difference between INTERVAL YEAR TO MONTH and
1390 * INTERVAL MONTH. In some cases we could meaningfully enforce that
1391 * higher-order fields are zero; for example INTERVAL DAY could reject
1392 * nonzero "month" field. However that seems a bit pointless when we
1393 * can't do it consistently. (We cannot enforce a range limit on the
1394 * highest expected field, since we do not have any equivalent of
1395 * SQL's <interval leading field precision>.) If we ever decide to
1396 * revisit this, interval_support will likely require adjusting.
1397 *
1398 * Note: before PG 8.4 we interpreted a limited set of fields as
1399 * actually causing a "modulo" operation on a given value, potentially
1400 * losing high-order as well as low-order information. But there is
1401 * no support for such behavior in the standard, and it seems fairly
1402 * undesirable on data consistency grounds anyway. Now we only
1403 * perform truncation or rounding of low-order fields.
1404 */
1406 {
1407 /* Do nothing... */
1408 }
1409 else if (range == INTERVAL_MASK(YEAR))
1410 {
1412 interval->day = 0;
1413 interval->time = 0;
1414 }
1415 else if (range == INTERVAL_MASK(MONTH))
1416 {
1417 interval->day = 0;
1418 interval->time = 0;
1419 }
1420 /* YEAR TO MONTH */
1421 else if (range == (INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH)))
1422 {
1423 interval->day = 0;
1424 interval->time = 0;
1425 }
1426 else if (range == INTERVAL_MASK(DAY))
1427 {
1428 interval->time = 0;
1429 }
1430 else if (range == INTERVAL_MASK(HOUR))
1431 {
1434 }
1435 else if (range == INTERVAL_MASK(MINUTE))
1436 {
1439 }
1440 else if (range == INTERVAL_MASK(SECOND))
1441 {
1442 /* fractional-second rounding will be dealt with below */
1443 }
1444 /* DAY TO HOUR */
1445 else if (range == (INTERVAL_MASK(DAY) |
1447 {
1450 }
1451 /* DAY TO MINUTE */
1452 else if (range == (INTERVAL_MASK(DAY) |
1455 {
1458 }
1459 /* DAY TO SECOND */
1460 else if (range == (INTERVAL_MASK(DAY) |
1464 {
1465 /* fractional-second rounding will be dealt with below */
1466 }
1467 /* HOUR TO MINUTE */
1468 else if (range == (INTERVAL_MASK(HOUR) |
1470 {
1473 }
1474 /* HOUR TO SECOND */
1475 else if (range == (INTERVAL_MASK(HOUR) |
1478 {
1479 /* fractional-second rounding will be dealt with below */
1480 }
1481 /* MINUTE TO SECOND */
1482 else if (range == (INTERVAL_MASK(MINUTE) |
1484 {
1485 /* fractional-second rounding will be dealt with below */
1486 }
1487 else
1488 elog(ERROR, "unrecognized interval typmod: %d", typmod);
1489
1490 /* Need to adjust sub-second precision? */
1491 if (precision != INTERVAL_FULL_PRECISION)
1492 {
1493 if (precision < 0 || precision > MAX_INTERVAL_PRECISION)
1494 ereturn(escontext, false,
1495 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1496 errmsg("interval(%d) precision must be between %d and %d",
1497 precision, 0, MAX_INTERVAL_PRECISION)));
1498
1499 if (interval->time >= INT64CONST(0))
1500 {
1502 IntervalOffsets[precision],
1503 &interval->time))
1504 ereturn(escontext, false,
1505 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1506 errmsg("interval out of range")));
1507 interval->time -= interval->time % IntervalScales[precision];
1508 }
1509 else
1510 {
1512 IntervalOffsets[precision],
1513 &interval->time))
1514 ereturn(escontext, false,
1515 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1516 errmsg("interval out of range")));
1517 interval->time -= interval->time % IntervalScales[precision];
1518 }
1519 }
1520 }
1521
1522 return true;
1523}
1524
1525/*
1526 * make_interval - numeric Interval constructor
1527 */
1528Datum
1530{
1531 int32 years = PG_GETARG_INT32(0);
1533 int32 weeks = PG_GETARG_INT32(2);
1535 int32 hours = PG_GETARG_INT32(4);
1536 int32 mins = PG_GETARG_INT32(5);
1537 double secs = PG_GETARG_FLOAT8(6);
1538 Interval *result;
1539
1540 /*
1541 * Reject out-of-range inputs. We reject any input values that cause
1542 * integer overflow of the corresponding interval fields.
1543 */
1544 if (isinf(secs) || isnan(secs))
1545 goto out_of_range;
1546
1547 result = (Interval *) palloc(sizeof(Interval));
1548
1549 /* years and months -> months */
1550 if (pg_mul_s32_overflow(years, MONTHS_PER_YEAR, &result->month) ||
1551 pg_add_s32_overflow(result->month, months, &result->month))
1552 goto out_of_range;
1553
1554 /* weeks and days -> days */
1555 if (pg_mul_s32_overflow(weeks, DAYS_PER_WEEK, &result->day) ||
1556 pg_add_s32_overflow(result->day, days, &result->day))
1557 goto out_of_range;
1558
1559 /* hours and mins -> usecs (cannot overflow 64-bit) */
1560 result->time = hours * USECS_PER_HOUR + mins * USECS_PER_MINUTE;
1561
1562 /* secs -> usecs */
1563 secs = rint(float8_mul(secs, USECS_PER_SEC));
1564 if (!FLOAT8_FITS_IN_INT64(secs) ||
1565 pg_add_s64_overflow(result->time, (int64) secs, &result->time))
1566 goto out_of_range;
1567
1568 /* make sure that the result is finite */
1569 if (INTERVAL_NOT_FINITE(result))
1570 goto out_of_range;
1571
1572 PG_RETURN_INTERVAL_P(result);
1573
1574out_of_range:
1575 ereport(ERROR,
1576 errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1577 errmsg("interval out of range"));
1578
1579 PG_RETURN_NULL(); /* keep compiler quiet */
1580}
1581
1582/* EncodeSpecialTimestamp()
1583 * Convert reserved timestamp data type to string.
1584 */
1585void
1587{
1588 if (TIMESTAMP_IS_NOBEGIN(dt))
1589 strcpy(str, EARLY);
1590 else if (TIMESTAMP_IS_NOEND(dt))
1591 strcpy(str, LATE);
1592 else /* shouldn't happen */
1593 elog(ERROR, "invalid argument for EncodeSpecialTimestamp");
1594}
1595
1596static void
1598{
1600 strcpy(str, EARLY);
1601 else if (INTERVAL_IS_NOEND(interval))
1602 strcpy(str, LATE);
1603 else /* shouldn't happen */
1604 elog(ERROR, "invalid argument for EncodeSpecialInterval");
1605}
1606
1607Datum
1609{
1611}
1612
1613Datum
1615{
1617}
1618
1619Datum
1621{
1623}
1624
1625Datum
1627{
1629}
1630
1631Datum
1633{
1635}
1636
1637/*
1638 * GetCurrentTimestamp -- get the current operating system time
1639 *
1640 * Result is in the form of a TimestampTz value, and is expressed to the
1641 * full precision of the gettimeofday() syscall
1642 */
1645{
1646 TimestampTz result;
1647 struct timeval tp;
1648
1649 gettimeofday(&tp, NULL);
1650
1651 result = (TimestampTz) tp.tv_sec -
1653 result = (result * USECS_PER_SEC) + tp.tv_usec;
1654
1655 return result;
1656}
1657
1658/*
1659 * GetSQLCurrentTimestamp -- implements CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(n)
1660 */
1663{
1664 TimestampTz ts;
1665
1667 if (typmod >= 0)
1668 AdjustTimestampForTypmod(&ts, typmod, NULL);
1669 return ts;
1670}
1671
1672/*
1673 * GetSQLLocalTimestamp -- implements LOCALTIMESTAMP, LOCALTIMESTAMP(n)
1674 */
1677{
1678 Timestamp ts;
1679
1681 if (typmod >= 0)
1682 AdjustTimestampForTypmod(&ts, typmod, NULL);
1683 return ts;
1684}
1685
1686/*
1687 * timeofday(*) -- returns the current time as a text.
1688 */
1689Datum
1691{
1692 struct timeval tp;
1693 char templ[128];
1694 char buf[128];
1695 pg_time_t tt;
1696
1697 gettimeofday(&tp, NULL);
1698 tt = (pg_time_t) tp.tv_sec;
1699 pg_strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%06d %Y %Z",
1701 snprintf(buf, sizeof(buf), templ, tp.tv_usec);
1702
1704}
1705
1706/*
1707 * TimestampDifference -- convert the difference between two timestamps
1708 * into integer seconds and microseconds
1709 *
1710 * This is typically used to calculate a wait timeout for select(2),
1711 * which explains the otherwise-odd choice of output format.
1712 *
1713 * Both inputs must be ordinary finite timestamps (in current usage,
1714 * they'll be results from GetCurrentTimestamp()).
1715 *
1716 * We expect start_time <= stop_time. If not, we return zeros,
1717 * since then we're already past the previously determined stop_time.
1718 */
1719void
1721 long *secs, int *microsecs)
1722{
1723 TimestampTz diff = stop_time - start_time;
1724
1725 if (diff <= 0)
1726 {
1727 *secs = 0;
1728 *microsecs = 0;
1729 }
1730 else
1731 {
1732 *secs = (long) (diff / USECS_PER_SEC);
1733 *microsecs = (int) (diff % USECS_PER_SEC);
1734 }
1735}
1736
1737/*
1738 * TimestampDifferenceMilliseconds -- convert the difference between two
1739 * timestamps into integer milliseconds
1740 *
1741 * This is typically used to calculate a wait timeout for WaitLatch()
1742 * or a related function. The choice of "long" as the result type
1743 * is to harmonize with that; furthermore, we clamp the result to at most
1744 * INT_MAX milliseconds, because that's all that WaitLatch() allows.
1745 *
1746 * We expect start_time <= stop_time. If not, we return zero,
1747 * since then we're already past the previously determined stop_time.
1748 *
1749 * Subtracting finite and infinite timestamps works correctly, returning
1750 * zero or INT_MAX as appropriate.
1751 *
1752 * Note we round up any fractional millisecond, since waiting for just
1753 * less than the intended timeout is undesirable.
1754 */
1755long
1757{
1758 TimestampTz diff;
1759
1760 /* Deal with zero or negative elapsed time quickly. */
1761 if (start_time >= stop_time)
1762 return 0;
1763 /* To not fail with timestamp infinities, we must detect overflow. */
1764 if (pg_sub_s64_overflow(stop_time, start_time, &diff))
1765 return (long) INT_MAX;
1766 if (diff >= (INT_MAX * INT64CONST(1000) - 999))
1767 return (long) INT_MAX;
1768 else
1769 return (long) ((diff + 999) / 1000);
1770}
1771
1772/*
1773 * TimestampDifferenceExceeds -- report whether the difference between two
1774 * timestamps is >= a threshold (expressed in milliseconds)
1775 *
1776 * Both inputs must be ordinary finite timestamps (in current usage,
1777 * they'll be results from GetCurrentTimestamp()).
1778 */
1779bool
1781 TimestampTz stop_time,
1782 int msec)
1783{
1784 TimestampTz diff = stop_time - start_time;
1785
1786 return (diff >= msec * INT64CONST(1000));
1787}
1788
1789/*
1790 * Check if the difference between two timestamps is >= a given
1791 * threshold (expressed in seconds).
1792 */
1793bool
1795 TimestampTz stop_time,
1796 int threshold_sec)
1797{
1798 long secs;
1799 int usecs;
1800
1801 /* Calculate the difference in seconds */
1802 TimestampDifference(start_time, stop_time, &secs, &usecs);
1803
1804 return (secs >= threshold_sec);
1805}
1806
1807/*
1808 * Convert a time_t to TimestampTz.
1809 *
1810 * We do not use time_t internally in Postgres, but this is provided for use
1811 * by functions that need to interpret, say, a stat(2) result.
1812 *
1813 * To avoid having the function's ABI vary depending on the width of time_t,
1814 * we declare the argument as pg_time_t, which is cast-compatible with
1815 * time_t but always 64 bits wide (unless the platform has no 64-bit type).
1816 * This detail should be invisible to callers, at least at source code level.
1817 */
1820{
1821 TimestampTz result;
1822
1823 result = (TimestampTz) tm -
1825 result *= USECS_PER_SEC;
1826
1827 return result;
1828}
1829
1830/*
1831 * Convert a TimestampTz to time_t.
1832 *
1833 * This too is just marginally useful, but some places need it.
1834 *
1835 * To avoid having the function's ABI vary depending on the width of time_t,
1836 * we declare the result as pg_time_t, which is cast-compatible with
1837 * time_t but always 64 bits wide (unless the platform has no 64-bit type).
1838 * This detail should be invisible to callers, at least at source code level.
1839 */
1842{
1843 pg_time_t result;
1844
1845 result = (pg_time_t) (t / USECS_PER_SEC +
1847
1848 return result;
1849}
1850
1851/*
1852 * Produce a C-string representation of a TimestampTz.
1853 *
1854 * This is mostly for use in emitting messages. The primary difference
1855 * from timestamptz_out is that we force the output format to ISO. Note
1856 * also that the result is in a static buffer, not pstrdup'd.
1857 *
1858 * See also pg_strftime.
1859 */
1860const char *
1862{
1863 static char buf[MAXDATELEN + 1];
1864 int tz;
1865 struct pg_tm tt,
1866 *tm = &tt;
1867 fsec_t fsec;
1868 const char *tzn;
1869
1870 if (TIMESTAMP_NOT_FINITE(t))
1872 else if (timestamp2tm(t, &tz, tm, &fsec, &tzn, NULL) == 0)
1873 EncodeDateTime(tm, fsec, true, tz, tzn, USE_ISO_DATES, buf);
1874 else
1875 strlcpy(buf, "(timestamp out of range)", sizeof(buf));
1876
1877 return buf;
1878}
1879
1880
1881void
1882dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
1883{
1884 TimeOffset time;
1885
1886 time = jd;
1887
1888 *hour = time / USECS_PER_HOUR;
1889 time -= (*hour) * USECS_PER_HOUR;
1890 *min = time / USECS_PER_MINUTE;
1891 time -= (*min) * USECS_PER_MINUTE;
1892 *sec = time / USECS_PER_SEC;
1893 *fsec = time - (*sec * USECS_PER_SEC);
1894} /* dt2time() */
1895
1896
1897/*
1898 * timestamp2tm() - Convert timestamp data type to POSIX time structure.
1899 *
1900 * Note that year is _not_ 1900-based, but is an explicit full value.
1901 * Also, month is one-based, _not_ zero-based.
1902 * Returns:
1903 * 0 on success
1904 * -1 on out of range
1905 *
1906 * If attimezone is NULL, the global timezone setting will be used.
1907 */
1908int
1909timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
1910{
1912 Timestamp time;
1913 pg_time_t utime;
1914
1915 /* Use session timezone if caller asks for default */
1916 if (attimezone == NULL)
1917 attimezone = session_timezone;
1918
1919 time = dt;
1920 TMODULO(time, date, USECS_PER_DAY);
1921
1922 if (time < INT64CONST(0))
1923 {
1924 time += USECS_PER_DAY;
1925 date -= 1;
1926 }
1927
1928 /* add offset to go from J2000 back to standard Julian date */
1930
1931 /* Julian day routine does not work for negative Julian days */
1932 if (date < 0 || date > (Timestamp) INT_MAX)
1933 return -1;
1934
1935 j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1936 dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
1937
1938 /* Done if no TZ conversion wanted */
1939 if (tzp == NULL)
1940 {
1941 tm->tm_isdst = -1;
1942 tm->tm_gmtoff = 0;
1943 tm->tm_zone = NULL;
1944 if (tzn != NULL)
1945 *tzn = NULL;
1946 return 0;
1947 }
1948
1949 /*
1950 * If the time falls within the range of pg_time_t, use pg_localtime() to
1951 * rotate to the local time zone.
1952 *
1953 * First, convert to an integral timestamp, avoiding possibly
1954 * platform-specific roundoff-in-wrong-direction errors, and adjust to
1955 * Unix epoch. Then see if we can convert to pg_time_t without loss. This
1956 * coding avoids hardwiring any assumptions about the width of pg_time_t,
1957 * so it should behave sanely on machines without int64.
1958 */
1959 dt = (dt - *fsec) / USECS_PER_SEC +
1961 utime = (pg_time_t) dt;
1962 if ((Timestamp) utime == dt)
1963 {
1964 struct pg_tm *tx = pg_localtime(&utime, attimezone);
1965
1966 tm->tm_year = tx->tm_year + 1900;
1967 tm->tm_mon = tx->tm_mon + 1;
1968 tm->tm_mday = tx->tm_mday;
1969 tm->tm_hour = tx->tm_hour;
1970 tm->tm_min = tx->tm_min;
1971 tm->tm_sec = tx->tm_sec;
1972 tm->tm_isdst = tx->tm_isdst;
1973 tm->tm_gmtoff = tx->tm_gmtoff;
1974 tm->tm_zone = tx->tm_zone;
1975 *tzp = -tm->tm_gmtoff;
1976 if (tzn != NULL)
1977 *tzn = tm->tm_zone;
1978 }
1979 else
1980 {
1981 /*
1982 * When out of range of pg_time_t, treat as GMT
1983 */
1984 *tzp = 0;
1985 /* Mark this as *no* time zone available */
1986 tm->tm_isdst = -1;
1987 tm->tm_gmtoff = 0;
1988 tm->tm_zone = NULL;
1989 if (tzn != NULL)
1990 *tzn = NULL;
1991 }
1992
1993 return 0;
1994}
1995
1996
1997/* tm2timestamp()
1998 * Convert a tm structure to a timestamp data type.
1999 * Note that year is _not_ 1900-based, but is an explicit full value.
2000 * Also, month is one-based, _not_ zero-based.
2001 *
2002 * Returns -1 on failure (value out of range).
2003 */
2004int
2005tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
2006{
2008 TimeOffset time;
2009
2010 /* Prevent overflow in Julian-day routines */
2012 {
2013 *result = 0; /* keep compiler quiet */
2014 return -1;
2015 }
2016
2018 time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
2019
2021 pg_add_s64_overflow(*result, time, result)))
2022 {
2023 *result = 0; /* keep compiler quiet */
2024 return -1;
2025 }
2026 if (tzp != NULL)
2027 *result = dt2local(*result, -(*tzp));
2028
2029 /* final range check catches just-out-of-range timestamps */
2030 if (!IS_VALID_TIMESTAMP(*result))
2031 {
2032 *result = 0; /* keep compiler quiet */
2033 return -1;
2034 }
2035
2036 return 0;
2037}
2038
2039
2040/* interval2itm()
2041 * Convert an Interval to a pg_itm structure.
2042 * Note: overflow is not possible, because the pg_itm fields are
2043 * wide enough for all possible conversion results.
2044 */
2045void
2046interval2itm(Interval span, struct pg_itm *itm)
2047{
2048 TimeOffset time;
2049 TimeOffset tfrac;
2050
2051 itm->tm_year = span.month / MONTHS_PER_YEAR;
2052 itm->tm_mon = span.month % MONTHS_PER_YEAR;
2053 itm->tm_mday = span.day;
2054 time = span.time;
2055
2056 tfrac = time / USECS_PER_HOUR;
2057 time -= tfrac * USECS_PER_HOUR;
2058 itm->tm_hour = tfrac;
2059 tfrac = time / USECS_PER_MINUTE;
2060 time -= tfrac * USECS_PER_MINUTE;
2061 itm->tm_min = (int) tfrac;
2062 tfrac = time / USECS_PER_SEC;
2063 time -= tfrac * USECS_PER_SEC;
2064 itm->tm_sec = (int) tfrac;
2065 itm->tm_usec = (int) time;
2066}
2067
2068/* itm2interval()
2069 * Convert a pg_itm structure to an Interval.
2070 * Returns 0 if OK, -1 on overflow.
2071 *
2072 * This is for use in computations expected to produce finite results. Any
2073 * inputs that lead to infinite results are treated as overflows.
2074 */
2075int
2076itm2interval(struct pg_itm *itm, Interval *span)
2077{
2078 int64 total_months = (int64) itm->tm_year * MONTHS_PER_YEAR + itm->tm_mon;
2079
2080 if (total_months > INT_MAX || total_months < INT_MIN)
2081 return -1;
2082 span->month = (int32) total_months;
2083 span->day = itm->tm_mday;
2085 &span->time))
2086 return -1;
2087 /* tm_min, tm_sec are 32 bits, so intermediate products can't overflow */
2089 &span->time))
2090 return -1;
2091 if (pg_add_s64_overflow(span->time, itm->tm_sec * USECS_PER_SEC,
2092 &span->time))
2093 return -1;
2094 if (pg_add_s64_overflow(span->time, itm->tm_usec,
2095 &span->time))
2096 return -1;
2097 if (INTERVAL_NOT_FINITE(span))
2098 return -1;
2099 return 0;
2100}
2101
2102/* itmin2interval()
2103 * Convert a pg_itm_in structure to an Interval.
2104 * Returns 0 if OK, -1 on overflow.
2105 *
2106 * Note: if the result is infinite, it is not treated as an overflow. This
2107 * avoids any dump/reload hazards from pre-17 databases that do not support
2108 * infinite intervals, but do allow finite intervals with all fields set to
2109 * INT_MIN/INT_MAX (outside the documented range). Such intervals will be
2110 * silently converted to +/-infinity. This may not be ideal, but seems
2111 * preferable to failure, and ought to be pretty unlikely in practice.
2112 */
2113int
2114itmin2interval(struct pg_itm_in *itm_in, Interval *span)
2115{
2116 int64 total_months = (int64) itm_in->tm_year * MONTHS_PER_YEAR + itm_in->tm_mon;
2117
2118 if (total_months > INT_MAX || total_months < INT_MIN)
2119 return -1;
2120 span->month = (int32) total_months;
2121 span->day = itm_in->tm_mday;
2122 span->time = itm_in->tm_usec;
2123 return 0;
2124}
2125
2126static TimeOffset
2127time2t(const int hour, const int min, const int sec, const fsec_t fsec)
2128{
2129 return (((((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec) * USECS_PER_SEC) + fsec;
2130}
2131
2132static Timestamp
2133dt2local(Timestamp dt, int timezone)
2134{
2135 dt -= (timezone * USECS_PER_SEC);
2136 return dt;
2137}
2138
2139
2140/*****************************************************************************
2141 * PUBLIC ROUTINES *
2142 *****************************************************************************/
2143
2144
2145Datum
2147{
2149
2151}
2152
2153Datum
2155{
2157
2159}
2160
2161
2162/*----------------------------------------------------------
2163 * Relational operators for timestamp.
2164 *---------------------------------------------------------*/
2165
2166void
2168{
2169 struct pg_tm *t0;
2170 pg_time_t epoch = 0;
2171
2172 t0 = pg_gmtime(&epoch);
2173
2174 if (t0 == NULL)
2175 elog(ERROR, "could not convert epoch to timestamp: %m");
2176
2177 tm->tm_year = t0->tm_year;
2178 tm->tm_mon = t0->tm_mon;
2179 tm->tm_mday = t0->tm_mday;
2180 tm->tm_hour = t0->tm_hour;
2181 tm->tm_min = t0->tm_min;
2182 tm->tm_sec = t0->tm_sec;
2183
2184 tm->tm_year += 1900;
2185 tm->tm_mon++;
2186}
2187
2190{
2191 Timestamp dt;
2192 struct pg_tm tt,
2193 *tm = &tt;
2194
2196 /* we don't bother to test for failure ... */
2197 tm2timestamp(tm, 0, NULL, &dt);
2198
2199 return dt;
2200} /* SetEpochTimestamp() */
2201
2202/*
2203 * We are currently sharing some code between timestamp and timestamptz.
2204 * The comparison functions are among them. - thomas 2001-09-25
2205 *
2206 * timestamp_relop - is timestamp1 relop timestamp2
2207 */
2208int
2210{
2211 return (dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0);
2212}
2213
2214Datum
2216{
2219
2220 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);
2221}
2222
2223Datum
2225{
2228
2229 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);
2230}
2231
2232Datum
2234{
2237
2239}
2240
2241Datum
2243{
2246
2248}
2249
2250Datum
2252{
2255
2256 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);
2257}
2258
2259Datum
2261{
2264
2265 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);
2266}
2267
2268Datum
2270{
2273
2275}
2276
2277#if SIZEOF_DATUM < 8
2278/* note: this is used for timestamptz also */
2279static int
2281{
2284
2285 return timestamp_cmp_internal(a, b);
2286}
2287#endif
2288
2289Datum
2291{
2293
2294#if SIZEOF_DATUM >= 8
2295
2296 /*
2297 * If this build has pass-by-value timestamps, then we can use a standard
2298 * comparator function.
2299 */
2300 ssup->comparator = ssup_datum_signed_cmp;
2301#else
2303#endif
2305}
2306
2307Datum
2309{
2310 return hashint8(fcinfo);
2311}
2312
2313Datum
2315{
2316 return hashint8extended(fcinfo);
2317}
2318
2319Datum
2321{
2322 return hashint8(fcinfo);
2323}
2324
2325Datum
2327{
2328 return hashint8extended(fcinfo);
2329}
2330
2331/*
2332 * Cross-type comparison functions for timestamp vs timestamptz
2333 */
2334
2335int32
2337{
2338 TimestampTz dt1;
2339 int overflow;
2340
2341 dt1 = timestamp2timestamptz_opt_overflow(timestampVal, &overflow);
2342 if (overflow > 0)
2343 {
2344 /* dt1 is larger than any finite timestamp, but less than infinity */
2345 return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1;
2346 }
2347 if (overflow < 0)
2348 {
2349 /* dt1 is less than any finite timestamp, but more than -infinity */
2350 return TIMESTAMP_IS_NOBEGIN(dt2) ? +1 : -1;
2351 }
2352
2353 return timestamptz_cmp_internal(dt1, dt2);
2354}
2355
2356Datum
2358{
2359 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2361
2362 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) == 0);
2363}
2364
2365Datum
2367{
2368 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2370
2371 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) != 0);
2372}
2373
2374Datum
2376{
2377 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2379
2380 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) < 0);
2381}
2382
2383Datum
2385{
2386 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2388
2389 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) > 0);
2390}
2391
2392Datum
2394{
2395 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2397
2398 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) <= 0);
2399}
2400
2401Datum
2403{
2404 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2406
2407 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) >= 0);
2408}
2409
2410Datum
2412{
2413 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2415
2417}
2418
2419Datum
2421{
2423 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2424
2425 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) == 0);
2426}
2427
2428Datum
2430{
2432 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2433
2434 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) != 0);
2435}
2436
2437Datum
2439{
2441 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2442
2443 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) > 0);
2444}
2445
2446Datum
2448{
2450 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2451
2452 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) < 0);
2453}
2454
2455Datum
2457{
2459 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2460
2461 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) >= 0);
2462}
2463
2464Datum
2466{
2468 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2469
2470 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) <= 0);
2471}
2472
2473Datum
2475{
2477 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2478
2480}
2481
2482
2483/*
2484 * interval_relop - is interval1 relop interval2
2485 *
2486 * Interval comparison is based on converting interval values to a linear
2487 * representation expressed in the units of the time field (microseconds,
2488 * in the case of integer timestamps) with days assumed to be always 24 hours
2489 * and months assumed to be always 30 days. To avoid overflow, we need a
2490 * wider-than-int64 datatype for the linear representation, so use INT128.
2491 */
2492
2493static inline INT128
2495{
2496 INT128 span;
2497 int64 days;
2498
2499 /*
2500 * Combine the month and day fields into an integral number of days.
2501 * Because the inputs are int32, int64 arithmetic suffices here.
2502 */
2503 days = interval->month * INT64CONST(30);
2504 days += interval->day;
2505
2506 /* Widen time field to 128 bits */
2507 span = int64_to_int128(interval->time);
2508
2509 /* Scale up days to microseconds, forming a 128-bit product */
2511
2512 return span;
2513}
2514
2515static int
2516interval_cmp_internal(const Interval *interval1, const Interval *interval2)
2517{
2518 INT128 span1 = interval_cmp_value(interval1);
2519 INT128 span2 = interval_cmp_value(interval2);
2520
2521 return int128_compare(span1, span2);
2522}
2523
2524static int
2526{
2528 INT128 zero = int64_to_int128(0);
2529
2530 return int128_compare(span, zero);
2531}
2532
2533Datum
2535{
2536 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2537 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2538
2539 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) == 0);
2540}
2541
2542Datum
2544{
2545 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2546 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2547
2548 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) != 0);
2549}
2550
2551Datum
2553{
2554 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2555 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2556
2557 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) < 0);
2558}
2559
2560Datum
2562{
2563 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2564 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2565
2566 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) > 0);
2567}
2568
2569Datum
2571{
2572 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2573 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2574
2575 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) <= 0);
2576}
2577
2578Datum
2580{
2581 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2582 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2583
2584 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) >= 0);
2585}
2586
2587Datum
2589{
2590 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2591 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2592
2593 PG_RETURN_INT32(interval_cmp_internal(interval1, interval2));
2594}
2595
2596/*
2597 * Hashing for intervals
2598 *
2599 * We must produce equal hashvals for values that interval_cmp_internal()
2600 * considers equal. So, compute the net span the same way it does,
2601 * and then hash that.
2602 */
2603Datum
2605{
2608 int64 span64;
2609
2610 /*
2611 * Use only the least significant 64 bits for hashing. The upper 64 bits
2612 * seldom add any useful information, and besides we must do it like this
2613 * for compatibility with hashes calculated before use of INT128 was
2614 * introduced.
2615 */
2616 span64 = int128_to_int64(span);
2617
2619}
2620
2621Datum
2623{
2626 int64 span64;
2627
2628 /* Same approach as interval_hash */
2629 span64 = int128_to_int64(span);
2630
2632 PG_GETARG_DATUM(1));
2633}
2634
2635/* overlaps_timestamp() --- implements the SQL OVERLAPS operator.
2636 *
2637 * Algorithm is per SQL spec. This is much harder than you'd think
2638 * because the spec requires us to deliver a non-null answer in some cases
2639 * where some of the inputs are null.
2640 */
2641Datum
2643{
2644 /*
2645 * The arguments are Timestamps, but we leave them as generic Datums to
2646 * avoid unnecessary conversions between value and reference forms --- not
2647 * to mention possible dereferences of null pointers.
2648 */
2649 Datum ts1 = PG_GETARG_DATUM(0);
2650 Datum te1 = PG_GETARG_DATUM(1);
2651 Datum ts2 = PG_GETARG_DATUM(2);
2652 Datum te2 = PG_GETARG_DATUM(3);
2653 bool ts1IsNull = PG_ARGISNULL(0);
2654 bool te1IsNull = PG_ARGISNULL(1);
2655 bool ts2IsNull = PG_ARGISNULL(2);
2656 bool te2IsNull = PG_ARGISNULL(3);
2657
2658#define TIMESTAMP_GT(t1,t2) \
2659 DatumGetBool(DirectFunctionCall2(timestamp_gt,t1,t2))
2660#define TIMESTAMP_LT(t1,t2) \
2661 DatumGetBool(DirectFunctionCall2(timestamp_lt,t1,t2))
2662
2663 /*
2664 * If both endpoints of interval 1 are null, the result is null (unknown).
2665 * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
2666 * take ts1 as the lesser endpoint.
2667 */
2668 if (ts1IsNull)
2669 {
2670 if (te1IsNull)
2672 /* swap null for non-null */
2673 ts1 = te1;
2674 te1IsNull = true;
2675 }
2676 else if (!te1IsNull)
2677 {
2678 if (TIMESTAMP_GT(ts1, te1))
2679 {
2680 Datum tt = ts1;
2681
2682 ts1 = te1;
2683 te1 = tt;
2684 }
2685 }
2686
2687 /* Likewise for interval 2. */
2688 if (ts2IsNull)
2689 {
2690 if (te2IsNull)
2692 /* swap null for non-null */
2693 ts2 = te2;
2694 te2IsNull = true;
2695 }
2696 else if (!te2IsNull)
2697 {
2698 if (TIMESTAMP_GT(ts2, te2))
2699 {
2700 Datum tt = ts2;
2701
2702 ts2 = te2;
2703 te2 = tt;
2704 }
2705 }
2706
2707 /*
2708 * At this point neither ts1 nor ts2 is null, so we can consider three
2709 * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
2710 */
2711 if (TIMESTAMP_GT(ts1, ts2))
2712 {
2713 /*
2714 * This case is ts1 < te2 OR te1 < te2, which may look redundant but
2715 * in the presence of nulls it's not quite completely so.
2716 */
2717 if (te2IsNull)
2719 if (TIMESTAMP_LT(ts1, te2))
2720 PG_RETURN_BOOL(true);
2721 if (te1IsNull)
2723
2724 /*
2725 * If te1 is not null then we had ts1 <= te1 above, and we just found
2726 * ts1 >= te2, hence te1 >= te2.
2727 */
2728 PG_RETURN_BOOL(false);
2729 }
2730 else if (TIMESTAMP_LT(ts1, ts2))
2731 {
2732 /* This case is ts2 < te1 OR te2 < te1 */
2733 if (te1IsNull)
2735 if (TIMESTAMP_LT(ts2, te1))
2736 PG_RETURN_BOOL(true);
2737 if (te2IsNull)
2739
2740 /*
2741 * If te2 is not null then we had ts2 <= te2 above, and we just found
2742 * ts2 >= te1, hence te2 >= te1.
2743 */
2744 PG_RETURN_BOOL(false);
2745 }
2746 else
2747 {
2748 /*
2749 * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
2750 * rather silly way of saying "true if both are non-null, else null".
2751 */
2752 if (te1IsNull || te2IsNull)
2754 PG_RETURN_BOOL(true);
2755 }
2756
2757#undef TIMESTAMP_GT
2758#undef TIMESTAMP_LT
2759}
2760
2761
2762/*----------------------------------------------------------
2763 * "Arithmetic" operators on date/times.
2764 *---------------------------------------------------------*/
2765
2766Datum
2768{
2771 Timestamp result;
2772
2773 /* use timestamp_cmp_internal to be sure this agrees with comparisons */
2774 if (timestamp_cmp_internal(dt1, dt2) < 0)
2775 result = dt1;
2776 else
2777 result = dt2;
2778 PG_RETURN_TIMESTAMP(result);
2779}
2780
2781Datum
2783{
2786 Timestamp result;
2787
2788 if (timestamp_cmp_internal(dt1, dt2) > 0)
2789 result = dt1;
2790 else
2791 result = dt2;
2792 PG_RETURN_TIMESTAMP(result);
2793}
2794
2795
2796Datum
2798{
2801 Interval *result;
2802
2803 result = (Interval *) palloc(sizeof(Interval));
2804
2805 /*
2806 * Handle infinities.
2807 *
2808 * We treat anything that amounts to "infinity - infinity" as an error,
2809 * since the interval type has nothing equivalent to NaN.
2810 */
2812 {
2813 if (TIMESTAMP_IS_NOBEGIN(dt1))
2814 {
2815 if (TIMESTAMP_IS_NOBEGIN(dt2))
2816 ereport(ERROR,
2817 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2818 errmsg("interval out of range")));
2819 else
2820 INTERVAL_NOBEGIN(result);
2821 }
2822 else if (TIMESTAMP_IS_NOEND(dt1))
2823 {
2824 if (TIMESTAMP_IS_NOEND(dt2))
2825 ereport(ERROR,
2826 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2827 errmsg("interval out of range")));
2828 else
2829 INTERVAL_NOEND(result);
2830 }
2831 else if (TIMESTAMP_IS_NOBEGIN(dt2))
2832 INTERVAL_NOEND(result);
2833 else /* TIMESTAMP_IS_NOEND(dt2) */
2834 INTERVAL_NOBEGIN(result);
2835
2836 PG_RETURN_INTERVAL_P(result);
2837 }
2838
2839 if (unlikely(pg_sub_s64_overflow(dt1, dt2, &result->time)))
2840 ereport(ERROR,
2841 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2842 errmsg("interval out of range")));
2843
2844 result->month = 0;
2845 result->day = 0;
2846
2847 /*----------
2848 * This is wrong, but removing it breaks a lot of regression tests.
2849 * For example:
2850 *
2851 * test=> SET timezone = 'EST5EDT';
2852 * test=> SELECT
2853 * test-> ('2005-10-30 13:22:00-05'::timestamptz -
2854 * test(> '2005-10-29 13:22:00-04'::timestamptz);
2855 * ?column?
2856 * ----------------
2857 * 1 day 01:00:00
2858 * (1 row)
2859 *
2860 * so adding that to the first timestamp gets:
2861 *
2862 * test=> SELECT
2863 * test-> ('2005-10-29 13:22:00-04'::timestamptz +
2864 * test(> ('2005-10-30 13:22:00-05'::timestamptz -
2865 * test(> '2005-10-29 13:22:00-04'::timestamptz)) at time zone 'EST';
2866 * timezone
2867 * --------------------
2868 * 2005-10-30 14:22:00
2869 * (1 row)
2870 *----------
2871 */
2873 IntervalPGetDatum(result)));
2874
2875 PG_RETURN_INTERVAL_P(result);
2876}
2877
2878/*
2879 * interval_justify_interval()
2880 *
2881 * Adjust interval so 'month', 'day', and 'time' portions are within
2882 * customary bounds. Specifically:
2883 *
2884 * 0 <= abs(time) < 24 hours
2885 * 0 <= abs(day) < 30 days
2886 *
2887 * Also, the sign bit on all three fields is made equal, so either
2888 * all three fields are negative or all are positive.
2889 */
2890Datum
2892{
2893 Interval *span = PG_GETARG_INTERVAL_P(0);
2894 Interval *result;
2895 TimeOffset wholeday;
2896 int32 wholemonth;
2897
2898 result = (Interval *) palloc(sizeof(Interval));
2899 result->month = span->month;
2900 result->day = span->day;
2901 result->time = span->time;
2902
2903 /* do nothing for infinite intervals */
2904 if (INTERVAL_NOT_FINITE(result))
2905 PG_RETURN_INTERVAL_P(result);
2906
2907 /* pre-justify days if it might prevent overflow */
2908 if ((result->day > 0 && result->time > 0) ||
2909 (result->day < 0 && result->time < 0))
2910 {
2911 wholemonth = result->day / DAYS_PER_MONTH;
2912 result->day -= wholemonth * DAYS_PER_MONTH;
2913 if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
2914 ereport(ERROR,
2915 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2916 errmsg("interval out of range")));
2917 }
2918
2919 /*
2920 * Since TimeOffset is int64, abs(wholeday) can't exceed about 1.07e8. If
2921 * we pre-justified then abs(result->day) is less than DAYS_PER_MONTH, so
2922 * this addition can't overflow. If we didn't pre-justify, then day and
2923 * time are of different signs, so it still can't overflow.
2924 */
2925 TMODULO(result->time, wholeday, USECS_PER_DAY);
2926 result->day += wholeday;
2927
2928 wholemonth = result->day / DAYS_PER_MONTH;
2929 result->day -= wholemonth * DAYS_PER_MONTH;
2930 if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
2931 ereport(ERROR,
2932 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2933 errmsg("interval out of range")));
2934
2935 if (result->month > 0 &&
2936 (result->day < 0 || (result->day == 0 && result->time < 0)))
2937 {
2938 result->day += DAYS_PER_MONTH;
2939 result->month--;
2940 }
2941 else if (result->month < 0 &&
2942 (result->day > 0 || (result->day == 0 && result->time > 0)))
2943 {
2944 result->day -= DAYS_PER_MONTH;
2945 result->month++;
2946 }
2947
2948 if (result->day > 0 && result->time < 0)
2949 {
2950 result->time += USECS_PER_DAY;
2951 result->day--;
2952 }
2953 else if (result->day < 0 && result->time > 0)
2954 {
2955 result->time -= USECS_PER_DAY;
2956 result->day++;
2957 }
2958
2959 PG_RETURN_INTERVAL_P(result);
2960}
2961
2962/*
2963 * interval_justify_hours()
2964 *
2965 * Adjust interval so 'time' contains less than a whole day, adding
2966 * the excess to 'day'. This is useful for
2967 * situations (such as non-TZ) where '1 day' = '24 hours' is valid,
2968 * e.g. interval subtraction and division.
2969 */
2970Datum
2972{
2973 Interval *span = PG_GETARG_INTERVAL_P(0);
2974 Interval *result;
2975 TimeOffset wholeday;
2976
2977 result = (Interval *) palloc(sizeof(Interval));
2978 result->month = span->month;
2979 result->day = span->day;
2980 result->time = span->time;
2981
2982 /* do nothing for infinite intervals */
2983 if (INTERVAL_NOT_FINITE(result))
2984 PG_RETURN_INTERVAL_P(result);
2985
2986 TMODULO(result->time, wholeday, USECS_PER_DAY);
2987 if (pg_add_s32_overflow(result->day, wholeday, &result->day))
2988 ereport(ERROR,
2989 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2990 errmsg("interval out of range")));
2991
2992 if (result->day > 0 && result->time < 0)
2993 {
2994 result->time += USECS_PER_DAY;
2995 result->day--;
2996 }
2997 else if (result->day < 0 && result->time > 0)
2998 {
2999 result->time -= USECS_PER_DAY;
3000 result->day++;
3001 }
3002
3003 PG_RETURN_INTERVAL_P(result);
3004}
3005
3006/*
3007 * interval_justify_days()
3008 *
3009 * Adjust interval so 'day' contains less than 30 days, adding
3010 * the excess to 'month'.
3011 */
3012Datum
3014{
3015 Interval *span = PG_GETARG_INTERVAL_P(0);
3016 Interval *result;
3017 int32 wholemonth;
3018
3019 result = (Interval *) palloc(sizeof(Interval));
3020 result->month = span->month;
3021 result->day = span->day;
3022 result->time = span->time;
3023
3024 /* do nothing for infinite intervals */
3025 if (INTERVAL_NOT_FINITE(result))
3026 PG_RETURN_INTERVAL_P(result);
3027
3028 wholemonth = result->day / DAYS_PER_MONTH;
3029 result->day -= wholemonth * DAYS_PER_MONTH;
3030 if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
3031 ereport(ERROR,
3032 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3033 errmsg("interval out of range")));
3034
3035 if (result->month > 0 && result->day < 0)
3036 {
3037 result->day += DAYS_PER_MONTH;
3038 result->month--;
3039 }
3040 else if (result->month < 0 && result->day > 0)
3041 {
3042 result->day -= DAYS_PER_MONTH;
3043 result->month++;
3044 }
3045
3046 PG_RETURN_INTERVAL_P(result);
3047}
3048
3049/* timestamp_pl_interval()
3050 * Add an interval to a timestamp data type.
3051 * Note that interval has provisions for qualitative year/month and day
3052 * units, so try to do the right thing with them.
3053 * To add a month, increment the month, and use the same day of month.
3054 * Then, if the next month has fewer days, set the day of month
3055 * to the last day of month.
3056 * To add a day, increment the mday, and use the same time of day.
3057 * Lastly, add in the "quantitative time".
3058 */
3059Datum
3061{
3063 Interval *span = PG_GETARG_INTERVAL_P(1);
3064 Timestamp result;
3065
3066 /*
3067 * Handle infinities.
3068 *
3069 * We treat anything that amounts to "infinity - infinity" as an error,
3070 * since the timestamp type has nothing equivalent to NaN.
3071 */
3072 if (INTERVAL_IS_NOBEGIN(span))
3073 {
3075 ereport(ERROR,
3076 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3077 errmsg("timestamp out of range")));
3078 else
3079 TIMESTAMP_NOBEGIN(result);
3080 }
3081 else if (INTERVAL_IS_NOEND(span))
3082 {
3084 ereport(ERROR,
3085 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3086 errmsg("timestamp out of range")));
3087 else
3088 TIMESTAMP_NOEND(result);
3089 }
3091 result = timestamp;
3092 else
3093 {
3094 if (span->month != 0)
3095 {
3096 struct pg_tm tt,
3097 *tm = &tt;
3098 fsec_t fsec;
3099
3100 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
3101 ereport(ERROR,
3102 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3103 errmsg("timestamp out of range")));
3104
3105 if (pg_add_s32_overflow(tm->tm_mon, span->month, &tm->tm_mon))
3106 ereport(ERROR,
3107 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3108 errmsg("timestamp out of range")));
3109 if (tm->tm_mon > MONTHS_PER_YEAR)
3110 {
3111 tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
3112 tm->tm_mon = ((tm->tm_mon - 1) % MONTHS_PER_YEAR) + 1;
3113 }
3114 else if (tm->tm_mon < 1)
3115 {
3116 tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;
3118 }
3119
3120 /* adjust for end of month boundary problems... */
3121 if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
3122 tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
3123
3124 if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)
3125 ereport(ERROR,
3126 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3127 errmsg("timestamp out of range")));
3128 }
3129
3130 if (span->day != 0)
3131 {
3132 struct pg_tm tt,
3133 *tm = &tt;
3134 fsec_t fsec;
3135 int julian;
3136
3137 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
3138 ereport(ERROR,
3139 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3140 errmsg("timestamp out of range")));
3141
3142 /*
3143 * Add days by converting to and from Julian. We need an overflow
3144 * check here since j2date expects a non-negative integer input.
3145 */
3146 julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3147 if (pg_add_s32_overflow(julian, span->day, &julian) ||
3148 julian < 0)
3149 ereport(ERROR,
3150 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3151 errmsg("timestamp out of range")));
3152 j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3153
3154 if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)
3155 ereport(ERROR,
3156 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3157 errmsg("timestamp out of range")));
3158 }
3159
3161 ereport(ERROR,
3162 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3163 errmsg("timestamp out of range")));
3164
3166 ereport(ERROR,
3167 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3168 errmsg("timestamp out of range")));
3169
3170 result = timestamp;
3171 }
3172
3173 PG_RETURN_TIMESTAMP(result);
3174}
3175
3176Datum
3178{
3180 Interval *span = PG_GETARG_INTERVAL_P(1);
3181 Interval tspan;
3182
3183 interval_um_internal(span, &tspan);
3184
3187 PointerGetDatum(&tspan));
3188}
3189
3190
3191/* timestamptz_pl_interval_internal()
3192 * Add an interval to a timestamptz, in the given (or session) timezone.
3193 *
3194 * Note that interval has provisions for qualitative year/month and day
3195 * units, so try to do the right thing with them.
3196 * To add a month, increment the month, and use the same day of month.
3197 * Then, if the next month has fewer days, set the day of month
3198 * to the last day of month.
3199 * To add a day, increment the mday, and use the same time of day.
3200 * Lastly, add in the "quantitative time".
3201 */
3202static TimestampTz
3204 Interval *span,
3205 pg_tz *attimezone)
3206{
3207 TimestampTz result;
3208 int tz;
3209
3210 /*
3211 * Handle infinities.
3212 *
3213 * We treat anything that amounts to "infinity - infinity" as an error,
3214 * since the timestamptz type has nothing equivalent to NaN.
3215 */
3216 if (INTERVAL_IS_NOBEGIN(span))
3217 {
3219 ereport(ERROR,
3220 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3221 errmsg("timestamp out of range")));
3222 else
3223 TIMESTAMP_NOBEGIN(result);
3224 }
3225 else if (INTERVAL_IS_NOEND(span))
3226 {
3228 ereport(ERROR,
3229 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3230 errmsg("timestamp out of range")));
3231 else
3232 TIMESTAMP_NOEND(result);
3233 }
3235 result = timestamp;
3236 else
3237 {
3238 /* Use session timezone if caller asks for default */
3239 if (attimezone == NULL)
3240 attimezone = session_timezone;
3241
3242 if (span->month != 0)
3243 {
3244 struct pg_tm tt,
3245 *tm = &tt;
3246 fsec_t fsec;
3247
3248 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, attimezone) != 0)
3249 ereport(ERROR,
3250 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3251 errmsg("timestamp out of range")));
3252
3253 if (pg_add_s32_overflow(tm->tm_mon, span->month, &tm->tm_mon))
3254 ereport(ERROR,
3255 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3256 errmsg("timestamp out of range")));
3257 if (tm->tm_mon > MONTHS_PER_YEAR)
3258 {
3259 tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
3260 tm->tm_mon = ((tm->tm_mon - 1) % MONTHS_PER_YEAR) + 1;
3261 }
3262 else if (tm->tm_mon < 1)
3263 {
3264 tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;
3266 }
3267
3268 /* adjust for end of month boundary problems... */
3269 if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
3270 tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
3271
3272 tz = DetermineTimeZoneOffset(tm, attimezone);
3273
3274 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
3275 ereport(ERROR,
3276 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3277 errmsg("timestamp out of range")));
3278 }
3279
3280 if (span->day != 0)
3281 {
3282 struct pg_tm tt,
3283 *tm = &tt;
3284 fsec_t fsec;
3285 int julian;
3286
3287 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, attimezone) != 0)
3288 ereport(ERROR,
3289 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3290 errmsg("timestamp out of range")));
3291
3292 /*
3293 * Add days by converting to and from Julian. We need an overflow
3294 * check here since j2date expects a non-negative integer input.
3295 * In practice though, it will give correct answers for small
3296 * negative Julian dates; we should allow -1 to avoid
3297 * timezone-dependent failures, as discussed in timestamp.h.
3298 */
3299 julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3300 if (pg_add_s32_overflow(julian, span->day, &julian) ||
3301 julian < -1)
3302 ereport(ERROR,
3303 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3304 errmsg("timestamp out of range")));
3305 j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3306
3307 tz = DetermineTimeZoneOffset(tm, attimezone);
3308
3309 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
3310 ereport(ERROR,
3311 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3312 errmsg("timestamp out of range")));
3313 }
3314
3316 ereport(ERROR,
3317 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3318 errmsg("timestamp out of range")));
3319
3321 ereport(ERROR,
3322 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3323 errmsg("timestamp out of range")));
3324
3325 result = timestamp;
3326 }
3327
3328 return result;
3329}
3330
3331/* timestamptz_mi_interval_internal()
3332 * As above, but subtract the interval.
3333 */
3334static TimestampTz
3336 Interval *span,
3337 pg_tz *attimezone)
3338{
3339 Interval tspan;
3340
3341 interval_um_internal(span, &tspan);
3342
3343 return timestamptz_pl_interval_internal(timestamp, &tspan, attimezone);
3344}
3345
3346/* timestamptz_pl_interval()
3347 * Add an interval to a timestamptz, in the session timezone.
3348 */
3349Datum
3351{
3353 Interval *span = PG_GETARG_INTERVAL_P(1);
3354
3356}
3357
3358Datum
3360{
3362 Interval *span = PG_GETARG_INTERVAL_P(1);
3363
3365}
3366
3367/* timestamptz_pl_interval_at_zone()
3368 * Add an interval to a timestamptz, in the specified timezone.
3369 */
3370Datum
3372{
3374 Interval *span = PG_GETARG_INTERVAL_P(1);
3376 pg_tz *attimezone = lookup_timezone(zone);
3377
3379}
3380
3381Datum
3383{
3385 Interval *span = PG_GETARG_INTERVAL_P(1);
3387 pg_tz *attimezone = lookup_timezone(zone);
3388
3390}
3391
3392/* interval_um_internal()
3393 * Negate an interval.
3394 */
3395static void
3397{
3399 INTERVAL_NOEND(result);
3400 else if (INTERVAL_IS_NOEND(interval))
3401 INTERVAL_NOBEGIN(result);
3402 else
3403 {
3404 /* Negate each field, guarding against overflow */
3405 if (pg_sub_s64_overflow(INT64CONST(0), interval->time, &result->time) ||
3406 pg_sub_s32_overflow(0, interval->day, &result->day) ||
3407 pg_sub_s32_overflow(0, interval->month, &result->month) ||
3408 INTERVAL_NOT_FINITE(result))
3409 ereport(ERROR,
3410 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3411 errmsg("interval out of range")));
3412 }
3413}
3414
3415Datum
3417{
3419 Interval *result;
3420
3421 result = (Interval *) palloc(sizeof(Interval));
3423
3424 PG_RETURN_INTERVAL_P(result);
3425}
3426
3427
3428Datum
3430{
3431 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
3432 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
3433 Interval *result;
3434
3435 /* use interval_cmp_internal to be sure this agrees with comparisons */
3436 if (interval_cmp_internal(interval1, interval2) < 0)
3437 result = interval1;
3438 else
3439 result = interval2;
3440 PG_RETURN_INTERVAL_P(result);
3441}
3442
3443Datum
3445{
3446 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
3447 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
3448 Interval *result;
3449
3450 if (interval_cmp_internal(interval1, interval2) > 0)
3451 result = interval1;
3452 else
3453 result = interval2;
3454 PG_RETURN_INTERVAL_P(result);
3455}
3456
3457static void
3458finite_interval_pl(const Interval *span1, const Interval *span2, Interval *result)
3459{
3460 Assert(!INTERVAL_NOT_FINITE(span1));
3461 Assert(!INTERVAL_NOT_FINITE(span2));
3462
3463 if (pg_add_s32_overflow(span1->month, span2->month, &result->month) ||
3464 pg_add_s32_overflow(span1->day, span2->day, &result->day) ||
3465 pg_add_s64_overflow(span1->time, span2->time, &result->time) ||
3466 INTERVAL_NOT_FINITE(result))
3467 ereport(ERROR,
3468 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3469 errmsg("interval out of range")));
3470}
3471
3472Datum
3474{
3475 Interval *span1 = PG_GETARG_INTERVAL_P(0);
3476 Interval *span2 = PG_GETARG_INTERVAL_P(1);
3477 Interval *result;
3478
3479 result = (Interval *) palloc(sizeof(Interval));
3480
3481 /*
3482 * Handle infinities.
3483 *
3484 * We treat anything that amounts to "infinity - infinity" as an error,
3485 * since the interval type has nothing equivalent to NaN.
3486 */
3487 if (INTERVAL_IS_NOBEGIN(span1))
3488 {
3489 if (INTERVAL_IS_NOEND(span2))
3490 ereport(ERROR,
3491 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3492 errmsg("interval out of range")));
3493 else
3494 INTERVAL_NOBEGIN(result);
3495 }
3496 else if (INTERVAL_IS_NOEND(span1))
3497 {
3498 if (INTERVAL_IS_NOBEGIN(span2))
3499 ereport(ERROR,
3500 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3501 errmsg("interval out of range")));
3502 else
3503 INTERVAL_NOEND(result);
3504 }
3505 else if (INTERVAL_NOT_FINITE(span2))
3506 memcpy(result, span2, sizeof(Interval));
3507 else
3508 finite_interval_pl(span1, span2, result);
3509
3510 PG_RETURN_INTERVAL_P(result);
3511}
3512
3513static void
3514finite_interval_mi(const Interval *span1, const Interval *span2, Interval *result)
3515{
3516 Assert(!INTERVAL_NOT_FINITE(span1));
3517 Assert(!INTERVAL_NOT_FINITE(span2));
3518
3519 if (pg_sub_s32_overflow(span1->month, span2->month, &result->month) ||
3520 pg_sub_s32_overflow(span1->day, span2->day, &result->day) ||
3521 pg_sub_s64_overflow(span1->time, span2->time, &result->time) ||
3522 INTERVAL_NOT_FINITE(result))
3523 ereport(ERROR,
3524 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3525 errmsg("interval out of range")));
3526}
3527
3528Datum
3530{
3531 Interval *span1 = PG_GETARG_INTERVAL_P(0);
3532 Interval *span2 = PG_GETARG_INTERVAL_P(1);
3533 Interval *result;
3534
3535 result = (Interval *) palloc(sizeof(Interval));
3536
3537 /*
3538 * Handle infinities.
3539 *
3540 * We treat anything that amounts to "infinity - infinity" as an error,
3541 * since the interval type has nothing equivalent to NaN.
3542 */
3543 if (INTERVAL_IS_NOBEGIN(span1))
3544 {
3545 if (INTERVAL_IS_NOBEGIN(span2))
3546 ereport(ERROR,
3547 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3548 errmsg("interval out of range")));
3549 else
3550 INTERVAL_NOBEGIN(result);
3551 }
3552 else if (INTERVAL_IS_NOEND(span1))
3553 {
3554 if (INTERVAL_IS_NOEND(span2))
3555 ereport(ERROR,
3556 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3557 errmsg("interval out of range")));
3558 else
3559 INTERVAL_NOEND(result);
3560 }
3561 else if (INTERVAL_IS_NOBEGIN(span2))
3562 INTERVAL_NOEND(result);
3563 else if (INTERVAL_IS_NOEND(span2))
3564 INTERVAL_NOBEGIN(result);
3565 else
3566 finite_interval_mi(span1, span2, result);
3567
3568 PG_RETURN_INTERVAL_P(result);
3569}
3570
3571/*
3572 * There is no interval_abs(): it is unclear what value to return:
3573 * http://archives.postgresql.org/pgsql-general/2009-10/msg01031.php
3574 * http://archives.postgresql.org/pgsql-general/2009-11/msg00041.php
3575 */
3576
3577Datum
3579{
3580 Interval *span = PG_GETARG_INTERVAL_P(0);
3581 float8 factor = PG_GETARG_FLOAT8(1);
3582 double month_remainder_days,
3583 sec_remainder,
3584 result_double;
3585 int32 orig_month = span->month,
3586 orig_day = span->day;
3587 Interval *result;
3588
3589 result = (Interval *) palloc(sizeof(Interval));
3590
3591 /*
3592 * Handle NaN and infinities.
3593 *
3594 * We treat "0 * infinity" and "infinity * 0" as errors, since the
3595 * interval type has nothing equivalent to NaN.
3596 */
3597 if (isnan(factor))
3598 goto out_of_range;
3599
3600 if (INTERVAL_NOT_FINITE(span))
3601 {
3602 if (factor == 0.0)
3603 goto out_of_range;
3604
3605 if (factor < 0.0)
3606 interval_um_internal(span, result);
3607 else
3608 memcpy(result, span, sizeof(Interval));
3609
3610 PG_RETURN_INTERVAL_P(result);
3611 }
3612 if (isinf(factor))
3613 {
3614 int isign = interval_sign(span);
3615
3616 if (isign == 0)
3617 goto out_of_range;
3618
3619 if (factor * isign < 0)
3620 INTERVAL_NOBEGIN(result);
3621 else
3622 INTERVAL_NOEND(result);
3623
3624 PG_RETURN_INTERVAL_P(result);
3625 }
3626
3627 result_double = span->month * factor;
3628 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3629 goto out_of_range;
3630 result->month = (int32) result_double;
3631
3632 result_double = span->day * factor;
3633 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3634 goto out_of_range;
3635 result->day = (int32) result_double;
3636
3637 /*
3638 * The above correctly handles the whole-number part of the month and day
3639 * products, but we have to do something with any fractional part
3640 * resulting when the factor is non-integral. We cascade the fractions
3641 * down to lower units using the conversion factors DAYS_PER_MONTH and
3642 * SECS_PER_DAY. Note we do NOT cascade up, since we are not forced to do
3643 * so by the representation. The user can choose to cascade up later,
3644 * using justify_hours and/or justify_days.
3645 */
3646
3647 /*
3648 * Fractional months full days into days.
3649 *
3650 * Floating point calculation are inherently imprecise, so these
3651 * calculations are crafted to produce the most reliable result possible.
3652 * TSROUND() is needed to more accurately produce whole numbers where
3653 * appropriate.
3654 */
3655 month_remainder_days = (orig_month * factor - result->month) * DAYS_PER_MONTH;
3656 month_remainder_days = TSROUND(month_remainder_days);
3657 sec_remainder = (orig_day * factor - result->day +
3658 month_remainder_days - (int) month_remainder_days) * SECS_PER_DAY;
3659 sec_remainder = TSROUND(sec_remainder);
3660
3661 /*
3662 * Might have 24:00:00 hours due to rounding, or >24 hours because of time
3663 * cascade from months and days. It might still be >24 if the combination
3664 * of cascade and the seconds factor operation itself.
3665 */
3666 if (fabs(sec_remainder) >= SECS_PER_DAY)
3667 {
3668 if (pg_add_s32_overflow(result->day,
3669 (int) (sec_remainder / SECS_PER_DAY),
3670 &result->day))
3671 goto out_of_range;
3672 sec_remainder -= (int) (sec_remainder / SECS_PER_DAY) * SECS_PER_DAY;
3673 }
3674
3675 /* cascade units down */
3676 if (pg_add_s32_overflow(result->day, (int32) month_remainder_days,
3677 &result->day))
3678 goto out_of_range;
3679 result_double = rint(span->time * factor + sec_remainder * USECS_PER_SEC);
3680 if (isnan(result_double) || !FLOAT8_FITS_IN_INT64(result_double))
3681 goto out_of_range;
3682 result->time = (int64) result_double;
3683
3684 if (INTERVAL_NOT_FINITE(result))
3685 goto out_of_range;
3686
3687 PG_RETURN_INTERVAL_P(result);
3688
3689out_of_range:
3690 ereport(ERROR,
3691 errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3692 errmsg("interval out of range"));
3693
3694 PG_RETURN_NULL(); /* keep compiler quiet */
3695}
3696
3697Datum
3699{
3700 /* Args are float8 and Interval *, but leave them as generic Datum */
3701 Datum factor = PG_GETARG_DATUM(0);
3702 Datum span = PG_GETARG_DATUM(1);
3703
3704 return DirectFunctionCall2(interval_mul, span, factor);
3705}
3706
3707Datum
3709{
3710 Interval *span = PG_GETARG_INTERVAL_P(0);
3711 float8 factor = PG_GETARG_FLOAT8(1);
3712 double month_remainder_days,
3713 sec_remainder,
3714 result_double;
3715 int32 orig_month = span->month,
3716 orig_day = span->day;
3717 Interval *result;
3718
3719 result = (Interval *) palloc(sizeof(Interval));
3720
3721 if (factor == 0.0)
3722 ereport(ERROR,
3723 (errcode(ERRCODE_DIVISION_BY_ZERO),
3724 errmsg("division by zero")));
3725
3726 /*
3727 * Handle NaN and infinities.
3728 *
3729 * We treat "infinity / infinity" as an error, since the interval type has
3730 * nothing equivalent to NaN. Otherwise, dividing by infinity is handled
3731 * by the regular division code, causing all fields to be set to zero.
3732 */
3733 if (isnan(factor))
3734 goto out_of_range;
3735
3736 if (INTERVAL_NOT_FINITE(span))
3737 {
3738 if (isinf(factor))
3739 goto out_of_range;
3740
3741 if (factor < 0.0)
3742 interval_um_internal(span, result);
3743 else
3744 memcpy(result, span, sizeof(Interval));
3745
3746 PG_RETURN_INTERVAL_P(result);
3747 }
3748
3749 result_double = span->month / factor;
3750 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3751 goto out_of_range;
3752 result->month = (int32) result_double;
3753
3754 result_double = span->day / factor;
3755 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3756 goto out_of_range;
3757 result->day = (int32) result_double;
3758
3759 /*
3760 * Fractional months full days into days. See comment in interval_mul().
3761 */
3762 month_remainder_days = (orig_month / factor - result->month) * DAYS_PER_MONTH;
3763 month_remainder_days = TSROUND(month_remainder_days);
3764 sec_remainder = (orig_day / factor - result->day +
3765 month_remainder_days - (int) month_remainder_days) * SECS_PER_DAY;
3766 sec_remainder = TSROUND(sec_remainder);
3767 if (fabs(sec_remainder) >= SECS_PER_DAY)
3768 {
3769 if (pg_add_s32_overflow(result->day,
3770 (int) (sec_remainder / SECS_PER_DAY),
3771 &result->day))
3772 goto out_of_range;
3773 sec_remainder -= (int) (sec_remainder / SECS_PER_DAY) * SECS_PER_DAY;
3774 }
3775
3776 /* cascade units down */
3777 if (pg_add_s32_overflow(result->day, (int32) month_remainder_days,
3778 &result->day))
3779 goto out_of_range;
3780 result_double = rint(span->time / factor + sec_remainder * USECS_PER_SEC);
3781 if (isnan(result_double) || !FLOAT8_FITS_IN_INT64(result_double))
3782 goto out_of_range;
3783 result->time = (int64) result_double;
3784
3785 if (INTERVAL_NOT_FINITE(result))
3786 goto out_of_range;
3787
3788 PG_RETURN_INTERVAL_P(result);
3789
3790out_of_range:
3791 ereport(ERROR,
3792 errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3793 errmsg("interval out of range"));
3794
3795 PG_RETURN_NULL(); /* keep compiler quiet */
3796}
3797
3798
3799/*
3800 * in_range support functions for timestamps and intervals.
3801 *
3802 * Per SQL spec, we support these with interval as the offset type.
3803 * The spec's restriction that the offset not be negative is a bit hard to
3804 * decipher for intervals, but we choose to interpret it the same as our
3805 * interval comparison operators would.
3806 */
3807
3808Datum
3810{
3813 Interval *offset = PG_GETARG_INTERVAL_P(2);
3814 bool sub = PG_GETARG_BOOL(3);
3815 bool less = PG_GETARG_BOOL(4);
3816 TimestampTz sum;
3817
3818 if (interval_sign(offset) < 0)
3819 ereport(ERROR,
3820 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
3821 errmsg("invalid preceding or following size in window function")));
3822
3823 /*
3824 * Deal with cases where both base and offset are infinite, and computing
3825 * base +/- offset would cause an error. As for float and numeric types,
3826 * we assume that all values infinitely precede +infinity and infinitely
3827 * follow -infinity. See in_range_float8_float8() for reasoning.
3828 */
3829 if (INTERVAL_IS_NOEND(offset) &&
3830 (sub ? TIMESTAMP_IS_NOEND(base) : TIMESTAMP_IS_NOBEGIN(base)))
3831 PG_RETURN_BOOL(true);
3832
3833 /* We don't currently bother to avoid overflow hazards here */
3834 if (sub)
3835 sum = timestamptz_mi_interval_internal(base, offset, NULL);
3836 else
3837 sum = timestamptz_pl_interval_internal(base, offset, NULL);
3838
3839 if (less)
3840 PG_RETURN_BOOL(val <= sum);
3841 else
3842 PG_RETURN_BOOL(val >= sum);
3843}
3844
3845Datum
3847{
3850 Interval *offset = PG_GETARG_INTERVAL_P(2);
3851 bool sub = PG_GETARG_BOOL(3);
3852 bool less = PG_GETARG_BOOL(4);
3853 Timestamp sum;
3854
3855 if (interval_sign(offset) < 0)
3856 ereport(ERROR,
3857 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
3858 errmsg("invalid preceding or following size in window function")));
3859
3860 /*
3861 * Deal with cases where both base and offset are infinite, and computing
3862 * base +/- offset would cause an error. As for float and numeric types,
3863 * we assume that all values infinitely precede +infinity and infinitely
3864 * follow -infinity. See in_range_float8_float8() for reasoning.
3865 */
3866 if (INTERVAL_IS_NOEND(offset) &&
3867 (sub ? TIMESTAMP_IS_NOEND(base) : TIMESTAMP_IS_NOBEGIN(base)))
3868 PG_RETURN_BOOL(true);
3869
3870 /* We don't currently bother to avoid overflow hazards here */
3871 if (sub)
3873 TimestampGetDatum(base),
3874 IntervalPGetDatum(offset)));
3875 else
3877 TimestampGetDatum(base),
3878 IntervalPGetDatum(offset)));
3879
3880 if (less)
3881 PG_RETURN_BOOL(val <= sum);
3882 else
3883 PG_RETURN_BOOL(val >= sum);
3884}
3885
3886Datum
3888{
3890 Interval *base = PG_GETARG_INTERVAL_P(1);
3891 Interval *offset = PG_GETARG_INTERVAL_P(2);
3892 bool sub = PG_GETARG_BOOL(3);
3893 bool less = PG_GETARG_BOOL(4);
3894 Interval *sum;
3895
3896 if (interval_sign(offset) < 0)
3897 ereport(ERROR,
3898 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
3899 errmsg("invalid preceding or following size in window function")));
3900
3901 /*
3902 * Deal with cases where both base and offset are infinite, and computing
3903 * base +/- offset would cause an error. As for float and numeric types,
3904 * we assume that all values infinitely precede +infinity and infinitely
3905 * follow -infinity. See in_range_float8_float8() for reasoning.
3906 */
3907 if (INTERVAL_IS_NOEND(offset) &&
3908 (sub ? INTERVAL_IS_NOEND(base) : INTERVAL_IS_NOBEGIN(base)))
3909 PG_RETURN_BOOL(true);
3910
3911 /* We don't currently bother to avoid overflow hazards here */
3912 if (sub)
3914 IntervalPGetDatum(base),
3915 IntervalPGetDatum(offset)));
3916 else
3918 IntervalPGetDatum(base),
3919 IntervalPGetDatum(offset)));
3920
3921 if (less)
3923 else
3925}
3926
3927
3928/*
3929 * Prepare state data for an interval aggregate function, that needs to compute
3930 * sum and count, in the aggregate's memory context.
3931 *
3932 * The function is used when the state data needs to be allocated in aggregate's
3933 * context. When the state data needs to be allocated in the current memory
3934 * context, we use palloc0 directly e.g. interval_avg_deserialize().
3935 */
3936static IntervalAggState *
3938{
3940 MemoryContext agg_context;
3941 MemoryContext old_context;
3942
3943 if (!AggCheckCallContext(fcinfo, &agg_context))
3944 elog(ERROR, "aggregate function called in non-aggregate context");
3945
3946 old_context = MemoryContextSwitchTo(agg_context);
3947
3949
3950 MemoryContextSwitchTo(old_context);
3951
3952 return state;
3953}
3954
3955/*
3956 * Accumulate a new input value for interval aggregate functions.
3957 */
3958static void
3960{
3961 /* Infinite inputs are counted separately, and do not affect "N" */
3963 {
3964 state->nInfcount++;
3965 return;
3966 }
3967
3969 {
3970 state->pInfcount++;
3971 return;
3972 }
3973
3974 finite_interval_pl(&state->sumX, newval, &state->sumX);
3975 state->N++;
3976}
3977
3978/*
3979 * Remove the given interval value from the aggregated state.
3980 */
3981static void
3983{
3984 /* Infinite inputs are counted separately, and do not affect "N" */
3986 {
3987 state->nInfcount--;
3988 return;
3989 }
3990
3992 {
3993 state->pInfcount--;
3994 return;
3995 }
3996
3997 /* Handle the to-be-discarded finite value. */
3998 state->N--;
3999 if (state->N > 0)
4000 finite_interval_mi(&state->sumX, newval, &state->sumX);
4001 else
4002 {
4003 /* All values discarded, reset the state */
4004 Assert(state->N == 0);
4005 memset(&state->sumX, 0, sizeof(state->sumX));
4006 }
4007}
4008
4009/*
4010 * Transition function for sum() and avg() interval aggregates.
4011 */
4012Datum
4014{
4016
4018
4019 /* Create the state data on the first call */
4020 if (state == NULL)
4021 state = makeIntervalAggState(fcinfo);
4022
4023 if (!PG_ARGISNULL(1))
4025
4027}
4028
4029/*
4030 * Combine function for sum() and avg() interval aggregates.
4031 *
4032 * Combine the given internal aggregate states and place the combination in
4033 * the first argument.
4034 */
4035Datum
4037{
4038 IntervalAggState *state1;
4039 IntervalAggState *state2;
4040
4041 state1 = PG_ARGISNULL(0) ? NULL : (IntervalAggState *) PG_GETARG_POINTER(0);
4042 state2 = PG_ARGISNULL(1) ? NULL : (IntervalAggState *) PG_GETARG_POINTER(1);
4043
4044 if (state2 == NULL)
4045 PG_RETURN_POINTER(state1);
4046
4047 if (state1 == NULL)
4048 {
4049 /* manually copy all fields from state2 to state1 */
4050 state1 = makeIntervalAggState(fcinfo);
4051
4052 state1->N = state2->N;
4053 state1->pInfcount = state2->pInfcount;
4054 state1->nInfcount = state2->nInfcount;
4055
4056 state1->sumX.day = state2->sumX.day;
4057 state1->sumX.month = state2->sumX.month;
4058 state1->sumX.time = state2->sumX.time;
4059
4060 PG_RETURN_POINTER(state1);
4061 }
4062
4063 state1->N += state2->N;
4064 state1->pInfcount += state2->pInfcount;
4065 state1->nInfcount += state2->nInfcount;
4066
4067 /* Accumulate finite interval values, if any. */
4068 if (state2->N > 0)
4069 finite_interval_pl(&state1->sumX, &state2->sumX, &state1->sumX);
4070
4071 PG_RETURN_POINTER(state1);
4072}
4073
4074/*
4075 * interval_avg_serialize
4076 * Serialize IntervalAggState for interval aggregates.
4077 */
4078Datum
4080{
4083 bytea *result;
4084
4085 /* Ensure we disallow calling when not in aggregate context */
4086 if (!AggCheckCallContext(fcinfo, NULL))
4087 elog(ERROR, "aggregate function called in non-aggregate context");
4088
4090
4092
4093 /* N */
4094 pq_sendint64(&buf, state->N);
4095
4096 /* sumX */
4097 pq_sendint64(&buf, state->sumX.time);
4098 pq_sendint32(&buf, state->sumX.day);
4099 pq_sendint32(&buf, state->sumX.month);
4100
4101 /* pInfcount */
4102 pq_sendint64(&buf, state->pInfcount);
4103
4104 /* nInfcount */
4105 pq_sendint64(&buf, state->nInfcount);
4106
4107 result = pq_endtypsend(&buf);
4108
4109 PG_RETURN_BYTEA_P(result);
4110}
4111
4112/*
4113 * interval_avg_deserialize
4114 * Deserialize bytea into IntervalAggState for interval aggregates.
4115 */
4116Datum
4118{
4119 bytea *sstate;
4120 IntervalAggState *result;
4122
4123 if (!AggCheckCallContext(fcinfo, NULL))
4124 elog(ERROR, "aggregate function called in non-aggregate context");
4125
4126 sstate = PG_GETARG_BYTEA_PP(0);
4127
4128 /*
4129 * Initialize a StringInfo so that we can "receive" it using the standard
4130 * recv-function infrastructure.
4131 */
4133 VARSIZE_ANY_EXHDR(sstate));
4134
4135 result = (IntervalAggState *) palloc0(sizeof(IntervalAggState));
4136
4137 /* N */
4138 result->N = pq_getmsgint64(&buf);
4139
4140 /* sumX */
4141 result->sumX.time = pq_getmsgint64(&buf);
4142 result->sumX.day = pq_getmsgint(&buf, 4);
4143 result->sumX.month = pq_getmsgint(&buf, 4);
4144
4145 /* pInfcount */
4146 result->pInfcount = pq_getmsgint64(&buf);
4147
4148 /* nInfcount */
4149 result->nInfcount = pq_getmsgint64(&buf);
4150
4151 pq_getmsgend(&buf);
4152
4153 PG_RETURN_POINTER(result);
4154}
4155
4156/*
4157 * Inverse transition function for sum() and avg() interval aggregates.
4158 */
4159Datum
4161{
4163
4165
4166 /* Should not get here with no state */
4167 if (state == NULL)
4168 elog(ERROR, "interval_avg_accum_inv called with NULL state");
4169
4170 if (!PG_ARGISNULL(1))
4172
4174}
4175
4176/* avg(interval) aggregate final function */
4177Datum
4179{
4181
4183
4184 /* If there were no non-null inputs, return NULL */
4185 if (state == NULL || IA_TOTAL_COUNT(state) == 0)
4187
4188 /*
4189 * Aggregating infinities that all have the same sign produces infinity
4190 * with that sign. Aggregating infinities with different signs results in
4191 * an error.
4192 */
4193 if (state->pInfcount > 0 || state->nInfcount > 0)
4194 {
4195 Interval *result;
4196
4197 if (state->pInfcount > 0 && state->nInfcount > 0)
4198 ereport(ERROR,
4199 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4200 errmsg("interval out of range")));
4201
4202 result = (Interval *) palloc(sizeof(Interval));
4203 if (state->pInfcount > 0)
4204 INTERVAL_NOEND(result);
4205 else
4206 INTERVAL_NOBEGIN(result);
4207
4208 PG_RETURN_INTERVAL_P(result);
4209 }
4210
4212 IntervalPGetDatum(&state->sumX),
4213 Float8GetDatum((double) state->N));
4214}
4215
4216/* sum(interval) aggregate final function */
4217Datum
4219{
4221 Interval *result;
4222
4224
4225 /* If there were no non-null inputs, return NULL */
4226 if (state == NULL || IA_TOTAL_COUNT(state) == 0)
4228
4229 /*
4230 * Aggregating infinities that all have the same sign produces infinity
4231 * with that sign. Aggregating infinities with different signs results in
4232 * an error.
4233 */
4234 if (state->pInfcount > 0 && state->nInfcount > 0)
4235 ereport(ERROR,
4236 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4237 errmsg("interval out of range")));
4238
4239 result = (Interval *) palloc(sizeof(Interval));
4240
4241 if (state->pInfcount > 0)
4242 INTERVAL_NOEND(result);
4243 else if (state->nInfcount > 0)
4244 INTERVAL_NOBEGIN(result);
4245 else
4246 memcpy(result, &state->sumX, sizeof(Interval));
4247
4248 PG_RETURN_INTERVAL_P(result);
4249}
4250
4251/* timestamp_age()
4252 * Calculate time difference while retaining year/month fields.
4253 * Note that this does not result in an accurate absolute time span
4254 * since year and month are out of context once the arithmetic
4255 * is done.
4256 */
4257Datum
4259{
4262 Interval *result;
4263 fsec_t fsec1,
4264 fsec2;
4265 struct pg_itm tt,
4266 *tm = &tt;
4267 struct pg_tm tt1,
4268 *tm1 = &tt1;
4269 struct pg_tm tt2,
4270 *tm2 = &tt2;
4271
4272 result = (Interval *) palloc(sizeof(Interval));
4273
4274 /*
4275 * Handle infinities.
4276 *
4277 * We treat anything that amounts to "infinity - infinity" as an error,
4278 * since the interval type has nothing equivalent to NaN.
4279 */
4280 if (TIMESTAMP_IS_NOBEGIN(dt1))
4281 {
4282 if (TIMESTAMP_IS_NOBEGIN(dt2))
4283 ereport(ERROR,
4284 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4285 errmsg("interval out of range")));
4286 else
4287 INTERVAL_NOBEGIN(result);
4288 }
4289 else if (TIMESTAMP_IS_NOEND(dt1))
4290 {
4291 if (TIMESTAMP_IS_NOEND(dt2))
4292 ereport(ERROR,
4293 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4294 errmsg("interval out of range")));
4295 else
4296 INTERVAL_NOEND(result);
4297 }
4298 else if (TIMESTAMP_IS_NOBEGIN(dt2))
4299 INTERVAL_NOEND(result);
4300 else if (TIMESTAMP_IS_NOEND(dt2))
4301 INTERVAL_NOBEGIN(result);
4302 else if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL, NULL) == 0 &&
4303 timestamp2tm(dt2, NULL, tm2, &fsec2, NULL, NULL) == 0)
4304 {
4305 /* form the symbolic difference */
4306 tm->tm_usec = fsec1 - fsec2;
4307 tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
4308 tm->tm_min = tm1->tm_min - tm2->tm_min;
4309 tm->tm_hour = tm1->tm_hour - tm2->tm_hour;
4310 tm->tm_mday = tm1->tm_mday - tm2->tm_mday;
4311 tm->tm_mon = tm1->tm_mon - tm2->tm_mon;
4312 tm->tm_year = tm1->tm_year - tm2->tm_year;
4313
4314 /* flip sign if necessary... */
4315 if (dt1 < dt2)
4316 {
4317 tm->tm_usec = -tm->tm_usec;
4318 tm->tm_sec = -tm->tm_sec;
4319 tm->tm_min = -tm->tm_min;
4320 tm->tm_hour = -tm->tm_hour;
4321 tm->tm_mday = -tm->tm_mday;
4322 tm->tm_mon = -tm->tm_mon;
4323 tm->tm_year = -tm->tm_year;
4324 }
4325
4326 /* propagate any negative fields into the next higher field */
4327 while (tm->tm_usec < 0)
4328 {
4329 tm->tm_usec += USECS_PER_SEC;
4330 tm->tm_sec--;
4331 }
4332
4333 while (tm->tm_sec < 0)
4334 {
4336 tm->tm_min--;
4337 }
4338
4339 while (tm->tm_min < 0)
4340 {
4342 tm->tm_hour--;
4343 }
4344
4345 while (tm->tm_hour < 0)
4346 {
4348 tm->tm_mday--;
4349 }
4350
4351 while (tm->tm_mday < 0)
4352 {
4353 if (dt1 < dt2)
4354 {
4355 tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
4356 tm->tm_mon--;
4357 }
4358 else
4359 {
4360 tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
4361 tm->tm_mon--;
4362 }
4363 }
4364
4365 while (tm->tm_mon < 0)
4366 {
4368 tm->tm_year--;
4369 }
4370
4371 /* recover sign if necessary... */
4372 if (dt1 < dt2)
4373 {
4374 tm->tm_usec = -tm->tm_usec;
4375 tm->tm_sec = -tm->tm_sec;
4376 tm->tm_min = -tm->tm_min;
4377 tm->tm_hour = -tm->tm_hour;
4378 tm->tm_mday = -tm->tm_mday;
4379 tm->tm_mon = -tm->tm_mon;
4380 tm->tm_year = -tm->tm_year;
4381 }
4382
4383 if (itm2interval(tm, result) != 0)
4384 ereport(ERROR,
4385 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4386 errmsg("interval out of range")));
4387 }
4388 else
4389 ereport(ERROR,
4390 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4391 errmsg("timestamp out of range")));
4392
4393 PG_RETURN_INTERVAL_P(result);
4394}
4395
4396
4397/* timestamptz_age()
4398 * Calculate time difference while retaining year/month fields.
4399 * Note that this does not result in an accurate absolute time span
4400 * since year and month are out of context once the arithmetic
4401 * is done.
4402 */
4403Datum
4405{
4408 Interval *result;
4409 fsec_t fsec1,
4410 fsec2;
4411 struct pg_itm tt,
4412 *tm = &tt;
4413 struct pg_tm tt1,
4414 *tm1 = &tt1;
4415 struct pg_tm tt2,
4416 *tm2 = &tt2;
4417 int tz1;
4418 int tz2;
4419
4420 result = (Interval *) palloc(sizeof(Interval));
4421
4422 /*
4423 * Handle infinities.
4424 *
4425 * We treat anything that amounts to "infinity - infinity" as an error,
4426 * since the interval type has nothing equivalent to NaN.
4427 */
4428 if (TIMESTAMP_IS_NOBEGIN(dt1))
4429 {
4430 if (TIMESTAMP_IS_NOBEGIN(dt2))
4431 ereport(ERROR,
4432 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4433 errmsg("interval out of range")));
4434 else
4435 INTERVAL_NOBEGIN(result);
4436 }
4437 else if (TIMESTAMP_IS_NOEND(dt1))
4438 {
4439 if (TIMESTAMP_IS_NOEND(dt2))
4440 ereport(ERROR,
4441 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4442 errmsg("interval out of range")));
4443 else
4444 INTERVAL_NOEND(result);
4445 }
4446 else if (TIMESTAMP_IS_NOBEGIN(dt2))
4447 INTERVAL_NOEND(result);
4448 else if (TIMESTAMP_IS_NOEND(dt2))
4449 INTERVAL_NOBEGIN(result);
4450 else if (timestamp2tm(dt1, &tz1, tm1, &fsec1, NULL, NULL) == 0 &&
4451 timestamp2tm(dt2, &tz2, tm2, &fsec2, NULL, NULL) == 0)
4452 {
4453 /* form the symbolic difference */
4454 tm->tm_usec = fsec1 - fsec2;
4455 tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
4456 tm->tm_min = tm1->tm_min - tm2->tm_min;
4457 tm->tm_hour = tm1->tm_hour - tm2->tm_hour;
4458 tm->tm_mday = tm1->tm_mday - tm2->tm_mday;
4459 tm->tm_mon = tm1->tm_mon - tm2->tm_mon;
4460 tm->tm_year = tm1->tm_year - tm2->tm_year;
4461
4462 /* flip sign if necessary... */
4463 if (dt1 < dt2)
4464 {
4465 tm->tm_usec = -tm->tm_usec;
4466 tm->tm_sec = -tm->tm_sec;
4467 tm->tm_min = -tm->tm_min;
4468 tm->tm_hour = -tm->tm_hour;
4469 tm->tm_mday = -tm->tm_mday;
4470 tm->tm_mon = -tm->tm_mon;
4471 tm->tm_year = -tm->tm_year;
4472 }
4473
4474 /* propagate any negative fields into the next higher field */
4475 while (tm->tm_usec < 0)
4476 {
4477 tm->tm_usec += USECS_PER_SEC;
4478 tm->tm_sec--;
4479 }
4480
4481 while (tm->tm_sec < 0)
4482 {
4484 tm->tm_min--;
4485 }
4486
4487 while (tm->tm_min < 0)
4488 {
4490 tm->tm_hour--;
4491 }
4492
4493 while (tm->tm_hour < 0)
4494 {
4496 tm->tm_mday--;
4497 }
4498
4499 while (tm->tm_mday < 0)
4500 {
4501 if (dt1 < dt2)
4502 {
4503 tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
4504 tm->tm_mon--;
4505 }
4506 else
4507 {
4508 tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
4509 tm->tm_mon--;
4510 }
4511 }
4512
4513 while (tm->tm_mon < 0)
4514 {
4516 tm->tm_year--;
4517 }
4518
4519 /*
4520 * Note: we deliberately ignore any difference between tz1 and tz2.
4521 */
4522
4523 /* recover sign if necessary... */
4524 if (dt1 < dt2)
4525 {
4526 tm->tm_usec = -tm->tm_usec;
4527 tm->tm_sec = -tm->tm_sec;
4528 tm->tm_min = -tm->tm_min;
4529 tm->tm_hour = -tm->tm_hour;
4530 tm->tm_mday = -tm->tm_mday;
4531 tm->tm_mon = -tm->tm_mon;
4532 tm->tm_year = -tm->tm_year;
4533 }
4534
4535 if (itm2interval(tm, result) != 0)
4536 ereport(ERROR,
4537 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4538 errmsg("interval out of range")));
4539 }
4540 else
4541 ereport(ERROR,
4542 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4543 errmsg("timestamp out of range")));
4544
4545 PG_RETURN_INTERVAL_P(result);
4546}
4547
4548
4549/*----------------------------------------------------------
4550 * Conversion operators.
4551 *---------------------------------------------------------*/
4552
4553
4554/* timestamp_bin()
4555 * Bin timestamp into specified interval.
4556 */
4557Datum
4559{
4560 Interval *stride = PG_GETARG_INTERVAL_P(0);
4562 Timestamp origin = PG_GETARG_TIMESTAMP(2);
4563 Timestamp result,
4564 stride_usecs,
4565 tm_diff,
4566 tm_modulo,
4567 tm_delta;
4568
4571
4572 if (TIMESTAMP_NOT_FINITE(origin))
4573 ereport(ERROR,
4574 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4575 errmsg("origin out of range")));
4576
4577 if (INTERVAL_NOT_FINITE(stride))
4578 ereport(ERROR,
4579 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4580 errmsg("timestamps cannot be binned into infinite intervals")));
4581
4582 if (stride->month != 0)
4583 ereport(ERROR,
4584 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4585 errmsg("timestamps cannot be binned into intervals containing months or years")));
4586
4587 if (unlikely(pg_mul_s64_overflow(stride->day, USECS_PER_DAY, &stride_usecs)) ||
4588 unlikely(pg_add_s64_overflow(stride_usecs, stride->time, &stride_usecs)))
4589 ereport(ERROR,
4590 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4591 errmsg("interval out of range")));
4592
4593 if (stride_usecs <= 0)
4594 ereport(ERROR,
4595 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4596 errmsg("stride must be greater than zero")));
4597
4598 if (unlikely(pg_sub_s64_overflow(timestamp, origin, &tm_diff)))
4599 ereport(ERROR,
4600 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4601 errmsg("interval out of range")));
4602
4603 /* These calculations cannot overflow */
4604 tm_modulo = tm_diff % stride_usecs;
4605 tm_delta = tm_diff - tm_modulo;
4606 result = origin + tm_delta;
4607
4608 /*
4609 * We want to round towards -infinity, not 0, when tm_diff is negative and
4610 * not a multiple of stride_usecs. This adjustment *can* cause overflow,
4611 * since the result might now be out of the range origin .. timestamp.
4612 */
4613 if (tm_modulo < 0)
4614 {
4615 if (unlikely(pg_sub_s64_overflow(result, stride_usecs, &result)) ||
4616 !IS_VALID_TIMESTAMP(result))
4617 ereport(ERROR,
4618 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4619 errmsg("timestamp out of range")));
4620 }
4621
4622 PG_RETURN_TIMESTAMP(result);
4623}
4624
4625/* timestamp_trunc()
4626 * Truncate timestamp to specified units.
4627 */
4628Datum
4630{
4631 text *units = PG_GETARG_TEXT_PP(0);
4633 Timestamp result;
4634 int type,
4635 val;
4636 char *lowunits;
4637 fsec_t fsec;
4638 struct pg_tm tt,
4639 *tm = &tt;
4640
4641 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
4642 VARSIZE_ANY_EXHDR(units),
4643 false);
4644
4645 type = DecodeUnits(0, lowunits, &val);
4646
4647 if (type == UNITS)
4648 {
4650 {
4651 /*
4652 * Errors thrown here for invalid units should exactly match those
4653 * below, else there will be unexpected discrepancies between
4654 * finite- and infinite-input cases.
4655 */
4656 switch (val)
4657 {
4658 case DTK_WEEK:
4659 case DTK_MILLENNIUM:
4660 case DTK_CENTURY:
4661 case DTK_DECADE:
4662 case DTK_YEAR:
4663 case DTK_QUARTER:
4664 case DTK_MONTH:
4665 case DTK_DAY:
4666 case DTK_HOUR:
4667 case DTK_MINUTE:
4668 case DTK_SECOND:
4669 case DTK_MILLISEC:
4670 case DTK_MICROSEC:
4672 break;
4673 default:
4674 ereport(ERROR,
4675 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4676 errmsg("unit \"%s\" not supported for type %s",
4677 lowunits, format_type_be(TIMESTAMPOID))));
4678 result = 0;
4679 }
4680 }
4681
4682 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
4683 ereport(ERROR,
4684 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4685 errmsg("timestamp out of range")));
4686
4687 switch (val)
4688 {
4689 case DTK_WEEK:
4690 {
4691 int woy;
4692
4694
4695 /*
4696 * If it is week 52/53 and the month is January, then the
4697 * week must belong to the previous year. Also, some
4698 * December dates belong to the next year.
4699 */
4700 if (woy >= 52 && tm->tm_mon == 1)
4701 --tm->tm_year;
4702 if (woy <= 1 && tm->tm_mon == MONTHS_PER_YEAR)
4703 ++tm->tm_year;
4704 isoweek2date(woy, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
4705 tm->tm_hour = 0;
4706 tm->tm_min = 0;
4707 tm->tm_sec = 0;
4708 fsec = 0;
4709 break;
4710 }
4711 case DTK_MILLENNIUM:
4712 /* see comments in timestamptz_trunc */
4713 if (tm->tm_year > 0)
4714 tm->tm_year = ((tm->tm_year + 999) / 1000) * 1000 - 999;
4715 else
4716 tm->tm_year = -((999 - (tm->tm_year - 1)) / 1000) * 1000 + 1;
4717 /* FALL THRU */
4718 case DTK_CENTURY:
4719 /* see comments in timestamptz_trunc */
4720 if (tm->tm_year > 0)
4721 tm->tm_year = ((tm->tm_year + 99) / 100) * 100 - 99;
4722 else
4723 tm->tm_year = -((99 - (tm->tm_year - 1)) / 100) * 100 + 1;
4724 /* FALL THRU */
4725 case DTK_DECADE:
4726 /* see comments in timestamptz_trunc */
4727 if (val != DTK_MILLENNIUM && val != DTK_CENTURY)
4728 {
4729 if (tm->tm_year > 0)
4730 tm->tm_year = (tm->tm_year / 10) * 10;
4731 else
4732 tm->tm_year = -((8 - (tm->tm_year - 1)) / 10) * 10;
4733 }
4734 /* FALL THRU */
4735 case DTK_YEAR:
4736 tm->tm_mon = 1;
4737 /* FALL THRU */
4738 case DTK_QUARTER:
4739 tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1;
4740 /* FALL THRU */
4741 case DTK_MONTH:
4742 tm->tm_mday = 1;
4743 /* FALL THRU */
4744 case DTK_DAY:
4745 tm->tm_hour = 0;
4746 /* FALL THRU */
4747 case DTK_HOUR:
4748 tm->tm_min = 0;
4749 /* FALL THRU */
4750 case DTK_MINUTE:
4751 tm->tm_sec = 0;
4752 /* FALL THRU */
4753 case DTK_SECOND:
4754 fsec = 0;
4755 break;
4756
4757 case DTK_MILLISEC:
4758 fsec = (fsec / 1000) * 1000;
4759 break;
4760
4761 case DTK_MICROSEC:
4762 break;
4763
4764 default:
4765 ereport(ERROR,
4766 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4767 errmsg("unit \"%s\" not supported for type %s",
4768 lowunits, format_type_be(TIMESTAMPOID))));
4769 result = 0;
4770 }
4771
4772 if (tm2timestamp(tm, fsec, NULL, &result) != 0)
4773 ereport(ERROR,
4774 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4775 errmsg("timestamp out of range")));
4776 }
4777 else
4778 {
4779 ereport(ERROR,
4780 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4781 errmsg("unit \"%s\" not recognized for type %s",
4782 lowunits, format_type_be(TIMESTAMPOID))));
4783 result = 0;
4784 }
4785
4786 PG_RETURN_TIMESTAMP(result);
4787}
4788
4789/* timestamptz_bin()
4790 * Bin timestamptz into specified interval using specified origin.
4791 */
4792Datum
4794{
4795 Interval *stride = PG_GETARG_INTERVAL_P(0);
4798 TimestampTz result,
4799 stride_usecs,
4800 tm_diff,
4801 tm_modulo,
4802 tm_delta;
4803
4806
4807 if (TIMESTAMP_NOT_FINITE(origin))
4808 ereport(ERROR,
4809 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4810 errmsg("origin out of range")));
4811
4812 if (INTERVAL_NOT_FINITE(stride))
4813 ereport(ERROR,
4814 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4815 errmsg("timestamps cannot be binned into infinite intervals")));
4816
4817 if (stride->month != 0)
4818 ereport(ERROR,
4819 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4820 errmsg("timestamps cannot be binned into intervals containing months or years")));
4821
4822 if (unlikely(pg_mul_s64_overflow(stride->day, USECS_PER_DAY, &stride_usecs)) ||
4823 unlikely(pg_add_s64_overflow(stride_usecs, stride->time, &stride_usecs)))
4824 ereport(ERROR,
4825 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4826 errmsg("interval out of range")));
4827
4828 if (stride_usecs <= 0)
4829 ereport(ERROR,
4830 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4831 errmsg("stride must be greater than zero")));
4832
4833 if (unlikely(pg_sub_s64_overflow(timestamp, origin, &tm_diff)))
4834 ereport(ERROR,
4835 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4836 errmsg("interval out of range")));
4837
4838 /* These calculations cannot overflow */
4839 tm_modulo = tm_diff % stride_usecs;
4840 tm_delta = tm_diff - tm_modulo;
4841 result = origin + tm_delta;
4842
4843 /*
4844 * We want to round towards -infinity, not 0, when tm_diff is negative and
4845 * not a multiple of stride_usecs. This adjustment *can* cause overflow,
4846 * since the result might now be out of the range origin .. timestamp.
4847 */
4848 if (tm_modulo < 0)
4849 {
4850 if (unlikely(pg_sub_s64_overflow(result, stride_usecs, &result)) ||
4851 !IS_VALID_TIMESTAMP(result))
4852 ereport(ERROR,
4853 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4854 errmsg("timestamp out of range")));
4855 }
4856
4857 PG_RETURN_TIMESTAMPTZ(result);
4858}
4859
4860/*
4861 * Common code for timestamptz_trunc() and timestamptz_trunc_zone().
4862 *
4863 * tzp identifies the zone to truncate with respect to. We assume
4864 * infinite timestamps have already been rejected.
4865 */
4866static TimestampTz
4868{
4869 TimestampTz result;
4870 int tz;
4871 int type,
4872 val;
4873 bool redotz = false;
4874 char *lowunits;
4875 fsec_t fsec;
4876 struct pg_tm tt,
4877 *tm = &tt;
4878
4879 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
4880 VARSIZE_ANY_EXHDR(units),
4881 false);
4882
4883 type = DecodeUnits(0, lowunits, &val);
4884
4885 if (type == UNITS)
4886 {
4888 {
4889 /*
4890 * Errors thrown here for invalid units should exactly match those
4891 * below, else there will be unexpected discrepancies between
4892 * finite- and infinite-input cases.
4893 */
4894 switch (val)
4895 {
4896 case DTK_WEEK:
4897 case DTK_MILLENNIUM:
4898 case DTK_CENTURY:
4899 case DTK_DECADE:
4900 case DTK_YEAR:
4901 case DTK_QUARTER:
4902 case DTK_MONTH:
4903 case DTK_DAY:
4904 case DTK_HOUR:
4905 case DTK_MINUTE:
4906 case DTK_SECOND:
4907 case DTK_MILLISEC:
4908 case DTK_MICROSEC:
4910 break;
4911
4912 default:
4913 ereport(ERROR,
4914 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4915 errmsg("unit \"%s\" not supported for type %s",
4916 lowunits, format_type_be(TIMESTAMPTZOID))));
4917 result = 0;
4918 }
4919 }
4920
4921 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, tzp) != 0)
4922 ereport(ERROR,
4923 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4924 errmsg("timestamp out of range")));
4925
4926 switch (val)
4927 {
4928 case DTK_WEEK:
4929 {
4930 int woy;
4931
4933
4934 /*
4935 * If it is week 52/53 and the month is January, then the
4936 * week must belong to the previous year. Also, some
4937 * December dates belong to the next year.
4938 */
4939 if (woy >= 52 && tm->tm_mon == 1)
4940 --tm->tm_year;
4941 if (woy <= 1 && tm->tm_mon == MONTHS_PER_YEAR)
4942 ++tm->tm_year;
4943 isoweek2date(woy, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
4944 tm->tm_hour = 0;
4945 tm->tm_min = 0;
4946 tm->tm_sec = 0;
4947 fsec = 0;
4948 redotz = true;
4949 break;
4950 }
4951 /* one may consider DTK_THOUSAND and DTK_HUNDRED... */
4952 case DTK_MILLENNIUM:
4953
4954 /*
4955 * truncating to the millennium? what is this supposed to
4956 * mean? let us put the first year of the millennium... i.e.
4957 * -1000, 1, 1001, 2001...
4958 */
4959 if (tm->tm_year > 0)
4960 tm->tm_year = ((tm->tm_year + 999) / 1000) * 1000 - 999;
4961 else
4962 tm->tm_year = -((999 - (tm->tm_year - 1)) / 1000) * 1000 + 1;
4963 /* FALL THRU */
4964 case DTK_CENTURY:
4965 /* truncating to the century? as above: -100, 1, 101... */
4966 if (tm->tm_year > 0)
4967 tm->tm_year = ((tm->tm_year + 99) / 100) * 100 - 99;
4968 else
4969 tm->tm_year = -((99 - (tm->tm_year - 1)) / 100) * 100 + 1;
4970 /* FALL THRU */
4971 case DTK_DECADE:
4972
4973 /*
4974 * truncating to the decade? first year of the decade. must
4975 * not be applied if year was truncated before!
4976 */
4977 if (val != DTK_MILLENNIUM && val != DTK_CENTURY)
4978 {
4979 if (tm->tm_year > 0)
4980 tm->tm_year = (tm->tm_year / 10) * 10;
4981 else
4982 tm->tm_year = -((8 - (tm->tm_year - 1)) / 10) * 10;
4983 }
4984 /* FALL THRU */
4985 case DTK_YEAR:
4986 tm->tm_mon = 1;
4987 /* FALL THRU */
4988 case DTK_QUARTER:
4989 tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1;
4990 /* FALL THRU */
4991 case DTK_MONTH:
4992 tm->tm_mday = 1;
4993 /* FALL THRU */
4994 case DTK_DAY:
4995 tm->tm_hour = 0;
4996 redotz = true; /* for all cases >= DAY */
4997 /* FALL THRU */
4998 case DTK_HOUR:
4999 tm->tm_min = 0;
5000 /* FALL THRU */
5001 case DTK_MINUTE:
5002 tm->tm_sec = 0;
5003 /* FALL THRU */
5004 case DTK_SECOND:
5005 fsec = 0;
5006 break;
5007 case DTK_MILLISEC:
5008 fsec = (fsec / 1000) * 1000;
5009 break;
5010 case DTK_MICROSEC:
5011 break;
5012
5013 default:
5014 ereport(ERROR,
5015 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5016 errmsg("unit \"%s\" not supported for type %s",
5017 lowunits, format_type_be(TIMESTAMPTZOID))));
5018 result = 0;
5019 }
5020
5021 if (redotz)
5022 tz = DetermineTimeZoneOffset(tm, tzp);
5023
5024 if (tm2timestamp(tm, fsec, &tz, &result) != 0)
5025 ereport(ERROR,
5026 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5027 errmsg("timestamp out of range")));
5028 }
5029 else
5030 {
5031 ereport(ERROR,
5032 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5033 errmsg("unit \"%s\" not recognized for type %s",
5034 lowunits, format_type_be(TIMESTAMPTZOID))));
5035 result = 0;
5036 }
5037
5038 return result;
5039}
5040
5041/* timestamptz_trunc()
5042 * Truncate timestamptz to specified units in session timezone.
5043 */
5044Datum
5046{
5047 text *units = PG_GETARG_TEXT_PP(0);
5049 TimestampTz result;
5050
5052
5053 PG_RETURN_TIMESTAMPTZ(result);
5054}
5055
5056/* timestamptz_trunc_zone()
5057 * Truncate timestamptz to specified units in specified timezone.
5058 */
5059Datum
5061{
5062 text *units = PG_GETARG_TEXT_PP(0);
5065 TimestampTz result;
5066 pg_tz *tzp;
5067
5068 /*
5069 * Look up the requested timezone.
5070 */
5071 tzp = lookup_timezone(zone);
5072
5073 result = timestamptz_trunc_internal(units, timestamp, tzp);
5074
5075 PG_RETURN_TIMESTAMPTZ(result);
5076}
5077
5078/* interval_trunc()
5079 * Extract specified field from interval.
5080 */
5081Datum
5083{
5084 text *units = PG_GETARG_TEXT_PP(0);
5086 Interval *result;
5087 int type,
5088 val;
5089 char *lowunits;
5090 struct pg_itm tt,
5091 *tm = &tt;
5092
5093 result = (Interval *) palloc(sizeof(Interval));
5094
5095 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
5096 VARSIZE_ANY_EXHDR(units),
5097 false);
5098
5099 type = DecodeUnits(0, lowunits, &val);
5100
5101 if (type == UNITS)
5102 {
5104 {
5105 /*
5106 * Errors thrown here for invalid units should exactly match those
5107 * below, else there will be unexpected discrepancies between
5108 * finite- and infinite-input cases.
5109 */
5110 switch (val)
5111 {
5112 case DTK_MILLENNIUM:
5113 case DTK_CENTURY:
5114 case DTK_DECADE:
5115 case DTK_YEAR:
5116 case DTK_QUARTER:
5117 case DTK_MONTH:
5118 case DTK_DAY:
5119 case DTK_HOUR:
5120 case DTK_MINUTE:
5121 case DTK_SECOND:
5122 case DTK_MILLISEC:
5123 case DTK_MICROSEC:
5124 memcpy(result, interval, sizeof(Interval));
5125 PG_RETURN_INTERVAL_P(result);
5126 break;
5127
5128 default:
5129 ereport(ERROR,
5130 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5131 errmsg("unit \"%s\" not supported for type %s",
5132 lowunits, format_type_be(INTERVALOID)),
5133 (val == DTK_WEEK) ? errdetail("Months usually have fractional weeks.") : 0));
5134 result = 0;
5135 }
5136 }
5137
5139 switch (val)
5140 {
5141 case DTK_MILLENNIUM:
5142 /* caution: C division may have negative remainder */
5143 tm->tm_year = (tm->tm_year / 1000) * 1000;
5144 /* FALL THRU */
5145 case DTK_CENTURY:
5146 /* caution: C division may have negative remainder */
5147 tm->tm_year = (tm->tm_year / 100) * 100;
5148 /* FALL THRU */
5149 case DTK_DECADE:
5150 /* caution: C division may have negative remainder */
5151 tm->tm_year = (tm->tm_year / 10) * 10;
5152 /* FALL THRU */
5153 case DTK_YEAR:
5154 tm->tm_mon = 0;
5155 /* FALL THRU */
5156 case DTK_QUARTER:
5157 tm->tm_mon = 3 * (tm->tm_mon / 3);
5158 /* FALL THRU */
5159 case DTK_MONTH:
5160 tm->tm_mday = 0;
5161 /* FALL THRU */
5162 case DTK_DAY:
5163 tm->tm_hour = 0;
5164 /* FALL THRU */
5165 case DTK_HOUR:
5166 tm->tm_min = 0;
5167 /* FALL THRU */
5168 case DTK_MINUTE:
5169 tm->tm_sec = 0;
5170 /* FALL THRU */
5171 case DTK_SECOND:
5172 tm->tm_usec = 0;
5173 break;
5174 case DTK_MILLISEC:
5175 tm->tm_usec = (tm->tm_usec / 1000) * 1000;
5176 break;
5177 case DTK_MICROSEC:
5178 break;
5179
5180 default:
5181 ereport(ERROR,
5182 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5183 errmsg("unit \"%s\" not supported for type %s",
5184 lowunits, format_type_be(INTERVALOID)),
5185 (val == DTK_WEEK) ? errdetail("Months usually have fractional weeks.") : 0));
5186 }
5187
5188 if (itm2interval(tm, result) != 0)
5189 ereport(ERROR,
5190 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5191 errmsg("interval out of range")));
5192 }
5193 else
5194 {
5195 ereport(ERROR,
5196 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5197 errmsg("unit \"%s\" not recognized for type %s",
5198 lowunits, format_type_be(INTERVALOID))));
5199 }
5200
5201 PG_RETURN_INTERVAL_P(result);
5202}
5203
5204/* isoweek2j()
5205 *
5206 * Return the Julian day which corresponds to the first day (Monday) of the given ISO 8601 year and week.
5207 * Julian days are used to convert between ISO week dates and Gregorian dates.
5208 *
5209 * XXX: This function has integer overflow hazards, but restructuring it to
5210 * work with the soft-error handling that its callers do is likely more
5211 * trouble than it's worth.
5212 */
5213int
5214isoweek2j(int year, int week)
5215{
5216 int day0,
5217 day4;
5218
5219 /* fourth day of current year */
5220 day4 = date2j(year, 1, 4);
5221
5222 /* day0 == offset to first day of week (Monday) */
5223 day0 = j2day(day4 - 1);
5224
5225 return ((week - 1) * 7) + (day4 - day0);
5226}
5227
5228/* isoweek2date()
5229 * Convert ISO week of year number to date.
5230 * The year field must be specified with the ISO year!
5231 * karel 2000/08/07
5232 */
5233void
5234isoweek2date(int woy, int *year, int *mon, int *mday)
5235{
5236 j2date(isoweek2j(*year, woy), year, mon, mday);
5237}
5238
5239/* isoweekdate2date()
5240 *
5241 * Convert an ISO 8601 week date (ISO year, ISO week) into a Gregorian date.
5242 * Gregorian day of week sent so weekday strings can be supplied.
5243 * Populates year, mon, and mday with the correct Gregorian values.
5244 * year must be passed in as the ISO year.
5245 */
5246void
5247isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
5248{
5249 int jday;
5250
5251 jday = isoweek2j(*year, isoweek);
5252 /* convert Gregorian week start (Sunday=1) to ISO week start (Monday=1) */
5253 if (wday > 1)
5254 jday += wday - 2;
5255 else
5256 jday += 6;
5257 j2date(jday, year, mon, mday);
5258}
5259
5260/* date2isoweek()
5261 *
5262 * Returns ISO week number of year.
5263 */
5264int
5265date2isoweek(int year, int mon, int mday)
5266{
5267 float8 result;
5268 int day0,
5269 day4,
5270 dayn;
5271
5272 /* current day */
5273 dayn = date2j(year, mon, mday);
5274
5275 /* fourth day of current year */
5276 day4 = date2j(year, 1, 4);
5277
5278 /* day0 == offset to first day of week (Monday) */
5279 day0 = j2day(day4 - 1);
5280
5281 /*
5282 * We need the first week containing a Thursday, otherwise this day falls
5283 * into the previous year for purposes of counting weeks
5284 */
5285 if (dayn < day4 - day0)
5286 {
5287 day4 = date2j(year - 1, 1, 4);
5288
5289 /* day0 == offset to first day of week (Monday) */
5290 day0 = j2day(day4 - 1);
5291 }
5292
5293 result = (dayn - (day4 - day0)) / 7 + 1;
5294
5295 /*
5296 * Sometimes the last few days in a year will fall into the first week of
5297 * the next year, so check for this.
5298 */
5299 if (result >= 52)
5300 {
5301 day4 = date2j(year + 1, 1, 4);
5302
5303 /* day0 == offset to first day of week (Monday) */
5304 day0 = j2day(day4 - 1);
5305
5306 if (dayn >= day4 - day0)
5307 result = (dayn - (day4 - day0)) / 7 + 1;
5308 }
5309
5310 return (int) result;
5311}
5312
5313
5314/* date2isoyear()
5315 *
5316 * Returns ISO 8601 year number.
5317 * Note: zero or negative results follow the year-zero-exists convention.
5318 */
5319int
5320date2isoyear(int year, int mon, int mday)
5321{
5322 float8 result;
5323 int day0,
5324 day4,
5325 dayn;
5326
5327 /* current day */
5328 dayn = date2j(year, mon, mday);
5329
5330 /* fourth day of current year */
5331 day4 = date2j(year, 1, 4);
5332
5333 /* day0 == offset to first day of week (Monday) */
5334 day0 = j2day(day4 - 1);
5335
5336 /*
5337 * We need the first week containing a Thursday, otherwise this day falls
5338 * into the previous year for purposes of counting weeks
5339 */
5340 if (dayn < day4 - day0)
5341 {
5342 day4 = date2j(year - 1, 1, 4);
5343
5344 /* day0 == offset to first day of week (Monday) */
5345 day0 = j2day(day4 - 1);
5346
5347 year--;
5348 }
5349
5350 result = (dayn - (day4 - day0)) / 7 + 1;
5351
5352 /*
5353 * Sometimes the last few days in a year will fall into the first week of
5354 * the next year, so check for this.
5355 */
5356 if (result >= 52)
5357 {
5358 day4 = date2j(year + 1, 1, 4);
5359
5360 /* day0 == offset to first day of week (Monday) */
5361 day0 = j2day(day4 - 1);
5362
5363 if (dayn >= day4 - day0)
5364 year++;
5365 }
5366
5367 return year;
5368}
5369
5370
5371/* date2isoyearday()
5372 *
5373 * Returns the ISO 8601 day-of-year, given a Gregorian year, month and day.
5374 * Possible return values are 1 through 371 (364 in non-leap years).
5375 */
5376int
5377date2isoyearday(int year, int mon, int mday)
5378{
5379 return date2j(year, mon, mday) - isoweek2j(date2isoyear(year, mon, mday), 1) + 1;
5380}
5381
5382/*
5383 * NonFiniteTimestampTzPart
5384 *
5385 * Used by timestamp_part and timestamptz_part when extracting from infinite
5386 * timestamp[tz]. Returns +/-Infinity if that is the appropriate result,
5387 * otherwise returns zero (which should be taken as meaning to return NULL).
5388 *
5389 * Errors thrown here for invalid units should exactly match those that
5390 * would be thrown in the calling functions, else there will be unexpected
5391 * discrepancies between finite- and infinite-input cases.
5392 */
5393static float8
5394NonFiniteTimestampTzPart(int type, int unit, char *lowunits,
5395 bool isNegative, bool isTz)
5396{
5397 if ((type != UNITS) && (type != RESERV))
5398 ereport(ERROR,
5399 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5400 errmsg("unit \"%s\" not recognized for type %s",
5401 lowunits,
5402 format_type_be(isTz ? TIMESTAMPTZOID : TIMESTAMPOID))));
5403
5404 switch (unit)
5405 {
5406 /* Oscillating units */
5407 case DTK_MICROSEC:
5408 case DTK_MILLISEC:
5409 case DTK_SECOND:
5410 case DTK_MINUTE:
5411 case DTK_HOUR:
5412 case DTK_DAY:
5413 case DTK_MONTH:
5414 case DTK_QUARTER:
5415 case DTK_WEEK:
5416 case DTK_DOW:
5417 case DTK_ISODOW:
5418 case DTK_DOY:
5419 case DTK_TZ:
5420 case DTK_TZ_MINUTE:
5421 case DTK_TZ_HOUR:
5422 return 0.0;
5423
5424 /* Monotonically-increasing units */
5425 case DTK_YEAR:
5426 case DTK_DECADE:
5427 case DTK_CENTURY:
5428 case DTK_MILLENNIUM:
5429 case DTK_JULIAN:
5430 case DTK_ISOYEAR:
5431 case DTK_EPOCH:
5432 if (isNegative)
5433 return -get_float8_infinity();
5434 else
5435 return get_float8_infinity();
5436
5437 default:
5438 ereport(ERROR,
5439 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5440 errmsg("unit \"%s\" not supported for type %s",
5441 lowunits,
5442 format_type_be(isTz ? TIMESTAMPTZOID : TIMESTAMPOID))));
5443 return 0.0; /* keep compiler quiet */
5444 }
5445}
5446
5447/* timestamp_part() and extract_timestamp()
5448 * Extract specified field from timestamp.
5449 */
5450static Datum
5452{
5453 text *units = PG_GETARG_TEXT_PP(0);
5455 int64 intresult;
5457 int type,
5458 val;
5459 char *lowunits;
5460 fsec_t fsec;
5461 struct pg_tm tt,
5462 *tm = &tt;
5463
5464 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
5465 VARSIZE_ANY_EXHDR(units),
5466 false);
5467
5468 type = DecodeUnits(0, lowunits, &val);
5469 if (type == UNKNOWN_FIELD)
5470 type = DecodeSpecial(0, lowunits, &val);
5471
5473 {
5474 double r = NonFiniteTimestampTzPart(type, val, lowunits,
5476 false);
5477
5478 if (r != 0.0)
5479 {
5480 if (retnumeric)
5481 {
5482 if (r < 0)
5484 CStringGetDatum("-Infinity"),
5486 Int32GetDatum(-1));
5487 else if (r > 0)
5489 CStringGetDatum("Infinity"),
5491 Int32GetDatum(-1));
5492 }
5493 else
5495 }
5496 else
5498 }
5499
5500 if (type == UNITS)
5501 {
5502 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
5503 ereport(ERROR,
5504 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5505 errmsg("timestamp out of range")));
5506
5507 switch (val)
5508 {
5509 case DTK_MICROSEC:
5510 intresult = tm->tm_sec * INT64CONST(1000000) + fsec;
5511 break;
5512
5513 case DTK_MILLISEC:
5514 if (retnumeric)
5515 /*---
5516 * tm->tm_sec * 1000 + fsec / 1000
5517 * = (tm->tm_sec * 1'000'000 + fsec) / 1000
5518 */
5520 else
5521 PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + fsec / 1000.0);
5522 break;
5523
5524 case DTK_SECOND:
5525 if (retnumeric)
5526 /*---
5527 * tm->tm_sec + fsec / 1'000'000
5528 * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
5529 */
5531 else
5532 PG_RETURN_FLOAT8(tm->tm_sec + fsec / 1000000.0);
5533 break;
5534
5535 case DTK_MINUTE:
5536 intresult = tm->tm_min;
5537 break;
5538
5539 case DTK_HOUR:
5540 intresult = tm->tm_hour;
5541 break;
5542
5543 case DTK_DAY:
5544 intresult = tm->tm_mday;
5545 break;
5546
5547 case DTK_MONTH:
5548 intresult = tm->tm_mon;
5549 break;
5550
5551 case DTK_QUARTER:
5552 intresult = (tm->tm_mon - 1) / 3 + 1;
5553 break;
5554
5555 case DTK_WEEK:
5556 intresult = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
5557 break;
5558
5559 case DTK_YEAR:
5560 if (tm->tm_year > 0)
5561 intresult = tm->tm_year;
5562 else
5563 /* there is no year 0, just 1 BC and 1 AD */
5564 intresult = tm->tm_year - 1;
5565 break;
5566
5567 case DTK_DECADE:
5568
5569 /*
5570 * what is a decade wrt dates? let us assume that decade 199
5571 * is 1990 thru 1999... decade 0 starts on year 1 BC, and -1
5572 * is 11 BC thru 2 BC...
5573 */
5574 if (tm->tm_year >= 0)
5575 intresult = tm->tm_year / 10;
5576 else
5577 intresult = -((8 - (tm->tm_year - 1)) / 10);
5578 break;
5579
5580 case DTK_CENTURY:
5581
5582 /* ----
5583 * centuries AD, c>0: year in [ (c-1)* 100 + 1 : c*100 ]
5584 * centuries BC, c<0: year in [ c*100 : (c+1) * 100 - 1]
5585 * there is no number 0 century.
5586 * ----
5587 */
5588 if (tm->tm_year > 0)
5589 intresult = (tm->tm_year + 99) / 100;
5590 else
5591 /* caution: C division may have negative remainder */
5592 intresult = -((99 - (tm->tm_year - 1)) / 100);
5593 break;
5594
5595 case DTK_MILLENNIUM:
5596 /* see comments above. */
5597 if (tm->tm_year > 0)
5598 intresult = (tm->tm_year + 999) / 1000;
5599 else
5600 intresult = -((999 - (tm->tm_year - 1)) / 1000);
5601 break;
5602
5603 case DTK_JULIAN:
5604 if (retnumeric)
5608 NULL),
5609 NULL));
5610 else
5613 tm->tm_sec + (fsec / 1000000.0)) / (double) SECS_PER_DAY);
5614 break;
5615
5616 case DTK_ISOYEAR:
5617 intresult = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
5618 /* Adjust BC years */
5619 if (intresult <= 0)
5620 intresult -= 1;
5621 break;
5622
5623 case DTK_DOW:
5624 case DTK_ISODOW:
5625 intresult = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
5626 if (val == DTK_ISODOW && intresult == 0)
5627 intresult = 7;
5628 break;
5629
5630 case DTK_DOY:
5631 intresult = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
5632 - date2j(tm->tm_year, 1, 1) + 1);
5633 break;
5634
5635 case DTK_TZ:
5636 case DTK_TZ_MINUTE:
5637 case DTK_TZ_HOUR:
5638 default:
5639 ereport(ERROR,
5640 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5641 errmsg("unit \"%s\" not supported for type %s",
5642 lowunits, format_type_be(TIMESTAMPOID))));
5643 intresult = 0;
5644 }
5645 }
5646 else if (type == RESERV)
5647 {
5648 switch (val)
5649 {
5650 case DTK_EPOCH:
5652 /* (timestamp - epoch) / 1000000 */
5653 if (retnumeric)
5654 {
5655 Numeric result;
5656
5657 if (timestamp < (PG_INT64_MAX + epoch))
5659 else
5660 {
5663 NULL),
5664 int64_to_numeric(1000000),
5665 NULL);
5667 NumericGetDatum(result),
5668 Int32GetDatum(6)));
5669 }
5670 PG_RETURN_NUMERIC(result);
5671 }
5672 else
5673 {
5674 float8 result;
5675
5676 /* try to avoid precision loss in subtraction */
5677 if (timestamp < (PG_INT64_MAX + epoch))
5678 result = (timestamp - epoch) / 1000000.0;
5679 else
5680 result = ((float8) timestamp - epoch) / 1000000.0;
5681 PG_RETURN_FLOAT8(result);
5682 }
5683 break;
5684
5685 default:
5686 ereport(ERROR,
5687 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5688 errmsg("unit \"%s\" not supported for type %s",
5689 lowunits, format_type_be(TIMESTAMPOID))));
5690 intresult = 0;
5691 }
5692 }
5693 else
5694 {
5695 ereport(ERROR,
5696 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5697 errmsg("unit \"%s\" not recognized for type %s",
5698 lowunits, format_type_be(TIMESTAMPOID))));
5699 intresult = 0;
5700 }
5701
5702 if (retnumeric)
5704 else
5705 PG_RETURN_FLOAT8(intresult);
5706}
5707
5708Datum
5710{
5711 return timestamp_part_common(fcinfo, false);
5712}
5713
5714Datum
5716{
5717 return timestamp_part_common(fcinfo, true);
5718}
5719
5720/* timestamptz_part() and extract_timestamptz()
5721 * Extract specified field from timestamp with time zone.
5722 */
5723static Datum
5725{
5726 text *units = PG_GETARG_TEXT_PP(0);
5728 int64 intresult;
5730 int tz;
5731 int type,
5732 val;
5733 char *lowunits;
5734 fsec_t fsec;
5735 struct pg_tm tt,
5736 *tm = &tt;
5737
5738 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
5739 VARSIZE_ANY_EXHDR(units),
5740 false);
5741
5742 type = DecodeUnits(0, lowunits, &val);
5743 if (type == UNKNOWN_FIELD)
5744 type = DecodeSpecial(0, lowunits, &val);
5745
5747 {
5748 double r = NonFiniteTimestampTzPart(type, val, lowunits,
5750 true);
5751
5752 if (r != 0.0)
5753 {
5754 if (retnumeric)
5755 {
5756 if (r < 0)
5758 CStringGetDatum("-Infinity"),
5760 Int32GetDatum(-1));
5761 else if (r > 0)
5763 CStringGetDatum("Infinity"),
5765 Int32GetDatum(-1));
5766 }
5767 else
5769 }
5770 else
5772 }
5773
5774 if (type == UNITS)
5775 {
5776 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
5777 ereport(ERROR,
5778 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5779 errmsg("timestamp out of range")));
5780
5781 switch (val)
5782 {
5783 case DTK_TZ:
5784 intresult = -tz;
5785 break;
5786
5787 case DTK_TZ_MINUTE:
5788 intresult = (-tz / SECS_PER_MINUTE) % MINS_PER_HOUR;
5789 break;
5790
5791 case DTK_TZ_HOUR:
5792 intresult = -tz / SECS_PER_HOUR;
5793 break;
5794
5795 case DTK_MICROSEC:
5796 intresult = tm->tm_sec * INT64CONST(1000000) + fsec;
5797 break;
5798
5799 case DTK_MILLISEC:
5800 if (retnumeric)
5801 /*---
5802 * tm->tm_sec * 1000 + fsec / 1000
5803 * = (tm->tm_sec * 1'000'000 + fsec) / 1000
5804 */
5806 else
5807 PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + fsec / 1000.0);
5808 break;
5809
5810 case DTK_SECOND:
5811 if (retnumeric)
5812 /*---
5813 * tm->tm_sec + fsec / 1'000'000
5814 * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
5815 */
5817 else
5818 PG_RETURN_FLOAT8(tm->tm_sec + fsec / 1000000.0);
5819 break;
5820
5821 case DTK_MINUTE:
5822 intresult = tm->tm_min;
5823 break;
5824
5825 case DTK_HOUR:
5826 intresult = tm->tm_hour;
5827 break;
5828
5829 case DTK_DAY:
5830 intresult = tm->tm_mday;
5831 break;
5832
5833 case DTK_MONTH:
5834 intresult = tm->tm_mon;
5835 break;
5836
5837 case DTK_QUARTER:
5838 intresult = (tm->tm_mon - 1) / 3 + 1;
5839 break;
5840
5841 case DTK_WEEK:
5842 intresult = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
5843 break;
5844
5845 case DTK_YEAR:
5846 if (tm->tm_year > 0)
5847 intresult = tm->tm_year;
5848 else
5849 /* there is no year 0, just 1 BC and 1 AD */
5850 intresult = tm->tm_year - 1;
5851 break;
5852
5853 case DTK_DECADE:
5854 /* see comments in timestamp_part */
5855 if (tm->tm_year > 0)
5856 intresult = tm->tm_year / 10;
5857 else
5858 intresult = -((8 - (tm->tm_year - 1)) / 10);
5859 break;
5860
5861 case DTK_CENTURY:
5862 /* see comments in timestamp_part */
5863 if (tm->tm_year > 0)
5864 intresult = (tm->tm_year + 99) / 100;
5865 else
5866 intresult = -((99 - (tm->tm_year - 1)) / 100);
5867 break;
5868
5869 case DTK_MILLENNIUM:
5870 /* see comments in timestamp_part */
5871 if (tm->tm_year > 0)
5872 intresult = (tm->tm_year + 999) / 1000;
5873 else
5874 intresult = -((999 - (tm->tm_year - 1)) / 1000);
5875 break;
5876
5877 case DTK_JULIAN:
5878 if (retnumeric)
5882 NULL),
5883 NULL));
5884 else
5887 tm->tm_sec + (fsec / 1000000.0)) / (double) SECS_PER_DAY);
5888 break;
5889
5890 case DTK_ISOYEAR:
5891 intresult = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
5892 /* Adjust BC years */
5893 if (intresult <= 0)
5894 intresult -= 1;
5895 break;
5896
5897 case DTK_DOW:
5898 case DTK_ISODOW:
5899 intresult = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
5900 if (val == DTK_ISODOW && intresult == 0)
5901 intresult = 7;
5902 break;
5903
5904 case DTK_DOY:
5905 intresult = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
5906 - date2j(tm->tm_year, 1, 1) + 1);
5907 break;
5908
5909 default:
5910 ereport(ERROR,
5911 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5912 errmsg("unit \"%s\" not supported for type %s",
5913 lowunits, format_type_be(TIMESTAMPTZOID))));
5914 intresult = 0;
5915 }
5916 }
5917 else if (type == RESERV)
5918 {
5919 switch (val)
5920 {
5921 case DTK_EPOCH:
5923 /* (timestamp - epoch) / 1000000 */
5924 if (retnumeric)
5925 {
5926 Numeric result;
5927
5928 if (timestamp < (PG_INT64_MAX + epoch))
5930 else
5931 {
5934 NULL),
5935 int64_to_numeric(1000000),
5936 NULL);
5938 NumericGetDatum(result),
5939 Int32GetDatum(6)));
5940 }
5941 PG_RETURN_NUMERIC(result);
5942 }
5943 else
5944 {
5945 float8 result;
5946
5947 /* try to avoid precision loss in subtraction */
5948 if (timestamp < (PG_INT64_MAX + epoch))
5949 result = (timestamp - epoch) / 1000000.0;
5950 else
5951 result = ((float8) timestamp - epoch) / 1000000.0;
5952 PG_RETURN_FLOAT8(result);
5953 }
5954 break;
5955
5956 default:
5957 ereport(ERROR,
5958 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5959 errmsg("unit \"%s\" not supported for type %s",
5960 lowunits, format_type_be(TIMESTAMPTZOID))));
5961 intresult = 0;
5962 }
5963 }
5964 else
5965 {
5966 ereport(ERROR,
5967 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5968 errmsg("unit \"%s\" not recognized for type %s",
5969 lowunits, format_type_be(TIMESTAMPTZOID))));
5970
5971 intresult = 0;
5972 }
5973
5974 if (retnumeric)
5976 else
5977 PG_RETURN_FLOAT8(intresult);
5978}
5979
5980Datum
5982{
5983 return timestamptz_part_common(fcinfo, false);
5984}
5985
5986Datum
5988{
5989 return timestamptz_part_common(fcinfo, true);
5990}
5991
5992/*
5993 * NonFiniteIntervalPart
5994 *
5995 * Used by interval_part when extracting from infinite interval. Returns
5996 * +/-Infinity if that is the appropriate result, otherwise returns zero
5997 * (which should be taken as meaning to return NULL).
5998 *
5999 * Errors thrown here for invalid units should exactly match those that
6000 * would be thrown in the calling functions, else there will be unexpected
6001 * discrepancies between finite- and infinite-input cases.
6002 */
6003static float8
6004NonFiniteIntervalPart(int type, int unit, char *lowunits, bool isNegative)
6005{
6006 if ((type != UNITS) && (type != RESERV))
6007 ereport(ERROR,
6008 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6009 errmsg("unit \"%s\" not recognized for type %s",
6010 lowunits, format_type_be(INTERVALOID))));
6011
6012 switch (unit)
6013 {
6014 /* Oscillating units */
6015 case DTK_MICROSEC:
6016 case DTK_MILLISEC:
6017 case DTK_SECOND:
6018 case DTK_MINUTE:
6019 case DTK_WEEK:
6020 case DTK_MONTH:
6021 case DTK_QUARTER:
6022 return 0.0;
6023
6024 /* Monotonically-increasing units */
6025 case DTK_HOUR:
6026 case DTK_DAY:
6027 case DTK_YEAR:
6028 case DTK_DECADE:
6029 case DTK_CENTURY:
6030 case DTK_MILLENNIUM:
6031 case DTK_EPOCH:
6032 if (isNegative)
6033 return -get_float8_infinity();
6034 else
6035 return get_float8_infinity();
6036
6037 default:
6038 ereport(ERROR,
6039 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6040 errmsg("unit \"%s\" not supported for type %s",
6041 lowunits, format_type_be(INTERVALOID))));
6042 return 0.0; /* keep compiler quiet */
6043 }
6044}
6045
6046/* interval_part() and extract_interval()
6047 * Extract specified field from interval.
6048 */
6049static Datum
6051{
6052 text *units = PG_GETARG_TEXT_PP(0);
6054 int64 intresult;
6055 int type,
6056 val;
6057 char *lowunits;
6058 struct pg_itm tt,
6059 *tm = &tt;
6060
6061 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
6062 VARSIZE_ANY_EXHDR(units),
6063 false);
6064
6065 type = DecodeUnits(0, lowunits, &val);
6066 if (type == UNKNOWN_FIELD)
6067 type = DecodeSpecial(0, lowunits, &val);
6068
6070 {
6071 double r = NonFiniteIntervalPart(type, val, lowunits,
6073
6074 if (r != 0.0)
6075 {
6076 if (retnumeric)
6077 {
6078 if (r < 0)
6080 CStringGetDatum("-Infinity"),
6082 Int32GetDatum(-1));
6083 else if (r > 0)
6085 CStringGetDatum("Infinity"),
6087 Int32GetDatum(-1));
6088 }
6089 else
6091 }
6092 else
6094 }
6095
6096 if (type == UNITS)
6097 {
6099 switch (val)
6100 {
6101 case DTK_MICROSEC:
6102 intresult = tm->tm_sec * INT64CONST(1000000) + tm->tm_usec;
6103 break;
6104
6105 case DTK_MILLISEC:
6106 if (retnumeric)
6107 /*---
6108 * tm->tm_sec * 1000 + fsec / 1000
6109 * = (tm->tm_sec * 1'000'000 + fsec) / 1000
6110 */
6112 else
6113 PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + tm->tm_usec / 1000.0);
6114 break;
6115
6116 case DTK_SECOND:
6117 if (retnumeric)
6118 /*---
6119 * tm->tm_sec + fsec / 1'000'000
6120 * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
6121 */
6123 else
6124 PG_RETURN_FLOAT8(tm->tm_sec + tm->tm_usec / 1000000.0);
6125 break;
6126
6127 case DTK_MINUTE:
6128 intresult = tm->tm_min;
6129 break;
6130
6131 case DTK_HOUR:
6132 intresult = tm->tm_hour;
6133 break;
6134
6135 case DTK_DAY:
6136 intresult = tm->tm_mday;
6137 break;
6138
6139 case DTK_WEEK:
6140 intresult = tm->tm_mday / 7;
6141 break;
6142
6143 case DTK_MONTH:
6144 intresult = tm->tm_mon;
6145 break;
6146
6147 case DTK_QUARTER:
6148
6149 /*
6150 * We want to maintain the rule that a field extracted from a
6151 * negative interval is the negative of the field's value for
6152 * the sign-reversed interval. The broken-down tm_year and
6153 * tm_mon aren't very helpful for that, so work from
6154 * interval->month.
6155 */
6156 if (interval->month >= 0)
6157 intresult = (tm->tm_mon / 3) + 1;
6158 else
6159 intresult = -(((-interval->month % MONTHS_PER_YEAR) / 3) + 1);
6160 break;
6161
6162 case DTK_YEAR:
6163 intresult = tm->tm_year;
6164 break;
6165
6166 case DTK_DECADE:
6167 /* caution: C division may have negative remainder */
6168 intresult = tm->tm_year / 10;
6169 break;
6170
6171 case DTK_CENTURY:
6172 /* caution: C division may have negative remainder */
6173 intresult = tm->tm_year / 100;
6174 break;
6175
6176 case DTK_MILLENNIUM:
6177 /* caution: C division may have negative remainder */
6178 intresult = tm->tm_year / 1000;
6179 break;
6180
6181 default:
6182 ereport(ERROR,
6183 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6184 errmsg("unit \"%s\" not supported for type %s",
6185 lowunits, format_type_be(INTERVALOID))));
6186 intresult = 0;
6187 }
6188 }
6189 else if (type == RESERV && val == DTK_EPOCH)
6190 {
6191 if (retnumeric)
6192 {
6193 Numeric result;
6194 int64 secs_from_day_month;
6195 int64 val;
6196
6197 /*
6198 * To do this calculation in integer arithmetic even though
6199 * DAYS_PER_YEAR is fractional, multiply everything by 4 and then
6200 * divide by 4 again at the end. This relies on DAYS_PER_YEAR
6201 * being a multiple of 0.25 and on SECS_PER_DAY being a multiple
6202 * of 4.
6203 */
6204 secs_from_day_month = ((int64) (4 * DAYS_PER_YEAR) * (interval->month / MONTHS_PER_YEAR) +
6206 (int64) 4 * interval->day) * (SECS_PER_DAY / 4);
6207
6208 /*---
6209 * result = secs_from_day_month + interval->time / 1'000'000
6210 * = (secs_from_day_month * 1'000'000 + interval->time) / 1'000'000
6211 */
6212
6213 /*
6214 * Try the computation inside int64; if it overflows, do it in
6215 * numeric (slower). This overflow happens around 10^9 days, so
6216 * not common in practice.
6217 */
6218 if (!pg_mul_s64_overflow(secs_from_day_month, 1000000, &val) &&
6220 result = int64_div_fast_to_numeric(val, 6);
6221 else
6222 result =
6224 int64_to_numeric(secs_from_day_month),
6225 NULL);
6226
6227 PG_RETURN_NUMERIC(result);
6228 }
6229 else
6230 {
6231 float8 result;
6232
6233 result = interval->time / 1000000.0;
6234 result += ((double) DAYS_PER_YEAR * SECS_PER_DAY) * (interval->month / MONTHS_PER_YEAR);
6235 result += ((double) DAYS_PER_MONTH * SECS_PER_DAY) * (interval->month % MONTHS_PER_YEAR);
6236 result += ((double) SECS_PER_DAY) * interval->day;
6237
6238 PG_RETURN_FLOAT8(result);
6239 }
6240 }
6241 else
6242 {
6243 ereport(ERROR,
6244 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6245 errmsg("unit \"%s\" not recognized for type %s",
6246 lowunits, format_type_be(INTERVALOID))));
6247 intresult = 0;
6248 }
6249
6250 if (retnumeric)
6252 else
6253 PG_RETURN_FLOAT8(intresult);
6254}
6255
6256Datum
6258{
6259 return interval_part_common(fcinfo, false);
6260}
6261
6262Datum
6264{
6265 return interval_part_common(fcinfo, true);
6266}
6267
6268
6269/* timestamp_zone()
6270 * Encode timestamp type with specified time zone.
6271 * This function is just timestamp2timestamptz() except instead of
6272 * shifting to the global timezone, we shift to the specified timezone.
6273 * This is different from the other AT TIME ZONE cases because instead
6274 * of shifting _to_ a new time zone, it sets the time to _be_ the
6275 * specified timezone.
6276 */
6277Datum
6279{
6282 TimestampTz result;
6283 int tz;
6284 char tzname[TZ_STRLEN_MAX + 1];
6285 int type,
6286 val;
6287 pg_tz *tzp;
6288 struct pg_tm tm;
6289 fsec_t fsec;
6290
6293
6294 /*
6295 * Look up the requested timezone.
6296 */
6297 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
6298
6299 type = DecodeTimezoneName(tzname, &val, &tzp);
6300
6302 {
6303 /* fixed-offset abbreviation */
6304 tz = val;
6305 result = dt2local(timestamp, tz);
6306 }
6307 else if (type == TZNAME_DYNTZ)
6308 {
6309 /* dynamic-offset abbreviation, resolve using specified time */
6310 if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, tzp) != 0)
6311 ereport(ERROR,
6312 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6313 errmsg("timestamp out of range")));
6314 tz = -DetermineTimeZoneAbbrevOffset(&tm, tzname, tzp);
6315 result = dt2local(timestamp, tz);
6316 }
6317 else
6318 {
6319 /* full zone name, rotate to that zone */
6320 if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, tzp) != 0)
6321 ereport(ERROR,
6322 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6323 errmsg("timestamp out of range")));
6324 tz = DetermineTimeZoneOffset(&tm, tzp);
6325 if (tm2timestamp(&tm, fsec, &tz, &result) != 0)
6326 ereport(ERROR,
6327 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6328 errmsg("timestamp out of range")));
6329 }
6330
6331 if (!IS_VALID_TIMESTAMP(result))
6332 ereport(ERROR,
6333 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6334 errmsg("timestamp out of range")));
6335
6336 PG_RETURN_TIMESTAMPTZ(result);
6337}
6338
6339/* timestamp_izone()
6340 * Encode timestamp type with specified time interval as time zone.
6341 */
6342Datum
6344{
6347 TimestampTz result;
6348 int tz;
6349
6352
6354 ereport(ERROR,
6355 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6356 errmsg("interval time zone \"%s\" must be finite",
6358 PointerGetDatum(zone))))));
6359
6360 if (zone->month != 0 || zone->day != 0)
6361 ereport(ERROR,
6362 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6363 errmsg("interval time zone \"%s\" must not include months or days",
6365 PointerGetDatum(zone))))));
6366
6367 tz = zone->time / USECS_PER_SEC;
6368
6369 result = dt2local(timestamp, tz);
6370
6371 if (!IS_VALID_TIMESTAMP(result))
6372 ereport(ERROR,
6373 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6374 errmsg("timestamp out of range")));
6375
6376 PG_RETURN_TIMESTAMPTZ(result);
6377} /* timestamp_izone() */
6378
6379/* TimestampTimestampTzRequiresRewrite()
6380 *
6381 * Returns false if the TimeZone GUC setting causes timestamp_timestamptz and
6382 * timestamptz_timestamp to be no-ops, where the return value has the same
6383 * bits as the argument. Since project convention is to assume a GUC changes
6384 * no more often than STABLE functions change, the answer is valid that long.
6385 */
6386bool
6388{
6389 long offset;
6390
6391 if (pg_get_timezone_offset(session_timezone, &offset) && offset == 0)
6392 return false;
6393 return true;
6394}
6395
6396/* timestamp_timestamptz()
6397 * Convert local timestamp to timestamp at GMT
6398 */
6399Datum
6401{
6403
6405}
6406
6407/*
6408 * Convert timestamp to timestamp with time zone.
6409 *
6410 * On successful conversion, *overflow is set to zero if it's not NULL.
6411 *
6412 * If the timestamp is finite but out of the valid range for timestamptz, then:
6413 * if overflow is NULL, we throw an out-of-range error.
6414 * if overflow is not NULL, we store +1 or -1 there to indicate the sign
6415 * of the overflow, and return the appropriate timestamptz infinity.
6416 */
6419{
6420 TimestampTz result;
6421 struct pg_tm tt,
6422 *tm = &tt;
6423 fsec_t fsec;
6424 int tz;
6425
6426 if (overflow)
6427 *overflow = 0;
6428
6430 return timestamp;
6431
6432 /* We don't expect this to fail, but check it pro forma */
6433 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
6434 {
6436
6437 result = dt2local(timestamp, -tz);
6438
6439 if (IS_VALID_TIMESTAMP(result))
6440 {
6441 return result;
6442 }
6443 else if (overflow)
6444 {
6445 if (result < MIN_TIMESTAMP)
6446 {
6447 *overflow = -1;
6448 TIMESTAMP_NOBEGIN(result);
6449 }
6450 else
6451 {
6452 *overflow = 1;
6453 TIMESTAMP_NOEND(result);
6454 }
6455 return result;
6456 }
6457 }
6458
6459 ereport(ERROR,
6460 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6461 errmsg("timestamp out of range")));
6462
6463 return 0;
6464}
6465
6466/*
6467 * Promote timestamp to timestamptz, throwing error for overflow.
6468 */
6469static TimestampTz
6471{
6473}
6474
6475/* timestamptz_timestamp()
6476 * Convert timestamp at GMT to local timestamp
6477 */
6478Datum
6480{
6482
6484}
6485
6486static Timestamp
6488{
6489 Timestamp result;
6490 struct pg_tm tt,
6491 *tm = &tt;
6492 fsec_t fsec;
6493 int tz;
6494
6496 result = timestamp;
6497 else
6498 {
6499 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
6500 ereport(ERROR,
6501 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6502 errmsg("timestamp out of range")));
6503 if (tm2timestamp(tm, fsec, NULL, &result) != 0)
6504 ereport(ERROR,
6505 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6506 errmsg("timestamp out of range")));
6507 }
6508 return result;
6509}
6510
6511/* timestamptz_zone()
6512 * Evaluate timestamp with time zone type at the specified time zone.
6513 * Returns a timestamp without time zone.
6514 */
6515Datum
6517{
6520 Timestamp result;
6521 int tz;
6522 char tzname[TZ_STRLEN_MAX + 1];
6523 int type,
6524 val;
6525 pg_tz *tzp;
6526
6529
6530 /*
6531 * Look up the requested timezone.
6532 */
6533 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
6534
6535 type = DecodeTimezoneName(tzname, &val, &tzp);
6536
6538 {
6539 /* fixed-offset abbreviation */
6540 tz = -val;
6541 result = dt2local(timestamp, tz);
6542 }
6543 else if (type == TZNAME_DYNTZ)
6544 {
6545 /* dynamic-offset abbreviation, resolve using specified time */
6546 int isdst;
6547
6548 tz = DetermineTimeZoneAbbrevOffsetTS(timestamp, tzname, tzp, &isdst);
6549 result = dt2local(timestamp, tz);
6550 }
6551 else
6552 {
6553 /* full zone name, rotate from that zone */
6554 struct pg_tm tm;
6555 fsec_t fsec;
6556
6557 if (timestamp2tm(timestamp, &tz, &tm, &fsec, NULL, tzp) != 0)
6558 ereport(ERROR,
6559 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6560 errmsg("timestamp out of range")));
6561 if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
6562 ereport(ERROR,
6563 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6564 errmsg("timestamp out of range")));
6565 }
6566
6567 if (!IS_VALID_TIMESTAMP(result))
6568 ereport(ERROR,
6569 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6570 errmsg("timestamp out of range")));
6571
6572 PG_RETURN_TIMESTAMP(result);
6573}
6574
6575/* timestamptz_izone()
6576 * Encode timestamp with time zone type with specified time interval as time zone.
6577 * Returns a timestamp without time zone.
6578 */
6579Datum
6581{
6584 Timestamp result;
6585 int tz;
6586
6589
6591 ereport(ERROR,
6592 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6593 errmsg("interval time zone \"%s\" must be finite",
6595 PointerGetDatum(zone))))));
6596
6597 if (zone->month != 0 || zone->day != 0)
6598 ereport(ERROR,
6599 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6600 errmsg("interval time zone \"%s\" must not include months or days",
6602 PointerGetDatum(zone))))));
6603
6604 tz = -(zone->time / USECS_PER_SEC);
6605
6606 result = dt2local(timestamp, tz);
6607
6608 if (!IS_VALID_TIMESTAMP(result))
6609 ereport(ERROR,
6610 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6611 errmsg("timestamp out of range")));
6612
6613 PG_RETURN_TIMESTAMP(result);
6614}
6615
6616/* generate_series_timestamp()
6617 * Generate the set of timestamps from start to finish by step
6618 */
6619Datum
6621{
6622 FuncCallContext *funcctx;
6624 Timestamp result;
6625
6626 /* stuff done only on the first call of the function */
6627 if (SRF_IS_FIRSTCALL())
6628 {
6630 Timestamp finish = PG_GETARG_TIMESTAMP(1);
6631 Interval *step = PG_GETARG_INTERVAL_P(2);
6632 MemoryContext oldcontext;
6633
6634 /* create a function context for cross-call persistence */
6635 funcctx = SRF_FIRSTCALL_INIT();
6636
6637 /*
6638 * switch to memory context appropriate for multiple function calls
6639 */
6640 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
6641
6642 /* allocate memory for user context */
6645
6646 /*
6647 * Use fctx to keep state from call to call. Seed current with the
6648 * original start value
6649 */
6650 fctx->current = start;
6651 fctx->finish = finish;
6652 fctx->step = *step;
6653
6654 /* Determine sign of the interval */
6655 fctx->step_sign = interval_sign(&fctx->step);
6656
6657 if (fctx->step_sign == 0)
6658 ereport(ERROR,
6659 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6660 errmsg("step size cannot equal zero")));
6661
6662 if (INTERVAL_NOT_FINITE((&fctx->step)))
6663 ereport(ERROR,
6664 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6665 errmsg("step size cannot be infinite")));
6666
6667 funcctx->user_fctx = fctx;
6668 MemoryContextSwitchTo(oldcontext);
6669 }
6670
6671 /* stuff done on every call of the function */
6672 funcctx = SRF_PERCALL_SETUP();
6673
6674 /*
6675 * get the saved state and use current as the result for this iteration
6676 */
6677 fctx = funcctx->user_fctx;
6678 result = fctx->current;
6679
6680 if (fctx->step_sign > 0 ?
6681 timestamp_cmp_internal(result, fctx->finish) <= 0 :
6682 timestamp_cmp_internal(result, fctx->finish) >= 0)
6683 {
6684 /* increment current in preparation for next iteration */
6687 PointerGetDatum(&fctx->step)));
6688
6689 /* do when there is more left to send */
6690 SRF_RETURN_NEXT(funcctx, TimestampGetDatum(result));
6691 }
6692 else
6693 {
6694 /* do when there is no more left */
6695 SRF_RETURN_DONE(funcctx);
6696 }
6697}
6698
6699/* generate_series_timestamptz()
6700 * Generate the set of timestamps from start to finish by step,
6701 * doing arithmetic in the specified or session timezone.
6702 */
6703static Datum
6705{
6706 FuncCallContext *funcctx;
6708 TimestampTz result;
6709
6710 /* stuff done only on the first call of the function */
6711 if (SRF_IS_FIRSTCALL())
6712 {
6715 Interval *step = PG_GETARG_INTERVAL_P(2);
6716 text *zone = (PG_NARGS() == 4) ? PG_GETARG_TEXT_PP(3) : NULL;
6717 MemoryContext oldcontext;
6718
6719 /* create a function context for cross-call persistence */
6720 funcctx = SRF_FIRSTCALL_INIT();
6721
6722 /*
6723 * switch to memory context appropriate for multiple function calls
6724 */
6725 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
6726
6727 /* allocate memory for user context */
6730
6731 /*
6732 * Use fctx to keep state from call to call. Seed current with the
6733 * original start value
6734 */
6735 fctx->current = start;
6736 fctx->finish = finish;
6737 fctx->step = *step;
6739
6740 /* Determine sign of the interval */
6741 fctx->step_sign = interval_sign(&fctx->step);
6742
6743 if (fctx->step_sign == 0)
6744 ereport(ERROR,
6745 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6746 errmsg("step size cannot equal zero")));
6747
6748 if (INTERVAL_NOT_FINITE((&fctx->step)))
6749 ereport(ERROR,
6750 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6751 errmsg("step size cannot be infinite")));
6752
6753 funcctx->user_fctx = fctx;
6754 MemoryContextSwitchTo(oldcontext);
6755 }
6756
6757 /* stuff done on every call of the function */
6758 funcctx = SRF_PERCALL_SETUP();
6759
6760 /*
6761 * get the saved state and use current as the result for this iteration
6762 */
6763 fctx = funcctx->user_fctx;
6764 result = fctx->current;
6765
6766 if (fctx->step_sign > 0 ?
6767 timestamp_cmp_internal(result, fctx->finish) <= 0 :
6768 timestamp_cmp_internal(result, fctx->finish) >= 0)
6769 {
6770 /* increment current in preparation for next iteration */
6772 &fctx->step,
6773 fctx->attimezone);
6774
6775 /* do when there is more left to send */
6776 SRF_RETURN_NEXT(funcctx, TimestampTzGetDatum(result));
6777 }
6778 else
6779 {
6780 /* do when there is no more left */
6781 SRF_RETURN_DONE(funcctx);
6782 }
6783}
6784
6785Datum
6787{
6789}
6790
6791Datum
6793{
6795}
6796
6797/*
6798 * Planner support function for generate_series(timestamp, timestamp, interval)
6799 */
6800Datum
6802{
6803 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
6804 Node *ret = NULL;
6805
6806 if (IsA(rawreq, SupportRequestRows))
6807 {
6808 /* Try to estimate the number of rows returned */
6809 SupportRequestRows *req = (SupportRequestRows *) rawreq;
6810
6811 if (is_funcclause(req->node)) /* be paranoid */
6812 {
6813 List *args = ((FuncExpr *) req->node)->args;
6814 Node *arg1,
6815 *arg2,
6816 *arg3;
6817
6818 /* We can use estimated argument values here */
6822
6823 /*
6824 * If any argument is constant NULL, we can safely assume that
6825 * zero rows are returned. Otherwise, if they're all non-NULL
6826 * constants, we can calculate the number of rows that will be
6827 * returned.
6828 */
6829 if ((IsA(arg1, Const) && ((Const *) arg1)->constisnull) ||
6830 (IsA(arg2, Const) && ((Const *) arg2)->constisnull) ||
6831 (IsA(arg3, Const) && ((Const *) arg3)->constisnull))
6832 {
6833 req->rows = 0;
6834 ret = (Node *) req;
6835 }
6836 else if (IsA(arg1, Const) && IsA(arg2, Const) && IsA(arg3, Const))
6837 {
6839 finish;
6840 Interval *step;
6841 Datum diff;
6842 double dstep;
6843 int64 dummy;
6844
6845 start = DatumGetTimestamp(((Const *) arg1)->constvalue);
6846 finish = DatumGetTimestamp(((Const *) arg2)->constvalue);
6847 step = DatumGetIntervalP(((Const *) arg3)->constvalue);
6848
6849 /*
6850 * Perform some prechecks which could cause timestamp_mi to
6851 * raise an ERROR. It's much better to just return some
6852 * default estimate than error out in a support function.
6853 */
6855 !pg_sub_s64_overflow(finish, start, &dummy))
6856 {
6858 TimestampGetDatum(finish),
6860
6861#define INTERVAL_TO_MICROSECONDS(i) ((((double) (i)->month * DAYS_PER_MONTH + (i)->day)) * USECS_PER_DAY + (i)->time)
6862
6863 dstep = INTERVAL_TO_MICROSECONDS(step);
6864
6865 /* This equation works for either sign of step */
6866 if (dstep != 0.0)
6867 {
6868 Interval *idiff = DatumGetIntervalP(diff);
6869 double ddiff = INTERVAL_TO_MICROSECONDS(idiff);
6870
6871 req->rows = floor(ddiff / dstep + 1.0);
6872 ret = (Node *) req;
6873 }
6874#undef INTERVAL_TO_MICROSECONDS
6875 }
6876 }
6877 }
6878 }
6879
6880 PG_RETURN_POINTER(ret);
6881}
6882
6883
6884/* timestamp_at_local()
6885 * timestamptz_at_local()
6886 *
6887 * The regression tests do not like two functions with the same proargs and
6888 * prosrc but different proname, but the grammar for AT LOCAL needs an
6889 * overloaded name to handle both types of timestamp, so we make simple
6890 * wrappers for it.
6891 */
6892Datum
6894{
6895 return timestamp_timestamptz(fcinfo);
6896}
6897
6898Datum
6900{
6901 return timestamptz_timestamp(fcinfo);
6902}
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
int32 * ArrayGetIntegerTypmods(ArrayType *arr, int *n)
Definition: arrayutils.c:233
const int day_tab[2][13]
Definition: datetime.c:75
Node * TemporalSimplify(int32 max_precis, Node *node)
Definition: datetime.c:4956
pg_tz * DecodeTimezoneNameToTz(const char *tzname)
Definition: datetime.c:3337
int DetermineTimeZoneAbbrevOffsetTS(TimestampTz ts, const char *abbr, pg_tz *tzp, int *isdst)
Definition: datetime.c:1794
int DecodeUnits(int field, const char *lowtoken, int *val)
Definition: datetime.c:4163
int j2day(int date)
Definition: datetime.c:354
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition: datetime.c:764
void EncodeInterval(struct pg_itm *itm, int style, char *str)
Definition: datetime.c:4701
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1595
void DateTimeParseError(int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, Node *escontext)
Definition: datetime.c:4208
int DecodeInterval(char **field, int *ftype, int nf, int range, int *dtype, struct pg_itm_in *itm_in)
Definition: datetime.c:3480
int DecodeISO8601Interval(char *str, int *dtype, struct pg_itm_in *itm_in)
Definition: datetime.c:3945
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2552
int DecodeSpecial(int field, const char *lowtoken, int *val)
Definition: datetime.c:3240
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:321
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4458
int DecodeTimezone(const char *str, int *tzp)
Definition: datetime.c:3051
const char *const months[]
Definition: datetime.c:81
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:988
int date2j(int year, int month, int day)
Definition: datetime.c:296
const char *const days[]
Definition: datetime.c:84
int DecodeTimezoneName(const char *tzname, int *offset, pg_tz **tz)
Definition: datetime.c:3282
int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
Definition: datetime.c:1756
Datum numeric_round(PG_FUNCTION_ARGS)
Definition: numeric.c:1543
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3262
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4401
Numeric int64_div_fast_to_numeric(int64 val1, int log10val2)
Definition: numeric.c:4422
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:637
Numeric numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3063
Numeric numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2985
void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
Definition: timestamp.c:1882
Datum interval_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:972
Datum interval_justify_hours(PG_FUNCTION_ARGS)
Definition: timestamp.c:2971
Datum make_timestamptz_at_timezone(PG_FUNCTION_ARGS)
Definition: timestamp.c:685
int timestamp_cmp_internal(Timestamp dt1, Timestamp dt2)
Definition: timestamp.c:2209
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition: timestamp.c:1756
void isoweek2date(int woy, int *year, int *mon, int *mday)
Definition: timestamp.c:5234
Datum in_range_timestamp_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3846
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:2167
Datum generate_series_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:6786
static float8 NonFiniteTimestampTzPart(int type, int unit, char *lowunits, bool isNegative, bool isTz)
Definition: timestamp.c:5394
static INT128 interval_cmp_value(const Interval *interval)
Definition: timestamp.c:2494
Datum interval_trunc(PG_FUNCTION_ARGS)
Definition: timestamp.c:5082
Datum overlaps_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2642
Datum extract_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:5715
Datum timestamptypmodout(PG_FUNCTION_ARGS)
Definition: timestamp.c:311
Datum interval_gt(PG_FUNCTION_ARGS)
Definition: timestamp.c:2561
Datum interval_avg_accum(PG_FUNCTION_ARGS)
Definition: timestamp.c:4013
int itmin2interval(struct pg_itm_in *itm_in, Interval *span)
Definition: timestamp.c:2114
Datum interval_justify_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:2891
static void finite_interval_mi(const Interval *span1, const Interval *span2, Interval *result)
Definition: timestamp.c:3514
Datum timestamptz_part(PG_FUNCTION_ARGS)
Definition: timestamp.c:5981
int isoweek2j(int year, int week)
Definition: timestamp.c:5214
Datum clock_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:1620
Datum timestamptz_pl_interval_at_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:3371
Datum timestamp_pl_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3060
Datum interval_le(PG_FUNCTION_ARGS)
Definition: timestamp.c:2570
Datum interval_avg_serialize(PG_FUNCTION_ARGS)
Definition: timestamp.c:4079
Datum interval_mi(PG_FUNCTION_ARGS)
Definition: timestamp.c:3529
TimestampTz time_t_to_timestamptz(pg_time_t tm)
Definition: timestamp.c:1819
Datum timestamp_le_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2393
Datum interval_lt(PG_FUNCTION_ARGS)
Definition: timestamp.c:2552
Datum timestamp_larger(PG_FUNCTION_ARGS)
Definition: timestamp.c:2782
static Datum timestamptz_part_common(PG_FUNCTION_ARGS, bool retnumeric)
Definition: timestamp.c:5724
Datum timestamptz_izone(PG_FUNCTION_ARGS)
Definition: timestamp.c:6580
Datum timestamp_cmp_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2411
static bool AdjustIntervalForTypmod(Interval *interval, int32 typmod, Node *escontext)
Definition: timestamp.c:1349
Datum timestamp_part(PG_FUNCTION_ARGS)
Definition: timestamp.c:5709
Datum timestamptz_eq_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2420
Datum interval_hash(PG_FUNCTION_ARGS)
Definition: timestamp.c:2604
Datum timestamptztypmodout(PG_FUNCTION_ARGS)
Definition: timestamp.c:856
int date2isoweek(int year, int mon, int mday)
Definition: timestamp.c:5265
Datum timestamptz_pl_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3350
Datum timestamp_cmp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2269
static TimestampTz timestamptz_trunc_internal(text *units, TimestampTz timestamp, pg_tz *tzp)
Definition: timestamp.c:4867
Datum timestamp_bin(PG_FUNCTION_ARGS)
Definition: timestamp.c:4558
Datum timestamp_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:6278
static pg_tz * lookup_timezone(text *zone)
Definition: timestamp.c:559
static TimestampTz timestamp2timestamptz(Timestamp timestamp)
Definition: timestamp.c:6470
Datum interval_finite(PG_FUNCTION_ARGS)
Definition: timestamp.c:2154
Timestamp SetEpochTimestamp(void)
Definition: timestamp.c:2189
Datum timestamptz_ne_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2429
Datum timestamptz_lt_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2438
Datum timestamp_sortsupport(PG_FUNCTION_ARGS)
Definition: timestamp.c:2290
Datum timestamp_mi_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3177
Datum timestamptypmodin(PG_FUNCTION_ARGS)
Definition: timestamp.c:303
bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
Definition: timestamp.c:367
Datum timestamptz_ge_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2465
Datum timestamp_smaller(PG_FUNCTION_ARGS)
Definition: timestamp.c:2767
TimestampTz timestamp2timestamptz_opt_overflow(Timestamp timestamp, int *overflow)
Definition: timestamp.c:6418
Datum interval_justify_days(PG_FUNCTION_ARGS)
Definition: timestamp.c:3013
Datum timestamp_ge(PG_FUNCTION_ARGS)
Definition: timestamp.c:2260
Datum interval_avg_accum_inv(PG_FUNCTION_ARGS)
Definition: timestamp.c:4160
Datum generate_series_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:6620
int date2isoyearday(int year, int mon, int mday)
Definition: timestamp.c:5377
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:2005
Datum timestamptz_cmp_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2474
Datum timestamp_ge_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2402
static Timestamp timestamptz2timestamp(TimestampTz timestamp)
Definition: timestamp.c:6487
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition: timestamp.c:1720
static void do_interval_accum(IntervalAggState *state, Interval *newval)
Definition: timestamp.c:3959
Datum timestamp_scale(PG_FUNCTION_ARGS)
Definition: timestamp.c:346
Datum timestamptz_scale(PG_FUNCTION_ARGS)
Definition: timestamp.c:869
Datum make_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:664
bool TimestampDifferenceExceedsSeconds(TimestampTz start_time, TimestampTz stop_time, int threshold_sec)
Definition: timestamp.c:1794
bool TimestampTimestampTzRequiresRewrite(void)
Definition: timestamp.c:6387
Datum timestamp_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:6400
Datum timestamp_recv(PG_FUNCTION_ARGS)
Definition: timestamp.c:259
Datum timestamp_lt(PG_FUNCTION_ARGS)
Definition: timestamp.c:2233
Datum timestamptz_trunc(PG_FUNCTION_ARGS)
Definition: timestamp.c:5045
Datum timestamptz_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:6516
static void finite_interval_pl(const Interval *span1, const Interval *span2, Interval *result)
Definition: timestamp.c:3458
void isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
Definition: timestamp.c:5247
int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2)
Definition: timestamp.c:2336
Datum timestamptz_gt_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2447
Datum timestamptz_hash_extended(PG_FUNCTION_ARGS)
Definition: timestamp.c:2326
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1780
static int32 anytimestamp_typmodin(bool istz, ArrayType *ta)
Definition: timestamp.c:103
Datum generate_series_timestamp_support(PG_FUNCTION_ARGS)
Definition: timestamp.c:6801
static int timestamp_fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: timestamp.c:2280
Datum interval_cmp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2588
Datum interval_sum(PG_FUNCTION_ARGS)
Definition: timestamp.c:4218
Datum timestamp_hash_extended(PG_FUNCTION_ARGS)
Definition: timestamp.c:2314
Datum timestamptz_le_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2456
Datum interval_pl(PG_FUNCTION_ARGS)
Definition: timestamp.c:3473
Datum interval_um(PG_FUNCTION_ARGS)
Definition: timestamp.c:3416
static float8 NonFiniteIntervalPart(int type, int unit, char *lowunits, bool isNegative)
Definition: timestamp.c:6004
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1586
Datum make_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:1529
static char * anytimestamp_typmodout(bool istz, int32 typmod)
Definition: timestamp.c:146
Datum interval_ge(PG_FUNCTION_ARGS)
Definition: timestamp.c:2579
static Timestamp make_timestamp_internal(int year, int month, int day, int hour, int min, double sec)
Definition: timestamp.c:573
Datum timestamp_gt_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2384
Datum timestamp_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:165
Datum timestamp_le(PG_FUNCTION_ARGS)
Definition: timestamp.c:2251
Datum interval_ne(PG_FUNCTION_ARGS)
Definition: timestamp.c:2543
Datum timestamptz_hash(PG_FUNCTION_ARGS)
Definition: timestamp.c:2320
Datum interval_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:890
static Timestamp dt2local(Timestamp dt, int timezone)
Definition: timestamp.c:2133
static Datum interval_part_common(PG_FUNCTION_ARGS, bool retnumeric)
Definition: timestamp.c:6050
TimestampTz PgReloadTime
Definition: timestamp.c:56
Datum timestamp_ne_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2366
Datum interval_hash_extended(PG_FUNCTION_ARGS)
Definition: timestamp.c:2622
Datum timestamptz_mi_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3359
Datum timestamp_age(PG_FUNCTION_ARGS)
Definition: timestamp.c:4258
Datum interval_smaller(PG_FUNCTION_ARGS)
Definition: timestamp.c:3429
static void EncodeSpecialInterval(const Interval *interval, char *str)
Definition: timestamp.c:1597
Datum timestamptz_mi_interval_at_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:3382
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1909
Datum interval_support(PG_FUNCTION_ARGS)
Definition: timestamp.c:1264
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:417
static int intervaltypmodleastfield(int32 typmod)
Definition: timestamp.c:1211
int32 anytimestamp_typmod_check(bool istz, int32 typmod)
Definition: timestamp.c:124
Datum extract_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:5987
Datum pg_postmaster_start_time(PG_FUNCTION_ARGS)
Definition: timestamp.c:1626
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1644
static TimeOffset time2t(const int hour, const int min, const int sec, const fsec_t fsec)
Definition: timestamp.c:2127
Datum interval_part(PG_FUNCTION_ARGS)
Definition: timestamp.c:6257
Datum pg_conf_load_time(PG_FUNCTION_ARGS)
Definition: timestamp.c:1632
Datum in_range_interval_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3887
#define IA_TOTAL_COUNT(ia)
Definition: timestamp.c:88
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1861
Datum interval_eq(PG_FUNCTION_ARGS)
Definition: timestamp.c:2534
Timestamp GetSQLLocalTimestamp(int32 typmod)
Definition: timestamp.c:1676
Datum timestamp_finite(PG_FUNCTION_ARGS)
Definition: timestamp.c:2146
static TimestampTz timestamptz_mi_interval_internal(TimestampTz timestamp, Interval *span, pg_tz *attimezone)
Definition: timestamp.c:3335
Datum timestamp_trunc(PG_FUNCTION_ARGS)
Definition: timestamp.c:4629
Datum mul_d_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3698
Datum timestamptztypmodin(PG_FUNCTION_ARGS)
Definition: timestamp.c:848
Datum interval_avg(PG_FUNCTION_ARGS)
Definition: timestamp.c:4178
TimestampTz PgStartTime
Definition: timestamp.c:53
Datum timestamp_send(PG_FUNCTION_ARGS)
Definition: timestamp.c:292
Datum timestamptz_send(PG_FUNCTION_ARGS)
Definition: timestamp.c:837
Datum timestamptz_recv(PG_FUNCTION_ARGS)
Definition: timestamp.c:803
Datum interval_scale(PG_FUNCTION_ARGS)
Definition: timestamp.c:1327
static Datum timestamp_part_common(PG_FUNCTION_ARGS, bool retnumeric)
Definition: timestamp.c:5451
Datum interval_larger(PG_FUNCTION_ARGS)
Definition: timestamp.c:3444
Datum timestamp_gt(PG_FUNCTION_ARGS)
Definition: timestamp.c:2242
static IntervalAggState * makeIntervalAggState(FunctionCallInfo fcinfo)
Definition: timestamp.c:3937
Datum timestamptz_bin(PG_FUNCTION_ARGS)
Definition: timestamp.c:4793
Datum timestamptz_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:6479
Datum timestamp_mi(PG_FUNCTION_ARGS)
Definition: timestamp.c:2797
Datum timestamptz_at_local(PG_FUNCTION_ARGS)
Definition: timestamp.c:6899
Datum interval_send(PG_FUNCTION_ARGS)
Definition: timestamp.c:1021
Datum intervaltypmodin(PG_FUNCTION_ARGS)
Definition: timestamp.c:1046
#define TIMESTAMP_GT(t1, t2)
Datum timestamp_lt_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2375
Datum timestamptz_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:775
static void interval_um_internal(const Interval *interval, Interval *result)
Definition: timestamp.c:3396
Datum timestamp_hash(PG_FUNCTION_ARGS)
Definition: timestamp.c:2308
Datum timestamp_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:233
Datum timestamp_support(PG_FUNCTION_ARGS)
Definition: timestamp.c:326
void interval2itm(Interval span, struct pg_itm *itm)
Definition: timestamp.c:2046
struct IntervalAggState IntervalAggState
Datum float8_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:725
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1608
Datum interval_avg_deserialize(PG_FUNCTION_ARGS)
Definition: timestamp.c:4117
Datum timestamp_ne(PG_FUNCTION_ARGS)
Definition: timestamp.c:2224
static int interval_cmp_internal(const Interval *interval1, const Interval *interval2)
Definition: timestamp.c:2516
Datum interval_recv(PG_FUNCTION_ARGS)
Definition: timestamp.c:996
#define INTERVAL_TO_MICROSECONDS(i)
Datum statement_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:1614
Datum timestamptz_age(PG_FUNCTION_ARGS)
Definition: timestamp.c:4404
Datum interval_mul(PG_FUNCTION_ARGS)
Definition: timestamp.c:3578
Datum interval_div(PG_FUNCTION_ARGS)
Definition: timestamp.c:3708
Datum timestamptz_trunc_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:5060
Datum timestamp_eq_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2357
static TimestampTz timestamptz_pl_interval_internal(TimestampTz timestamp, Interval *span, pg_tz *attimezone)
Definition: timestamp.c:3203
static Datum generate_series_timestamptz_internal(FunctionCallInfo fcinfo)
Definition: timestamp.c:6704
int itm2interval(struct pg_itm *itm, Interval *span)
Definition: timestamp.c:2076
pg_time_t timestamptz_to_time_t(TimestampTz t)
Definition: timestamp.c:1841
Datum make_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:644
Datum intervaltypmodout(PG_FUNCTION_ARGS)
Definition: timestamp.c:1125
static int interval_sign(const Interval *interval)
Definition: timestamp.c:2525
static void do_interval_discard(IntervalAggState *state, Interval *newval)
Definition: timestamp.c:3982
Datum timeofday(PG_FUNCTION_ARGS)
Definition: timestamp.c:1690
Datum generate_series_timestamptz_at_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:6792
int date2isoyear(int year, int mon, int mday)
Definition: timestamp.c:5320
Datum timestamp_izone(PG_FUNCTION_ARGS)
Definition: timestamp.c:6343
static int parse_sane_timezone(struct pg_tm *tm, text *zone)
Definition: timestamp.c:490
Datum timestamp_at_local(PG_FUNCTION_ARGS)
Definition: timestamp.c:6893
TimestampTz GetSQLCurrentTimestamp(int32 typmod)
Definition: timestamp.c:1662
Datum in_range_timestamptz_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3809
Datum interval_avg_combine(PG_FUNCTION_ARGS)
Definition: timestamp.c:4036
Datum extract_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:6263
Datum timestamp_eq(PG_FUNCTION_ARGS)
Definition: timestamp.c:2215
#define TIMESTAMP_LT(t1, t2)
#define INT64CONST(x)
Definition: c.h:516
#define FLOAT8_FITS_IN_INT32(num)
Definition: c.h:1061
int64_t int64
Definition: c.h:499
double float8
Definition: c.h:601
#define FLOAT8_FITS_IN_INT64(num)
Definition: c.h:1063
int32_t int32
Definition: c.h:498
#define PG_INT64_MAX
Definition: c.h:563
#define unlikely(x)
Definition: c.h:347
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2395
int64 Timestamp
Definition: timestamp.h:38
#define DATETIME_MIN_JULIAN
Definition: timestamp.h:251
#define INTERVAL_NOEND(i)
Definition: timestamp.h:185
int64 TimestampTz
Definition: timestamp.h:39
#define SECS_PER_HOUR
Definition: timestamp.h:127
#define MAX_TIMESTAMP_PRECISION
Definition: timestamp.h:92
int32 fsec_t
Definition: timestamp.h:41
#define INTERVAL_NOT_FINITE(i)
Definition: timestamp.h:195
#define TIMESTAMP_NOBEGIN(j)
Definition: timestamp.h:159
#define USECS_PER_HOUR
Definition: timestamp.h:132
#define TIMESTAMP_END_JULIAN
Definition: timestamp.h:253
#define MONTHS_PER_YEAR
Definition: timestamp.h:108
#define MINS_PER_HOUR
Definition: timestamp.h:129
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:227
#define INTERVAL_NOBEGIN(i)
Definition: timestamp.h:175
#define INTERVAL_IS_NOBEGIN(i)
Definition: timestamp.h:182
#define IS_VALID_TIMESTAMP(t)
Definition: timestamp.h:267
#define MAX_INTERVAL_PRECISION
Definition: timestamp.h:93
#define SECS_PER_MINUTE
Definition: timestamp.h:128
#define USECS_PER_DAY
Definition: timestamp.h:131
#define USECS_PER_SEC
Definition: timestamp.h:134
#define HOURS_PER_DAY
Definition: timestamp.h:118
#define INTERVAL_IS_NOEND(i)
Definition: timestamp.h:192
#define TIMESTAMP_IS_NOEND(j)
Definition: timestamp.h:167
#define USECS_PER_MINUTE
Definition: timestamp.h:133
#define DAYS_PER_YEAR
Definition: timestamp.h:107
#define DAYS_PER_WEEK
Definition: timestamp.h:117
#define TIMESTAMP_IS_NOBEGIN(j)
Definition: timestamp.h:162
#define DAYS_PER_MONTH
Definition: timestamp.h:116
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:234
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:169
#define TSROUND(j)
Definition: timestamp.h:100
#define SECS_PER_DAY
Definition: timestamp.h:126
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
#define TIMESTAMP_NOEND(j)
Definition: timestamp.h:164
#define MIN_TIMESTAMP
Definition: timestamp.h:256
int64 TimeOffset
Definition: timestamp.h:40
bool float_time_overflows(int hour, int min, double sec)
Definition: date.c:1470
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
static float8 float8_mul(const float8 val1, const float8 val2)
Definition: float.h:208
static float8 get_float8_infinity(void)
Definition: float.h:94
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1816
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:308
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_NARGS()
Definition: fmgr.h:203
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:645
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
int DateStyle
Definition: globals.c:124
int IntervalStyle
Definition: globals.c:126
#define newval
Assert(PointerIsAligned(start, uint64))
return str start
const char * str
Datum hashint8extended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:103
Datum hashint8(PG_FUNCTION_ARGS)
Definition: hashfunc.c:83
#define MAXDATEFIELDS
Definition: datetime.h:202
#define DTK_EPOCH
Definition: datetime.h:152
#define TMODULO(t, q, u)
Definition: datetime.h:248
#define UNKNOWN_FIELD
Definition: datetime.h:124
#define DTK_DECADE
Definition: datetime.h:168
#define DTK_SECOND
Definition: datetime.h:160
#define DTERR_INTERVAL_OVERFLOW
Definition: datetime.h:285
#define DTK_QUARTER
Definition: datetime.h:166
#define DTK_JULIAN
Definition: datetime.h:173
#define MONTH
Definition: datetime.h:91
#define DTK_DELTA
Definition: datetime.h:159
#define DTK_TZ_HOUR
Definition: datetime.h:177
#define HOUR
Definition: datetime.h:100
#define DTK_TZ_MINUTE
Definition: datetime.h:178
#define DAY
Definition: datetime.h:93
#define DTK_LATE
Definition: datetime.h:151
#define YEAR
Definition: datetime.h:92
#define DTK_DATE
Definition: datetime.h:144
#define DTK_CENTURY
Definition: datetime.h:169
#define DTK_ISODOW
Definition: datetime.h:180
#define DTK_DAY
Definition: datetime.h:163
#define RESERV
Definition: datetime.h:90
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
#define DTK_DATE_M
Definition: datetime.h:191
#define DTK_MILLENNIUM
Definition: datetime.h:170
#define DTK_EARLY
Definition: datetime.h:150
#define DTK_ISOYEAR
Definition: datetime.h:179
#define MAXDATELEN
Definition: datetime.h:200
#define SECOND
Definition: datetime.h:102
#define isleap(y)
Definition: datetime.h:271
#define DTK_DOY
Definition: datetime.h:176
#define DTK_TZ
Definition: datetime.h:146
#define TZNAME_FIXED_OFFSET
Definition: datetime.h:299
#define TZNAME_DYNTZ
Definition: datetime.h:300
#define DTERR_TZDISP_OVERFLOW
Definition: datetime.h:286
#define EARLY
Definition: datetime.h:39
#define DTK_HOUR
Definition: datetime.h:162
#define DTK_WEEK
Definition: datetime.h:164
#define MINUTE
Definition: datetime.h:101
#define LATE
Definition: datetime.h:40
#define DTK_MICROSEC
Definition: datetime.h:172
#define DTK_DOW
Definition: datetime.h:175
#define DTK_YEAR
Definition: datetime.h:167
#define DTK_MILLISEC
Definition: datetime.h:171
#define DTK_MONTH
Definition: datetime.h:165
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:283
#define DTK_MINUTE
Definition: datetime.h:161
#define UNITS
Definition: datetime.h:107
long val
Definition: informix.c:689
static int int128_compare(INT128 x, INT128 y)
Definition: int128.h:238
static INT128 int64_to_int128(int64 v)
Definition: int128.h:255
static int64 int128_to_int64(INT128 val)
Definition: int128.h:269
static void int128_add_int64_mul_int64(INT128 *i128, int64 x, int64 y)
Definition: int128.h:177
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:293
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:262
static bool pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:187
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:169
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:235
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:151
int y
Definition: isn.c:73
int b
Definition: isn.c:71
int x
Definition: isn.c:72
int a
Definition: isn.c:70
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:78
static struct pg_tm tm
Definition: localtime.c:104
char * pstrdup(const char *in)
Definition: mcxt.c:1699
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
#define USE_ISO_DATES
Definition: miscadmin.h:236
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4541
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:301
Node * relabel_to_typmod(Node *expr, int32 typmod)
Definition: nodeFuncs.c:689
static bool is_funcclause(const void *clause)
Definition: nodeFuncs.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:160
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:61
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:80
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static time_t start_time
Definition: pg_ctl.c:95
static int list_length(const List *l)
Definition: pg_list.h:152
#define lthird(l)
Definition: pg_list.h:188
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
static rewind_source * source
Definition: pg_rewind.c:89
static char * buf
Definition: pg_test_fsync.c:72
#define TZ_STRLEN_MAX
Definition: pgtime.h:54
bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
Definition: localtime.c:1965
PGDLLIMPORT pg_tz * session_timezone
Definition: pgtz.c:28
int64 pg_time_t
Definition: pgtime.h:23
size_t pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_tm *t)
Definition: strftime.c:128
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1344
struct pg_tm * pg_gmtime(const pg_time_t *timep)
Definition: localtime.c:1389
long date
Definition: pgtypes_date.h:9
int64 timestamp
#define snprintf
Definition: port.h:239
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define Int64GetDatumFast(X)
Definition: postgres.h:559
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static char * DatumGetCString(Datum X)
Definition: postgres.h:340
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:207
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:635
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:453
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:152
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition: scansup.c:37
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
StringInfoData * StringInfo
Definition: stringinfo.h:54
static void initReadOnlyStringInfo(StringInfo str, char *data, int len)
Definition: stringinfo.h:157
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
List * args
Definition: primnodes.h:785
Definition: int128.h:108
Interval sumX
Definition: timestamp.c:82
int32 day
Definition: timestamp.h:51
int32 month
Definition: timestamp.h:52
TimeOffset time
Definition: timestamp.h:49
Definition: pg_list.h:54
Definition: nodes.h:131
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:106
struct PlannerInfo * root
Definition: supportnodes.h:163
int tm_mon
Definition: timestamp.h:86
int tm_year
Definition: timestamp.h:87
int tm_mday
Definition: timestamp.h:85
int64 tm_usec
Definition: timestamp.h:84
int64 tm_hour
Definition: timestamp.h:70
int tm_year
Definition: timestamp.h:73
int tm_mon
Definition: timestamp.h:72
int tm_mday
Definition: timestamp.h:71
int tm_sec
Definition: timestamp.h:68
int tm_min
Definition: timestamp.h:69
int tm_usec
Definition: timestamp.h:67
Definition: pgtime.h:35
int tm_hour
Definition: pgtime.h:38
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_min
Definition: pgtime.h:37
const char * tm_zone
Definition: pgtime.h:46
int tm_sec
Definition: pgtime.h:36
int tm_isdst
Definition: pgtime.h:44
long int tm_gmtoff
Definition: pgtime.h:45
int tm_year
Definition: pgtime.h:41
Definition: pgtz.h:66
Definition: regguts.h:323
Definition: lexi.c:60
Definition: c.h:658
Definition: zic.c:94
#define INTERVAL_FULL_RANGE
Definition: timestamp.h:76
#define timestamptz_cmp_internal(dt1, dt2)
Definition: timestamp.h:143
#define INTERVAL_PRECISION(t)
Definition: timestamp.h:81
static Datum TimestampTzGetDatum(TimestampTz X)
Definition: timestamp.h:52
#define INTERVAL_RANGE(t)
Definition: timestamp.h:82
static Datum TimestampGetDatum(Timestamp X)
Definition: timestamp.h:46
#define PG_GETARG_TIMESTAMP(n)
Definition: timestamp.h:63
static Datum IntervalPGetDatum(const Interval *X)
Definition: timestamp.h:58
#define PG_RETURN_TIMESTAMP(x)
Definition: timestamp.h:67
#define PG_GETARG_INTERVAL_P(n)
Definition: timestamp.h:65
#define PG_GETARG_TIMESTAMPTZ(n)
Definition: timestamp.h:64
#define PG_RETURN_TIMESTAMPTZ(x)
Definition: timestamp.h:68
static Interval * DatumGetIntervalP(Datum X)
Definition: timestamp.h:40
#define PG_RETURN_INTERVAL_P(x)
Definition: timestamp.h:69
#define INTERVAL_TYPMOD(p, r)
Definition: timestamp.h:80
#define INTERVAL_MASK(b)
Definition: timestamp.h:73
static Timestamp DatumGetTimestamp(Datum X)
Definition: timestamp.h:28
#define INTERVAL_FULL_PRECISION
Definition: timestamp.h:78
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
text * cstring_to_text(const char *s)
Definition: varlena.c:192
void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len)
Definition: varlena.c:256
const char * type
static const unsigned __int64 epoch
int gettimeofday(struct timeval *tp, void *tzp)
TimestampTz GetCurrentStatementStartTimestamp(void)
Definition: xact.c:879
TimestampTz GetCurrentTransactionStartTimestamp(void)
Definition: xact.c:870