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