PostgreSQL Source Code git master
timestamp.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * timestamp.c
4 * Functions for the built-in SQL types "timestamp" and "interval".
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/adt/timestamp.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres.h"
17
18#include <ctype.h>
19#include <math.h>
20#include <limits.h>
21#include <sys/time.h>
22
23#include "access/xact.h"
24#include "catalog/pg_type.h"
25#include "common/int.h"
26#include "common/int128.h"
27#include "funcapi.h"
28#include "libpq/pqformat.h"
29#include "miscadmin.h"
30#include "nodes/nodeFuncs.h"
31#include "nodes/supportnodes.h"
32#include "optimizer/optimizer.h"
33#include "parser/scansup.h"
34#include "utils/array.h"
35#include "utils/builtins.h"
36#include "utils/date.h"
37#include "utils/datetime.h"
38#include "utils/float.h"
39#include "utils/numeric.h"
40#include "utils/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
59typedef struct
60{
66
67typedef struct
68{
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);
93static Timestamp dt2local(Timestamp dt, int timezone);
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
109 tl = ArrayGetIntegerTypmods(ta, &n);
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)
117 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
118 errmsg("invalid type modifier")));
119
120 return anytimestamp_typmod_check(istz, tl[0]);
121}
122
123/* exported so parse_expr.c can use it */
124int32
126{
127 if (typmod < 0)
129 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
130 errmsg("TIMESTAMP(%d)%s precision must not be negative",
131 typmod, (istz ? " WITH TIME ZONE" : ""))));
132 if (typmod > MAX_TIMESTAMP_PRECISION)
133 {
135 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
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];
184 char workbuf[MAXDATELEN + MAXDATEFIELDS];
185 DateTimeErrorExtra extra;
186
187 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
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,
203 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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
249 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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 ||
281 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
282 errmsg("timestamp out of range")));
283
284 AdjustTimestampForTypmod(&timestamp, typmod, NULL);
285
287}
288
289/*
290 * timestamp_send - converts timestamp to binary format
291 */
292Datum
294{
297
301}
302
303Datum
305{
307
309}
310
311Datum
313{
314 int32 typmod = PG_GETARG_INT32(0);
315
317}
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
328{
329 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
330 Node *ret = NULL;
331
332 if (IsA(rawreq, SupportRequestSimplify))
333 {
335
337 }
338
340}
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
380 static const int64 TimestampOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
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 {
393 if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)
394 ereturn(escontext, false,
395 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
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];
436 char workbuf[MAXDATELEN + MAXDATEFIELDS];
437 DateTimeErrorExtra extra;
438
439 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
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,
456 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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
497 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
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))
511 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
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
516 dterr = DecodeTimezone(tzname, &tz);
517 if (dterr != 0)
518 {
519 int type,
520 val;
521 pg_tz *tzp;
522
523 if (dterr == DTERR_TZDISP_OVERFLOW)
525 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
526 errmsg("numeric time zone \"%s\" out of range", tzname)));
527 else if (dterr != DTERR_BAD_FORMAT)
529 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
530 errmsg("time zone \"%s\" not recognized", tzname)));
531
532 type = DecodeTimezoneName(tzname, &val, &tzp);
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 */
542 tz = DetermineTimeZoneAbbrevOffset(tm, tzname, tzp);
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
564 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
565
566 return DecodeTimezoneNameToTz(tzname);
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)
599 (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
600 errmsg("date field value out of range: %d-%02d-%02d",
601 year, month, day)));
602
605 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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))
614 (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
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)
620 * USECS_PER_SEC) + (int64) rint(sec * USECS_PER_SEC);
621
623 pg_add_s64_overflow(result, time, &result)))
625 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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))
633 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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);
649 int32 mday = PG_GETARG_INT32(2);
650 int32 hour = PG_GETARG_INT32(3);
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);
669 int32 mday = PG_GETARG_INT32(2);
670 int32 hour = PG_GETARG_INT32(3);
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);
690 int32 mday = PG_GETARG_INT32(2);
691 int32 hour = PG_GETARG_INT32(3);
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
701 timestamp = make_timestamp_internal(year, month, mday,
702 hour, min, sec);
703
704 if (timestamp2tm(timestamp, NULL, &tt, &fsec, NULL, NULL) != 0)
706 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
707 errmsg("timestamp out of range")));
708
709 tz = parse_sane_timezone(&tt, zone);
710
711 result = dt2local(timestamp, -tz);
712
713 if (!IS_VALID_TIMESTAMP(result))
715 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
728 float8 seconds = PG_GETARG_FLOAT8(0);
729 TimestampTz result;
730
731 /* Deal with NaN and infinite inputs ... */
732 if (isnan(seconds))
734 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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 >=
752 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
753 errmsg("timestamp out of range: \"%g\"", seconds)));
754
755 /* Convert UNIX epoch to Postgres epoch */
757
758 seconds = rint(seconds * USECS_PER_SEC);
759 result = (int64) seconds;
760
761 /* Recheck in case roundoff produces something just out of range */
762 if (!IS_VALID_TIMESTAMP(result))
764 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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
787 if (TIMESTAMP_NOT_FINITE(dt))
789 else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn, NULL) == 0)
790 EncodeDateTime(tm, fsec, true, tz, tzn, DateStyle, buf);
791 else
793 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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 ||
826 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
827 errmsg("timestamp out of range")));
828
829 AdjustTimestampForTypmod(&timestamp, typmod, NULL);
830
832}
833
834/*
835 * timestamptz_send - converts timestamptz to binary format
836 */
837Datum
839{
842
846}
847
848Datum
850{
852
854}
855
856Datum
858{
859 int32 typmod = PG_GETARG_INT32(0);
860
862}
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 {
934 if (dterr == DTERR_FIELD_OVERFLOW)
936 DateTimeParseError(dterr, &extra, str, "interval", escontext);
938 }
939
940 result = (Interval *) palloc(sizeof(Interval));
941
942 switch (dtype)
943 {
944 case DTK_DELTA:
945 if (itmin2interval(itm_in, result) != 0)
946 ereturn(escontext, (Datum) 0,
947 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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
981 if (INTERVAL_NOT_FINITE(span))
983 else
984 {
985 interval2itm(*span, itm);
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
1007 interval = (Interval *) palloc(sizeof(Interval));
1008
1010 interval->day = pq_getmsgint(buf, sizeof(interval->day));
1012
1013 AdjustIntervalForTypmod(interval, typmod, NULL);
1014
1016}
1017
1018/*
1019 * interval_send - converts interval to binary format
1020 */
1021Datum
1023{
1026
1029 pq_sendint32(&buf, interval->day);
1032}
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
1054 tl = ArrayGetIntegerTypmods(ta, &n);
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,
1084 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
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,
1100 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1101 errmsg("INTERVAL(%d) precision must not be negative",
1102 tl[1])));
1103 if (tl[1] > MAX_INTERVAL_PRECISION)
1104 {
1106 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1107 errmsg("INTERVAL(%d) precision reduced to maximum allowed, %d",
1108 tl[1], MAX_INTERVAL_PRECISION)));
1109 typmod = INTERVAL_TYPMOD(MAX_INTERVAL_PRECISION, tl[0]);
1110 }
1111 else
1112 typmod = INTERVAL_TYPMOD(tl[1], tl[0]);
1113 }
1114 else
1115 {
1116 ereport(ERROR,
1117 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
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{
1267 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1268 Node *ret = NULL;
1269
1270 if (IsA(rawreq, SupportRequestSimplify))
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);
1283 int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
1284 bool noop;
1285
1286 if (new_typmod < 0)
1287 noop = true;
1288 else
1289 {
1290 int32 old_typmod = exprTypmod(source);
1291 int old_least_field;
1292 int new_least_field;
1293 int old_precis;
1294 int new_precis;
1295
1296 old_least_field = intervaltypmodleastfield(old_typmod);
1297 new_least_field = intervaltypmodleastfield(new_typmod);
1298 if (old_typmod < 0)
1299 old_precis = INTERVAL_FULL_PRECISION;
1300 else
1301 old_precis = INTERVAL_PRECISION(old_typmod);
1302 new_precis = INTERVAL_PRECISION(new_typmod);
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 */
1310 noop = (new_least_field <= old_least_field) &&
1311 (old_least_field > 0 /* SECOND */ ||
1312 new_precis >= MAX_INTERVAL_PRECISION ||
1313 new_precis >= old_precis);
1314 }
1315 if (noop)
1316 ret = relabel_to_typmod(source, new_typmod);
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(sizeof(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 {
1494 if (precision < 0 || precision > MAX_INTERVAL_PRECISION)
1495 ereturn(escontext, false,
1496 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
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,
1506 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
1516 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
1532 int32 years = PG_GETARG_INT32(0);
1534 int32 weeks = PG_GETARG_INT32(2);
1536 int32 hours = PG_GETARG_INT32(4);
1537 int32 mins = PG_GETARG_INT32(5);
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 = (Interval *) palloc(sizeof(Interval));
1549
1550 /* years and months -> months */
1551 if (pg_mul_s32_overflow(years, MONTHS_PER_YEAR, &result->month) ||
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) */
1561 result->time = hours * USECS_PER_HOUR + mins * USECS_PER_MINUTE;
1562
1563 /* secs -> usecs */
1564 secs = rint(float8_mul(secs, USECS_PER_SEC));
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
1575out_of_range:
1576 ereport(ERROR,
1577 errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
1589 if (TIMESTAMP_IS_NOBEGIN(dt))
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
1610{
1612}
1613
1614Datum
1616{
1618}
1619
1620Datum
1622{
1624}
1625
1626Datum
1628{
1630}
1631
1632Datum
1634{
1636}
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{
1724 TimestampTz diff = stop_time - start_time;
1725
1726 if (diff <= 0)
1727 {
1728 *secs = 0;
1729 *microsecs = 0;
1730 }
1731 else
1732 {
1733 *secs = (long) (diff / USECS_PER_SEC);
1734 *microsecs = (int) (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{
1759 TimestampTz diff;
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. */
1765 if (pg_sub_s64_overflow(stop_time, start_time, &diff))
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
1782 TimestampTz stop_time,
1783 int msec)
1784{
1785 TimestampTz diff = stop_time - start_time;
1786
1787 return (diff >= msec * INT64CONST(1000));
1788}
1789
1790/*
1791 * Check if the difference between two timestamps is >= a given
1792 * threshold (expressed in seconds).
1793 */
1794bool
1796 TimestampTz stop_time,
1797 int threshold_sec)
1798{
1799 long secs;
1800 int usecs;
1801
1802 /* Calculate the difference in seconds */
1803 TimestampDifference(start_time, stop_time, &secs, &usecs);
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;
1914 pg_time_t utime;
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 */
1933 if (date < 0 || date > (Timestamp) INT_MAX)
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
2047interval2itm(Interval span, struct pg_itm *itm)
2048{
2049 TimeOffset time;
2050 TimeOffset tfrac;
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
2077itm2interval(struct pg_itm *itm, Interval *span)
2078{
2079 int64 total_months = (int64) itm->tm_year * MONTHS_PER_YEAR + itm->tm_mon;
2080
2081 if (total_months > INT_MAX || total_months < INT_MIN)
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 */
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;
2098 if (INTERVAL_NOT_FINITE(span))
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
2115itmin2interval(struct pg_itm_in *itm_in, Interval *span)
2116{
2117 int64 total_months = (int64) itm_in->tm_year * MONTHS_PER_YEAR + itm_in->tm_mon;
2118
2119 if (total_months > INT_MAX || total_months < INT_MIN)
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
2134dt2local(Timestamp dt, int timezone)
2135{
2136 dt -= (timezone * USECS_PER_SEC);
2137 return dt;
2138}
2139
2140
2141/*****************************************************************************
2142 * PUBLIC ROUTINES *
2143 *****************************************************************************/
2144
2145
2146Datum
2148{
2150
2152}
2153
2154Datum
2156{
2158
2160}
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
2217{
2220
2221 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);
2222}
2223
2224Datum
2226{
2229
2230 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);
2231}
2232
2233Datum
2235{
2238
2240}
2241
2242Datum
2244{
2247
2249}
2250
2251Datum
2253{
2256
2257 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);
2258}
2259
2260Datum
2262{
2265
2266 PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);
2267}
2268
2269Datum
2271{
2274
2276}
2277
2278Datum
2280{
2282
2285}
2286
2287/* note: this is used for timestamptz also */
2288static Datum
2289timestamp_decrement(Relation rel, Datum existing, bool *underflow)
2290{
2291 Timestamp texisting = DatumGetTimestamp(existing);
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
2306timestamp_increment(Relation rel, Datum existing, bool *overflow)
2307{
2308 Timestamp texisting = DatumGetTimestamp(existing);
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
2323{
2325
2330
2332}
2333
2334Datum
2336{
2337 return hashint8(fcinfo);
2338}
2339
2340Datum
2342{
2343 return hashint8extended(fcinfo);
2344}
2345
2346Datum
2348{
2349 return hashint8(fcinfo);
2350}
2351
2352Datum
2354{
2355 return hashint8extended(fcinfo);
2356}
2357
2358/*
2359 * Cross-type comparison functions for timestamp vs timestamptz
2360 */
2361
2362int32
2364{
2365 TimestampTz dt1;
2366 ErrorSaveContext escontext = {T_ErrorSaveContext};
2367
2368 dt1 = timestamp2timestamptz_safe(timestampVal, (Node *) &escontext);
2369 if (escontext.error_occurred)
2370 {
2371 if (TIMESTAMP_IS_NOEND(dt1))
2372 {
2373 /* dt1 is larger than any finite timestamp, but less than infinity */
2374 return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1;
2375 }
2376 if (TIMESTAMP_IS_NOBEGIN(dt1))
2377 {
2378 /* dt1 is less than any finite timestamp, but more than -infinity */
2379 return TIMESTAMP_IS_NOBEGIN(dt2) ? +1 : -1;
2380 }
2381 }
2382
2383 return timestamptz_cmp_internal(dt1, dt2);
2384}
2385
2386Datum
2388{
2389 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2391
2392 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) == 0);
2393}
2394
2395Datum
2397{
2398 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2400
2401 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) != 0);
2402}
2403
2404Datum
2406{
2407 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2409
2410 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) < 0);
2411}
2412
2413Datum
2415{
2416 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2418
2419 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) > 0);
2420}
2421
2422Datum
2424{
2425 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2427
2428 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) <= 0);
2429}
2430
2431Datum
2433{
2434 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2436
2437 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) >= 0);
2438}
2439
2440Datum
2442{
2443 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2445
2447}
2448
2449Datum
2451{
2453 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2454
2455 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) == 0);
2456}
2457
2458Datum
2460{
2462 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2463
2464 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) != 0);
2465}
2466
2467Datum
2469{
2471 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2472
2473 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) > 0);
2474}
2475
2476Datum
2478{
2480 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2481
2482 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) < 0);
2483}
2484
2485Datum
2487{
2489 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2490
2491 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) >= 0);
2492}
2493
2494Datum
2496{
2498 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2499
2500 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) <= 0);
2501}
2502
2503Datum
2505{
2507 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2508
2510}
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 */
2537 span = int64_to_int128(interval->time);
2538
2539 /* Scale up days to microseconds, forming a 128-bit product */
2541
2542 return span;
2543}
2544
2545static int
2546interval_cmp_internal(const Interval *interval1, const Interval *interval2)
2547{
2548 INT128 span1 = interval_cmp_value(interval1);
2549 INT128 span2 = interval_cmp_value(interval2);
2550
2551 return int128_compare(span1, span2);
2552}
2553
2554static int
2556{
2558 INT128 zero = int64_to_int128(0);
2559
2560 return int128_compare(span, zero);
2561}
2562
2563Datum
2565{
2566 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2567 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2568
2569 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) == 0);
2570}
2571
2572Datum
2574{
2575 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2576 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2577
2578 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) != 0);
2579}
2580
2581Datum
2583{
2584 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2585 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2586
2587 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) < 0);
2588}
2589
2590Datum
2592{
2593 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2594 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2595
2596 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) > 0);
2597}
2598
2599Datum
2601{
2602 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2603 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2604
2605 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) <= 0);
2606}
2607
2608Datum
2610{
2611 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2612 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2613
2614 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) >= 0);
2615}
2616
2617Datum
2619{
2620 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2621 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2622
2623 PG_RETURN_INT32(interval_cmp_internal(interval1, interval2));
2624}
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 */
2646 span64 = int128_to_int64(span);
2647
2649}
2650
2651Datum
2653{
2656 int64 span64;
2657
2658 /* Same approach as interval_hash */
2659 span64 = int128_to_int64(span);
2660
2662 PG_GETARG_DATUM(1));
2663}
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 */
2679 Datum ts1 = PG_GETARG_DATUM(0);
2680 Datum te1 = PG_GETARG_DATUM(1);
2681 Datum ts2 = PG_GETARG_DATUM(2);
2682 Datum te2 = PG_GETARG_DATUM(3);
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 = (Interval *) palloc(sizeof(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 {
2843 if (TIMESTAMP_IS_NOBEGIN(dt1))
2844 {
2845 if (TIMESTAMP_IS_NOBEGIN(dt2))
2846 ereport(ERROR,
2847 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2848 errmsg("interval out of range")));
2849 else
2850 INTERVAL_NOBEGIN(result);
2851 }
2852 else if (TIMESTAMP_IS_NOEND(dt1))
2853 {
2854 if (TIMESTAMP_IS_NOEND(dt2))
2855 ereport(ERROR,
2856 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
2871 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
2923 Interval *span = PG_GETARG_INTERVAL_P(0);
2924 Interval *result;
2925 TimeOffset wholeday;
2926 int32 wholemonth;
2927
2928 result = (Interval *) palloc(sizeof(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,
2945 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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 */
2955 TMODULO(result->time, wholeday, USECS_PER_DAY);
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,
2962 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
3003 Interval *span = PG_GETARG_INTERVAL_P(0);
3004 Interval *result;
3005 TimeOffset wholeday;
3006
3007 result = (Interval *) palloc(sizeof(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
3016 TMODULO(result->time, wholeday, USECS_PER_DAY);
3017 if (pg_add_s32_overflow(result->day, wholeday, &result->day))
3018 ereport(ERROR,
3019 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
3045 Interval *span = PG_GETARG_INTERVAL_P(0);
3046 Interval *result;
3047 int32 wholemonth;
3048
3049 result = (Interval *) palloc(sizeof(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,
3062 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
3093 Interval *span = PG_GETARG_INTERVAL_P(1);
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 */
3102 if (INTERVAL_IS_NOBEGIN(span))
3103 {
3105 ereport(ERROR,
3106 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3107 errmsg("timestamp out of range")));
3108 else
3109 TIMESTAMP_NOBEGIN(result);
3110 }
3111 else if (INTERVAL_IS_NOEND(span))
3112 {
3114 ereport(ERROR,
3115 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
3132 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3133 errmsg("timestamp out of range")));
3134
3135 if (pg_add_s32_overflow(tm->tm_mon, span->month, &tm->tm_mon))
3136 ereport(ERROR,
3137 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
3156 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
3169 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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 */
3176 julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3177 if (pg_add_s32_overflow(julian, span->day, &julian) ||
3178 julian < 0)
3179 ereport(ERROR,
3180 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3181 errmsg("timestamp out of range")));
3182 j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3183
3184 if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)
3185 ereport(ERROR,
3186 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3187 errmsg("timestamp out of range")));
3188 }
3189
3191 ereport(ERROR,
3192 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3193 errmsg("timestamp out of range")));
3194
3196 ereport(ERROR,
3197 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3198 errmsg("timestamp out of range")));
3199
3200 result = timestamp;
3201 }
3202
3203 PG_RETURN_TIMESTAMP(result);
3204}
3205
3206Datum
3208{
3210 Interval *span = PG_GETARG_INTERVAL_P(1);
3211 Interval tspan;
3212
3213 interval_um_internal(span, &tspan);
3214
3217 PointerGetDatum(&tspan));
3218}
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 */
3246 if (INTERVAL_IS_NOBEGIN(span))
3247 {
3249 ereport(ERROR,
3250 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3251 errmsg("timestamp out of range")));
3252 else
3253 TIMESTAMP_NOBEGIN(result);
3254 }
3255 else if (INTERVAL_IS_NOEND(span))
3256 {
3258 ereport(ERROR,
3259 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
3280 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3281 errmsg("timestamp out of range")));
3282
3283 if (pg_add_s32_overflow(tm->tm_mon, span->month, &tm->tm_mon))
3284 ereport(ERROR,
3285 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
3306 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
3319 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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 */
3329 julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3330 if (pg_add_s32_overflow(julian, span->day, &julian) ||
3331 julian < -1)
3332 ereport(ERROR,
3333 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3334 errmsg("timestamp out of range")));
3335 j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3336
3337 tz = DetermineTimeZoneOffset(tm, attimezone);
3338
3339 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
3340 ereport(ERROR,
3341 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3342 errmsg("timestamp out of range")));
3343 }
3344
3346 ereport(ERROR,
3347 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3348 errmsg("timestamp out of range")));
3349
3351 ereport(ERROR,
3352 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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
3366 Interval *span,
3367 pg_tz *attimezone)
3368{
3369 Interval tspan;
3370
3371 interval_um_internal(span, &tspan);
3372
3373 return timestamptz_pl_interval_internal(timestamp, &tspan, attimezone);
3374}
3375
3376/* timestamptz_pl_interval()
3377 * Add an interval to a timestamptz, in the session timezone.
3378 */
3379Datum
3381{
3383 Interval *span = PG_GETARG_INTERVAL_P(1);
3384
3386}
3387
3388Datum
3390{
3392 Interval *span = PG_GETARG_INTERVAL_P(1);
3393
3395}
3396
3397/* timestamptz_pl_interval_at_zone()
3398 * Add an interval to a timestamptz, in the specified timezone.
3399 */
3400Datum
3402{
3404 Interval *span = PG_GETARG_INTERVAL_P(1);
3406 pg_tz *attimezone = lookup_timezone(zone);
3407
3409}
3410
3411Datum
3413{
3415 Interval *span = PG_GETARG_INTERVAL_P(1);
3417 pg_tz *attimezone = lookup_timezone(zone);
3418
3420}
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,
3440 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3441 errmsg("interval out of range")));
3442 }
3443}
3444
3445Datum
3447{
3449 Interval *result;
3450
3451 result = (Interval *) palloc(sizeof(Interval));
3453
3454 PG_RETURN_INTERVAL_P(result);
3455}
3456
3457
3458Datum
3460{
3461 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
3462 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
3463 Interval *result;
3464
3465 /* use interval_cmp_internal to be sure this agrees with comparisons */
3466 if (interval_cmp_internal(interval1, interval2) < 0)
3467 result = interval1;
3468 else
3469 result = interval2;
3470 PG_RETURN_INTERVAL_P(result);
3471}
3472
3473Datum
3475{
3476 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
3477 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
3478 Interval *result;
3479
3480 if (interval_cmp_internal(interval1, interval2) > 0)
3481 result = interval1;
3482 else
3483 result = interval2;
3484 PG_RETURN_INTERVAL_P(result);
3485}
3486
3487static void
3488finite_interval_pl(const Interval *span1, const Interval *span2, Interval *result)
3489{
3490 Assert(!INTERVAL_NOT_FINITE(span1));
3491 Assert(!INTERVAL_NOT_FINITE(span2));
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,
3498 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3499 errmsg("interval out of range")));
3500}
3501
3502Datum
3504{
3505 Interval *span1 = PG_GETARG_INTERVAL_P(0);
3506 Interval *span2 = PG_GETARG_INTERVAL_P(1);
3507 Interval *result;
3508
3509 result = (Interval *) palloc(sizeof(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 */
3517 if (INTERVAL_IS_NOBEGIN(span1))
3518 {
3519 if (INTERVAL_IS_NOEND(span2))
3520 ereport(ERROR,
3521 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3522 errmsg("interval out of range")));
3523 else
3524 INTERVAL_NOBEGIN(result);
3525 }
3526 else if (INTERVAL_IS_NOEND(span1))
3527 {
3528 if (INTERVAL_IS_NOBEGIN(span2))
3529 ereport(ERROR,
3530 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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
3544finite_interval_mi(const Interval *span1, const Interval *span2, Interval *result)
3545{
3546 Assert(!INTERVAL_NOT_FINITE(span1));
3547 Assert(!INTERVAL_NOT_FINITE(span2));
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,
3554 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3555 errmsg("interval out of range")));
3556}
3557
3558Datum
3560{
3561 Interval *span1 = PG_GETARG_INTERVAL_P(0);
3562 Interval *span2 = PG_GETARG_INTERVAL_P(1);
3563 Interval *result;
3564
3565 result = (Interval *) palloc(sizeof(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 */
3573 if (INTERVAL_IS_NOBEGIN(span1))
3574 {
3575 if (INTERVAL_IS_NOBEGIN(span2))
3576 ereport(ERROR,
3577 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3578 errmsg("interval out of range")));
3579 else
3580 INTERVAL_NOBEGIN(result);
3581 }
3582 else if (INTERVAL_IS_NOEND(span1))
3583 {
3584 if (INTERVAL_IS_NOEND(span2))
3585 ereport(ERROR,
3586 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
3610 Interval *span = PG_GETARG_INTERVAL_P(0);
3611 float8 factor = PG_GETARG_FLOAT8(1);
3612 double month_remainder_days,
3613 sec_remainder,
3614 result_double;
3615 int32 orig_month = span->month,
3616 orig_day = span->day;
3617 Interval *result;
3618
3619 result = (Interval *) palloc(sizeof(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
3630 if (INTERVAL_NOT_FINITE(span))
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;
3658 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3659 goto out_of_range;
3660 result->month = (int32) result_double;
3661
3662 result_double = span->day * factor;
3663 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
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 */
3685 month_remainder_days = (orig_month * factor - result->month) * DAYS_PER_MONTH;
3686 month_remainder_days = TSROUND(month_remainder_days);
3687 sec_remainder = (orig_day * factor - result->day +
3688 month_remainder_days - (int) month_remainder_days) * SECS_PER_DAY;
3689 sec_remainder = TSROUND(sec_remainder);
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 */
3696 if (fabs(sec_remainder) >= SECS_PER_DAY)
3697 {
3698 if (pg_add_s32_overflow(result->day,
3699 (int) (sec_remainder / SECS_PER_DAY),
3700 &result->day))
3701 goto out_of_range;
3702 sec_remainder -= (int) (sec_remainder / SECS_PER_DAY) * SECS_PER_DAY;
3703 }
3704
3705 /* cascade units down */
3706 if (pg_add_s32_overflow(result->day, (int32) month_remainder_days,
3707 &result->day))
3708 goto out_of_range;
3709 result_double = rint(span->time * factor + sec_remainder * USECS_PER_SEC);
3710 if (isnan(result_double) || !FLOAT8_FITS_IN_INT64(result_double))
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
3719out_of_range:
3720 ereport(ERROR,
3721 errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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 */
3731 Datum factor = PG_GETARG_DATUM(0);
3732 Datum span = PG_GETARG_DATUM(1);
3733
3734 return DirectFunctionCall2(interval_mul, span, factor);
3735}
3736
3737Datum
3739{
3740 Interval *span = PG_GETARG_INTERVAL_P(0);
3741 float8 factor = PG_GETARG_FLOAT8(1);
3742 double month_remainder_days,
3743 sec_remainder,
3744 result_double;
3745 int32 orig_month = span->month,
3746 orig_day = span->day;
3747 Interval *result;
3748
3749 result = (Interval *) palloc(sizeof(Interval));
3750
3751 if (factor == 0.0)
3752 ereport(ERROR,
3753 (errcode(ERRCODE_DIVISION_BY_ZERO),
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
3766 if (INTERVAL_NOT_FINITE(span))
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;
3780 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3781 goto out_of_range;
3782 result->month = (int32) result_double;
3783
3784 result_double = span->day / factor;
3785 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
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 */
3792 month_remainder_days = (orig_month / factor - result->month) * DAYS_PER_MONTH;
3793 month_remainder_days = TSROUND(month_remainder_days);
3794 sec_remainder = (orig_day / factor - result->day +
3795 month_remainder_days - (int) month_remainder_days) * SECS_PER_DAY;
3796 sec_remainder = TSROUND(sec_remainder);
3797 if (fabs(sec_remainder) >= SECS_PER_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;
3803 sec_remainder -= (int) (sec_remainder / SECS_PER_DAY) * SECS_PER_DAY;
3804 }
3805
3806 /* cascade units down */
3807 if (pg_add_s32_overflow(result->day, (int32) month_remainder_days,
3808 &result->day))
3809 goto out_of_range;
3810 result_double = rint(span->time / factor + sec_remainder * USECS_PER_SEC);
3811 if (isnan(result_double) || !FLOAT8_FITS_IN_INT64(result_double))
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
3820out_of_range:
3821 ereport(ERROR,
3822 errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
3850 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
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,
3887 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
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,
3928 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
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;
3971 MemoryContext old_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
3980 MemoryContextSwitchTo(old_context);
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{
4068 IntervalAggState *state1;
4069 IntervalAggState *state2;
4070
4071 state1 = PG_ARGISNULL(0) ? NULL : (IntervalAggState *) PG_GETARG_POINTER(0);
4072 state2 = PG_ARGISNULL(1) ? NULL : (IntervalAggState *) PG_GETARG_POINTER(1);
4073
4074 if (state2 == NULL)
4075 PG_RETURN_POINTER(state1);
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
4090 PG_RETURN_POINTER(state1);
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
4101 PG_RETURN_POINTER(state1);
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
4165 result = (IntervalAggState *) palloc0(sizeof(IntervalAggState));
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,
4229 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4230 errmsg("interval out of range")));
4231
4232 result = (Interval *) palloc(sizeof(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,
4266 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4267 errmsg("interval out of range")));
4268
4269 result = (Interval *) palloc(sizeof(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 = (Interval *) palloc(sizeof(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 */
4310 if (TIMESTAMP_IS_NOBEGIN(dt1))
4311 {
4312 if (TIMESTAMP_IS_NOBEGIN(dt2))
4313 ereport(ERROR,
4314 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4315 errmsg("interval out of range")));
4316 else
4317 INTERVAL_NOBEGIN(result);
4318 }
4319 else if (TIMESTAMP_IS_NOEND(dt1))
4320 {
4321 if (TIMESTAMP_IS_NOEND(dt2))
4322 ereport(ERROR,
4323 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
4415 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4416 errmsg("interval out of range")));
4417 }
4418 else
4419 ereport(ERROR,
4420 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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 = (Interval *) palloc(sizeof(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 */
4458 if (TIMESTAMP_IS_NOBEGIN(dt1))
4459 {
4460 if (TIMESTAMP_IS_NOBEGIN(dt2))
4461 ereport(ERROR,
4462 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4463 errmsg("interval out of range")));
4464 else
4465 INTERVAL_NOBEGIN(result);
4466 }
4467 else if (TIMESTAMP_IS_NOEND(dt1))
4468 {
4469 if (TIMESTAMP_IS_NOEND(dt2))
4470 ereport(ERROR,
4471 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
4567 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4568 errmsg("interval out of range")));
4569 }
4570 else
4571 ereport(ERROR,
4572 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
4590 Interval *stride = PG_GETARG_INTERVAL_P(0);
4592 Timestamp origin = PG_GETARG_TIMESTAMP(2);
4593 Timestamp result,
4594 stride_usecs,
4595 tm_diff,
4596 tm_modulo,
4597 tm_delta;
4598
4601
4602 if (TIMESTAMP_NOT_FINITE(origin))
4603 ereport(ERROR,
4604 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4605 errmsg("origin out of range")));
4606
4607 if (INTERVAL_NOT_FINITE(stride))
4608 ereport(ERROR,
4609 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4610 errmsg("timestamps cannot be binned into infinite intervals")));
4611
4612 if (stride->month != 0)
4613 ereport(ERROR,
4614 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4615 errmsg("timestamps cannot be binned into intervals containing months or years")));
4616
4617 if (unlikely(pg_mul_s64_overflow(stride->day, USECS_PER_DAY, &stride_usecs)) ||
4618 unlikely(pg_add_s64_overflow(stride_usecs, stride->time, &stride_usecs)))
4619 ereport(ERROR,
4620 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4621 errmsg("interval out of range")));
4622
4623 if (stride_usecs <= 0)
4624 ereport(ERROR,
4625 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4626 errmsg("stride must be greater than zero")));
4627
4628 if (unlikely(pg_sub_s64_overflow(timestamp, origin, &tm_diff)))
4629 ereport(ERROR,
4630 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4631 errmsg("interval out of range")));
4632
4633 /* These calculations cannot overflow */
4634 tm_modulo = tm_diff % stride_usecs;
4635 tm_delta = tm_diff - tm_modulo;
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,
4648 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
4661 text *units = PG_GETARG_TEXT_PP(0);
4663 Timestamp result;
4664 int type,
4665 val;
4666 char *lowunits;
4667 fsec_t fsec;
4668 struct pg_tm tt,
4669 *tm = &tt;
4670
4671 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
4672 VARSIZE_ANY_EXHDR(units),
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,
4705 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4706 errmsg("unit \"%s\" not supported for type %s",
4707 lowunits, format_type_be(TIMESTAMPOID))));
4708 result = 0;
4709 }
4710 }
4711
4712 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
4713 ereport(ERROR,
4714 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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;
4732 if (woy <= 1 && tm->tm_mon == MONTHS_PER_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,
4796 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4797 errmsg("unit \"%s\" not supported for type %s",
4798 lowunits, format_type_be(TIMESTAMPOID))));
4799 result = 0;
4800 }
4801
4802 if (tm2timestamp(tm, fsec, NULL, &result) != 0)
4803 ereport(ERROR,
4804 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4805 errmsg("timestamp out of range")));
4806 }
4807 else
4808 {
4809 ereport(ERROR,
4810 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4811 errmsg("unit \"%s\" not recognized for type %s",
4812 lowunits, format_type_be(TIMESTAMPOID))));
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{
4825 Interval *stride = PG_GETARG_INTERVAL_P(0);
4828 TimestampTz result,
4829 stride_usecs,
4830 tm_diff,
4831 tm_modulo,
4832 tm_delta;
4833
4836
4837 if (TIMESTAMP_NOT_FINITE(origin))
4838 ereport(ERROR,
4839 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4840 errmsg("origin out of range")));
4841
4842 if (INTERVAL_NOT_FINITE(stride))
4843 ereport(ERROR,
4844 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4845 errmsg("timestamps cannot be binned into infinite intervals")));
4846
4847 if (stride->month != 0)
4848 ereport(ERROR,
4849 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4850 errmsg("timestamps cannot be binned into intervals containing months or years")));
4851
4852 if (unlikely(pg_mul_s64_overflow(stride->day, USECS_PER_DAY, &stride_usecs)) ||
4853 unlikely(pg_add_s64_overflow(stride_usecs, stride->time, &stride_usecs)))
4854 ereport(ERROR,
4855 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4856 errmsg("interval out of range")));
4857
4858 if (stride_usecs <= 0)
4859 ereport(ERROR,
4860 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4861 errmsg("stride must be greater than zero")));
4862
4863 if (unlikely(pg_sub_s64_overflow(timestamp, origin, &tm_diff)))
4864 ereport(ERROR,
4865 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4866 errmsg("interval out of range")));
4867
4868 /* These calculations cannot overflow */
4869 tm_modulo = tm_diff % stride_usecs;
4870 tm_delta = tm_diff - tm_modulo;
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,
4883 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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
4909 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
4910 VARSIZE_ANY_EXHDR(units),
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,
4944 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4945 errmsg("unit \"%s\" not supported for type %s",
4946 lowunits, format_type_be(TIMESTAMPTZOID))));
4947 result = 0;
4948 }
4949 }
4950
4951 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, tzp) != 0)
4952 ereport(ERROR,
4953 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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;
4971 if (woy <= 1 && tm->tm_mon == MONTHS_PER_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,
5045 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5046 errmsg("unit \"%s\" not supported for type %s",
5047 lowunits, format_type_be(TIMESTAMPTZOID))));
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,
5056 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5057 errmsg("timestamp out of range")));
5058 }
5059 else
5060 {
5061 ereport(ERROR,
5062 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5063 errmsg("unit \"%s\" not recognized for type %s",
5064 lowunits, format_type_be(TIMESTAMPTZOID))));
5065 result = 0;
5066 }
5067
5068 return result;
5069}
5070
5071/* timestamptz_trunc()
5072 * Truncate timestamptz to specified units in session timezone.
5073 */
5074Datum
5076{
5077 text *units = PG_GETARG_TEXT_PP(0);
5079 TimestampTz result;
5080
5082
5083 PG_RETURN_TIMESTAMPTZ(result);
5084}
5085
5086/* timestamptz_trunc_zone()
5087 * Truncate timestamptz to specified units in specified timezone.
5088 */
5089Datum
5091{
5092 text *units = PG_GETARG_TEXT_PP(0);
5095 TimestampTz result;
5096 pg_tz *tzp;
5097
5098 /*
5099 * Look up the requested timezone.
5100 */
5101 tzp = lookup_timezone(zone);
5102
5103 result = timestamptz_trunc_internal(units, timestamp, tzp);
5104
5105 PG_RETURN_TIMESTAMPTZ(result);
5106}
5107
5108/* interval_trunc()
5109 * Extract specified field from interval.
5110 */
5111Datum
5113{
5114 text *units = PG_GETARG_TEXT_PP(0);
5116 Interval *result;
5117 int type,
5118 val;
5119 char *lowunits;
5120 struct pg_itm tt,
5121 *tm = &tt;
5122
5123 result = (Interval *) palloc(sizeof(Interval));
5124
5125 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
5126 VARSIZE_ANY_EXHDR(units),
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,
5160 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5161 errmsg("unit \"%s\" not supported for type %s",
5162 lowunits, format_type_be(INTERVALOID)),
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,
5212 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5213 errmsg("unit \"%s\" not supported for type %s",
5214 lowunits, format_type_be(INTERVALOID)),
5215 (val == DTK_WEEK) ? errdetail("Months usually have fractional weeks.") : 0));
5216 }
5217
5218 if (itm2interval(tm, result) != 0)
5219 ereport(ERROR,
5220 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5221 errmsg("interval out of range")));
5222 }
5223 else
5224 {
5225 ereport(ERROR,
5226 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5227 errmsg("unit \"%s\" not recognized for type %s",
5228 lowunits, format_type_be(INTERVALOID))));
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
5424NonFiniteTimestampTzPart(int type, int unit, char *lowunits,
5425 bool isNegative, bool isTz)
5426{
5427 if ((type != UNITS) && (type != RESERV))
5428 ereport(ERROR,
5429 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5430 errmsg("unit \"%s\" not recognized for type %s",
5431 lowunits,
5432 format_type_be(isTz ? TIMESTAMPTZOID : TIMESTAMPOID))));
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,
5469 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5470 errmsg("unit \"%s\" not supported for type %s",
5471 lowunits,
5472 format_type_be(isTz ? TIMESTAMPTZOID : TIMESTAMPOID))));
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{
5483 text *units = PG_GETARG_TEXT_PP(0);
5485 int64 intresult;
5487 int type,
5488 val;
5489 char *lowunits;
5490 fsec_t fsec;
5491 struct pg_tm tt,
5492 *tm = &tt;
5493
5494 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
5495 VARSIZE_ANY_EXHDR(units),
5496 false);
5497
5498 type = DecodeUnits(0, lowunits, &val);
5499 if (type == UNKNOWN_FIELD)
5500 type = DecodeSpecial(0, lowunits, &val);
5501
5503 {
5504 double r = NonFiniteTimestampTzPart(type, val, lowunits,
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,
5534 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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:
5586 intresult = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
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:
5647 intresult = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
5648 /* Adjust BC years */
5649 if (intresult <= 0)
5650 intresult -= 1;
5651 break;
5652
5653 case DTK_DOW:
5654 case DTK_ISODOW:
5655 intresult = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
5656 if (val == DTK_ISODOW && intresult == 0)
5657 intresult = 7;
5658 break;
5659
5660 case DTK_DOY:
5661 intresult = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
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,
5670 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5671 errmsg("unit \"%s\" not supported for type %s",
5672 lowunits, format_type_be(TIMESTAMPOID))));
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,
5717 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5718 errmsg("unit \"%s\" not supported for type %s",
5719 lowunits, format_type_be(TIMESTAMPOID))));
5720 intresult = 0;
5721 }
5722 }
5723 else
5724 {
5725 ereport(ERROR,
5726 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5727 errmsg("unit \"%s\" not recognized for type %s",
5728 lowunits, format_type_be(TIMESTAMPOID))));
5729 intresult = 0;
5730 }
5731
5732 if (retnumeric)
5734 else
5735 PG_RETURN_FLOAT8(intresult);
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{
5756 text *units = PG_GETARG_TEXT_PP(0);
5758 int64 intresult;
5760 int tz;
5761 int type,
5762 val;
5763 char *lowunits;
5764 fsec_t fsec;
5765 struct pg_tm tt,
5766 *tm = &tt;
5767
5768 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
5769 VARSIZE_ANY_EXHDR(units),
5770 false);
5771
5772 type = DecodeUnits(0, lowunits, &val);
5773 if (type == UNKNOWN_FIELD)
5774 type = DecodeSpecial(0, lowunits, &val);
5775
5777 {
5778 double r = NonFiniteTimestampTzPart(type, val, lowunits,
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,
5808 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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:
5818 intresult = (-tz / SECS_PER_MINUTE) % MINS_PER_HOUR;
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:
5872 intresult = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
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:
5921 intresult = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
5922 /* Adjust BC years */
5923 if (intresult <= 0)
5924 intresult -= 1;
5925 break;
5926
5927 case DTK_DOW:
5928 case DTK_ISODOW:
5929 intresult = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
5930 if (val == DTK_ISODOW && intresult == 0)
5931 intresult = 7;
5932 break;
5933
5934 case DTK_DOY:
5935 intresult = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
5936 - date2j(tm->tm_year, 1, 1) + 1);
5937 break;
5938
5939 default:
5940 ereport(ERROR,
5941 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5942 errmsg("unit \"%s\" not supported for type %s",
5943 lowunits, format_type_be(TIMESTAMPTZOID))));
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,
5988 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5989 errmsg("unit \"%s\" not supported for type %s",
5990 lowunits, format_type_be(TIMESTAMPTZOID))));
5991 intresult = 0;
5992 }
5993 }
5994 else
5995 {
5996 ereport(ERROR,
5997 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5998 errmsg("unit \"%s\" not recognized for type %s",
5999 lowunits, format_type_be(TIMESTAMPTZOID))));
6000
6001 intresult = 0;
6002 }
6003
6004 if (retnumeric)
6006 else
6007 PG_RETURN_FLOAT8(intresult);
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
6034NonFiniteIntervalPart(int type, int unit, char *lowunits, bool isNegative)
6035{
6036 if ((type != UNITS) && (type != RESERV))
6037 ereport(ERROR,
6038 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6039 errmsg("unit \"%s\" not recognized for type %s",
6040 lowunits, format_type_be(INTERVALOID))));
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,
6069 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6070 errmsg("unit \"%s\" not supported for type %s",
6071 lowunits, format_type_be(INTERVALOID))));
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{
6082 text *units = PG_GETARG_TEXT_PP(0);
6084 int64 intresult;
6085 int type,
6086 val;
6087 char *lowunits;
6088 struct pg_itm tt,
6089 *tm = &tt;
6090
6091 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
6092 VARSIZE_ANY_EXHDR(units),
6093 false);
6094
6095 type = DecodeUnits(0, lowunits, &val);
6096 if (type == UNKNOWN_FIELD)
6097 type = DecodeSpecial(0, lowunits, &val);
6098
6100 {
6101 double r = NonFiniteIntervalPart(type, val, lowunits,
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,
6213 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6214 errmsg("unit \"%s\" not supported for type %s",
6215 lowunits, format_type_be(INTERVALOID))));
6216 intresult = 0;
6217 }
6218 }
6219 else if (type == RESERV && val == DTK_EPOCH)
6220 {
6221 if (retnumeric)
6222 {
6223 Numeric result;
6224 int64 secs_from_day_month;
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 */
6234 secs_from_day_month = ((int64) (4 * DAYS_PER_YEAR) * (interval->month / MONTHS_PER_YEAR) +
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 =
6254 int64_to_numeric(secs_from_day_month),
6255 NULL);
6256
6257 PG_RETURN_NUMERIC(result);
6258 }
6259 else
6260 {
6261 float8 result;
6262
6263 result = interval->time / 1000000.0;
6264 result += ((double) DAYS_PER_YEAR * SECS_PER_DAY) * (interval->month / MONTHS_PER_YEAR);
6265 result += ((double) DAYS_PER_MONTH * SECS_PER_DAY) * (interval->month % MONTHS_PER_YEAR);
6266 result += ((double) SECS_PER_DAY) * interval->day;
6267
6268 PG_RETURN_FLOAT8(result);
6269 }
6270 }
6271 else
6272 {
6273 ereport(ERROR,
6274 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6275 errmsg("unit \"%s\" not recognized for type %s",
6276 lowunits, format_type_be(INTERVALOID))));
6277 intresult = 0;
6278 }
6279
6280 if (retnumeric)
6282 else
6283 PG_RETURN_FLOAT8(intresult);
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 */
6327 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
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,
6342 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6343 errmsg("timestamp out of range")));
6344 tz = -DetermineTimeZoneAbbrevOffset(&tm, tzname, tzp);
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,
6352 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6353 errmsg("timestamp out of range")));
6354 tz = DetermineTimeZoneOffset(&tm, tzp);
6355 if (tm2timestamp(&tm, fsec, &tz, &result) != 0)
6356 ereport(ERROR,
6357 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6358 errmsg("timestamp out of range")));
6359 }
6360
6361 if (!IS_VALID_TIMESTAMP(result))
6362 ereport(ERROR,
6363 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
6385 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6386 errmsg("interval time zone \"%s\" must be finite",
6388 PointerGetDatum(zone))))));
6389
6390 if (zone->month != 0 || zone->day != 0)
6391 ereport(ERROR,
6392 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
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,
6403 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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
6431{
6433
6435}
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,
6476 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6477 errmsg("timestamp out of range")));
6478}
6479
6480/*
6481 * Promote timestamp to timestamptz, throwing error for overflow.
6482 */
6483static TimestampTz
6485{
6487}
6488
6489/* timestamptz_timestamp()
6490 * Convert timestamp at GMT to local timestamp
6491 */
6492Datum
6494{
6496
6498}
6499
6500/*
6501 * Convert timestamptz to timestamp, throwing error for overflow.
6502 */
6503static Timestamp
6505{
6507}
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,
6540 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
6551 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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 */
6580 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
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
6595 tz = DetermineTimeZoneAbbrevOffsetTS(timestamp, tzname, tzp, &isdst);
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,
6606 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6607 errmsg("timestamp out of range")));
6608 if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
6609 ereport(ERROR,
6610 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6611 errmsg("timestamp out of range")));
6612 }
6613
6614 if (!IS_VALID_TIMESTAMP(result))
6615 ereport(ERROR,
6616 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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,
6639 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6640 errmsg("interval time zone \"%s\" must be finite",
6642 PointerGetDatum(zone))))));
6643
6644 if (zone->month != 0 || zone->day != 0)
6645 ereport(ERROR,
6646 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
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,
6657 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
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{
6669 FuncCallContext *funcctx;
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 */
6682 funcctx = SRF_FIRSTCALL_INIT();
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 */
6692
6693 /*
6694 * Use fctx to keep state from call to call. Seed current with the
6695 * original start value
6696 */
6697 fctx->current = start;
6698 fctx->finish = finish;
6699 fctx->step = *step;
6700
6701 /* Determine sign of the interval */
6702 fctx->step_sign = interval_sign(&fctx->step);
6703
6704 if (fctx->step_sign == 0)
6705 ereport(ERROR,
6706 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6707 errmsg("step size cannot equal zero")));
6708
6709 if (INTERVAL_NOT_FINITE((&fctx->step)))
6710 ereport(ERROR,
6711 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6712 errmsg("step size cannot be infinite")));
6713
6714 funcctx->user_fctx = fctx;
6715 MemoryContextSwitchTo(oldcontext);
6716 }
6717
6718 /* stuff done on every call of the function */
6719 funcctx = SRF_PERCALL_SETUP();
6720
6721 /*
6722 * get the saved state and use current as the result for this iteration
6723 */
6724 fctx = funcctx->user_fctx;
6725 result = fctx->current;
6726
6727 if (fctx->step_sign > 0 ?
6728 timestamp_cmp_internal(result, fctx->finish) <= 0 :
6729 timestamp_cmp_internal(result, fctx->finish) >= 0)
6730 {
6731 /* increment current in preparation for next iteration */
6734 PointerGetDatum(&fctx->step)));
6735
6736 /* do when there is more left to send */
6737 SRF_RETURN_NEXT(funcctx, TimestampGetDatum(result));
6738 }
6739 else
6740 {
6741 /* do when there is no more left */
6742 SRF_RETURN_DONE(funcctx);
6743 }
6744}
6745
6746/* generate_series_timestamptz()
6747 * Generate the set of timestamps from start to finish by step,
6748 * doing arithmetic in the specified or session timezone.
6749 */
6750static Datum
6752{
6753 FuncCallContext *funcctx;
6755 TimestampTz result;
6756
6757 /* stuff done only on the first call of the function */
6758 if (SRF_IS_FIRSTCALL())
6759 {
6762 Interval *step = PG_GETARG_INTERVAL_P(2);
6763 text *zone = (PG_NARGS() == 4) ? PG_GETARG_TEXT_PP(3) : NULL;
6764 MemoryContext oldcontext;
6765
6766 /* create a function context for cross-call persistence */
6767 funcctx = SRF_FIRSTCALL_INIT();
6768
6769 /*
6770 * switch to memory context appropriate for multiple function calls
6771 */
6772 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
6773
6774 /* allocate memory for user context */
6777
6778 /*
6779 * Use fctx to keep state from call to call. Seed current with the
6780 * original start value
6781 */
6782 fctx->current = start;
6783 fctx->finish = finish;
6784 fctx->step = *step;
6786
6787 /* Determine sign of the interval */
6788 fctx->step_sign = interval_sign(&fctx->step);
6789
6790 if (fctx->step_sign == 0)
6791 ereport(ERROR,
6792 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6793 errmsg("step size cannot equal zero")));
6794
6795 if (INTERVAL_NOT_FINITE((&fctx->step)))
6796 ereport(ERROR,
6797 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6798 errmsg("step size cannot be infinite")));
6799
6800 funcctx->user_fctx = fctx;
6801 MemoryContextSwitchTo(oldcontext);
6802 }
6803
6804 /* stuff done on every call of the function */
6805 funcctx = SRF_PERCALL_SETUP();
6806
6807 /*
6808 * get the saved state and use current as the result for this iteration
6809 */
6810 fctx = funcctx->user_fctx;
6811 result = fctx->current;
6812
6813 if (fctx->step_sign > 0 ?
6814 timestamp_cmp_internal(result, fctx->finish) <= 0 :
6815 timestamp_cmp_internal(result, fctx->finish) >= 0)
6816 {
6817 /* increment current in preparation for next iteration */
6819 &fctx->step,
6820 fctx->attimezone);
6821
6822 /* do when there is more left to send */
6823 SRF_RETURN_NEXT(funcctx, TimestampTzGetDatum(result));
6824 }
6825 else
6826 {
6827 /* do when there is no more left */
6828 SRF_RETURN_DONE(funcctx);
6829 }
6830}
6831
6832Datum
6834{
6836}
6837
6838Datum
6840{
6842}
6843
6844/*
6845 * Planner support function for generate_series(timestamp, timestamp, interval)
6846 */
6847Datum
6849{
6850 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
6851 Node *ret = NULL;
6852
6853 if (IsA(rawreq, SupportRequestRows))
6854 {
6855 /* Try to estimate the number of rows returned */
6856 SupportRequestRows *req = (SupportRequestRows *) rawreq;
6857
6858 if (is_funcclause(req->node)) /* be paranoid */
6859 {
6860 List *args = ((FuncExpr *) req->node)->args;
6861 Node *arg1,
6862 *arg2,
6863 *arg3;
6864
6865 /* We can use estimated argument values here */
6869
6870 /*
6871 * If any argument is constant NULL, we can safely assume that
6872 * zero rows are returned. Otherwise, if they're all non-NULL
6873 * constants, we can calculate the number of rows that will be
6874 * returned.
6875 */
6876 if ((IsA(arg1, Const) && ((Const *) arg1)->constisnull) ||
6877 (IsA(arg2, Const) && ((Const *) arg2)->constisnull) ||
6878 (IsA(arg3, Const) && ((Const *) arg3)->constisnull))
6879 {
6880 req->rows = 0;
6881 ret = (Node *) req;
6882 }
6883 else if (IsA(arg1, Const) && IsA(arg2, Const) && IsA(arg3, Const))
6884 {
6886 finish;
6887 Interval *step;
6888 Datum diff;
6889 double dstep;
6890 int64 dummy;
6891
6892 start = DatumGetTimestamp(((Const *) arg1)->constvalue);
6893 finish = DatumGetTimestamp(((Const *) arg2)->constvalue);
6894 step = DatumGetIntervalP(((Const *) arg3)->constvalue);
6895
6896 /*
6897 * Perform some prechecks which could cause timestamp_mi to
6898 * raise an ERROR. It's much better to just return some
6899 * default estimate than error out in a support function.
6900 */
6902 !pg_sub_s64_overflow(finish, start, &dummy))
6903 {
6905 TimestampGetDatum(finish),
6907
6908#define INTERVAL_TO_MICROSECONDS(i) ((((double) (i)->month * DAYS_PER_MONTH + (i)->day)) * USECS_PER_DAY + (i)->time)
6909
6910 dstep = INTERVAL_TO_MICROSECONDS(step);
6911
6912 /* This equation works for either sign of step */
6913 if (dstep != 0.0)
6914 {
6915 Interval *idiff = DatumGetIntervalP(diff);
6916 double ddiff = INTERVAL_TO_MICROSECONDS(idiff);
6917
6918 req->rows = floor(ddiff / dstep + 1.0);
6919 ret = (Node *) req;
6920 }
6921#undef INTERVAL_TO_MICROSECONDS
6922 }
6923 }
6924 }
6925 }
6926
6927 PG_RETURN_POINTER(ret);
6928}
6929
6930
6931/* timestamp_at_local()
6932 * timestamptz_at_local()
6933 *
6934 * The regression tests do not like two functions with the same proargs and
6935 * prosrc but different proname, but the grammar for AT LOCAL needs an
6936 * overloaded name to handle both types of timestamp, so we make simple
6937 * wrappers for it.
6938 */
6939Datum
6941{
6942 return timestamp_timestamptz(fcinfo);
6943}
6944
6945Datum
6947{
6948 return timestamptz_timestamp(fcinfo);
6949}
#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:4260
Numeric numeric_add_safe(Numeric num1, Numeric num2, Node *escontext)
Definition: numeric.c:2882
Numeric int64_div_fast_to_numeric(int64 val1, int log10val2)
Definition: numeric.c:4281
Numeric numeric_div_safe(Numeric num1, Numeric num2, Node *escontext)
Definition: numeric.c:3153
Numeric numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext)
Definition: numeric.c:2958
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:6833
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:6848
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:6946
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
struct IntervalAggState IntervalAggState
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:6751
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:6839
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:6940
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:555
#define FLOAT8_FITS_IN_INT32(num)
Definition: c.h:1092
int64_t int64
Definition: c.h:538
double float8
Definition: c.h:638
#define FLOAT8_FITS_IN_INT64(num)
Definition: c.h:1094
int32_t int32
Definition: c.h:537
#define PG_INT64_MAX
Definition: c.h:600
#define PG_INT64_MIN
Definition: c.h:599
#define unlikely(x)
Definition: c.h:407
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2411
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
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:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:308
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:684
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_NARGS()
Definition: fmgr.h:203
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:686
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
int DateStyle
Definition: globals.c:125
int IntervalStyle
Definition: globals.c:127
#define newval
Assert(PointerIsAligned(start, uint64))
return str start
const char * str
Datum hashint8extended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:103
Datum hashint8(PG_FUNCTION_ARGS)
Definition: hashfunc.c:83
#define MAXDATEFIELDS
Definition: datetime.h:202
#define DTK_EPOCH
Definition: datetime.h:152
#define TMODULO(t, q, u)
Definition: datetime.h:248
#define UNKNOWN_FIELD
Definition: datetime.h:124
#define DTK_DECADE
Definition: datetime.h:168
#define DTK_SECOND
Definition: datetime.h:160
#define DTERR_INTERVAL_OVERFLOW
Definition: datetime.h:285
#define DTK_QUARTER
Definition: datetime.h:166
#define DTK_JULIAN
Definition: datetime.h:173
#define MONTH
Definition: datetime.h:91
#define DTK_DELTA
Definition: datetime.h:159
#define DTK_TZ_HOUR
Definition: datetime.h:177
#define HOUR
Definition: datetime.h:100
#define DTK_TZ_MINUTE
Definition: datetime.h:178
#define DAY
Definition: datetime.h:93
#define DTK_LATE
Definition: datetime.h:151
#define YEAR
Definition: datetime.h:92
#define DTK_DATE
Definition: datetime.h:144
#define DTK_CENTURY
Definition: datetime.h:169
#define DTK_ISODOW
Definition: datetime.h:180
#define DTK_DAY
Definition: datetime.h:163
#define RESERV
Definition: datetime.h:90
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
#define DTK_DATE_M
Definition: datetime.h:191
#define DTK_MILLENNIUM
Definition: datetime.h:170
#define DTK_EARLY
Definition: datetime.h:150
#define DTK_ISOYEAR
Definition: datetime.h:179
#define MAXDATELEN
Definition: datetime.h:200
#define SECOND
Definition: datetime.h:102
#define isleap(y)
Definition: datetime.h:271
#define DTK_DOY
Definition: datetime.h:176
#define DTK_TZ
Definition: datetime.h:146
#define TZNAME_FIXED_OFFSET
Definition: datetime.h:299
#define TZNAME_DYNTZ
Definition: datetime.h:300
#define DTERR_TZDISP_OVERFLOW
Definition: datetime.h:286
#define EARLY
Definition: datetime.h:39
#define DTK_HOUR
Definition: datetime.h:162
#define DTK_WEEK
Definition: datetime.h:164
#define MINUTE
Definition: datetime.h:101
#define LATE
Definition: datetime.h:40
#define DTK_MICROSEC
Definition: datetime.h:172
#define DTK_DOW
Definition: datetime.h:175
#define DTK_YEAR
Definition: datetime.h:167
#define DTK_MILLISEC
Definition: datetime.h:171
#define DTK_MONTH
Definition: datetime.h:165
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:283
#define DTK_MINUTE
Definition: datetime.h:161
#define UNITS
Definition: datetime.h:107
long val
Definition: informix.c:689
static int int128_compare(INT128 x, INT128 y)
Definition: int128.h: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
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
static struct pg_tm tm
Definition: localtime.c:104
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void * palloc0(Size size)
Definition: mcxt.c:1395
void * palloc(Size size)
Definition: mcxt.c:1365
#define USE_ISO_DATES
Definition: miscadmin.h:237
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4613
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
Definition: pg_test_fsync.c:72
#define TZ_STRLEN_MAX
Definition: pgtime.h:54
bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
Definition: localtime.c: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:515
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
static char * DatumGetCString(Datum X)
Definition: postgres.h:345
uint64_t Datum
Definition: postgres.h:70
static Datum Float8GetDatum(float8 X)
Definition: postgres.h:492
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:360
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:222
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:635
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:453
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:152
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition: scansup.c:37
struct 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
bool error_occurred
Definition: miscnodes.h:47
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
List * args
Definition: primnodes.h:800
Definition: int128.h:55
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: sortsupport.h:106
PlannerInfo * root
Definition: supportnodes.h:218
int tm_mon
Definition: timestamp.h:86
int tm_year
Definition: timestamp.h:87
int tm_mday
Definition: timestamp.h:85
int64 tm_usec
Definition: timestamp.h:84
int64 tm_hour
Definition: timestamp.h:70
int tm_year
Definition: timestamp.h:73
int tm_mon
Definition: timestamp.h:72
int tm_mday
Definition: timestamp.h:71
int tm_sec
Definition: timestamp.h:68
int tm_min
Definition: timestamp.h:69
int tm_usec
Definition: timestamp.h:67
Definition: pgtime.h:35
int tm_hour
Definition: pgtime.h:38
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_min
Definition: pgtime.h:37
const char * tm_zone
Definition: pgtime.h:46
int tm_sec
Definition: pgtime.h:36
int tm_isdst
Definition: pgtime.h:44
long int tm_gmtoff
Definition: pgtime.h:45
int tm_year
Definition: pgtime.h:41
Definition: pgtz.h:66
Definition: regguts.h:323
Definition: lexi.c:60
Definition: c.h:695
Definition: zic.c:99
int ssup_datum_signed_cmp(Datum x, Datum y, SortSupport ssup)
Definition: tuplesort.c:3144
#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