PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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
2278#if SIZEOF_DATUM < 8
2279/* note: this is used for timestamptz also */
2280static int
2282{
2285
2286 return timestamp_cmp_internal(a, b);
2287}
2288#endif
2289
2290Datum
2292{
2294
2295#if SIZEOF_DATUM >= 8
2296
2297 /*
2298 * If this build has pass-by-value timestamps, then we can use a standard
2299 * comparator function.
2300 */
2301 ssup->comparator = ssup_datum_signed_cmp;
2302#else
2304#endif
2306}
2307
2308/* note: this is used for timestamptz also */
2309static Datum
2310timestamp_decrement(Relation rel, Datum existing, bool *underflow)
2311{
2312 Timestamp texisting = DatumGetTimestamp(existing);
2313
2314 if (texisting == PG_INT64_MIN)
2315 {
2316 /* return value is undefined */
2317 *underflow = true;
2318 return (Datum) 0;
2319 }
2320
2321 *underflow = false;
2322 return TimestampGetDatum(texisting - 1);
2323}
2324
2325/* note: this is used for timestamptz also */
2326static Datum
2327timestamp_increment(Relation rel, Datum existing, bool *overflow)
2328{
2329 Timestamp texisting = DatumGetTimestamp(existing);
2330
2331 if (texisting == PG_INT64_MAX)
2332 {
2333 /* return value is undefined */
2334 *overflow = true;
2335 return (Datum) 0;
2336 }
2337
2338 *overflow = false;
2339 return TimestampGetDatum(texisting + 1);
2340}
2341
2342Datum
2344{
2346
2351
2353}
2354
2355Datum
2357{
2358 return hashint8(fcinfo);
2359}
2360
2361Datum
2363{
2364 return hashint8extended(fcinfo);
2365}
2366
2367Datum
2369{
2370 return hashint8(fcinfo);
2371}
2372
2373Datum
2375{
2376 return hashint8extended(fcinfo);
2377}
2378
2379/*
2380 * Cross-type comparison functions for timestamp vs timestamptz
2381 */
2382
2383int32
2385{
2386 TimestampTz dt1;
2387 int overflow;
2388
2389 dt1 = timestamp2timestamptz_opt_overflow(timestampVal, &overflow);
2390 if (overflow > 0)
2391 {
2392 /* dt1 is larger than any finite timestamp, but less than infinity */
2393 return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1;
2394 }
2395 if (overflow < 0)
2396 {
2397 /* dt1 is less than any finite timestamp, but more than -infinity */
2398 return TIMESTAMP_IS_NOBEGIN(dt2) ? +1 : -1;
2399 }
2400
2401 return timestamptz_cmp_internal(dt1, dt2);
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
2446 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) <= 0);
2447}
2448
2449Datum
2451{
2452 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2454
2455 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) >= 0);
2456}
2457
2458Datum
2460{
2461 Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2463
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
2509 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) >= 0);
2510}
2511
2512Datum
2514{
2516 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2517
2518 PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) <= 0);
2519}
2520
2521Datum
2523{
2525 Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2526
2528}
2529
2530
2531/*
2532 * interval_relop - is interval1 relop interval2
2533 *
2534 * Interval comparison is based on converting interval values to a linear
2535 * representation expressed in the units of the time field (microseconds,
2536 * in the case of integer timestamps) with days assumed to be always 24 hours
2537 * and months assumed to be always 30 days. To avoid overflow, we need a
2538 * wider-than-int64 datatype for the linear representation, so use INT128.
2539 */
2540
2541static inline INT128
2543{
2544 INT128 span;
2545 int64 days;
2546
2547 /*
2548 * Combine the month and day fields into an integral number of days.
2549 * Because the inputs are int32, int64 arithmetic suffices here.
2550 */
2551 days = interval->month * INT64CONST(30);
2552 days += interval->day;
2553
2554 /* Widen time field to 128 bits */
2555 span = int64_to_int128(interval->time);
2556
2557 /* Scale up days to microseconds, forming a 128-bit product */
2559
2560 return span;
2561}
2562
2563static int
2564interval_cmp_internal(const Interval *interval1, const Interval *interval2)
2565{
2566 INT128 span1 = interval_cmp_value(interval1);
2567 INT128 span2 = interval_cmp_value(interval2);
2568
2569 return int128_compare(span1, span2);
2570}
2571
2572static int
2574{
2576 INT128 zero = int64_to_int128(0);
2577
2578 return int128_compare(span, zero);
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_BOOL(interval_cmp_internal(interval1, interval2) <= 0);
2624}
2625
2626Datum
2628{
2629 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2630 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2631
2632 PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) >= 0);
2633}
2634
2635Datum
2637{
2638 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2639 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2640
2641 PG_RETURN_INT32(interval_cmp_internal(interval1, interval2));
2642}
2643
2644/*
2645 * Hashing for intervals
2646 *
2647 * We must produce equal hashvals for values that interval_cmp_internal()
2648 * considers equal. So, compute the net span the same way it does,
2649 * and then hash that.
2650 */
2651Datum
2653{
2656 int64 span64;
2657
2658 /*
2659 * Use only the least significant 64 bits for hashing. The upper 64 bits
2660 * seldom add any useful information, and besides we must do it like this
2661 * for compatibility with hashes calculated before use of INT128 was
2662 * introduced.
2663 */
2664 span64 = int128_to_int64(span);
2665
2667}
2668
2669Datum
2671{
2674 int64 span64;
2675
2676 /* Same approach as interval_hash */
2677 span64 = int128_to_int64(span);
2678
2680 PG_GETARG_DATUM(1));
2681}
2682
2683/* overlaps_timestamp() --- implements the SQL OVERLAPS operator.
2684 *
2685 * Algorithm is per SQL spec. This is much harder than you'd think
2686 * because the spec requires us to deliver a non-null answer in some cases
2687 * where some of the inputs are null.
2688 */
2689Datum
2691{
2692 /*
2693 * The arguments are Timestamps, but we leave them as generic Datums to
2694 * avoid unnecessary conversions between value and reference forms --- not
2695 * to mention possible dereferences of null pointers.
2696 */
2697 Datum ts1 = PG_GETARG_DATUM(0);
2698 Datum te1 = PG_GETARG_DATUM(1);
2699 Datum ts2 = PG_GETARG_DATUM(2);
2700 Datum te2 = PG_GETARG_DATUM(3);
2701 bool ts1IsNull = PG_ARGISNULL(0);
2702 bool te1IsNull = PG_ARGISNULL(1);
2703 bool ts2IsNull = PG_ARGISNULL(2);
2704 bool te2IsNull = PG_ARGISNULL(3);
2705
2706#define TIMESTAMP_GT(t1,t2) \
2707 DatumGetBool(DirectFunctionCall2(timestamp_gt,t1,t2))
2708#define TIMESTAMP_LT(t1,t2) \
2709 DatumGetBool(DirectFunctionCall2(timestamp_lt,t1,t2))
2710
2711 /*
2712 * If both endpoints of interval 1 are null, the result is null (unknown).
2713 * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
2714 * take ts1 as the lesser endpoint.
2715 */
2716 if (ts1IsNull)
2717 {
2718 if (te1IsNull)
2720 /* swap null for non-null */
2721 ts1 = te1;
2722 te1IsNull = true;
2723 }
2724 else if (!te1IsNull)
2725 {
2726 if (TIMESTAMP_GT(ts1, te1))
2727 {
2728 Datum tt = ts1;
2729
2730 ts1 = te1;
2731 te1 = tt;
2732 }
2733 }
2734
2735 /* Likewise for interval 2. */
2736 if (ts2IsNull)
2737 {
2738 if (te2IsNull)
2740 /* swap null for non-null */
2741 ts2 = te2;
2742 te2IsNull = true;
2743 }
2744 else if (!te2IsNull)
2745 {
2746 if (TIMESTAMP_GT(ts2, te2))
2747 {
2748 Datum tt = ts2;
2749
2750 ts2 = te2;
2751 te2 = tt;
2752 }
2753 }
2754
2755 /*
2756 * At this point neither ts1 nor ts2 is null, so we can consider three
2757 * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
2758 */
2759 if (TIMESTAMP_GT(ts1, ts2))
2760 {
2761 /*
2762 * This case is ts1 < te2 OR te1 < te2, which may look redundant but
2763 * in the presence of nulls it's not quite completely so.
2764 */
2765 if (te2IsNull)
2767 if (TIMESTAMP_LT(ts1, te2))
2768 PG_RETURN_BOOL(true);
2769 if (te1IsNull)
2771
2772 /*
2773 * If te1 is not null then we had ts1 <= te1 above, and we just found
2774 * ts1 >= te2, hence te1 >= te2.
2775 */
2776 PG_RETURN_BOOL(false);
2777 }
2778 else if (TIMESTAMP_LT(ts1, ts2))
2779 {
2780 /* This case is ts2 < te1 OR te2 < te1 */
2781 if (te1IsNull)
2783 if (TIMESTAMP_LT(ts2, te1))
2784 PG_RETURN_BOOL(true);
2785 if (te2IsNull)
2787
2788 /*
2789 * If te2 is not null then we had ts2 <= te2 above, and we just found
2790 * ts2 >= te1, hence te2 >= te1.
2791 */
2792 PG_RETURN_BOOL(false);
2793 }
2794 else
2795 {
2796 /*
2797 * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
2798 * rather silly way of saying "true if both are non-null, else null".
2799 */
2800 if (te1IsNull || te2IsNull)
2802 PG_RETURN_BOOL(true);
2803 }
2804
2805#undef TIMESTAMP_GT
2806#undef TIMESTAMP_LT
2807}
2808
2809
2810/*----------------------------------------------------------
2811 * "Arithmetic" operators on date/times.
2812 *---------------------------------------------------------*/
2813
2814Datum
2816{
2819 Timestamp result;
2820
2821 /* use timestamp_cmp_internal to be sure this agrees with comparisons */
2822 if (timestamp_cmp_internal(dt1, dt2) < 0)
2823 result = dt1;
2824 else
2825 result = dt2;
2826 PG_RETURN_TIMESTAMP(result);
2827}
2828
2829Datum
2831{
2834 Timestamp result;
2835
2836 if (timestamp_cmp_internal(dt1, dt2) > 0)
2837 result = dt1;
2838 else
2839 result = dt2;
2840 PG_RETURN_TIMESTAMP(result);
2841}
2842
2843
2844Datum
2846{
2849 Interval *result;
2850
2851 result = (Interval *) palloc(sizeof(Interval));
2852
2853 /*
2854 * Handle infinities.
2855 *
2856 * We treat anything that amounts to "infinity - infinity" as an error,
2857 * since the interval type has nothing equivalent to NaN.
2858 */
2860 {
2861 if (TIMESTAMP_IS_NOBEGIN(dt1))
2862 {
2863 if (TIMESTAMP_IS_NOBEGIN(dt2))
2864 ereport(ERROR,
2865 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2866 errmsg("interval out of range")));
2867 else
2868 INTERVAL_NOBEGIN(result);
2869 }
2870 else if (TIMESTAMP_IS_NOEND(dt1))
2871 {
2872 if (TIMESTAMP_IS_NOEND(dt2))
2873 ereport(ERROR,
2874 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2875 errmsg("interval out of range")));
2876 else
2877 INTERVAL_NOEND(result);
2878 }
2879 else if (TIMESTAMP_IS_NOBEGIN(dt2))
2880 INTERVAL_NOEND(result);
2881 else /* TIMESTAMP_IS_NOEND(dt2) */
2882 INTERVAL_NOBEGIN(result);
2883
2884 PG_RETURN_INTERVAL_P(result);
2885 }
2886
2887 if (unlikely(pg_sub_s64_overflow(dt1, dt2, &result->time)))
2888 ereport(ERROR,
2889 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2890 errmsg("interval out of range")));
2891
2892 result->month = 0;
2893 result->day = 0;
2894
2895 /*----------
2896 * This is wrong, but removing it breaks a lot of regression tests.
2897 * For example:
2898 *
2899 * test=> SET timezone = 'EST5EDT';
2900 * test=> SELECT
2901 * test-> ('2005-10-30 13:22:00-05'::timestamptz -
2902 * test(> '2005-10-29 13:22:00-04'::timestamptz);
2903 * ?column?
2904 * ----------------
2905 * 1 day 01:00:00
2906 * (1 row)
2907 *
2908 * so adding that to the first timestamp gets:
2909 *
2910 * test=> SELECT
2911 * test-> ('2005-10-29 13:22:00-04'::timestamptz +
2912 * test(> ('2005-10-30 13:22:00-05'::timestamptz -
2913 * test(> '2005-10-29 13:22:00-04'::timestamptz)) at time zone 'EST';
2914 * timezone
2915 * --------------------
2916 * 2005-10-30 14:22:00
2917 * (1 row)
2918 *----------
2919 */
2921 IntervalPGetDatum(result)));
2922
2923 PG_RETURN_INTERVAL_P(result);
2924}
2925
2926/*
2927 * interval_justify_interval()
2928 *
2929 * Adjust interval so 'month', 'day', and 'time' portions are within
2930 * customary bounds. Specifically:
2931 *
2932 * 0 <= abs(time) < 24 hours
2933 * 0 <= abs(day) < 30 days
2934 *
2935 * Also, the sign bit on all three fields is made equal, so either
2936 * all three fields are negative or all are positive.
2937 */
2938Datum
2940{
2941 Interval *span = PG_GETARG_INTERVAL_P(0);
2942 Interval *result;
2943 TimeOffset wholeday;
2944 int32 wholemonth;
2945
2946 result = (Interval *) palloc(sizeof(Interval));
2947 result->month = span->month;
2948 result->day = span->day;
2949 result->time = span->time;
2950
2951 /* do nothing for infinite intervals */
2952 if (INTERVAL_NOT_FINITE(result))
2953 PG_RETURN_INTERVAL_P(result);
2954
2955 /* pre-justify days if it might prevent overflow */
2956 if ((result->day > 0 && result->time > 0) ||
2957 (result->day < 0 && result->time < 0))
2958 {
2959 wholemonth = result->day / DAYS_PER_MONTH;
2960 result->day -= wholemonth * DAYS_PER_MONTH;
2961 if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
2962 ereport(ERROR,
2963 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2964 errmsg("interval out of range")));
2965 }
2966
2967 /*
2968 * Since TimeOffset is int64, abs(wholeday) can't exceed about 1.07e8. If
2969 * we pre-justified then abs(result->day) is less than DAYS_PER_MONTH, so
2970 * this addition can't overflow. If we didn't pre-justify, then day and
2971 * time are of different signs, so it still can't overflow.
2972 */
2973 TMODULO(result->time, wholeday, USECS_PER_DAY);
2974 result->day += wholeday;
2975
2976 wholemonth = result->day / DAYS_PER_MONTH;
2977 result->day -= wholemonth * DAYS_PER_MONTH;
2978 if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
2979 ereport(ERROR,
2980 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2981 errmsg("interval out of range")));
2982
2983 if (result->month > 0 &&
2984 (result->day < 0 || (result->day == 0 && result->time < 0)))
2985 {
2986 result->day += DAYS_PER_MONTH;
2987 result->month--;
2988 }
2989 else if (result->month < 0 &&
2990 (result->day > 0 || (result->day == 0 && result->time > 0)))
2991 {
2992 result->day -= DAYS_PER_MONTH;
2993 result->month++;
2994 }
2995
2996 if (result->day > 0 && result->time < 0)
2997 {
2998 result->time += USECS_PER_DAY;
2999 result->day--;
3000 }
3001 else if (result->day < 0 && result->time > 0)
3002 {
3003 result->time -= USECS_PER_DAY;
3004 result->day++;
3005 }
3006
3007 PG_RETURN_INTERVAL_P(result);
3008}
3009
3010/*
3011 * interval_justify_hours()
3012 *
3013 * Adjust interval so 'time' contains less than a whole day, adding
3014 * the excess to 'day'. This is useful for
3015 * situations (such as non-TZ) where '1 day' = '24 hours' is valid,
3016 * e.g. interval subtraction and division.
3017 */
3018Datum
3020{
3021 Interval *span = PG_GETARG_INTERVAL_P(0);
3022 Interval *result;
3023 TimeOffset wholeday;
3024
3025 result = (Interval *) palloc(sizeof(Interval));
3026 result->month = span->month;
3027 result->day = span->day;
3028 result->time = span->time;
3029
3030 /* do nothing for infinite intervals */
3031 if (INTERVAL_NOT_FINITE(result))
3032 PG_RETURN_INTERVAL_P(result);
3033
3034 TMODULO(result->time, wholeday, USECS_PER_DAY);
3035 if (pg_add_s32_overflow(result->day, wholeday, &result->day))
3036 ereport(ERROR,
3037 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3038 errmsg("interval out of range")));
3039
3040 if (result->day > 0 && result->time < 0)
3041 {
3042 result->time += USECS_PER_DAY;
3043 result->day--;
3044 }
3045 else if (result->day < 0 && result->time > 0)
3046 {
3047 result->time -= USECS_PER_DAY;
3048 result->day++;
3049 }
3050
3051 PG_RETURN_INTERVAL_P(result);
3052}
3053
3054/*
3055 * interval_justify_days()
3056 *
3057 * Adjust interval so 'day' contains less than 30 days, adding
3058 * the excess to 'month'.
3059 */
3060Datum
3062{
3063 Interval *span = PG_GETARG_INTERVAL_P(0);
3064 Interval *result;
3065 int32 wholemonth;
3066
3067 result = (Interval *) palloc(sizeof(Interval));
3068 result->month = span->month;
3069 result->day = span->day;
3070 result->time = span->time;
3071
3072 /* do nothing for infinite intervals */
3073 if (INTERVAL_NOT_FINITE(result))
3074 PG_RETURN_INTERVAL_P(result);
3075
3076 wholemonth = result->day / DAYS_PER_MONTH;
3077 result->day -= wholemonth * DAYS_PER_MONTH;
3078 if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
3079 ereport(ERROR,
3080 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3081 errmsg("interval out of range")));
3082
3083 if (result->month > 0 && result->day < 0)
3084 {
3085 result->day += DAYS_PER_MONTH;
3086 result->month--;
3087 }
3088 else if (result->month < 0 && result->day > 0)
3089 {
3090 result->day -= DAYS_PER_MONTH;
3091 result->month++;
3092 }
3093
3094 PG_RETURN_INTERVAL_P(result);
3095}
3096
3097/* timestamp_pl_interval()
3098 * Add an interval to a timestamp data type.
3099 * Note that interval has provisions for qualitative year/month and day
3100 * units, so try to do the right thing with them.
3101 * To add a month, increment the month, and use the same day of month.
3102 * Then, if the next month has fewer days, set the day of month
3103 * to the last day of month.
3104 * To add a day, increment the mday, and use the same time of day.
3105 * Lastly, add in the "quantitative time".
3106 */
3107Datum
3109{
3111 Interval *span = PG_GETARG_INTERVAL_P(1);
3112 Timestamp result;
3113
3114 /*
3115 * Handle infinities.
3116 *
3117 * We treat anything that amounts to "infinity - infinity" as an error,
3118 * since the timestamp type has nothing equivalent to NaN.
3119 */
3120 if (INTERVAL_IS_NOBEGIN(span))
3121 {
3123 ereport(ERROR,
3124 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3125 errmsg("timestamp out of range")));
3126 else
3127 TIMESTAMP_NOBEGIN(result);
3128 }
3129 else if (INTERVAL_IS_NOEND(span))
3130 {
3132 ereport(ERROR,
3133 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3134 errmsg("timestamp out of range")));
3135 else
3136 TIMESTAMP_NOEND(result);
3137 }
3139 result = timestamp;
3140 else
3141 {
3142 if (span->month != 0)
3143 {
3144 struct pg_tm tt,
3145 *tm = &tt;
3146 fsec_t fsec;
3147
3148 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
3149 ereport(ERROR,
3150 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3151 errmsg("timestamp out of range")));
3152
3153 if (pg_add_s32_overflow(tm->tm_mon, span->month, &tm->tm_mon))
3154 ereport(ERROR,
3155 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3156 errmsg("timestamp out of range")));
3157 if (tm->tm_mon > MONTHS_PER_YEAR)
3158 {
3159 tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
3160 tm->tm_mon = ((tm->tm_mon - 1) % MONTHS_PER_YEAR) + 1;
3161 }
3162 else if (tm->tm_mon < 1)
3163 {
3164 tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;
3166 }
3167
3168 /* adjust for end of month boundary problems... */
3169 if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
3170 tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
3171
3172 if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)
3173 ereport(ERROR,
3174 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3175 errmsg("timestamp out of range")));
3176 }
3177
3178 if (span->day != 0)
3179 {
3180 struct pg_tm tt,
3181 *tm = &tt;
3182 fsec_t fsec;
3183 int julian;
3184
3185 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
3186 ereport(ERROR,
3187 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3188 errmsg("timestamp out of range")));
3189
3190 /*
3191 * Add days by converting to and from Julian. We need an overflow
3192 * check here since j2date expects a non-negative integer input.
3193 */
3194 julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3195 if (pg_add_s32_overflow(julian, span->day, &julian) ||
3196 julian < 0)
3197 ereport(ERROR,
3198 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3199 errmsg("timestamp out of range")));
3200 j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3201
3202 if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)
3203 ereport(ERROR,
3204 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3205 errmsg("timestamp out of range")));
3206 }
3207
3209 ereport(ERROR,
3210 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3211 errmsg("timestamp out of range")));
3212
3214 ereport(ERROR,
3215 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3216 errmsg("timestamp out of range")));
3217
3218 result = timestamp;
3219 }
3220
3221 PG_RETURN_TIMESTAMP(result);
3222}
3223
3224Datum
3226{
3228 Interval *span = PG_GETARG_INTERVAL_P(1);
3229 Interval tspan;
3230
3231 interval_um_internal(span, &tspan);
3232
3235 PointerGetDatum(&tspan));
3236}
3237
3238
3239/* timestamptz_pl_interval_internal()
3240 * Add an interval to a timestamptz, in the given (or session) timezone.
3241 *
3242 * Note that interval has provisions for qualitative year/month and day
3243 * units, so try to do the right thing with them.
3244 * To add a month, increment the month, and use the same day of month.
3245 * Then, if the next month has fewer days, set the day of month
3246 * to the last day of month.
3247 * To add a day, increment the mday, and use the same time of day.
3248 * Lastly, add in the "quantitative time".
3249 */
3250static TimestampTz
3252 Interval *span,
3253 pg_tz *attimezone)
3254{
3255 TimestampTz result;
3256 int tz;
3257
3258 /*
3259 * Handle infinities.
3260 *
3261 * We treat anything that amounts to "infinity - infinity" as an error,
3262 * since the timestamptz type has nothing equivalent to NaN.
3263 */
3264 if (INTERVAL_IS_NOBEGIN(span))
3265 {
3267 ereport(ERROR,
3268 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3269 errmsg("timestamp out of range")));
3270 else
3271 TIMESTAMP_NOBEGIN(result);
3272 }
3273 else if (INTERVAL_IS_NOEND(span))
3274 {
3276 ereport(ERROR,
3277 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3278 errmsg("timestamp out of range")));
3279 else
3280 TIMESTAMP_NOEND(result);
3281 }
3283 result = timestamp;
3284 else
3285 {
3286 /* Use session timezone if caller asks for default */
3287 if (attimezone == NULL)
3288 attimezone = session_timezone;
3289
3290 if (span->month != 0)
3291 {
3292 struct pg_tm tt,
3293 *tm = &tt;
3294 fsec_t fsec;
3295
3296 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, attimezone) != 0)
3297 ereport(ERROR,
3298 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3299 errmsg("timestamp out of range")));
3300
3301 if (pg_add_s32_overflow(tm->tm_mon, span->month, &tm->tm_mon))
3302 ereport(ERROR,
3303 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3304 errmsg("timestamp out of range")));
3305 if (tm->tm_mon > MONTHS_PER_YEAR)
3306 {
3307 tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
3308 tm->tm_mon = ((tm->tm_mon - 1) % MONTHS_PER_YEAR) + 1;
3309 }
3310 else if (tm->tm_mon < 1)
3311 {
3312 tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;
3314 }
3315
3316 /* adjust for end of month boundary problems... */
3317 if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
3318 tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
3319
3320 tz = DetermineTimeZoneOffset(tm, attimezone);
3321
3322 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
3323 ereport(ERROR,
3324 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3325 errmsg("timestamp out of range")));
3326 }
3327
3328 if (span->day != 0)
3329 {
3330 struct pg_tm tt,
3331 *tm = &tt;
3332 fsec_t fsec;
3333 int julian;
3334
3335 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, attimezone) != 0)
3336 ereport(ERROR,
3337 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3338 errmsg("timestamp out of range")));
3339
3340 /*
3341 * Add days by converting to and from Julian. We need an overflow
3342 * check here since j2date expects a non-negative integer input.
3343 * In practice though, it will give correct answers for small
3344 * negative Julian dates; we should allow -1 to avoid
3345 * timezone-dependent failures, as discussed in timestamp.h.
3346 */
3347 julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3348 if (pg_add_s32_overflow(julian, span->day, &julian) ||
3349 julian < -1)
3350 ereport(ERROR,
3351 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3352 errmsg("timestamp out of range")));
3353 j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3354
3355 tz = DetermineTimeZoneOffset(tm, attimezone);
3356
3357 if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
3358 ereport(ERROR,
3359 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3360 errmsg("timestamp out of range")));
3361 }
3362
3364 ereport(ERROR,
3365 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3366 errmsg("timestamp out of range")));
3367
3369 ereport(ERROR,
3370 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3371 errmsg("timestamp out of range")));
3372
3373 result = timestamp;
3374 }
3375
3376 return result;
3377}
3378
3379/* timestamptz_mi_interval_internal()
3380 * As above, but subtract the interval.
3381 */
3382static TimestampTz
3384 Interval *span,
3385 pg_tz *attimezone)
3386{
3387 Interval tspan;
3388
3389 interval_um_internal(span, &tspan);
3390
3391 return timestamptz_pl_interval_internal(timestamp, &tspan, attimezone);
3392}
3393
3394/* timestamptz_pl_interval()
3395 * Add an interval to a timestamptz, in the session timezone.
3396 */
3397Datum
3399{
3401 Interval *span = PG_GETARG_INTERVAL_P(1);
3402
3404}
3405
3406Datum
3408{
3410 Interval *span = PG_GETARG_INTERVAL_P(1);
3411
3413}
3414
3415/* timestamptz_pl_interval_at_zone()
3416 * Add an interval to a timestamptz, in the specified timezone.
3417 */
3418Datum
3420{
3422 Interval *span = PG_GETARG_INTERVAL_P(1);
3424 pg_tz *attimezone = lookup_timezone(zone);
3425
3427}
3428
3429Datum
3431{
3433 Interval *span = PG_GETARG_INTERVAL_P(1);
3435 pg_tz *attimezone = lookup_timezone(zone);
3436
3438}
3439
3440/* interval_um_internal()
3441 * Negate an interval.
3442 */
3443static void
3445{
3447 INTERVAL_NOEND(result);
3448 else if (INTERVAL_IS_NOEND(interval))
3449 INTERVAL_NOBEGIN(result);
3450 else
3451 {
3452 /* Negate each field, guarding against overflow */
3453 if (pg_sub_s64_overflow(INT64CONST(0), interval->time, &result->time) ||
3454 pg_sub_s32_overflow(0, interval->day, &result->day) ||
3455 pg_sub_s32_overflow(0, interval->month, &result->month) ||
3456 INTERVAL_NOT_FINITE(result))
3457 ereport(ERROR,
3458 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3459 errmsg("interval out of range")));
3460 }
3461}
3462
3463Datum
3465{
3467 Interval *result;
3468
3469 result = (Interval *) palloc(sizeof(Interval));
3471
3472 PG_RETURN_INTERVAL_P(result);
3473}
3474
3475
3476Datum
3478{
3479 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
3480 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
3481 Interval *result;
3482
3483 /* use interval_cmp_internal to be sure this agrees with comparisons */
3484 if (interval_cmp_internal(interval1, interval2) < 0)
3485 result = interval1;
3486 else
3487 result = interval2;
3488 PG_RETURN_INTERVAL_P(result);
3489}
3490
3491Datum
3493{
3494 Interval *interval1 = PG_GETARG_INTERVAL_P(0);
3495 Interval *interval2 = PG_GETARG_INTERVAL_P(1);
3496 Interval *result;
3497
3498 if (interval_cmp_internal(interval1, interval2) > 0)
3499 result = interval1;
3500 else
3501 result = interval2;
3502 PG_RETURN_INTERVAL_P(result);
3503}
3504
3505static void
3506finite_interval_pl(const Interval *span1, const Interval *span2, Interval *result)
3507{
3508 Assert(!INTERVAL_NOT_FINITE(span1));
3509 Assert(!INTERVAL_NOT_FINITE(span2));
3510
3511 if (pg_add_s32_overflow(span1->month, span2->month, &result->month) ||
3512 pg_add_s32_overflow(span1->day, span2->day, &result->day) ||
3513 pg_add_s64_overflow(span1->time, span2->time, &result->time) ||
3514 INTERVAL_NOT_FINITE(result))
3515 ereport(ERROR,
3516 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3517 errmsg("interval out of range")));
3518}
3519
3520Datum
3522{
3523 Interval *span1 = PG_GETARG_INTERVAL_P(0);
3524 Interval *span2 = PG_GETARG_INTERVAL_P(1);
3525 Interval *result;
3526
3527 result = (Interval *) palloc(sizeof(Interval));
3528
3529 /*
3530 * Handle infinities.
3531 *
3532 * We treat anything that amounts to "infinity - infinity" as an error,
3533 * since the interval type has nothing equivalent to NaN.
3534 */
3535 if (INTERVAL_IS_NOBEGIN(span1))
3536 {
3537 if (INTERVAL_IS_NOEND(span2))
3538 ereport(ERROR,
3539 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3540 errmsg("interval out of range")));
3541 else
3542 INTERVAL_NOBEGIN(result);
3543 }
3544 else if (INTERVAL_IS_NOEND(span1))
3545 {
3546 if (INTERVAL_IS_NOBEGIN(span2))
3547 ereport(ERROR,
3548 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3549 errmsg("interval out of range")));
3550 else
3551 INTERVAL_NOEND(result);
3552 }
3553 else if (INTERVAL_NOT_FINITE(span2))
3554 memcpy(result, span2, sizeof(Interval));
3555 else
3556 finite_interval_pl(span1, span2, result);
3557
3558 PG_RETURN_INTERVAL_P(result);
3559}
3560
3561static void
3562finite_interval_mi(const Interval *span1, const Interval *span2, Interval *result)
3563{
3564 Assert(!INTERVAL_NOT_FINITE(span1));
3565 Assert(!INTERVAL_NOT_FINITE(span2));
3566
3567 if (pg_sub_s32_overflow(span1->month, span2->month, &result->month) ||
3568 pg_sub_s32_overflow(span1->day, span2->day, &result->day) ||
3569 pg_sub_s64_overflow(span1->time, span2->time, &result->time) ||
3570 INTERVAL_NOT_FINITE(result))
3571 ereport(ERROR,
3572 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3573 errmsg("interval out of range")));
3574}
3575
3576Datum
3578{
3579 Interval *span1 = PG_GETARG_INTERVAL_P(0);
3580 Interval *span2 = PG_GETARG_INTERVAL_P(1);
3581 Interval *result;
3582
3583 result = (Interval *) palloc(sizeof(Interval));
3584
3585 /*
3586 * Handle infinities.
3587 *
3588 * We treat anything that amounts to "infinity - infinity" as an error,
3589 * since the interval type has nothing equivalent to NaN.
3590 */
3591 if (INTERVAL_IS_NOBEGIN(span1))
3592 {
3593 if (INTERVAL_IS_NOBEGIN(span2))
3594 ereport(ERROR,
3595 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3596 errmsg("interval out of range")));
3597 else
3598 INTERVAL_NOBEGIN(result);
3599 }
3600 else if (INTERVAL_IS_NOEND(span1))
3601 {
3602 if (INTERVAL_IS_NOEND(span2))
3603 ereport(ERROR,
3604 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3605 errmsg("interval out of range")));
3606 else
3607 INTERVAL_NOEND(result);
3608 }
3609 else if (INTERVAL_IS_NOBEGIN(span2))
3610 INTERVAL_NOEND(result);
3611 else if (INTERVAL_IS_NOEND(span2))
3612 INTERVAL_NOBEGIN(result);
3613 else
3614 finite_interval_mi(span1, span2, result);
3615
3616 PG_RETURN_INTERVAL_P(result);
3617}
3618
3619/*
3620 * There is no interval_abs(): it is unclear what value to return:
3621 * http://archives.postgresql.org/pgsql-general/2009-10/msg01031.php
3622 * http://archives.postgresql.org/pgsql-general/2009-11/msg00041.php
3623 */
3624
3625Datum
3627{
3628 Interval *span = PG_GETARG_INTERVAL_P(0);
3629 float8 factor = PG_GETARG_FLOAT8(1);
3630 double month_remainder_days,
3631 sec_remainder,
3632 result_double;
3633 int32 orig_month = span->month,
3634 orig_day = span->day;
3635 Interval *result;
3636
3637 result = (Interval *) palloc(sizeof(Interval));
3638
3639 /*
3640 * Handle NaN and infinities.
3641 *
3642 * We treat "0 * infinity" and "infinity * 0" as errors, since the
3643 * interval type has nothing equivalent to NaN.
3644 */
3645 if (isnan(factor))
3646 goto out_of_range;
3647
3648 if (INTERVAL_NOT_FINITE(span))
3649 {
3650 if (factor == 0.0)
3651 goto out_of_range;
3652
3653 if (factor < 0.0)
3654 interval_um_internal(span, result);
3655 else
3656 memcpy(result, span, sizeof(Interval));
3657
3658 PG_RETURN_INTERVAL_P(result);
3659 }
3660 if (isinf(factor))
3661 {
3662 int isign = interval_sign(span);
3663
3664 if (isign == 0)
3665 goto out_of_range;
3666
3667 if (factor * isign < 0)
3668 INTERVAL_NOBEGIN(result);
3669 else
3670 INTERVAL_NOEND(result);
3671
3672 PG_RETURN_INTERVAL_P(result);
3673 }
3674
3675 result_double = span->month * factor;
3676 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3677 goto out_of_range;
3678 result->month = (int32) result_double;
3679
3680 result_double = span->day * factor;
3681 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3682 goto out_of_range;
3683 result->day = (int32) result_double;
3684
3685 /*
3686 * The above correctly handles the whole-number part of the month and day
3687 * products, but we have to do something with any fractional part
3688 * resulting when the factor is non-integral. We cascade the fractions
3689 * down to lower units using the conversion factors DAYS_PER_MONTH and
3690 * SECS_PER_DAY. Note we do NOT cascade up, since we are not forced to do
3691 * so by the representation. The user can choose to cascade up later,
3692 * using justify_hours and/or justify_days.
3693 */
3694
3695 /*
3696 * Fractional months full days into days.
3697 *
3698 * Floating point calculation are inherently imprecise, so these
3699 * calculations are crafted to produce the most reliable result possible.
3700 * TSROUND() is needed to more accurately produce whole numbers where
3701 * appropriate.
3702 */
3703 month_remainder_days = (orig_month * factor - result->month) * DAYS_PER_MONTH;
3704 month_remainder_days = TSROUND(month_remainder_days);
3705 sec_remainder = (orig_day * factor - result->day +
3706 month_remainder_days - (int) month_remainder_days) * SECS_PER_DAY;
3707 sec_remainder = TSROUND(sec_remainder);
3708
3709 /*
3710 * Might have 24:00:00 hours due to rounding, or >24 hours because of time
3711 * cascade from months and days. It might still be >24 if the combination
3712 * of cascade and the seconds factor operation itself.
3713 */
3714 if (fabs(sec_remainder) >= SECS_PER_DAY)
3715 {
3716 if (pg_add_s32_overflow(result->day,
3717 (int) (sec_remainder / SECS_PER_DAY),
3718 &result->day))
3719 goto out_of_range;
3720 sec_remainder -= (int) (sec_remainder / SECS_PER_DAY) * SECS_PER_DAY;
3721 }
3722
3723 /* cascade units down */
3724 if (pg_add_s32_overflow(result->day, (int32) month_remainder_days,
3725 &result->day))
3726 goto out_of_range;
3727 result_double = rint(span->time * factor + sec_remainder * USECS_PER_SEC);
3728 if (isnan(result_double) || !FLOAT8_FITS_IN_INT64(result_double))
3729 goto out_of_range;
3730 result->time = (int64) result_double;
3731
3732 if (INTERVAL_NOT_FINITE(result))
3733 goto out_of_range;
3734
3735 PG_RETURN_INTERVAL_P(result);
3736
3737out_of_range:
3738 ereport(ERROR,
3739 errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3740 errmsg("interval out of range"));
3741
3742 PG_RETURN_NULL(); /* keep compiler quiet */
3743}
3744
3745Datum
3747{
3748 /* Args are float8 and Interval *, but leave them as generic Datum */
3749 Datum factor = PG_GETARG_DATUM(0);
3750 Datum span = PG_GETARG_DATUM(1);
3751
3752 return DirectFunctionCall2(interval_mul, span, factor);
3753}
3754
3755Datum
3757{
3758 Interval *span = PG_GETARG_INTERVAL_P(0);
3759 float8 factor = PG_GETARG_FLOAT8(1);
3760 double month_remainder_days,
3761 sec_remainder,
3762 result_double;
3763 int32 orig_month = span->month,
3764 orig_day = span->day;
3765 Interval *result;
3766
3767 result = (Interval *) palloc(sizeof(Interval));
3768
3769 if (factor == 0.0)
3770 ereport(ERROR,
3771 (errcode(ERRCODE_DIVISION_BY_ZERO),
3772 errmsg("division by zero")));
3773
3774 /*
3775 * Handle NaN and infinities.
3776 *
3777 * We treat "infinity / infinity" as an error, since the interval type has
3778 * nothing equivalent to NaN. Otherwise, dividing by infinity is handled
3779 * by the regular division code, causing all fields to be set to zero.
3780 */
3781 if (isnan(factor))
3782 goto out_of_range;
3783
3784 if (INTERVAL_NOT_FINITE(span))
3785 {
3786 if (isinf(factor))
3787 goto out_of_range;
3788
3789 if (factor < 0.0)
3790 interval_um_internal(span, result);
3791 else
3792 memcpy(result, span, sizeof(Interval));
3793
3794 PG_RETURN_INTERVAL_P(result);
3795 }
3796
3797 result_double = span->month / factor;
3798 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3799 goto out_of_range;
3800 result->month = (int32) result_double;
3801
3802 result_double = span->day / factor;
3803 if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3804 goto out_of_range;
3805 result->day = (int32) result_double;
3806
3807 /*
3808 * Fractional months full days into days. See comment in interval_mul().
3809 */
3810 month_remainder_days = (orig_month / factor - result->month) * DAYS_PER_MONTH;
3811 month_remainder_days = TSROUND(month_remainder_days);
3812 sec_remainder = (orig_day / factor - result->day +
3813 month_remainder_days - (int) month_remainder_days) * SECS_PER_DAY;
3814 sec_remainder = TSROUND(sec_remainder);
3815 if (fabs(sec_remainder) >= SECS_PER_DAY)
3816 {
3817 if (pg_add_s32_overflow(result->day,
3818 (int) (sec_remainder / SECS_PER_DAY),
3819 &result->day))
3820 goto out_of_range;
3821 sec_remainder -= (int) (sec_remainder / SECS_PER_DAY) * SECS_PER_DAY;
3822 }
3823
3824 /* cascade units down */
3825 if (pg_add_s32_overflow(result->day, (int32) month_remainder_days,
3826 &result->day))
3827 goto out_of_range;
3828 result_double = rint(span->time / factor + sec_remainder * USECS_PER_SEC);
3829 if (isnan(result_double) || !FLOAT8_FITS_IN_INT64(result_double))
3830 goto out_of_range;
3831 result->time = (int64) result_double;
3832
3833 if (INTERVAL_NOT_FINITE(result))
3834 goto out_of_range;
3835
3836 PG_RETURN_INTERVAL_P(result);
3837
3838out_of_range:
3839 ereport(ERROR,
3840 errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3841 errmsg("interval out of range"));
3842
3843 PG_RETURN_NULL(); /* keep compiler quiet */
3844}
3845
3846
3847/*
3848 * in_range support functions for timestamps and intervals.
3849 *
3850 * Per SQL spec, we support these with interval as the offset type.
3851 * The spec's restriction that the offset not be negative is a bit hard to
3852 * decipher for intervals, but we choose to interpret it the same as our
3853 * interval comparison operators would.
3854 */
3855
3856Datum
3858{
3861 Interval *offset = PG_GETARG_INTERVAL_P(2);
3862 bool sub = PG_GETARG_BOOL(3);
3863 bool less = PG_GETARG_BOOL(4);
3864 TimestampTz sum;
3865
3866 if (interval_sign(offset) < 0)
3867 ereport(ERROR,
3868 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
3869 errmsg("invalid preceding or following size in window function")));
3870
3871 /*
3872 * Deal with cases where both base and offset are infinite, and computing
3873 * base +/- offset would cause an error. As for float and numeric types,
3874 * we assume that all values infinitely precede +infinity and infinitely
3875 * follow -infinity. See in_range_float8_float8() for reasoning.
3876 */
3877 if (INTERVAL_IS_NOEND(offset) &&
3878 (sub ? TIMESTAMP_IS_NOEND(base) : TIMESTAMP_IS_NOBEGIN(base)))
3879 PG_RETURN_BOOL(true);
3880
3881 /* We don't currently bother to avoid overflow hazards here */
3882 if (sub)
3883 sum = timestamptz_mi_interval_internal(base, offset, NULL);
3884 else
3885 sum = timestamptz_pl_interval_internal(base, offset, NULL);
3886
3887 if (less)
3888 PG_RETURN_BOOL(val <= sum);
3889 else
3890 PG_RETURN_BOOL(val >= sum);
3891}
3892
3893Datum
3895{
3898 Interval *offset = PG_GETARG_INTERVAL_P(2);
3899 bool sub = PG_GETARG_BOOL(3);
3900 bool less = PG_GETARG_BOOL(4);
3901 Timestamp sum;
3902
3903 if (interval_sign(offset) < 0)
3904 ereport(ERROR,
3905 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
3906 errmsg("invalid preceding or following size in window function")));
3907
3908 /*
3909 * Deal with cases where both base and offset are infinite, and computing
3910 * base +/- offset would cause an error. As for float and numeric types,
3911 * we assume that all values infinitely precede +infinity and infinitely
3912 * follow -infinity. See in_range_float8_float8() for reasoning.
3913 */
3914 if (INTERVAL_IS_NOEND(offset) &&
3915 (sub ? TIMESTAMP_IS_NOEND(base) : TIMESTAMP_IS_NOBEGIN(base)))
3916 PG_RETURN_BOOL(true);
3917
3918 /* We don't currently bother to avoid overflow hazards here */
3919 if (sub)
3921 TimestampGetDatum(base),
3922 IntervalPGetDatum(offset)));
3923 else
3925 TimestampGetDatum(base),
3926 IntervalPGetDatum(offset)));
3927
3928 if (less)
3929 PG_RETURN_BOOL(val <= sum);
3930 else
3931 PG_RETURN_BOOL(val >= sum);
3932}
3933
3934Datum
3936{
3938 Interval *base = PG_GETARG_INTERVAL_P(1);
3939 Interval *offset = PG_GETARG_INTERVAL_P(2);
3940 bool sub = PG_GETARG_BOOL(3);
3941 bool less = PG_GETARG_BOOL(4);
3942 Interval *sum;
3943
3944 if (interval_sign(offset) < 0)
3945 ereport(ERROR,
3946 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
3947 errmsg("invalid preceding or following size in window function")));
3948
3949 /*
3950 * Deal with cases where both base and offset are infinite, and computing
3951 * base +/- offset would cause an error. As for float and numeric types,
3952 * we assume that all values infinitely precede +infinity and infinitely
3953 * follow -infinity. See in_range_float8_float8() for reasoning.
3954 */
3955 if (INTERVAL_IS_NOEND(offset) &&
3956 (sub ? INTERVAL_IS_NOEND(base) : INTERVAL_IS_NOBEGIN(base)))
3957 PG_RETURN_BOOL(true);
3958
3959 /* We don't currently bother to avoid overflow hazards here */
3960 if (sub)
3962 IntervalPGetDatum(base),
3963 IntervalPGetDatum(offset)));
3964 else
3966 IntervalPGetDatum(base),
3967 IntervalPGetDatum(offset)));
3968
3969 if (less)
3971 else
3973}
3974
3975
3976/*
3977 * Prepare state data for an interval aggregate function, that needs to compute
3978 * sum and count, in the aggregate's memory context.
3979 *
3980 * The function is used when the state data needs to be allocated in aggregate's
3981 * context. When the state data needs to be allocated in the current memory
3982 * context, we use palloc0 directly e.g. interval_avg_deserialize().
3983 */
3984static IntervalAggState *
3986{
3988 MemoryContext agg_context;
3989 MemoryContext old_context;
3990
3991 if (!AggCheckCallContext(fcinfo, &agg_context))
3992 elog(ERROR, "aggregate function called in non-aggregate context");
3993
3994 old_context = MemoryContextSwitchTo(agg_context);
3995
3997
3998 MemoryContextSwitchTo(old_context);
3999
4000 return state;
4001}
4002
4003/*
4004 * Accumulate a new input value for interval aggregate functions.
4005 */
4006static void
4008{
4009 /* Infinite inputs are counted separately, and do not affect "N" */
4011 {
4012 state->nInfcount++;
4013 return;
4014 }
4015
4017 {
4018 state->pInfcount++;
4019 return;
4020 }
4021
4022 finite_interval_pl(&state->sumX, newval, &state->sumX);
4023 state->N++;
4024}
4025
4026/*
4027 * Remove the given interval value from the aggregated state.
4028 */
4029static void
4031{
4032 /* Infinite inputs are counted separately, and do not affect "N" */
4034 {
4035 state->nInfcount--;
4036 return;
4037 }
4038
4040 {
4041 state->pInfcount--;
4042 return;
4043 }
4044
4045 /* Handle the to-be-discarded finite value. */
4046 state->N--;
4047 if (state->N > 0)
4048 finite_interval_mi(&state->sumX, newval, &state->sumX);
4049 else
4050 {
4051 /* All values discarded, reset the state */
4052 Assert(state->N == 0);
4053 memset(&state->sumX, 0, sizeof(state->sumX));
4054 }
4055}
4056
4057/*
4058 * Transition function for sum() and avg() interval aggregates.
4059 */
4060Datum
4062{
4064
4066
4067 /* Create the state data on the first call */
4068 if (state == NULL)
4069 state = makeIntervalAggState(fcinfo);
4070
4071 if (!PG_ARGISNULL(1))
4073
4075}
4076
4077/*
4078 * Combine function for sum() and avg() interval aggregates.
4079 *
4080 * Combine the given internal aggregate states and place the combination in
4081 * the first argument.
4082 */
4083Datum
4085{
4086 IntervalAggState *state1;
4087 IntervalAggState *state2;
4088
4089 state1 = PG_ARGISNULL(0) ? NULL : (IntervalAggState *) PG_GETARG_POINTER(0);
4090 state2 = PG_ARGISNULL(1) ? NULL : (IntervalAggState *) PG_GETARG_POINTER(1);
4091
4092 if (state2 == NULL)
4093 PG_RETURN_POINTER(state1);
4094
4095 if (state1 == NULL)
4096 {
4097 /* manually copy all fields from state2 to state1 */
4098 state1 = makeIntervalAggState(fcinfo);
4099
4100 state1->N = state2->N;
4101 state1->pInfcount = state2->pInfcount;
4102 state1->nInfcount = state2->nInfcount;
4103
4104 state1->sumX.day = state2->sumX.day;
4105 state1->sumX.month = state2->sumX.month;
4106 state1->sumX.time = state2->sumX.time;
4107
4108 PG_RETURN_POINTER(state1);
4109 }
4110
4111 state1->N += state2->N;
4112 state1->pInfcount += state2->pInfcount;
4113 state1->nInfcount += state2->nInfcount;
4114
4115 /* Accumulate finite interval values, if any. */
4116 if (state2->N > 0)
4117 finite_interval_pl(&state1->sumX, &state2->sumX, &state1->sumX);
4118
4119 PG_RETURN_POINTER(state1);
4120}
4121
4122/*
4123 * interval_avg_serialize
4124 * Serialize IntervalAggState for interval aggregates.
4125 */
4126Datum
4128{
4131 bytea *result;
4132
4133 /* Ensure we disallow calling when not in aggregate context */
4134 if (!AggCheckCallContext(fcinfo, NULL))
4135 elog(ERROR, "aggregate function called in non-aggregate context");
4136
4138
4140
4141 /* N */
4142 pq_sendint64(&buf, state->N);
4143
4144 /* sumX */
4145 pq_sendint64(&buf, state->sumX.time);
4146 pq_sendint32(&buf, state->sumX.day);
4147 pq_sendint32(&buf, state->sumX.month);
4148
4149 /* pInfcount */
4150 pq_sendint64(&buf, state->pInfcount);
4151
4152 /* nInfcount */
4153 pq_sendint64(&buf, state->nInfcount);
4154
4155 result = pq_endtypsend(&buf);
4156
4157 PG_RETURN_BYTEA_P(result);
4158}
4159
4160/*
4161 * interval_avg_deserialize
4162 * Deserialize bytea into IntervalAggState for interval aggregates.
4163 */
4164Datum
4166{
4167 bytea *sstate;
4168 IntervalAggState *result;
4170
4171 if (!AggCheckCallContext(fcinfo, NULL))
4172 elog(ERROR, "aggregate function called in non-aggregate context");
4173
4174 sstate = PG_GETARG_BYTEA_PP(0);
4175
4176 /*
4177 * Initialize a StringInfo so that we can "receive" it using the standard
4178 * recv-function infrastructure.
4179 */
4181 VARSIZE_ANY_EXHDR(sstate));
4182
4183 result = (IntervalAggState *) palloc0(sizeof(IntervalAggState));
4184
4185 /* N */
4186 result->N = pq_getmsgint64(&buf);
4187
4188 /* sumX */
4189 result->sumX.time = pq_getmsgint64(&buf);
4190 result->sumX.day = pq_getmsgint(&buf, 4);
4191 result->sumX.month = pq_getmsgint(&buf, 4);
4192
4193 /* pInfcount */
4194 result->pInfcount = pq_getmsgint64(&buf);
4195
4196 /* nInfcount */
4197 result->nInfcount = pq_getmsgint64(&buf);
4198
4199 pq_getmsgend(&buf);
4200
4201 PG_RETURN_POINTER(result);
4202}
4203
4204/*
4205 * Inverse transition function for sum() and avg() interval aggregates.
4206 */
4207Datum
4209{
4211
4213
4214 /* Should not get here with no state */
4215 if (state == NULL)
4216 elog(ERROR, "interval_avg_accum_inv called with NULL state");
4217
4218 if (!PG_ARGISNULL(1))
4220
4222}
4223
4224/* avg(interval) aggregate final function */
4225Datum
4227{
4229
4231
4232 /* If there were no non-null inputs, return NULL */
4233 if (state == NULL || IA_TOTAL_COUNT(state) == 0)
4235
4236 /*
4237 * Aggregating infinities that all have the same sign produces infinity
4238 * with that sign. Aggregating infinities with different signs results in
4239 * an error.
4240 */
4241 if (state->pInfcount > 0 || state->nInfcount > 0)
4242 {
4243 Interval *result;
4244
4245 if (state->pInfcount > 0 && state->nInfcount > 0)
4246 ereport(ERROR,
4247 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4248 errmsg("interval out of range")));
4249
4250 result = (Interval *) palloc(sizeof(Interval));
4251 if (state->pInfcount > 0)
4252 INTERVAL_NOEND(result);
4253 else
4254 INTERVAL_NOBEGIN(result);
4255
4256 PG_RETURN_INTERVAL_P(result);
4257 }
4258
4260 IntervalPGetDatum(&state->sumX),
4261 Float8GetDatum((double) state->N));
4262}
4263
4264/* sum(interval) aggregate final function */
4265Datum
4267{
4269 Interval *result;
4270
4272
4273 /* If there were no non-null inputs, return NULL */
4274 if (state == NULL || IA_TOTAL_COUNT(state) == 0)
4276
4277 /*
4278 * Aggregating infinities that all have the same sign produces infinity
4279 * with that sign. Aggregating infinities with different signs results in
4280 * an error.
4281 */
4282 if (state->pInfcount > 0 && state->nInfcount > 0)
4283 ereport(ERROR,
4284 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4285 errmsg("interval out of range")));
4286
4287 result = (Interval *) palloc(sizeof(Interval));
4288
4289 if (state->pInfcount > 0)
4290 INTERVAL_NOEND(result);
4291 else if (state->nInfcount > 0)
4292 INTERVAL_NOBEGIN(result);
4293 else
4294 memcpy(result, &state->sumX, sizeof(Interval));
4295
4296 PG_RETURN_INTERVAL_P(result);
4297}
4298
4299/* timestamp_age()
4300 * Calculate time difference while retaining year/month fields.
4301 * Note that this does not result in an accurate absolute time span
4302 * since year and month are out of context once the arithmetic
4303 * is done.
4304 */
4305Datum
4307{
4310 Interval *result;
4311 fsec_t fsec1,
4312 fsec2;
4313 struct pg_itm tt,
4314 *tm = &tt;
4315 struct pg_tm tt1,
4316 *tm1 = &tt1;
4317 struct pg_tm tt2,
4318 *tm2 = &tt2;
4319
4320 result = (Interval *) palloc(sizeof(Interval));
4321
4322 /*
4323 * Handle infinities.
4324 *
4325 * We treat anything that amounts to "infinity - infinity" as an error,
4326 * since the interval type has nothing equivalent to NaN.
4327 */
4328 if (TIMESTAMP_IS_NOBEGIN(dt1))
4329 {
4330 if (TIMESTAMP_IS_NOBEGIN(dt2))
4331 ereport(ERROR,
4332 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4333 errmsg("interval out of range")));
4334 else
4335 INTERVAL_NOBEGIN(result);
4336 }
4337 else if (TIMESTAMP_IS_NOEND(dt1))
4338 {
4339 if (TIMESTAMP_IS_NOEND(dt2))
4340 ereport(ERROR,
4341 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4342 errmsg("interval out of range")));
4343 else
4344 INTERVAL_NOEND(result);
4345 }
4346 else if (TIMESTAMP_IS_NOBEGIN(dt2))
4347 INTERVAL_NOEND(result);
4348 else if (TIMESTAMP_IS_NOEND(dt2))
4349 INTERVAL_NOBEGIN(result);
4350 else if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL, NULL) == 0 &&
4351 timestamp2tm(dt2, NULL, tm2, &fsec2, NULL, NULL) == 0)
4352 {
4353 /* form the symbolic difference */
4354 tm->tm_usec = fsec1 - fsec2;
4355 tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
4356 tm->tm_min = tm1->tm_min - tm2->tm_min;
4357 tm->tm_hour = tm1->tm_hour - tm2->tm_hour;
4358 tm->tm_mday = tm1->tm_mday - tm2->tm_mday;
4359 tm->tm_mon = tm1->tm_mon - tm2->tm_mon;
4360 tm->tm_year = tm1->tm_year - tm2->tm_year;
4361
4362 /* flip sign if necessary... */
4363 if (dt1 < dt2)
4364 {
4365 tm->tm_usec = -tm->tm_usec;
4366 tm->tm_sec = -tm->tm_sec;
4367 tm->tm_min = -tm->tm_min;
4368 tm->tm_hour = -tm->tm_hour;
4369 tm->tm_mday = -tm->tm_mday;
4370 tm->tm_mon = -tm->tm_mon;
4371 tm->tm_year = -tm->tm_year;
4372 }
4373
4374 /* propagate any negative fields into the next higher field */
4375 while (tm->tm_usec < 0)
4376 {
4377 tm->tm_usec += USECS_PER_SEC;
4378 tm->tm_sec--;
4379 }
4380
4381 while (tm->tm_sec < 0)
4382 {
4384 tm->tm_min--;
4385 }
4386
4387 while (tm->tm_min < 0)
4388 {
4390 tm->tm_hour--;
4391 }
4392
4393 while (tm->tm_hour < 0)
4394 {
4396 tm->tm_mday--;
4397 }
4398
4399 while (tm->tm_mday < 0)
4400 {
4401 if (dt1 < dt2)
4402 {
4403 tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
4404 tm->tm_mon--;
4405 }
4406 else
4407 {
4408 tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
4409 tm->tm_mon--;
4410 }
4411 }
4412
4413 while (tm->tm_mon < 0)
4414 {
4416 tm->tm_year--;
4417 }
4418
4419 /* recover sign if necessary... */
4420 if (dt1 < dt2)
4421 {
4422 tm->tm_usec = -tm->tm_usec;
4423 tm->tm_sec = -tm->tm_sec;
4424 tm->tm_min = -tm->tm_min;
4425 tm->tm_hour = -tm->tm_hour;
4426 tm->tm_mday = -tm->tm_mday;
4427 tm->tm_mon = -tm->tm_mon;
4428 tm->tm_year = -tm->tm_year;
4429 }
4430
4431 if (itm2interval(tm, result) != 0)
4432 ereport(ERROR,
4433 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4434 errmsg("interval out of range")));
4435 }
4436 else
4437 ereport(ERROR,
4438 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4439 errmsg("timestamp out of range")));
4440
4441 PG_RETURN_INTERVAL_P(result);
4442}
4443
4444
4445/* timestamptz_age()
4446 * Calculate time difference while retaining year/month fields.
4447 * Note that this does not result in an accurate absolute time span
4448 * since year and month are out of context once the arithmetic
4449 * is done.
4450 */
4451Datum
4453{
4456 Interval *result;
4457 fsec_t fsec1,
4458 fsec2;
4459 struct pg_itm tt,
4460 *tm = &tt;
4461 struct pg_tm tt1,
4462 *tm1 = &tt1;
4463 struct pg_tm tt2,
4464 *tm2 = &tt2;
4465 int tz1;
4466 int tz2;
4467
4468 result = (Interval *) palloc(sizeof(Interval));
4469
4470 /*
4471 * Handle infinities.
4472 *
4473 * We treat anything that amounts to "infinity - infinity" as an error,
4474 * since the interval type has nothing equivalent to NaN.
4475 */
4476 if (TIMESTAMP_IS_NOBEGIN(dt1))
4477 {
4478 if (TIMESTAMP_IS_NOBEGIN(dt2))
4479 ereport(ERROR,
4480 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4481 errmsg("interval out of range")));
4482 else
4483 INTERVAL_NOBEGIN(result);
4484 }
4485 else if (TIMESTAMP_IS_NOEND(dt1))
4486 {
4487 if (TIMESTAMP_IS_NOEND(dt2))
4488 ereport(ERROR,
4489 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4490 errmsg("interval out of range")));
4491 else
4492 INTERVAL_NOEND(result);
4493 }
4494 else if (TIMESTAMP_IS_NOBEGIN(dt2))
4495 INTERVAL_NOEND(result);
4496 else if (TIMESTAMP_IS_NOEND(dt2))
4497 INTERVAL_NOBEGIN(result);
4498 else if (timestamp2tm(dt1, &tz1, tm1, &fsec1, NULL, NULL) == 0 &&
4499 timestamp2tm(dt2, &tz2, tm2, &fsec2, NULL, NULL) == 0)
4500 {
4501 /* form the symbolic difference */
4502 tm->tm_usec = fsec1 - fsec2;
4503 tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
4504 tm->tm_min = tm1->tm_min - tm2->tm_min;
4505 tm->tm_hour = tm1->tm_hour - tm2->tm_hour;
4506 tm->tm_mday = tm1->tm_mday - tm2->tm_mday;
4507 tm->tm_mon = tm1->tm_mon - tm2->tm_mon;
4508 tm->tm_year = tm1->tm_year - tm2->tm_year;
4509
4510 /* flip sign if necessary... */
4511 if (dt1 < dt2)
4512 {
4513 tm->tm_usec = -tm->tm_usec;
4514 tm->tm_sec = -tm->tm_sec;
4515 tm->tm_min = -tm->tm_min;
4516 tm->tm_hour = -tm->tm_hour;
4517 tm->tm_mday = -tm->tm_mday;
4518 tm->tm_mon = -tm->tm_mon;
4519 tm->tm_year = -tm->tm_year;
4520 }
4521
4522 /* propagate any negative fields into the next higher field */
4523 while (tm->tm_usec < 0)
4524 {
4525 tm->tm_usec += USECS_PER_SEC;
4526 tm->tm_sec--;
4527 }
4528
4529 while (tm->tm_sec < 0)
4530 {
4532 tm->tm_min--;
4533 }
4534
4535 while (tm->tm_min < 0)
4536 {
4538 tm->tm_hour--;
4539 }
4540
4541 while (tm->tm_hour < 0)
4542 {
4544 tm->tm_mday--;
4545 }
4546
4547 while (tm->tm_mday < 0)
4548 {
4549 if (dt1 < dt2)
4550 {
4551 tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
4552 tm->tm_mon--;
4553 }
4554 else
4555 {
4556 tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
4557 tm->tm_mon--;
4558 }
4559 }
4560
4561 while (tm->tm_mon < 0)
4562 {
4564 tm->tm_year--;
4565 }
4566
4567 /*
4568 * Note: we deliberately ignore any difference between tz1 and tz2.
4569 */
4570
4571 /* recover sign if necessary... */
4572 if (dt1 < dt2)
4573 {
4574 tm->tm_usec = -tm->tm_usec;
4575 tm->tm_sec = -tm->tm_sec;
4576 tm->tm_min = -tm->tm_min;
4577 tm->tm_hour = -tm->tm_hour;
4578 tm->tm_mday = -tm->tm_mday;
4579 tm->tm_mon = -tm->tm_mon;
4580 tm->tm_year = -tm->tm_year;
4581 }
4582
4583 if (itm2interval(tm, result) != 0)
4584 ereport(ERROR,
4585 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4586 errmsg("interval out of range")));
4587 }
4588 else
4589 ereport(ERROR,
4590 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4591 errmsg("timestamp out of range")));
4592
4593 PG_RETURN_INTERVAL_P(result);
4594}
4595
4596
4597/*----------------------------------------------------------
4598 * Conversion operators.
4599 *---------------------------------------------------------*/
4600
4601
4602/* timestamp_bin()
4603 * Bin timestamp into specified interval.
4604 */
4605Datum
4607{
4608 Interval *stride = PG_GETARG_INTERVAL_P(0);
4610 Timestamp origin = PG_GETARG_TIMESTAMP(2);
4611 Timestamp result,
4612 stride_usecs,
4613 tm_diff,
4614 tm_modulo,
4615 tm_delta;
4616
4619
4620 if (TIMESTAMP_NOT_FINITE(origin))
4621 ereport(ERROR,
4622 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4623 errmsg("origin out of range")));
4624
4625 if (INTERVAL_NOT_FINITE(stride))
4626 ereport(ERROR,
4627 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4628 errmsg("timestamps cannot be binned into infinite intervals")));
4629
4630 if (stride->month != 0)
4631 ereport(ERROR,
4632 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4633 errmsg("timestamps cannot be binned into intervals containing months or years")));
4634
4635 if (unlikely(pg_mul_s64_overflow(stride->day, USECS_PER_DAY, &stride_usecs)) ||
4636 unlikely(pg_add_s64_overflow(stride_usecs, stride->time, &stride_usecs)))
4637 ereport(ERROR,
4638 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4639 errmsg("interval out of range")));
4640
4641 if (stride_usecs <= 0)
4642 ereport(ERROR,
4643 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4644 errmsg("stride must be greater than zero")));
4645
4646 if (unlikely(pg_sub_s64_overflow(timestamp, origin, &tm_diff)))
4647 ereport(ERROR,
4648 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4649 errmsg("interval out of range")));
4650
4651 /* These calculations cannot overflow */
4652 tm_modulo = tm_diff % stride_usecs;
4653 tm_delta = tm_diff - tm_modulo;
4654 result = origin + tm_delta;
4655
4656 /*
4657 * We want to round towards -infinity, not 0, when tm_diff is negative and
4658 * not a multiple of stride_usecs. This adjustment *can* cause overflow,
4659 * since the result might now be out of the range origin .. timestamp.
4660 */
4661 if (tm_modulo < 0)
4662 {
4663 if (unlikely(pg_sub_s64_overflow(result, stride_usecs, &result)) ||
4664 !IS_VALID_TIMESTAMP(result))
4665 ereport(ERROR,
4666 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4667 errmsg("timestamp out of range")));
4668 }
4669
4670 PG_RETURN_TIMESTAMP(result);
4671}
4672
4673/* timestamp_trunc()
4674 * Truncate timestamp to specified units.
4675 */
4676Datum
4678{
4679 text *units = PG_GETARG_TEXT_PP(0);
4681 Timestamp result;
4682 int type,
4683 val;
4684 char *lowunits;
4685 fsec_t fsec;
4686 struct pg_tm tt,
4687 *tm = &tt;
4688
4689 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
4690 VARSIZE_ANY_EXHDR(units),
4691 false);
4692
4693 type = DecodeUnits(0, lowunits, &val);
4694
4695 if (type == UNITS)
4696 {
4698 {
4699 /*
4700 * Errors thrown here for invalid units should exactly match those
4701 * below, else there will be unexpected discrepancies between
4702 * finite- and infinite-input cases.
4703 */
4704 switch (val)
4705 {
4706 case DTK_WEEK:
4707 case DTK_MILLENNIUM:
4708 case DTK_CENTURY:
4709 case DTK_DECADE:
4710 case DTK_YEAR:
4711 case DTK_QUARTER:
4712 case DTK_MONTH:
4713 case DTK_DAY:
4714 case DTK_HOUR:
4715 case DTK_MINUTE:
4716 case DTK_SECOND:
4717 case DTK_MILLISEC:
4718 case DTK_MICROSEC:
4720 break;
4721 default:
4722 ereport(ERROR,
4723 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4724 errmsg("unit \"%s\" not supported for type %s",
4725 lowunits, format_type_be(TIMESTAMPOID))));
4726 result = 0;
4727 }
4728 }
4729
4730 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
4731 ereport(ERROR,
4732 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4733 errmsg("timestamp out of range")));
4734
4735 switch (val)
4736 {
4737 case DTK_WEEK:
4738 {
4739 int woy;
4740
4742
4743 /*
4744 * If it is week 52/53 and the month is January, then the
4745 * week must belong to the previous year. Also, some
4746 * December dates belong to the next year.
4747 */
4748 if (woy >= 52 && tm->tm_mon == 1)
4749 --tm->tm_year;
4750 if (woy <= 1 && tm->tm_mon == MONTHS_PER_YEAR)
4751 ++tm->tm_year;
4752 isoweek2date(woy, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
4753 tm->tm_hour = 0;
4754 tm->tm_min = 0;
4755 tm->tm_sec = 0;
4756 fsec = 0;
4757 break;
4758 }
4759 case DTK_MILLENNIUM:
4760 /* see comments in timestamptz_trunc */
4761 if (tm->tm_year > 0)
4762 tm->tm_year = ((tm->tm_year + 999) / 1000) * 1000 - 999;
4763 else
4764 tm->tm_year = -((999 - (tm->tm_year - 1)) / 1000) * 1000 + 1;
4765 /* FALL THRU */
4766 case DTK_CENTURY:
4767 /* see comments in timestamptz_trunc */
4768 if (tm->tm_year > 0)
4769 tm->tm_year = ((tm->tm_year + 99) / 100) * 100 - 99;
4770 else
4771 tm->tm_year = -((99 - (tm->tm_year - 1)) / 100) * 100 + 1;
4772 /* FALL THRU */
4773 case DTK_DECADE:
4774 /* see comments in timestamptz_trunc */
4775 if (val != DTK_MILLENNIUM && val != DTK_CENTURY)
4776 {
4777 if (tm->tm_year > 0)
4778 tm->tm_year = (tm->tm_year / 10) * 10;
4779 else
4780 tm->tm_year = -((8 - (tm->tm_year - 1)) / 10) * 10;
4781 }
4782 /* FALL THRU */
4783 case DTK_YEAR:
4784 tm->tm_mon = 1;
4785 /* FALL THRU */
4786 case DTK_QUARTER:
4787 tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1;
4788 /* FALL THRU */
4789 case DTK_MONTH:
4790 tm->tm_mday = 1;
4791 /* FALL THRU */
4792 case DTK_DAY:
4793 tm->tm_hour = 0;
4794 /* FALL THRU */
4795 case DTK_HOUR:
4796 tm->tm_min = 0;
4797 /* FALL THRU */
4798 case DTK_MINUTE:
4799 tm->tm_sec = 0;
4800 /* FALL THRU */
4801 case DTK_SECOND:
4802 fsec = 0;
4803 break;
4804
4805 case DTK_MILLISEC:
4806 fsec = (fsec / 1000) * 1000;
4807 break;
4808
4809 case DTK_MICROSEC:
4810 break;
4811
4812 default:
4813 ereport(ERROR,
4814 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4815 errmsg("unit \"%s\" not supported for type %s",
4816 lowunits, format_type_be(TIMESTAMPOID))));
4817 result = 0;
4818 }
4819
4820 if (tm2timestamp(tm, fsec, NULL, &result) != 0)
4821 ereport(ERROR,
4822 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4823 errmsg("timestamp out of range")));
4824 }
4825 else
4826 {
4827 ereport(ERROR,
4828 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4829 errmsg("unit \"%s\" not recognized for type %s",
4830 lowunits, format_type_be(TIMESTAMPOID))));
4831 result = 0;
4832 }
4833
4834 PG_RETURN_TIMESTAMP(result);
4835}
4836
4837/* timestamptz_bin()
4838 * Bin timestamptz into specified interval using specified origin.
4839 */
4840Datum
4842{
4843 Interval *stride = PG_GETARG_INTERVAL_P(0);
4846 TimestampTz result,
4847 stride_usecs,
4848 tm_diff,
4849 tm_modulo,
4850 tm_delta;
4851
4854
4855 if (TIMESTAMP_NOT_FINITE(origin))
4856 ereport(ERROR,
4857 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4858 errmsg("origin out of range")));
4859
4860 if (INTERVAL_NOT_FINITE(stride))
4861 ereport(ERROR,
4862 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4863 errmsg("timestamps cannot be binned into infinite intervals")));
4864
4865 if (stride->month != 0)
4866 ereport(ERROR,
4867 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4868 errmsg("timestamps cannot be binned into intervals containing months or years")));
4869
4870 if (unlikely(pg_mul_s64_overflow(stride->day, USECS_PER_DAY, &stride_usecs)) ||
4871 unlikely(pg_add_s64_overflow(stride_usecs, stride->time, &stride_usecs)))
4872 ereport(ERROR,
4873 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4874 errmsg("interval out of range")));
4875
4876 if (stride_usecs <= 0)
4877 ereport(ERROR,
4878 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4879 errmsg("stride must be greater than zero")));
4880
4881 if (unlikely(pg_sub_s64_overflow(timestamp, origin, &tm_diff)))
4882 ereport(ERROR,
4883 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4884 errmsg("interval out of range")));
4885
4886 /* These calculations cannot overflow */
4887 tm_modulo = tm_diff % stride_usecs;
4888 tm_delta = tm_diff - tm_modulo;
4889 result = origin + tm_delta;
4890
4891 /*
4892 * We want to round towards -infinity, not 0, when tm_diff is negative and
4893 * not a multiple of stride_usecs. This adjustment *can* cause overflow,
4894 * since the result might now be out of the range origin .. timestamp.
4895 */
4896 if (tm_modulo < 0)
4897 {
4898 if (unlikely(pg_sub_s64_overflow(result, stride_usecs, &result)) ||
4899 !IS_VALID_TIMESTAMP(result))
4900 ereport(ERROR,
4901 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4902 errmsg("timestamp out of range")));
4903 }
4904
4905 PG_RETURN_TIMESTAMPTZ(result);
4906}
4907
4908/*
4909 * Common code for timestamptz_trunc() and timestamptz_trunc_zone().
4910 *
4911 * tzp identifies the zone to truncate with respect to. We assume
4912 * infinite timestamps have already been rejected.
4913 */
4914static TimestampTz
4916{
4917 TimestampTz result;
4918 int tz;
4919 int type,
4920 val;
4921 bool redotz = false;
4922 char *lowunits;
4923 fsec_t fsec;
4924 struct pg_tm tt,
4925 *tm = &tt;
4926
4927 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
4928 VARSIZE_ANY_EXHDR(units),
4929 false);
4930
4931 type = DecodeUnits(0, lowunits, &val);
4932
4933 if (type == UNITS)
4934 {
4936 {
4937 /*
4938 * Errors thrown here for invalid units should exactly match those
4939 * below, else there will be unexpected discrepancies between
4940 * finite- and infinite-input cases.
4941 */
4942 switch (val)
4943 {
4944 case DTK_WEEK:
4945 case DTK_MILLENNIUM:
4946 case DTK_CENTURY:
4947 case DTK_DECADE:
4948 case DTK_YEAR:
4949 case DTK_QUARTER:
4950 case DTK_MONTH:
4951 case DTK_DAY:
4952 case DTK_HOUR:
4953 case DTK_MINUTE:
4954 case DTK_SECOND:
4955 case DTK_MILLISEC:
4956 case DTK_MICROSEC:
4958 break;
4959
4960 default:
4961 ereport(ERROR,
4962 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4963 errmsg("unit \"%s\" not supported for type %s",
4964 lowunits, format_type_be(TIMESTAMPTZOID))));
4965 result = 0;
4966 }
4967 }
4968
4969 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, tzp) != 0)
4970 ereport(ERROR,
4971 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4972 errmsg("timestamp out of range")));
4973
4974 switch (val)
4975 {
4976 case DTK_WEEK:
4977 {
4978 int woy;
4979
4981
4982 /*
4983 * If it is week 52/53 and the month is January, then the
4984 * week must belong to the previous year. Also, some
4985 * December dates belong to the next year.
4986 */
4987 if (woy >= 52 && tm->tm_mon == 1)
4988 --tm->tm_year;
4989 if (woy <= 1 && tm->tm_mon == MONTHS_PER_YEAR)
4990 ++tm->tm_year;
4991 isoweek2date(woy, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
4992 tm->tm_hour = 0;
4993 tm->tm_min = 0;
4994 tm->tm_sec = 0;
4995 fsec = 0;
4996 redotz = true;
4997 break;
4998 }
4999 /* one may consider DTK_THOUSAND and DTK_HUNDRED... */
5000 case DTK_MILLENNIUM:
5001
5002 /*
5003 * truncating to the millennium? what is this supposed to
5004 * mean? let us put the first year of the millennium... i.e.
5005 * -1000, 1, 1001, 2001...
5006 */
5007 if (tm->tm_year > 0)
5008 tm->tm_year = ((tm->tm_year + 999) / 1000) * 1000 - 999;
5009 else
5010 tm->tm_year = -((999 - (tm->tm_year - 1)) / 1000) * 1000 + 1;
5011 /* FALL THRU */
5012 case DTK_CENTURY:
5013 /* truncating to the century? as above: -100, 1, 101... */
5014 if (tm->tm_year > 0)
5015 tm->tm_year = ((tm->tm_year + 99) / 100) * 100 - 99;
5016 else
5017 tm->tm_year = -((99 - (tm->tm_year - 1)) / 100) * 100 + 1;
5018 /* FALL THRU */
5019 case DTK_DECADE:
5020
5021 /*
5022 * truncating to the decade? first year of the decade. must
5023 * not be applied if year was truncated before!
5024 */
5025 if (val != DTK_MILLENNIUM && val != DTK_CENTURY)
5026 {
5027 if (tm->tm_year > 0)
5028 tm->tm_year = (tm->tm_year / 10) * 10;
5029 else
5030 tm->tm_year = -((8 - (tm->tm_year - 1)) / 10) * 10;
5031 }
5032 /* FALL THRU */
5033 case DTK_YEAR:
5034 tm->tm_mon = 1;
5035 /* FALL THRU */
5036 case DTK_QUARTER:
5037 tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1;
5038 /* FALL THRU */
5039 case DTK_MONTH:
5040 tm->tm_mday = 1;
5041 /* FALL THRU */
5042 case DTK_DAY:
5043 tm->tm_hour = 0;
5044 redotz = true; /* for all cases >= DAY */
5045 /* FALL THRU */
5046 case DTK_HOUR:
5047 tm->tm_min = 0;
5048 /* FALL THRU */
5049 case DTK_MINUTE:
5050 tm->tm_sec = 0;
5051 /* FALL THRU */
5052 case DTK_SECOND:
5053 fsec = 0;
5054 break;
5055 case DTK_MILLISEC:
5056 fsec = (fsec / 1000) * 1000;
5057 break;
5058 case DTK_MICROSEC:
5059 break;
5060
5061 default:
5062 ereport(ERROR,
5063 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5064 errmsg("unit \"%s\" not supported for type %s",
5065 lowunits, format_type_be(TIMESTAMPTZOID))));
5066 result = 0;
5067 }
5068
5069 if (redotz)
5070 tz = DetermineTimeZoneOffset(tm, tzp);
5071
5072 if (tm2timestamp(tm, fsec, &tz, &result) != 0)
5073 ereport(ERROR,
5074 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5075 errmsg("timestamp out of range")));
5076 }
5077 else
5078 {
5079 ereport(ERROR,
5080 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5081 errmsg("unit \"%s\" not recognized for type %s",
5082 lowunits, format_type_be(TIMESTAMPTZOID))));
5083 result = 0;
5084 }
5085
5086 return result;
5087}
5088
5089/* timestamptz_trunc()
5090 * Truncate timestamptz to specified units in session timezone.
5091 */
5092Datum
5094{
5095 text *units = PG_GETARG_TEXT_PP(0);
5097 TimestampTz result;
5098
5100
5101 PG_RETURN_TIMESTAMPTZ(result);
5102}
5103
5104/* timestamptz_trunc_zone()
5105 * Truncate timestamptz to specified units in specified timezone.
5106 */
5107Datum
5109{
5110 text *units = PG_GETARG_TEXT_PP(0);
5113 TimestampTz result;
5114 pg_tz *tzp;
5115
5116 /*
5117 * Look up the requested timezone.
5118 */
5119 tzp = lookup_timezone(zone);
5120
5121 result = timestamptz_trunc_internal(units, timestamp, tzp);
5122
5123 PG_RETURN_TIMESTAMPTZ(result);
5124}
5125
5126/* interval_trunc()
5127 * Extract specified field from interval.
5128 */
5129Datum
5131{
5132 text *units = PG_GETARG_TEXT_PP(0);
5134 Interval *result;
5135 int type,
5136 val;
5137 char *lowunits;
5138 struct pg_itm tt,
5139 *tm = &tt;
5140
5141 result = (Interval *) palloc(sizeof(Interval));
5142
5143 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
5144 VARSIZE_ANY_EXHDR(units),
5145 false);
5146
5147 type = DecodeUnits(0, lowunits, &val);
5148
5149 if (type == UNITS)
5150 {
5152 {
5153 /*
5154 * Errors thrown here for invalid units should exactly match those
5155 * below, else there will be unexpected discrepancies between
5156 * finite- and infinite-input cases.
5157 */
5158 switch (val)
5159 {
5160 case DTK_MILLENNIUM:
5161 case DTK_CENTURY:
5162 case DTK_DECADE:
5163 case DTK_YEAR:
5164 case DTK_QUARTER:
5165 case DTK_MONTH:
5166 case DTK_DAY:
5167 case DTK_HOUR:
5168 case DTK_MINUTE:
5169 case DTK_SECOND:
5170 case DTK_MILLISEC:
5171 case DTK_MICROSEC:
5172 memcpy(result, interval, sizeof(Interval));
5173 PG_RETURN_INTERVAL_P(result);
5174 break;
5175
5176 default:
5177 ereport(ERROR,
5178 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5179 errmsg("unit \"%s\" not supported for type %s",
5180 lowunits, format_type_be(INTERVALOID)),
5181 (val == DTK_WEEK) ? errdetail("Months usually have fractional weeks.") : 0));
5182 result = 0;
5183 }
5184 }
5185
5187 switch (val)
5188 {
5189 case DTK_MILLENNIUM:
5190 /* caution: C division may have negative remainder */
5191 tm->tm_year = (tm->tm_year / 1000) * 1000;
5192 /* FALL THRU */
5193 case DTK_CENTURY:
5194 /* caution: C division may have negative remainder */
5195 tm->tm_year = (tm->tm_year / 100) * 100;
5196 /* FALL THRU */
5197 case DTK_DECADE:
5198 /* caution: C division may have negative remainder */
5199 tm->tm_year = (tm->tm_year / 10) * 10;
5200 /* FALL THRU */
5201 case DTK_YEAR:
5202 tm->tm_mon = 0;
5203 /* FALL THRU */
5204 case DTK_QUARTER:
5205 tm->tm_mon = 3 * (tm->tm_mon / 3);
5206 /* FALL THRU */
5207 case DTK_MONTH:
5208 tm->tm_mday = 0;
5209 /* FALL THRU */
5210 case DTK_DAY:
5211 tm->tm_hour = 0;
5212 /* FALL THRU */
5213 case DTK_HOUR:
5214 tm->tm_min = 0;
5215 /* FALL THRU */
5216 case DTK_MINUTE:
5217 tm->tm_sec = 0;
5218 /* FALL THRU */
5219 case DTK_SECOND:
5220 tm->tm_usec = 0;
5221 break;
5222 case DTK_MILLISEC:
5223 tm->tm_usec = (tm->tm_usec / 1000) * 1000;
5224 break;
5225 case DTK_MICROSEC:
5226 break;
5227
5228 default:
5229 ereport(ERROR,
5230 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5231 errmsg("unit \"%s\" not supported for type %s",
5232 lowunits, format_type_be(INTERVALOID)),
5233 (val == DTK_WEEK) ? errdetail("Months usually have fractional weeks.") : 0));
5234 }
5235
5236 if (itm2interval(tm, result) != 0)
5237 ereport(ERROR,
5238 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5239 errmsg("interval out of range")));
5240 }
5241 else
5242 {
5243 ereport(ERROR,
5244 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5245 errmsg("unit \"%s\" not recognized for type %s",
5246 lowunits, format_type_be(INTERVALOID))));
5247 }
5248
5249 PG_RETURN_INTERVAL_P(result);
5250}
5251
5252/* isoweek2j()
5253 *
5254 * Return the Julian day which corresponds to the first day (Monday) of the given ISO 8601 year and week.
5255 * Julian days are used to convert between ISO week dates and Gregorian dates.
5256 *
5257 * XXX: This function has integer overflow hazards, but restructuring it to
5258 * work with the soft-error handling that its callers do is likely more
5259 * trouble than it's worth.
5260 */
5261int
5262isoweek2j(int year, int week)
5263{
5264 int day0,
5265 day4;
5266
5267 /* fourth day of current year */
5268 day4 = date2j(year, 1, 4);
5269
5270 /* day0 == offset to first day of week (Monday) */
5271 day0 = j2day(day4 - 1);
5272
5273 return ((week - 1) * 7) + (day4 - day0);
5274}
5275
5276/* isoweek2date()
5277 * Convert ISO week of year number to date.
5278 * The year field must be specified with the ISO year!
5279 * karel 2000/08/07
5280 */
5281void
5282isoweek2date(int woy, int *year, int *mon, int *mday)
5283{
5284 j2date(isoweek2j(*year, woy), year, mon, mday);
5285}
5286
5287/* isoweekdate2date()
5288 *
5289 * Convert an ISO 8601 week date (ISO year, ISO week) into a Gregorian date.
5290 * Gregorian day of week sent so weekday strings can be supplied.
5291 * Populates year, mon, and mday with the correct Gregorian values.
5292 * year must be passed in as the ISO year.
5293 */
5294void
5295isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
5296{
5297 int jday;
5298
5299 jday = isoweek2j(*year, isoweek);
5300 /* convert Gregorian week start (Sunday=1) to ISO week start (Monday=1) */
5301 if (wday > 1)
5302 jday += wday - 2;
5303 else
5304 jday += 6;
5305 j2date(jday, year, mon, mday);
5306}
5307
5308/* date2isoweek()
5309 *
5310 * Returns ISO week number of year.
5311 */
5312int
5313date2isoweek(int year, int mon, int mday)
5314{
5315 float8 result;
5316 int day0,
5317 day4,
5318 dayn;
5319
5320 /* current day */
5321 dayn = date2j(year, mon, mday);
5322
5323 /* fourth day of current year */
5324 day4 = date2j(year, 1, 4);
5325
5326 /* day0 == offset to first day of week (Monday) */
5327 day0 = j2day(day4 - 1);
5328
5329 /*
5330 * We need the first week containing a Thursday, otherwise this day falls
5331 * into the previous year for purposes of counting weeks
5332 */
5333 if (dayn < day4 - day0)
5334 {
5335 day4 = date2j(year - 1, 1, 4);
5336
5337 /* day0 == offset to first day of week (Monday) */
5338 day0 = j2day(day4 - 1);
5339 }
5340
5341 result = (dayn - (day4 - day0)) / 7 + 1;
5342
5343 /*
5344 * Sometimes the last few days in a year will fall into the first week of
5345 * the next year, so check for this.
5346 */
5347 if (result >= 52)
5348 {
5349 day4 = date2j(year + 1, 1, 4);
5350
5351 /* day0 == offset to first day of week (Monday) */
5352 day0 = j2day(day4 - 1);
5353
5354 if (dayn >= day4 - day0)
5355 result = (dayn - (day4 - day0)) / 7 + 1;
5356 }
5357
5358 return (int) result;
5359}
5360
5361
5362/* date2isoyear()
5363 *
5364 * Returns ISO 8601 year number.
5365 * Note: zero or negative results follow the year-zero-exists convention.
5366 */
5367int
5368date2isoyear(int year, int mon, int mday)
5369{
5370 float8 result;
5371 int day0,
5372 day4,
5373 dayn;
5374
5375 /* current day */
5376 dayn = date2j(year, mon, mday);
5377
5378 /* fourth day of current year */
5379 day4 = date2j(year, 1, 4);
5380
5381 /* day0 == offset to first day of week (Monday) */
5382 day0 = j2day(day4 - 1);
5383
5384 /*
5385 * We need the first week containing a Thursday, otherwise this day falls
5386 * into the previous year for purposes of counting weeks
5387 */
5388 if (dayn < day4 - day0)
5389 {
5390 day4 = date2j(year - 1, 1, 4);
5391
5392 /* day0 == offset to first day of week (Monday) */
5393 day0 = j2day(day4 - 1);
5394
5395 year--;
5396 }
5397
5398 result = (dayn - (day4 - day0)) / 7 + 1;
5399
5400 /*
5401 * Sometimes the last few days in a year will fall into the first week of
5402 * the next year, so check for this.
5403 */
5404 if (result >= 52)
5405 {
5406 day4 = date2j(year + 1, 1, 4);
5407
5408 /* day0 == offset to first day of week (Monday) */
5409 day0 = j2day(day4 - 1);
5410
5411 if (dayn >= day4 - day0)
5412 year++;
5413 }
5414
5415 return year;
5416}
5417
5418
5419/* date2isoyearday()
5420 *
5421 * Returns the ISO 8601 day-of-year, given a Gregorian year, month and day.
5422 * Possible return values are 1 through 371 (364 in non-leap years).
5423 */
5424int
5425date2isoyearday(int year, int mon, int mday)
5426{
5427 return date2j(year, mon, mday) - isoweek2j(date2isoyear(year, mon, mday), 1) + 1;
5428}
5429
5430/*
5431 * NonFiniteTimestampTzPart
5432 *
5433 * Used by timestamp_part and timestamptz_part when extracting from infinite
5434 * timestamp[tz]. Returns +/-Infinity if that is the appropriate result,
5435 * otherwise returns zero (which should be taken as meaning to return NULL).
5436 *
5437 * Errors thrown here for invalid units should exactly match those that
5438 * would be thrown in the calling functions, else there will be unexpected
5439 * discrepancies between finite- and infinite-input cases.
5440 */
5441static float8
5442NonFiniteTimestampTzPart(int type, int unit, char *lowunits,
5443 bool isNegative, bool isTz)
5444{
5445 if ((type != UNITS) && (type != RESERV))
5446 ereport(ERROR,
5447 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5448 errmsg("unit \"%s\" not recognized for type %s",
5449 lowunits,
5450 format_type_be(isTz ? TIMESTAMPTZOID : TIMESTAMPOID))));
5451
5452 switch (unit)
5453 {
5454 /* Oscillating units */
5455 case DTK_MICROSEC:
5456 case DTK_MILLISEC:
5457 case DTK_SECOND:
5458 case DTK_MINUTE:
5459 case DTK_HOUR:
5460 case DTK_DAY:
5461 case DTK_MONTH:
5462 case DTK_QUARTER:
5463 case DTK_WEEK:
5464 case DTK_DOW:
5465 case DTK_ISODOW:
5466 case DTK_DOY:
5467 case DTK_TZ:
5468 case DTK_TZ_MINUTE:
5469 case DTK_TZ_HOUR:
5470 return 0.0;
5471
5472 /* Monotonically-increasing units */
5473 case DTK_YEAR:
5474 case DTK_DECADE:
5475 case DTK_CENTURY:
5476 case DTK_MILLENNIUM:
5477 case DTK_JULIAN:
5478 case DTK_ISOYEAR:
5479 case DTK_EPOCH:
5480 if (isNegative)
5481 return -get_float8_infinity();
5482 else
5483 return get_float8_infinity();
5484
5485 default:
5486 ereport(ERROR,
5487 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5488 errmsg("unit \"%s\" not supported for type %s",
5489 lowunits,
5490 format_type_be(isTz ? TIMESTAMPTZOID : TIMESTAMPOID))));
5491 return 0.0; /* keep compiler quiet */
5492 }
5493}
5494
5495/* timestamp_part() and extract_timestamp()
5496 * Extract specified field from timestamp.
5497 */
5498static Datum
5500{
5501 text *units = PG_GETARG_TEXT_PP(0);
5503 int64 intresult;
5505 int type,
5506 val;
5507 char *lowunits;
5508 fsec_t fsec;
5509 struct pg_tm tt,
5510 *tm = &tt;
5511
5512 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
5513 VARSIZE_ANY_EXHDR(units),
5514 false);
5515
5516 type = DecodeUnits(0, lowunits, &val);
5517 if (type == UNKNOWN_FIELD)
5518 type = DecodeSpecial(0, lowunits, &val);
5519
5521 {
5522 double r = NonFiniteTimestampTzPart(type, val, lowunits,
5524 false);
5525
5526 if (r != 0.0)
5527 {
5528 if (retnumeric)
5529 {
5530 if (r < 0)
5532 CStringGetDatum("-Infinity"),
5534 Int32GetDatum(-1));
5535 else if (r > 0)
5537 CStringGetDatum("Infinity"),
5539 Int32GetDatum(-1));
5540 }
5541 else
5543 }
5544 else
5546 }
5547
5548 if (type == UNITS)
5549 {
5550 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
5551 ereport(ERROR,
5552 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5553 errmsg("timestamp out of range")));
5554
5555 switch (val)
5556 {
5557 case DTK_MICROSEC:
5558 intresult = tm->tm_sec * INT64CONST(1000000) + fsec;
5559 break;
5560
5561 case DTK_MILLISEC:
5562 if (retnumeric)
5563 /*---
5564 * tm->tm_sec * 1000 + fsec / 1000
5565 * = (tm->tm_sec * 1'000'000 + fsec) / 1000
5566 */
5568 else
5569 PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + fsec / 1000.0);
5570 break;
5571
5572 case DTK_SECOND:
5573 if (retnumeric)
5574 /*---
5575 * tm->tm_sec + fsec / 1'000'000
5576 * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
5577 */
5579 else
5580 PG_RETURN_FLOAT8(tm->tm_sec + fsec / 1000000.0);
5581 break;
5582
5583 case DTK_MINUTE:
5584 intresult = tm->tm_min;
5585 break;
5586
5587 case DTK_HOUR:
5588 intresult = tm->tm_hour;
5589 break;
5590
5591 case DTK_DAY:
5592 intresult = tm->tm_mday;
5593 break;
5594
5595 case DTK_MONTH:
5596 intresult = tm->tm_mon;
5597 break;
5598
5599 case DTK_QUARTER:
5600 intresult = (tm->tm_mon - 1) / 3 + 1;
5601 break;
5602
5603 case DTK_WEEK:
5604 intresult = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
5605 break;
5606
5607 case DTK_YEAR:
5608 if (tm->tm_year > 0)
5609 intresult = tm->tm_year;
5610 else
5611 /* there is no year 0, just 1 BC and 1 AD */
5612 intresult = tm->tm_year - 1;
5613 break;
5614
5615 case DTK_DECADE:
5616
5617 /*
5618 * what is a decade wrt dates? let us assume that decade 199
5619 * is 1990 thru 1999... decade 0 starts on year 1 BC, and -1
5620 * is 11 BC thru 2 BC...
5621 */
5622 if (tm->tm_year >= 0)
5623 intresult = tm->tm_year / 10;
5624 else
5625 intresult = -((8 - (tm->tm_year - 1)) / 10);
5626 break;
5627
5628 case DTK_CENTURY:
5629
5630 /* ----
5631 * centuries AD, c>0: year in [ (c-1)* 100 + 1 : c*100 ]
5632 * centuries BC, c<0: year in [ c*100 : (c+1) * 100 - 1]
5633 * there is no number 0 century.
5634 * ----
5635 */
5636 if (tm->tm_year > 0)
5637 intresult = (tm->tm_year + 99) / 100;
5638 else
5639 /* caution: C division may have negative remainder */
5640 intresult = -((99 - (tm->tm_year - 1)) / 100);
5641 break;
5642
5643 case DTK_MILLENNIUM:
5644 /* see comments above. */
5645 if (tm->tm_year > 0)
5646 intresult = (tm->tm_year + 999) / 1000;
5647 else
5648 intresult = -((999 - (tm->tm_year - 1)) / 1000);
5649 break;
5650
5651 case DTK_JULIAN:
5652 if (retnumeric)
5656 NULL),
5657 NULL));
5658 else
5661 tm->tm_sec + (fsec / 1000000.0)) / (double) SECS_PER_DAY);
5662 break;
5663
5664 case DTK_ISOYEAR:
5665 intresult = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
5666 /* Adjust BC years */
5667 if (intresult <= 0)
5668 intresult -= 1;
5669 break;
5670
5671 case DTK_DOW:
5672 case DTK_ISODOW:
5673 intresult = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
5674 if (val == DTK_ISODOW && intresult == 0)
5675 intresult = 7;
5676 break;
5677
5678 case DTK_DOY:
5679 intresult = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
5680 - date2j(tm->tm_year, 1, 1) + 1);
5681 break;
5682
5683 case DTK_TZ:
5684 case DTK_TZ_MINUTE:
5685 case DTK_TZ_HOUR:
5686 default:
5687 ereport(ERROR,
5688 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5689 errmsg("unit \"%s\" not supported for type %s",
5690 lowunits, format_type_be(TIMESTAMPOID))));
5691 intresult = 0;
5692 }
5693 }
5694 else if (type == RESERV)
5695 {
5696 switch (val)
5697 {
5698 case DTK_EPOCH:
5700 /* (timestamp - epoch) / 1000000 */
5701 if (retnumeric)
5702 {
5703 Numeric result;
5704
5705 if (timestamp < (PG_INT64_MAX + epoch))
5707 else
5708 {
5711 NULL),
5712 int64_to_numeric(1000000),
5713 NULL);
5715 NumericGetDatum(result),
5716 Int32GetDatum(6)));
5717 }
5718 PG_RETURN_NUMERIC(result);
5719 }
5720 else
5721 {
5722 float8 result;
5723
5724 /* try to avoid precision loss in subtraction */
5725 if (timestamp < (PG_INT64_MAX + epoch))
5726 result = (timestamp - epoch) / 1000000.0;
5727 else
5728 result = ((float8) timestamp - epoch) / 1000000.0;
5729 PG_RETURN_FLOAT8(result);
5730 }
5731 break;
5732
5733 default:
5734 ereport(ERROR,
5735 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5736 errmsg("unit \"%s\" not supported for type %s",
5737 lowunits, format_type_be(TIMESTAMPOID))));
5738 intresult = 0;
5739 }
5740 }
5741 else
5742 {
5743 ereport(ERROR,
5744 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5745 errmsg("unit \"%s\" not recognized for type %s",
5746 lowunits, format_type_be(TIMESTAMPOID))));
5747 intresult = 0;
5748 }
5749
5750 if (retnumeric)
5752 else
5753 PG_RETURN_FLOAT8(intresult);
5754}
5755
5756Datum
5758{
5759 return timestamp_part_common(fcinfo, false);
5760}
5761
5762Datum
5764{
5765 return timestamp_part_common(fcinfo, true);
5766}
5767
5768/* timestamptz_part() and extract_timestamptz()
5769 * Extract specified field from timestamp with time zone.
5770 */
5771static Datum
5773{
5774 text *units = PG_GETARG_TEXT_PP(0);
5776 int64 intresult;
5778 int tz;
5779 int type,
5780 val;
5781 char *lowunits;
5782 fsec_t fsec;
5783 struct pg_tm tt,
5784 *tm = &tt;
5785
5786 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
5787 VARSIZE_ANY_EXHDR(units),
5788 false);
5789
5790 type = DecodeUnits(0, lowunits, &val);
5791 if (type == UNKNOWN_FIELD)
5792 type = DecodeSpecial(0, lowunits, &val);
5793
5795 {
5796 double r = NonFiniteTimestampTzPart(type, val, lowunits,
5798 true);
5799
5800 if (r != 0.0)
5801 {
5802 if (retnumeric)
5803 {
5804 if (r < 0)
5806 CStringGetDatum("-Infinity"),
5808 Int32GetDatum(-1));
5809 else if (r > 0)
5811 CStringGetDatum("Infinity"),
5813 Int32GetDatum(-1));
5814 }
5815 else
5817 }
5818 else
5820 }
5821
5822 if (type == UNITS)
5823 {
5824 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
5825 ereport(ERROR,
5826 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5827 errmsg("timestamp out of range")));
5828
5829 switch (val)
5830 {
5831 case DTK_TZ:
5832 intresult = -tz;
5833 break;
5834
5835 case DTK_TZ_MINUTE:
5836 intresult = (-tz / SECS_PER_MINUTE) % MINS_PER_HOUR;
5837 break;
5838
5839 case DTK_TZ_HOUR:
5840 intresult = -tz / SECS_PER_HOUR;
5841 break;
5842
5843 case DTK_MICROSEC:
5844 intresult = tm->tm_sec * INT64CONST(1000000) + fsec;
5845 break;
5846
5847 case DTK_MILLISEC:
5848 if (retnumeric)
5849 /*---
5850 * tm->tm_sec * 1000 + fsec / 1000
5851 * = (tm->tm_sec * 1'000'000 + fsec) / 1000
5852 */
5854 else
5855 PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + fsec / 1000.0);
5856 break;
5857
5858 case DTK_SECOND:
5859 if (retnumeric)
5860 /*---
5861 * tm->tm_sec + fsec / 1'000'000
5862 * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
5863 */
5865 else
5866 PG_RETURN_FLOAT8(tm->tm_sec + fsec / 1000000.0);
5867 break;
5868
5869 case DTK_MINUTE:
5870 intresult = tm->tm_min;
5871 break;
5872
5873 case DTK_HOUR:
5874 intresult = tm->tm_hour;
5875 break;
5876
5877 case DTK_DAY:
5878 intresult = tm->tm_mday;
5879 break;
5880
5881 case DTK_MONTH:
5882 intresult = tm->tm_mon;
5883 break;
5884
5885 case DTK_QUARTER:
5886 intresult = (tm->tm_mon - 1) / 3 + 1;
5887 break;
5888
5889 case DTK_WEEK:
5890 intresult = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
5891 break;
5892
5893 case DTK_YEAR:
5894 if (tm->tm_year > 0)
5895 intresult = tm->tm_year;
5896 else
5897 /* there is no year 0, just 1 BC and 1 AD */
5898 intresult = tm->tm_year - 1;
5899 break;
5900
5901 case DTK_DECADE:
5902 /* see comments in timestamp_part */
5903 if (tm->tm_year > 0)
5904 intresult = tm->tm_year / 10;
5905 else
5906 intresult = -((8 - (tm->tm_year - 1)) / 10);
5907 break;
5908
5909 case DTK_CENTURY:
5910 /* see comments in timestamp_part */
5911 if (tm->tm_year > 0)
5912 intresult = (tm->tm_year + 99) / 100;
5913 else
5914 intresult = -((99 - (tm->tm_year - 1)) / 100);
5915 break;
5916
5917 case DTK_MILLENNIUM:
5918 /* see comments in timestamp_part */
5919 if (tm->tm_year > 0)
5920 intresult = (tm->tm_year + 999) / 1000;
5921 else
5922 intresult = -((999 - (tm->tm_year - 1)) / 1000);
5923 break;
5924
5925 case DTK_JULIAN:
5926 if (retnumeric)
5930 NULL),
5931 NULL));
5932 else
5935 tm->tm_sec + (fsec / 1000000.0)) / (double) SECS_PER_DAY);
5936 break;
5937
5938 case DTK_ISOYEAR:
5939 intresult = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
5940 /* Adjust BC years */
5941 if (intresult <= 0)
5942 intresult -= 1;
5943 break;
5944
5945 case DTK_DOW:
5946 case DTK_ISODOW:
5947 intresult = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
5948 if (val == DTK_ISODOW && intresult == 0)
5949 intresult = 7;
5950 break;
5951
5952 case DTK_DOY:
5953 intresult = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
5954 - date2j(tm->tm_year, 1, 1) + 1);
5955 break;
5956
5957 default:
5958 ereport(ERROR,
5959 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5960 errmsg("unit \"%s\" not supported for type %s",
5961 lowunits, format_type_be(TIMESTAMPTZOID))));
5962 intresult = 0;
5963 }
5964 }
5965 else if (type == RESERV)
5966 {
5967 switch (val)
5968 {
5969 case DTK_EPOCH:
5971 /* (timestamp - epoch) / 1000000 */
5972 if (retnumeric)
5973 {
5974 Numeric result;
5975
5976 if (timestamp < (PG_INT64_MAX + epoch))
5978 else
5979 {
5982 NULL),
5983 int64_to_numeric(1000000),
5984 NULL);
5986 NumericGetDatum(result),
5987 Int32GetDatum(6)));
5988 }
5989 PG_RETURN_NUMERIC(result);
5990 }
5991 else
5992 {
5993 float8 result;
5994
5995 /* try to avoid precision loss in subtraction */
5996 if (timestamp < (PG_INT64_MAX + epoch))
5997 result = (timestamp - epoch) / 1000000.0;
5998 else
5999 result = ((float8) timestamp - epoch) / 1000000.0;
6000 PG_RETURN_FLOAT8(result);
6001 }
6002 break;
6003
6004 default:
6005 ereport(ERROR,
6006 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6007 errmsg("unit \"%s\" not supported for type %s",
6008 lowunits, format_type_be(TIMESTAMPTZOID))));
6009 intresult = 0;
6010 }
6011 }
6012 else
6013 {
6014 ereport(ERROR,
6015 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6016 errmsg("unit \"%s\" not recognized for type %s",
6017 lowunits, format_type_be(TIMESTAMPTZOID))));
6018
6019 intresult = 0;
6020 }
6021
6022 if (retnumeric)
6024 else
6025 PG_RETURN_FLOAT8(intresult);
6026}
6027
6028Datum
6030{
6031 return timestamptz_part_common(fcinfo, false);
6032}
6033
6034Datum
6036{
6037 return timestamptz_part_common(fcinfo, true);
6038}
6039
6040/*
6041 * NonFiniteIntervalPart
6042 *
6043 * Used by interval_part when extracting from infinite interval. Returns
6044 * +/-Infinity if that is the appropriate result, otherwise returns zero
6045 * (which should be taken as meaning to return NULL).
6046 *
6047 * Errors thrown here for invalid units should exactly match those that
6048 * would be thrown in the calling functions, else there will be unexpected
6049 * discrepancies between finite- and infinite-input cases.
6050 */
6051static float8
6052NonFiniteIntervalPart(int type, int unit, char *lowunits, bool isNegative)
6053{
6054 if ((type != UNITS) && (type != RESERV))
6055 ereport(ERROR,
6056 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6057 errmsg("unit \"%s\" not recognized for type %s",
6058 lowunits, format_type_be(INTERVALOID))));
6059
6060 switch (unit)
6061 {
6062 /* Oscillating units */
6063 case DTK_MICROSEC:
6064 case DTK_MILLISEC:
6065 case DTK_SECOND:
6066 case DTK_MINUTE:
6067 case DTK_WEEK:
6068 case DTK_MONTH:
6069 case DTK_QUARTER:
6070 return 0.0;
6071
6072 /* Monotonically-increasing units */
6073 case DTK_HOUR:
6074 case DTK_DAY:
6075 case DTK_YEAR:
6076 case DTK_DECADE:
6077 case DTK_CENTURY:
6078 case DTK_MILLENNIUM:
6079 case DTK_EPOCH:
6080 if (isNegative)
6081 return -get_float8_infinity();
6082 else
6083 return get_float8_infinity();
6084
6085 default:
6086 ereport(ERROR,
6087 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6088 errmsg("unit \"%s\" not supported for type %s",
6089 lowunits, format_type_be(INTERVALOID))));
6090 return 0.0; /* keep compiler quiet */
6091 }
6092}
6093
6094/* interval_part() and extract_interval()
6095 * Extract specified field from interval.
6096 */
6097static Datum
6099{
6100 text *units = PG_GETARG_TEXT_PP(0);
6102 int64 intresult;
6103 int type,
6104 val;
6105 char *lowunits;
6106 struct pg_itm tt,
6107 *tm = &tt;
6108
6109 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
6110 VARSIZE_ANY_EXHDR(units),
6111 false);
6112
6113 type = DecodeUnits(0, lowunits, &val);
6114 if (type == UNKNOWN_FIELD)
6115 type = DecodeSpecial(0, lowunits, &val);
6116
6118 {
6119 double r = NonFiniteIntervalPart(type, val, lowunits,
6121
6122 if (r != 0.0)
6123 {
6124 if (retnumeric)
6125 {
6126 if (r < 0)
6128 CStringGetDatum("-Infinity"),
6130 Int32GetDatum(-1));
6131 else if (r > 0)
6133 CStringGetDatum("Infinity"),
6135 Int32GetDatum(-1));
6136 }
6137 else
6139 }
6140 else
6142 }
6143
6144 if (type == UNITS)
6145 {
6147 switch (val)
6148 {
6149 case DTK_MICROSEC:
6150 intresult = tm->tm_sec * INT64CONST(1000000) + tm->tm_usec;
6151 break;
6152
6153 case DTK_MILLISEC:
6154 if (retnumeric)
6155 /*---
6156 * tm->tm_sec * 1000 + fsec / 1000
6157 * = (tm->tm_sec * 1'000'000 + fsec) / 1000
6158 */
6160 else
6161 PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + tm->tm_usec / 1000.0);
6162 break;
6163
6164 case DTK_SECOND:
6165 if (retnumeric)
6166 /*---
6167 * tm->tm_sec + fsec / 1'000'000
6168 * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
6169 */
6171 else
6172 PG_RETURN_FLOAT8(tm->tm_sec + tm->tm_usec / 1000000.0);
6173 break;
6174
6175 case DTK_MINUTE:
6176 intresult = tm->tm_min;
6177 break;
6178
6179 case DTK_HOUR:
6180 intresult = tm->tm_hour;
6181 break;
6182
6183 case DTK_DAY:
6184 intresult = tm->tm_mday;
6185 break;
6186
6187 case DTK_WEEK:
6188 intresult = tm->tm_mday / 7;
6189 break;
6190
6191 case DTK_MONTH:
6192 intresult = tm->tm_mon;
6193 break;
6194
6195 case DTK_QUARTER:
6196
6197 /*
6198 * We want to maintain the rule that a field extracted from a
6199 * negative interval is the negative of the field's value for
6200 * the sign-reversed interval. The broken-down tm_year and
6201 * tm_mon aren't very helpful for that, so work from
6202 * interval->month.
6203 */
6204 if (interval->month >= 0)
6205 intresult = (tm->tm_mon / 3) + 1;
6206 else
6207 intresult = -(((-interval->month % MONTHS_PER_YEAR) / 3) + 1);
6208 break;
6209
6210 case DTK_YEAR:
6211 intresult = tm->tm_year;
6212 break;
6213
6214 case DTK_DECADE:
6215 /* caution: C division may have negative remainder */
6216 intresult = tm->tm_year / 10;
6217 break;
6218
6219 case DTK_CENTURY:
6220 /* caution: C division may have negative remainder */
6221 intresult = tm->tm_year / 100;
6222 break;
6223
6224 case DTK_MILLENNIUM:
6225 /* caution: C division may have negative remainder */
6226 intresult = tm->tm_year / 1000;
6227 break;
6228
6229 default:
6230 ereport(ERROR,
6231 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6232 errmsg("unit \"%s\" not supported for type %s",
6233 lowunits, format_type_be(INTERVALOID))));
6234 intresult = 0;
6235 }
6236 }
6237 else if (type == RESERV && val == DTK_EPOCH)
6238 {
6239 if (retnumeric)
6240 {
6241 Numeric result;
6242 int64 secs_from_day_month;
6243 int64 val;
6244
6245 /*
6246 * To do this calculation in integer arithmetic even though
6247 * DAYS_PER_YEAR is fractional, multiply everything by 4 and then
6248 * divide by 4 again at the end. This relies on DAYS_PER_YEAR
6249 * being a multiple of 0.25 and on SECS_PER_DAY being a multiple
6250 * of 4.
6251 */
6252 secs_from_day_month = ((int64) (4 * DAYS_PER_YEAR) * (interval->month / MONTHS_PER_YEAR) +
6254 (int64) 4 * interval->day) * (SECS_PER_DAY / 4);
6255
6256 /*---
6257 * result = secs_from_day_month + interval->time / 1'000'000
6258 * = (secs_from_day_month * 1'000'000 + interval->time) / 1'000'000
6259 */
6260
6261 /*
6262 * Try the computation inside int64; if it overflows, do it in
6263 * numeric (slower). This overflow happens around 10^9 days, so
6264 * not common in practice.
6265 */
6266 if (!pg_mul_s64_overflow(secs_from_day_month, 1000000, &val) &&
6268 result = int64_div_fast_to_numeric(val, 6);
6269 else
6270 result =
6272 int64_to_numeric(secs_from_day_month),
6273 NULL);
6274
6275 PG_RETURN_NUMERIC(result);
6276 }
6277 else
6278 {
6279 float8 result;
6280
6281 result = interval->time / 1000000.0;
6282 result += ((double) DAYS_PER_YEAR * SECS_PER_DAY) * (interval->month / MONTHS_PER_YEAR);
6283 result += ((double) DAYS_PER_MONTH * SECS_PER_DAY) * (interval->month % MONTHS_PER_YEAR);
6284 result += ((double) SECS_PER_DAY) * interval->day;
6285
6286 PG_RETURN_FLOAT8(result);
6287 }
6288 }
6289 else
6290 {
6291 ereport(ERROR,
6292 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6293 errmsg("unit \"%s\" not recognized for type %s",
6294 lowunits, format_type_be(INTERVALOID))));
6295 intresult = 0;
6296 }
6297
6298 if (retnumeric)
6300 else
6301 PG_RETURN_FLOAT8(intresult);
6302}
6303
6304Datum
6306{
6307 return interval_part_common(fcinfo, false);
6308}
6309
6310Datum
6312{
6313 return interval_part_common(fcinfo, true);
6314}
6315
6316
6317/* timestamp_zone()
6318 * Encode timestamp type with specified time zone.
6319 * This function is just timestamp2timestamptz() except instead of
6320 * shifting to the global timezone, we shift to the specified timezone.
6321 * This is different from the other AT TIME ZONE cases because instead
6322 * of shifting _to_ a new time zone, it sets the time to _be_ the
6323 * specified timezone.
6324 */
6325Datum
6327{
6330 TimestampTz result;
6331 int tz;
6332 char tzname[TZ_STRLEN_MAX + 1];
6333 int type,
6334 val;
6335 pg_tz *tzp;
6336 struct pg_tm tm;
6337 fsec_t fsec;
6338
6341
6342 /*
6343 * Look up the requested timezone.
6344 */
6345 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
6346
6347 type = DecodeTimezoneName(tzname, &val, &tzp);
6348
6350 {
6351 /* fixed-offset abbreviation */
6352 tz = val;
6353 result = dt2local(timestamp, tz);
6354 }
6355 else if (type == TZNAME_DYNTZ)
6356 {
6357 /* dynamic-offset abbreviation, resolve using specified time */
6358 if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, tzp) != 0)
6359 ereport(ERROR,
6360 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6361 errmsg("timestamp out of range")));
6362 tz = -DetermineTimeZoneAbbrevOffset(&tm, tzname, tzp);
6363 result = dt2local(timestamp, tz);
6364 }
6365 else
6366 {
6367 /* full zone name, rotate to that zone */
6368 if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, tzp) != 0)
6369 ereport(ERROR,
6370 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6371 errmsg("timestamp out of range")));
6372 tz = DetermineTimeZoneOffset(&tm, tzp);
6373 if (tm2timestamp(&tm, fsec, &tz, &result) != 0)
6374 ereport(ERROR,
6375 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6376 errmsg("timestamp out of range")));
6377 }
6378
6379 if (!IS_VALID_TIMESTAMP(result))
6380 ereport(ERROR,
6381 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6382 errmsg("timestamp out of range")));
6383
6384 PG_RETURN_TIMESTAMPTZ(result);
6385}
6386
6387/* timestamp_izone()
6388 * Encode timestamp type with specified time interval as time zone.
6389 */
6390Datum
6392{
6395 TimestampTz result;
6396 int tz;
6397
6400
6402 ereport(ERROR,
6403 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6404 errmsg("interval time zone \"%s\" must be finite",
6406 PointerGetDatum(zone))))));
6407
6408 if (zone->month != 0 || zone->day != 0)
6409 ereport(ERROR,
6410 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6411 errmsg("interval time zone \"%s\" must not include months or days",
6413 PointerGetDatum(zone))))));
6414
6415 tz = zone->time / USECS_PER_SEC;
6416
6417 result = dt2local(timestamp, tz);
6418
6419 if (!IS_VALID_TIMESTAMP(result))
6420 ereport(ERROR,
6421 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6422 errmsg("timestamp out of range")));
6423
6424 PG_RETURN_TIMESTAMPTZ(result);
6425} /* timestamp_izone() */
6426
6427/* TimestampTimestampTzRequiresRewrite()
6428 *
6429 * Returns false if the TimeZone GUC setting causes timestamp_timestamptz and
6430 * timestamptz_timestamp to be no-ops, where the return value has the same
6431 * bits as the argument. Since project convention is to assume a GUC changes
6432 * no more often than STABLE functions change, the answer is valid that long.
6433 */
6434bool
6436{
6437 long offset;
6438
6439 if (pg_get_timezone_offset(session_timezone, &offset) && offset == 0)
6440 return false;
6441 return true;
6442}
6443
6444/* timestamp_timestamptz()
6445 * Convert local timestamp to timestamp at GMT
6446 */
6447Datum
6449{
6451
6453}
6454
6455/*
6456 * Convert timestamp to timestamp with time zone.
6457 *
6458 * On successful conversion, *overflow is set to zero if it's not NULL.
6459 *
6460 * If the timestamp is finite but out of the valid range for timestamptz, then:
6461 * if overflow is NULL, we throw an out-of-range error.
6462 * if overflow is not NULL, we store +1 or -1 there to indicate the sign
6463 * of the overflow, and return the appropriate timestamptz infinity.
6464 */
6467{
6468 TimestampTz result;
6469 struct pg_tm tt,
6470 *tm = &tt;
6471 fsec_t fsec;
6472 int tz;
6473
6474 if (overflow)
6475 *overflow = 0;
6476
6478 return timestamp;
6479
6480 /* We don't expect this to fail, but check it pro forma */
6481 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
6482 {
6484
6485 result = dt2local(timestamp, -tz);
6486
6487 if (IS_VALID_TIMESTAMP(result))
6488 {
6489 return result;
6490 }
6491 else if (overflow)
6492 {
6493 if (result < MIN_TIMESTAMP)
6494 {
6495 *overflow = -1;
6496 TIMESTAMP_NOBEGIN(result);
6497 }
6498 else
6499 {
6500 *overflow = 1;
6501 TIMESTAMP_NOEND(result);
6502 }
6503 return result;
6504 }
6505 }
6506
6507 ereport(ERROR,
6508 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6509 errmsg("timestamp out of range")));
6510
6511 return 0;
6512}
6513
6514/*
6515 * Promote timestamp to timestamptz, throwing error for overflow.
6516 */
6517static TimestampTz
6519{
6521}
6522
6523/* timestamptz_timestamp()
6524 * Convert timestamp at GMT to local timestamp
6525 */
6526Datum
6528{
6530
6532}
6533
6534static Timestamp
6536{
6537 Timestamp result;
6538 struct pg_tm tt,
6539 *tm = &tt;
6540 fsec_t fsec;
6541 int tz;
6542
6544 result = timestamp;
6545 else
6546 {
6547 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
6548 ereport(ERROR,
6549 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6550 errmsg("timestamp out of range")));
6551 if (tm2timestamp(tm, fsec, NULL, &result) != 0)
6552 ereport(ERROR,
6553 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6554 errmsg("timestamp out of range")));
6555 }
6556 return result;
6557}
6558
6559/* timestamptz_zone()
6560 * Evaluate timestamp with time zone type at the specified time zone.
6561 * Returns a timestamp without time zone.
6562 */
6563Datum
6565{
6568 Timestamp result;
6569 int tz;
6570 char tzname[TZ_STRLEN_MAX + 1];
6571 int type,
6572 val;
6573 pg_tz *tzp;
6574
6577
6578 /*
6579 * Look up the requested timezone.
6580 */
6581 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
6582
6583 type = DecodeTimezoneName(tzname, &val, &tzp);
6584
6586 {
6587 /* fixed-offset abbreviation */
6588 tz = -val;
6589 result = dt2local(timestamp, tz);
6590 }
6591 else if (type == TZNAME_DYNTZ)
6592 {
6593 /* dynamic-offset abbreviation, resolve using specified time */
6594 int isdst;
6595
6596 tz = DetermineTimeZoneAbbrevOffsetTS(timestamp, tzname, tzp, &isdst);
6597 result = dt2local(timestamp, tz);
6598 }
6599 else
6600 {
6601 /* full zone name, rotate from that zone */
6602 struct pg_tm tm;
6603 fsec_t fsec;
6604
6605 if (timestamp2tm(timestamp, &tz, &tm, &fsec, NULL, tzp) != 0)
6606 ereport(ERROR,
6607 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6608 errmsg("timestamp out of range")));
6609 if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
6610 ereport(ERROR,
6611 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6612 errmsg("timestamp out of range")));
6613 }
6614
6615 if (!IS_VALID_TIMESTAMP(result))
6616 ereport(ERROR,
6617 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6618 errmsg("timestamp out of range")));
6619
6620 PG_RETURN_TIMESTAMP(result);
6621}
6622
6623/* timestamptz_izone()
6624 * Encode timestamp with time zone type with specified time interval as time zone.
6625 * Returns a timestamp without time zone.
6626 */
6627Datum
6629{
6632 Timestamp result;
6633 int tz;
6634
6637
6639 ereport(ERROR,
6640 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6641 errmsg("interval time zone \"%s\" must be finite",
6643 PointerGetDatum(zone))))));
6644
6645 if (zone->month != 0 || zone->day != 0)
6646 ereport(ERROR,
6647 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6648 errmsg("interval time zone \"%s\" must not include months or days",
6650 PointerGetDatum(zone))))));
6651
6652 tz = -(zone->time / USECS_PER_SEC);
6653
6654 result = dt2local(timestamp, tz);
6655
6656 if (!IS_VALID_TIMESTAMP(result))
6657 ereport(ERROR,
6658 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
6659 errmsg("timestamp out of range")));
6660
6661 PG_RETURN_TIMESTAMP(result);
6662}
6663
6664/* generate_series_timestamp()
6665 * Generate the set of timestamps from start to finish by step
6666 */
6667Datum
6669{
6670 FuncCallContext *funcctx;
6672 Timestamp result;
6673
6674 /* stuff done only on the first call of the function */
6675 if (SRF_IS_FIRSTCALL())
6676 {
6678 Timestamp finish = PG_GETARG_TIMESTAMP(1);
6679 Interval *step = PG_GETARG_INTERVAL_P(2);
6680 MemoryContext oldcontext;
6681
6682 /* create a function context for cross-call persistence */
6683 funcctx = SRF_FIRSTCALL_INIT();
6684
6685 /*
6686 * switch to memory context appropriate for multiple function calls
6687 */
6688 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
6689
6690 /* allocate memory for user context */
6693
6694 /*
6695 * Use fctx to keep state from call to call. Seed current with the
6696 * original start value
6697 */
6698 fctx->current = start;
6699 fctx->finish = finish;
6700 fctx->step = *step;
6701
6702 /* Determine sign of the interval */
6703 fctx->step_sign = interval_sign(&fctx->step);
6704
6705 if (fctx->step_sign == 0)
6706 ereport(ERROR,
6707 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6708 errmsg("step size cannot equal zero")));
6709
6710 if (INTERVAL_NOT_FINITE((&fctx->step)))
6711 ereport(ERROR,
6712 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6713 errmsg("step size cannot be infinite")));
6714
6715 funcctx->user_fctx = fctx;
6716 MemoryContextSwitchTo(oldcontext);
6717 }
6718
6719 /* stuff done on every call of the function */
6720 funcctx = SRF_PERCALL_SETUP();
6721
6722 /*
6723 * get the saved state and use current as the result for this iteration
6724 */
6725 fctx = funcctx->user_fctx;
6726 result = fctx->current;
6727
6728 if (fctx->step_sign > 0 ?
6729 timestamp_cmp_internal(result, fctx->finish) <= 0 :
6730 timestamp_cmp_internal(result, fctx->finish) >= 0)
6731 {
6732 /* increment current in preparation for next iteration */
6735 PointerGetDatum(&fctx->step)));
6736
6737 /* do when there is more left to send */
6738 SRF_RETURN_NEXT(funcctx, TimestampGetDatum(result));
6739 }
6740 else
6741 {
6742 /* do when there is no more left */
6743 SRF_RETURN_DONE(funcctx);
6744 }
6745}
6746
6747/* generate_series_timestamptz()
6748 * Generate the set of timestamps from start to finish by step,
6749 * doing arithmetic in the specified or session timezone.
6750 */
6751static Datum
6753{
6754 FuncCallContext *funcctx;
6756 TimestampTz result;
6757
6758 /* stuff done only on the first call of the function */
6759 if (SRF_IS_FIRSTCALL())
6760 {
6763 Interval *step = PG_GETARG_INTERVAL_P(2);
6764 text *zone = (PG_NARGS() == 4) ? PG_GETARG_TEXT_PP(3) : NULL;
6765 MemoryContext oldcontext;
6766
6767 /* create a function context for cross-call persistence */
6768 funcctx = SRF_FIRSTCALL_INIT();
6769
6770 /*
6771 * switch to memory context appropriate for multiple function calls
6772 */
6773 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
6774
6775 /* allocate memory for user context */
6778
6779 /*
6780 * Use fctx to keep state from call to call. Seed current with the
6781 * original start value
6782 */
6783 fctx->current = start;
6784 fctx->finish = finish;
6785 fctx->step = *step;
6787
6788 /* Determine sign of the interval */
6789 fctx->step_sign = interval_sign(&fctx->step);
6790
6791 if (fctx->step_sign == 0)
6792 ereport(ERROR,
6793 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6794 errmsg("step size cannot equal zero")));
6795
6796 if (INTERVAL_NOT_FINITE((&fctx->step)))
6797 ereport(ERROR,
6798 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6799 errmsg("step size cannot be infinite")));
6800
6801 funcctx->user_fctx = fctx;
6802 MemoryContextSwitchTo(oldcontext);
6803 }
6804
6805 /* stuff done on every call of the function */
6806 funcctx = SRF_PERCALL_SETUP();
6807
6808 /*
6809 * get the saved state and use current as the result for this iteration
6810 */
6811 fctx = funcctx->user_fctx;
6812 result = fctx->current;
6813
6814 if (fctx->step_sign > 0 ?
6815 timestamp_cmp_internal(result, fctx->finish) <= 0 :
6816 timestamp_cmp_internal(result, fctx->finish) >= 0)
6817 {
6818 /* increment current in preparation for next iteration */
6820 &fctx->step,
6821 fctx->attimezone);
6822
6823 /* do when there is more left to send */
6824 SRF_RETURN_NEXT(funcctx, TimestampTzGetDatum(result));
6825 }
6826 else
6827 {
6828 /* do when there is no more left */
6829 SRF_RETURN_DONE(funcctx);
6830 }
6831}
6832
6833Datum
6835{
6837}
6838
6839Datum
6841{
6843}
6844
6845/*
6846 * Planner support function for generate_series(timestamp, timestamp, interval)
6847 */
6848Datum
6850{
6851 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
6852 Node *ret = NULL;
6853
6854 if (IsA(rawreq, SupportRequestRows))
6855 {
6856 /* Try to estimate the number of rows returned */
6857 SupportRequestRows *req = (SupportRequestRows *) rawreq;
6858
6859 if (is_funcclause(req->node)) /* be paranoid */
6860 {
6861 List *args = ((FuncExpr *) req->node)->args;
6862 Node *arg1,
6863 *arg2,
6864 *arg3;
6865
6866 /* We can use estimated argument values here */
6870
6871 /*
6872 * If any argument is constant NULL, we can safely assume that
6873 * zero rows are returned. Otherwise, if they're all non-NULL
6874 * constants, we can calculate the number of rows that will be
6875 * returned.
6876 */
6877 if ((IsA(arg1, Const) && ((Const *) arg1)->constisnull) ||
6878 (IsA(arg2, Const) && ((Const *) arg2)->constisnull) ||
6879 (IsA(arg3, Const) && ((Const *) arg3)->constisnull))
6880 {
6881 req->rows = 0;
6882 ret = (Node *) req;
6883 }
6884 else if (IsA(arg1, Const) && IsA(arg2, Const) && IsA(arg3, Const))
6885 {
6887 finish;
6888 Interval *step;
6889 Datum diff;
6890 double dstep;
6891 int64 dummy;
6892
6893 start = DatumGetTimestamp(((Const *) arg1)->constvalue);
6894 finish = DatumGetTimestamp(((Const *) arg2)->constvalue);
6895 step = DatumGetIntervalP(((Const *) arg3)->constvalue);
6896
6897 /*
6898 * Perform some prechecks which could cause timestamp_mi to
6899 * raise an ERROR. It's much better to just return some
6900 * default estimate than error out in a support function.
6901 */
6903 !pg_sub_s64_overflow(finish, start, &dummy))
6904 {
6906 TimestampGetDatum(finish),
6908
6909#define INTERVAL_TO_MICROSECONDS(i) ((((double) (i)->month * DAYS_PER_MONTH + (i)->day)) * USECS_PER_DAY + (i)->time)
6910
6911 dstep = INTERVAL_TO_MICROSECONDS(step);
6912
6913 /* This equation works for either sign of step */
6914 if (dstep != 0.0)
6915 {
6916 Interval *idiff = DatumGetIntervalP(diff);
6917 double ddiff = INTERVAL_TO_MICROSECONDS(idiff);
6918
6919 req->rows = floor(ddiff / dstep + 1.0);
6920 ret = (Node *) req;
6921 }
6922#undef INTERVAL_TO_MICROSECONDS
6923 }
6924 }
6925 }
6926 }
6927
6928 PG_RETURN_POINTER(ret);
6929}
6930
6931
6932/* timestamp_at_local()
6933 * timestamptz_at_local()
6934 *
6935 * The regression tests do not like two functions with the same proargs and
6936 * prosrc but different proname, but the grammar for AT LOCAL needs an
6937 * overloaded name to handle both types of timestamp, so we make simple
6938 * wrappers for it.
6939 */
6940Datum
6942{
6943 return timestamp_timestamptz(fcinfo);
6944}
6945
6946Datum
6948{
6949 return timestamptz_timestamp(fcinfo);
6950}
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
int32 * ArrayGetIntegerTypmods(ArrayType *arr, int *n)
Definition: arrayutils.c:233
const int day_tab[2][13]
Definition: datetime.c:75
Node * TemporalSimplify(int32 max_precis, Node *node)
Definition: datetime.c:4956
pg_tz * DecodeTimezoneNameToTz(const char *tzname)
Definition: datetime.c:3337
int DetermineTimeZoneAbbrevOffsetTS(TimestampTz ts, const char *abbr, pg_tz *tzp, int *isdst)
Definition: datetime.c:1794
int DecodeUnits(int field, const char *lowtoken, int *val)
Definition: datetime.c:4163
int j2day(int date)
Definition: datetime.c:354
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition: datetime.c:764
void EncodeInterval(struct pg_itm *itm, int style, char *str)
Definition: datetime.c:4701
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1595
void DateTimeParseError(int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, Node *escontext)
Definition: datetime.c:4208
int DecodeInterval(char **field, int *ftype, int nf, int range, int *dtype, struct pg_itm_in *itm_in)
Definition: datetime.c:3480
int DecodeISO8601Interval(char *str, int *dtype, struct pg_itm_in *itm_in)
Definition: datetime.c:3945
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2552
int DecodeSpecial(int field, const char *lowtoken, int *val)
Definition: datetime.c:3240
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:321
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4458
int DecodeTimezone(const char *str, int *tzp)
Definition: datetime.c:3051
const char *const months[]
Definition: datetime.c:81
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:988
int date2j(int year, int month, int day)
Definition: datetime.c:296
const char *const days[]
Definition: datetime.c:84
int DecodeTimezoneName(const char *tzname, int *offset, pg_tz **tz)
Definition: datetime.c:3282
int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
Definition: datetime.c:1756
Datum numeric_round(PG_FUNCTION_ARGS)
Definition: numeric.c:1543
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3262
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4401
Numeric int64_div_fast_to_numeric(int64 val1, int log10val2)
Definition: numeric.c:4422
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:637
Numeric numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3063
Numeric numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2985
void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
Definition: timestamp.c:1883
Datum interval_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:973
Datum interval_justify_hours(PG_FUNCTION_ARGS)
Definition: timestamp.c:3019
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:5282
Datum in_range_timestamp_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3894
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:2168
Datum generate_series_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:6834
static float8 NonFiniteTimestampTzPart(int type, int unit, char *lowunits, bool isNegative, bool isTz)
Definition: timestamp.c:5442
static INT128 interval_cmp_value(const Interval *interval)
Definition: timestamp.c:2542
Datum interval_trunc(PG_FUNCTION_ARGS)
Definition: timestamp.c:5130
Datum overlaps_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2690
Datum extract_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:5763
Datum timestamptypmodout(PG_FUNCTION_ARGS)
Definition: timestamp.c:312
Datum interval_gt(PG_FUNCTION_ARGS)
Definition: timestamp.c:2609
Datum interval_avg_accum(PG_FUNCTION_ARGS)
Definition: timestamp.c:4061
int itmin2interval(struct pg_itm_in *itm_in, Interval *span)
Definition: timestamp.c:2115
Datum interval_justify_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:2939
static void finite_interval_mi(const Interval *span1, const Interval *span2, Interval *result)
Definition: timestamp.c:3562
Datum timestamptz_part(PG_FUNCTION_ARGS)
Definition: timestamp.c:6029
int isoweek2j(int year, int week)
Definition: timestamp.c:5262
Datum clock_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:1621
Datum timestamptz_pl_interval_at_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:3419
Datum timestamp_pl_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3108
Datum interval_le(PG_FUNCTION_ARGS)
Definition: timestamp.c:2618
Datum interval_avg_serialize(PG_FUNCTION_ARGS)
Definition: timestamp.c:4127
Datum interval_mi(PG_FUNCTION_ARGS)
Definition: timestamp.c:3577
TimestampTz time_t_to_timestamptz(pg_time_t tm)
Definition: timestamp.c:1820
Datum timestamp_le_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2441
Datum interval_lt(PG_FUNCTION_ARGS)
Definition: timestamp.c:2600
Datum timestamp_larger(PG_FUNCTION_ARGS)
Definition: timestamp.c:2830
static Datum timestamptz_part_common(PG_FUNCTION_ARGS, bool retnumeric)
Definition: timestamp.c:5772
Datum timestamptz_izone(PG_FUNCTION_ARGS)
Definition: timestamp.c:6628
Datum timestamp_cmp_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2459
static bool AdjustIntervalForTypmod(Interval *interval, int32 typmod, Node *escontext)
Definition: timestamp.c:1350
Datum timestamp_part(PG_FUNCTION_ARGS)
Definition: timestamp.c:5757
Datum timestamptz_eq_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2468
Datum interval_hash(PG_FUNCTION_ARGS)
Definition: timestamp.c:2652
Datum timestamptztypmodout(PG_FUNCTION_ARGS)
Definition: timestamp.c:857
int date2isoweek(int year, int mon, int mday)
Definition: timestamp.c:5313
Datum timestamptz_pl_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3398
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:4915
Datum timestamp_bin(PG_FUNCTION_ARGS)
Definition: timestamp.c:4606
Datum timestamp_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:6326
static pg_tz * lookup_timezone(text *zone)
Definition: timestamp.c:560
static TimestampTz timestamp2timestamptz(Timestamp timestamp)
Definition: timestamp.c:6518
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:2477
Datum timestamptz_lt_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2486
Datum timestamp_sortsupport(PG_FUNCTION_ARGS)
Definition: timestamp.c:2291
Datum timestamp_mi_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3225
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:2513
Datum timestamp_smaller(PG_FUNCTION_ARGS)
Definition: timestamp.c:2815
TimestampTz timestamp2timestamptz_opt_overflow(Timestamp timestamp, int *overflow)
Definition: timestamp.c:6466
Datum interval_justify_days(PG_FUNCTION_ARGS)
Definition: timestamp.c:3061
Datum timestamp_ge(PG_FUNCTION_ARGS)
Definition: timestamp.c:2261
Datum interval_avg_accum_inv(PG_FUNCTION_ARGS)
Definition: timestamp.c:4208
Datum generate_series_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:6668
int date2isoyearday(int year, int mon, int mday)
Definition: timestamp.c:5425
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:2522
Datum timestamp_ge_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2450
static Timestamp timestamptz2timestamp(TimestampTz timestamp)
Definition: timestamp.c:6535
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:4007
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:6435
Datum timestamp_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:6448
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:5093
Datum timestamptz_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:6564
static void finite_interval_pl(const Interval *span1, const Interval *span2, Interval *result)
Definition: timestamp.c:3506
void isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
Definition: timestamp.c:5295
int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2)
Definition: timestamp.c:2384
Datum timestamptz_gt_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2495
Datum timestamptz_hash_extended(PG_FUNCTION_ARGS)
Definition: timestamp.c:2374
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:6849
static int timestamp_fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: timestamp.c:2281
Datum interval_cmp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2636
Datum interval_sum(PG_FUNCTION_ARGS)
Definition: timestamp.c:4266
Datum timestamp_hash_extended(PG_FUNCTION_ARGS)
Definition: timestamp.c:2362
Datum timestamptz_le_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2504
Datum interval_pl(PG_FUNCTION_ARGS)
Definition: timestamp.c:3521
Datum interval_um(PG_FUNCTION_ARGS)
Definition: timestamp.c:3464
Datum timestamp_skipsupport(PG_FUNCTION_ARGS)
Definition: timestamp.c:2343
static float8 NonFiniteIntervalPart(int type, int unit, char *lowunits, bool isNegative)
Definition: timestamp.c:6052
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:2627
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:2432
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:2591
Datum timestamptz_hash(PG_FUNCTION_ARGS)
Definition: timestamp.c:2368
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:6098
TimestampTz PgReloadTime
Definition: timestamp.c:57
Datum timestamp_ne_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2414
Datum interval_hash_extended(PG_FUNCTION_ARGS)
Definition: timestamp.c:2670
Datum timestamptz_mi_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3407
Datum timestamp_age(PG_FUNCTION_ARGS)
Definition: timestamp.c:4306
Datum interval_smaller(PG_FUNCTION_ARGS)
Definition: timestamp.c:3477
static void EncodeSpecialInterval(const Interval *interval, char *str)
Definition: timestamp.c:1598
Datum timestamptz_mi_interval_at_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:3430
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:6035
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:6305
Datum pg_conf_load_time(PG_FUNCTION_ARGS)
Definition: timestamp.c:1633
Datum in_range_interval_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3935
#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:2582
static Datum timestamp_increment(Relation rel, Datum existing, bool *overflow)
Definition: timestamp.c:2327
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:3383
Datum timestamp_trunc(PG_FUNCTION_ARGS)
Definition: timestamp.c:4677
Datum mul_d_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3746
Datum timestamptztypmodin(PG_FUNCTION_ARGS)
Definition: timestamp.c:849
Datum interval_avg(PG_FUNCTION_ARGS)
Definition: timestamp.c:4226
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:5499
Datum interval_larger(PG_FUNCTION_ARGS)
Definition: timestamp.c:3492
Datum timestamp_gt(PG_FUNCTION_ARGS)
Definition: timestamp.c:2243
static IntervalAggState * makeIntervalAggState(FunctionCallInfo fcinfo)
Definition: timestamp.c:3985
Datum timestamptz_bin(PG_FUNCTION_ARGS)
Definition: timestamp.c:4841
Datum timestamptz_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:6527
Datum timestamp_mi(PG_FUNCTION_ARGS)
Definition: timestamp.c:2845
Datum timestamptz_at_local(PG_FUNCTION_ARGS)
Definition: timestamp.c:6947
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:2423
Datum timestamptz_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:776
static void interval_um_internal(const Interval *interval, Interval *result)
Definition: timestamp.c:3444
Datum timestamp_hash(PG_FUNCTION_ARGS)
Definition: timestamp.c:2356
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:4165
Datum timestamp_ne(PG_FUNCTION_ARGS)
Definition: timestamp.c:2225
static int interval_cmp_internal(const Interval *interval1, const Interval *interval2)
Definition: timestamp.c:2564
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:4452
Datum interval_mul(PG_FUNCTION_ARGS)
Definition: timestamp.c:3626
Datum interval_div(PG_FUNCTION_ARGS)
Definition: timestamp.c:3756
Datum timestamptz_trunc_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:5108
Datum timestamp_eq_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:2405
static TimestampTz timestamptz_pl_interval_internal(TimestampTz timestamp, Interval *span, pg_tz *attimezone)
Definition: timestamp.c:3251
static Datum generate_series_timestamptz_internal(FunctionCallInfo fcinfo)
Definition: timestamp.c:6752
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:2573
static void do_interval_discard(IntervalAggState *state, Interval *newval)
Definition: timestamp.c:4030
Datum timeofday(PG_FUNCTION_ARGS)
Definition: timestamp.c:1691
Datum generate_series_timestamptz_at_zone(PG_FUNCTION_ARGS)
Definition: timestamp.c:6840
int date2isoyear(int year, int mon, int mday)
Definition: timestamp.c:5368
Datum timestamp_izone(PG_FUNCTION_ARGS)
Definition: timestamp.c:6391
static Datum timestamp_decrement(Relation rel, Datum existing, bool *underflow)
Definition: timestamp.c:2310
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:6941
TimestampTz GetSQLCurrentTimestamp(int32 typmod)
Definition: timestamp.c:1663
Datum in_range_timestamptz_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3857
Datum interval_avg_combine(PG_FUNCTION_ARGS)
Definition: timestamp.c:4084
Datum extract_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:6311
Datum timestamp_eq(PG_FUNCTION_ARGS)
Definition: timestamp.c:2216
#define TIMESTAMP_LT(t1, t2)
#define INT64CONST(x)
Definition: c.h:516
#define FLOAT8_FITS_IN_INT32(num)
Definition: c.h:1061
int64_t int64
Definition: c.h:499
double float8
Definition: c.h:601
#define FLOAT8_FITS_IN_INT64(num)
Definition: c.h:1063
int32_t int32
Definition: c.h:498
#define PG_INT64_MAX
Definition: c.h:563
#define PG_INT64_MIN
Definition: c.h:562
#define unlikely(x)
Definition: c.h:347
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2397
int64 Timestamp
Definition: timestamp.h:38
#define DATETIME_MIN_JULIAN
Definition: timestamp.h:251
#define INTERVAL_NOEND(i)
Definition: timestamp.h:185
int64 TimestampTz
Definition: timestamp.h:39
#define SECS_PER_HOUR
Definition: timestamp.h:127
#define MAX_TIMESTAMP_PRECISION
Definition: timestamp.h:92
int32 fsec_t
Definition: timestamp.h:41
#define INTERVAL_NOT_FINITE(i)
Definition: timestamp.h:195
#define TIMESTAMP_NOBEGIN(j)
Definition: timestamp.h:159
#define USECS_PER_HOUR
Definition: timestamp.h:132
#define TIMESTAMP_END_JULIAN
Definition: timestamp.h:253
#define MONTHS_PER_YEAR
Definition: timestamp.h:108
#define MINS_PER_HOUR
Definition: timestamp.h:129
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:227
#define INTERVAL_NOBEGIN(i)
Definition: timestamp.h:175
#define INTERVAL_IS_NOBEGIN(i)
Definition: timestamp.h:182
#define IS_VALID_TIMESTAMP(t)
Definition: timestamp.h:267
#define MAX_INTERVAL_PRECISION
Definition: timestamp.h:93
#define SECS_PER_MINUTE
Definition: timestamp.h:128
#define USECS_PER_DAY
Definition: timestamp.h:131
#define USECS_PER_SEC
Definition: timestamp.h:134
#define HOURS_PER_DAY
Definition: timestamp.h:118
#define INTERVAL_IS_NOEND(i)
Definition: timestamp.h:192
#define TIMESTAMP_IS_NOEND(j)
Definition: timestamp.h:167
#define USECS_PER_MINUTE
Definition: timestamp.h:133
#define DAYS_PER_YEAR
Definition: timestamp.h:107
#define DAYS_PER_WEEK
Definition: timestamp.h:117
#define TIMESTAMP_IS_NOBEGIN(j)
Definition: timestamp.h:162
#define DAYS_PER_MONTH
Definition: timestamp.h:116
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:234
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:169
#define TSROUND(j)
Definition: timestamp.h:100
#define SECS_PER_DAY
Definition: timestamp.h:126
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
#define TIMESTAMP_NOEND(j)
Definition: timestamp.h:164
#define MIN_TIMESTAMP
Definition: timestamp.h:256
int64 TimeOffset
Definition: timestamp.h:40
bool float_time_overflows(int hour, int min, double sec)
Definition: date.c:1516
int errdetail(const char *fmt,...)
Definition: elog.c:1204
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#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:149
static float8 float8_mul(const float8 val1, const float8 val2)
Definition: float.h:208
static float8 get_float8_infinity(void)
Definition: float.h:94
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1816
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:308
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h: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:126
int IntervalStyle
Definition: globals.c:128
#define newval
Assert(PointerIsAligned(start, uint64))
return str start
const char * str
Datum hashint8extended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:103
Datum hashint8(PG_FUNCTION_ARGS)
Definition: hashfunc.c:83
#define MAXDATEFIELDS
Definition: datetime.h:202
#define DTK_EPOCH
Definition: datetime.h:152
#define TMODULO(t, q, u)
Definition: datetime.h:248
#define UNKNOWN_FIELD
Definition: datetime.h:124
#define DTK_DECADE
Definition: datetime.h:168
#define DTK_SECOND
Definition: datetime.h:160
#define DTERR_INTERVAL_OVERFLOW
Definition: datetime.h:285
#define DTK_QUARTER
Definition: datetime.h:166
#define DTK_JULIAN
Definition: datetime.h:173
#define MONTH
Definition: datetime.h:91
#define DTK_DELTA
Definition: datetime.h:159
#define DTK_TZ_HOUR
Definition: datetime.h:177
#define HOUR
Definition: datetime.h:100
#define DTK_TZ_MINUTE
Definition: datetime.h:178
#define DAY
Definition: datetime.h:93
#define DTK_LATE
Definition: datetime.h:151
#define YEAR
Definition: datetime.h:92
#define DTK_DATE
Definition: datetime.h:144
#define DTK_CENTURY
Definition: datetime.h:169
#define DTK_ISODOW
Definition: datetime.h:180
#define DTK_DAY
Definition: datetime.h:163
#define RESERV
Definition: datetime.h:90
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
#define DTK_DATE_M
Definition: datetime.h:191
#define DTK_MILLENNIUM
Definition: datetime.h:170
#define DTK_EARLY
Definition: datetime.h:150
#define DTK_ISOYEAR
Definition: datetime.h:179
#define MAXDATELEN
Definition: datetime.h:200
#define SECOND
Definition: datetime.h:102
#define isleap(y)
Definition: datetime.h:271
#define DTK_DOY
Definition: datetime.h:176
#define DTK_TZ
Definition: datetime.h:146
#define TZNAME_FIXED_OFFSET
Definition: datetime.h:299
#define TZNAME_DYNTZ
Definition: datetime.h:300
#define DTERR_TZDISP_OVERFLOW
Definition: datetime.h:286
#define EARLY
Definition: datetime.h:39
#define DTK_HOUR
Definition: datetime.h:162
#define DTK_WEEK
Definition: datetime.h:164
#define MINUTE
Definition: datetime.h:101
#define LATE
Definition: datetime.h:40
#define DTK_MICROSEC
Definition: datetime.h:172
#define DTK_DOW
Definition: datetime.h:175
#define DTK_YEAR
Definition: datetime.h:167
#define DTK_MILLISEC
Definition: datetime.h:171
#define DTK_MONTH
Definition: datetime.h:165
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:283
#define DTK_MINUTE
Definition: datetime.h:161
#define UNITS
Definition: datetime.h:107
long val
Definition: informix.c:689
static int int128_compare(INT128 x, INT128 y)
Definition: int128.h:238
static INT128 int64_to_int128(int64 v)
Definition: int128.h:255
static int64 int128_to_int64(INT128 val)
Definition: int128.h:269
static void int128_add_int64_mul_int64(INT128 *i128, int64 x, int64 y)
Definition: int128.h:177
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:293
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:262
static bool pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:187
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:169
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:235
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:151
int y
Definition: isn.c:76
int b
Definition: isn.c:74
int x
Definition: isn.c:75
int a
Definition: isn.c:73
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:2322
void * palloc0(Size size)
Definition: mcxt.c:1970
void * palloc(Size size)
Definition: mcxt.c:1940
#define USE_ISO_DATES
Definition: miscadmin.h:237
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4614
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:61
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:80
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static time_t start_time
Definition: pg_ctl.c:95
static int list_length(const List *l)
Definition: pg_list.h:152
#define lthird(l)
Definition: pg_list.h:188
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
static rewind_source * source
Definition: pg_rewind.c:89
static char * buf
Definition: pg_test_fsync.c:72
#define TZ_STRLEN_MAX
Definition: pgtime.h:54
bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
Definition: localtime.c:1965
PGDLLIMPORT pg_tz * session_timezone
Definition: pgtz.c:28
int64 pg_time_t
Definition: pgtime.h:23
size_t pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_tm *t)
Definition: strftime.c:128
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1344
struct pg_tm * pg_gmtime(const pg_time_t *timep)
Definition: localtime.c:1389
long date
Definition: pgtypes_date.h:9
int64 timestamp
#define snprintf
Definition: port.h:239
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define Int64GetDatumFast(X)
Definition: postgres.h:559
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static char * DatumGetCString(Datum X)
Definition: postgres.h:340
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:207
#define InvalidOid
Definition: postgres_ext.h:35
unsigned int Oid
Definition: postgres_ext.h:30
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
StringInfoData * StringInfo
Definition: stringinfo.h:54
static void initReadOnlyStringInfo(StringInfo str, char *data, int len)
Definition: stringinfo.h:157
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
List * args
Definition: primnodes.h:785
Definition: int128.h:108
Interval sumX
Definition: timestamp.c: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
struct PlannerInfo * root
Definition: supportnodes.h:163
int tm_mon
Definition: timestamp.h:86
int tm_year
Definition: timestamp.h:87
int tm_mday
Definition: timestamp.h:85
int64 tm_usec
Definition: timestamp.h:84
int64 tm_hour
Definition: timestamp.h:70
int tm_year
Definition: timestamp.h:73
int tm_mon
Definition: timestamp.h:72
int tm_mday
Definition: timestamp.h:71
int tm_sec
Definition: timestamp.h:68
int tm_min
Definition: timestamp.h:69
int tm_usec
Definition: timestamp.h:67
Definition: pgtime.h:35
int tm_hour
Definition: pgtime.h:38
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_min
Definition: pgtime.h:37
const char * tm_zone
Definition: pgtime.h:46
int tm_sec
Definition: pgtime.h:36
int tm_isdst
Definition: pgtime.h:44
long int tm_gmtoff
Definition: pgtime.h:45
int tm_year
Definition: pgtime.h:41
Definition: pgtz.h:66
Definition: regguts.h:323
Definition: lexi.c:60
Definition: c.h:658
Definition: zic.c:94
#define INTERVAL_FULL_RANGE
Definition: timestamp.h:76
#define timestamptz_cmp_internal(dt1, dt2)
Definition: timestamp.h:143
#define INTERVAL_PRECISION(t)
Definition: timestamp.h:81
static Datum TimestampTzGetDatum(TimestampTz X)
Definition: timestamp.h:52
#define INTERVAL_RANGE(t)
Definition: timestamp.h:82
static Datum TimestampGetDatum(Timestamp X)
Definition: timestamp.h:46
#define PG_GETARG_TIMESTAMP(n)
Definition: timestamp.h:63
static Datum IntervalPGetDatum(const Interval *X)
Definition: timestamp.h:58
#define PG_RETURN_TIMESTAMP(x)
Definition: timestamp.h:67
#define PG_GETARG_INTERVAL_P(n)
Definition: timestamp.h:65
#define PG_GETARG_TIMESTAMPTZ(n)
Definition: timestamp.h:64
#define PG_RETURN_TIMESTAMPTZ(x)
Definition: timestamp.h:68
static Interval * DatumGetIntervalP(Datum X)
Definition: timestamp.h:40
#define PG_RETURN_INTERVAL_P(x)
Definition: timestamp.h:69
#define INTERVAL_TYPMOD(p, r)
Definition: timestamp.h:80
#define INTERVAL_MASK(b)
Definition: timestamp.h:73
static Timestamp DatumGetTimestamp(Datum X)
Definition: timestamp.h:28
#define INTERVAL_FULL_PRECISION
Definition: timestamp.h:78
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
text * cstring_to_text(const char *s)
Definition: varlena.c:192
void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len)
Definition: varlena.c:256
const char * type
static const unsigned __int64 epoch
int gettimeofday(struct timeval *tp, void *tzp)
TimestampTz GetCurrentStatementStartTimestamp(void)
Definition: xact.c:879
TimestampTz GetCurrentTransactionStartTimestamp(void)
Definition: xact.c:870