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