PostgreSQL Source Code  git master
date.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * date.c
4  * implements DATE and TIME data types specified in SQL standard
5  *
6  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994-5, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/adt/date.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres.h"
17 
18 #include <ctype.h>
19 #include <limits.h>
20 #include <float.h>
21 #include <math.h>
22 #include <time.h>
23 
24 #include "access/xact.h"
25 #include "catalog/pg_type.h"
26 #include "common/hashfn.h"
27 #include "libpq/pqformat.h"
28 #include "miscadmin.h"
29 #include "nodes/supportnodes.h"
30 #include "parser/scansup.h"
31 #include "utils/array.h"
32 #include "utils/builtins.h"
33 #include "utils/date.h"
34 #include "utils/datetime.h"
35 #include "utils/numeric.h"
36 #include "utils/sortsupport.h"
37 
38 /*
39  * gcc's -ffast-math switch breaks routines that expect exact results from
40  * expressions like timeval / SECS_PER_HOUR, where timeval is double.
41  */
42 #ifdef __FAST_MATH__
43 #error -ffast-math is known to break this code
44 #endif
45 
46 
47 /* common code for timetypmodin and timetztypmodin */
48 static int32
49 anytime_typmodin(bool istz, ArrayType *ta)
50 {
51  int32 *tl;
52  int n;
53 
54  tl = ArrayGetIntegerTypmods(ta, &n);
55 
56  /*
57  * we're not too tense about good error message here because grammar
58  * shouldn't allow wrong number of modifiers for TIME
59  */
60  if (n != 1)
61  ereport(ERROR,
62  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
63  errmsg("invalid type modifier")));
64 
65  return anytime_typmod_check(istz, tl[0]);
66 }
67 
68 /* exported so parse_expr.c can use it */
69 int32
70 anytime_typmod_check(bool istz, int32 typmod)
71 {
72  if (typmod < 0)
73  ereport(ERROR,
74  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
75  errmsg("TIME(%d)%s precision must not be negative",
76  typmod, (istz ? " WITH TIME ZONE" : ""))));
77  if (typmod > MAX_TIME_PRECISION)
78  {
80  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
81  errmsg("TIME(%d)%s precision reduced to maximum allowed, %d",
82  typmod, (istz ? " WITH TIME ZONE" : ""),
84  typmod = MAX_TIME_PRECISION;
85  }
86 
87  return typmod;
88 }
89 
90 /* common code for timetypmodout and timetztypmodout */
91 static char *
92 anytime_typmodout(bool istz, int32 typmod)
93 {
94  const char *tz = istz ? " with time zone" : " without time zone";
95 
96  if (typmod >= 0)
97  return psprintf("(%d)%s", (int) typmod, tz);
98  else
99  return pstrdup(tz);
100 }
101 
102 
103 /*****************************************************************************
104  * Date ADT
105  *****************************************************************************/
106 
107 
108 /* date_in()
109  * Given date text string, convert to internal date format.
110  */
111 Datum
113 {
114  char *str = PG_GETARG_CSTRING(0);
115  Node *escontext = fcinfo->context;
116  DateADT date;
117  fsec_t fsec;
118  struct pg_tm tt,
119  *tm = &tt;
120  int tzp;
121  int dtype;
122  int nf;
123  int dterr;
124  char *field[MAXDATEFIELDS];
125  int ftype[MAXDATEFIELDS];
126  char workbuf[MAXDATELEN + 1];
127  DateTimeErrorExtra extra;
128 
129  dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
130  field, ftype, MAXDATEFIELDS, &nf);
131  if (dterr == 0)
132  dterr = DecodeDateTime(field, ftype, nf,
133  &dtype, tm, &fsec, &tzp, &extra);
134  if (dterr != 0)
135  {
136  DateTimeParseError(dterr, &extra, str, "date", escontext);
137  PG_RETURN_NULL();
138  }
139 
140  switch (dtype)
141  {
142  case DTK_DATE:
143  break;
144 
145  case DTK_EPOCH:
146  GetEpochTime(tm);
147  break;
148 
149  case DTK_LATE:
150  DATE_NOEND(date);
152 
153  case DTK_EARLY:
156 
157  default:
158  DateTimeParseError(DTERR_BAD_FORMAT, &extra, str, "date", escontext);
159  PG_RETURN_NULL();
160  }
161 
162  /* Prevent overflow in Julian-day routines */
164  ereturn(escontext, (Datum) 0,
165  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
166  errmsg("date out of range: \"%s\"", str)));
167 
169 
170  /* Now check for just-out-of-range dates */
171  if (!IS_VALID_DATE(date))
172  ereturn(escontext, (Datum) 0,
173  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
174  errmsg("date out of range: \"%s\"", str)));
175 
177 }
178 
179 /* date_out()
180  * Given internal format date, convert to text string.
181  */
182 Datum
184 {
186  char *result;
187  struct pg_tm tt,
188  *tm = &tt;
189  char buf[MAXDATELEN + 1];
190 
191  if (DATE_NOT_FINITE(date))
193  else
194  {
196  &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
198  }
199 
200  result = pstrdup(buf);
201  PG_RETURN_CSTRING(result);
202 }
203 
204 /*
205  * date_recv - converts external binary format to date
206  */
207 Datum
209 {
211  DateADT result;
212 
213  result = (DateADT) pq_getmsgint(buf, sizeof(DateADT));
214 
215  /* Limit to the same range that date_in() accepts. */
216  if (DATE_NOT_FINITE(result))
217  /* ok */ ;
218  else if (!IS_VALID_DATE(result))
219  ereport(ERROR,
220  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
221  errmsg("date out of range")));
222 
223  PG_RETURN_DATEADT(result);
224 }
225 
226 /*
227  * date_send - converts date to binary format
228  */
229 Datum
231 {
234 
236  pq_sendint32(&buf, date);
238 }
239 
240 /*
241  * make_date - date constructor
242  */
243 Datum
245 {
246  struct pg_tm tm;
247  DateADT date;
248  int dterr;
249  bool bc = false;
250 
254 
255  /* Handle negative years as BC */
256  if (tm.tm_year < 0)
257  {
258  bc = true;
259  tm.tm_year = -tm.tm_year;
260  }
261 
262  dterr = ValidateDate(DTK_DATE_M, false, false, bc, &tm);
263 
264  if (dterr != 0)
265  ereport(ERROR,
266  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
267  errmsg("date field value out of range: %d-%02d-%02d",
268  tm.tm_year, tm.tm_mon, tm.tm_mday)));
269 
270  /* Prevent overflow in Julian-day routines */
272  ereport(ERROR,
273  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
274  errmsg("date out of range: %d-%02d-%02d",
275  tm.tm_year, tm.tm_mon, tm.tm_mday)));
276 
278 
279  /* Now check for just-out-of-range dates */
280  if (!IS_VALID_DATE(date))
281  ereport(ERROR,
282  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
283  errmsg("date out of range: %d-%02d-%02d",
284  tm.tm_year, tm.tm_mon, tm.tm_mday)));
285 
287 }
288 
289 /*
290  * Convert reserved date values to string.
291  */
292 void
294 {
295  if (DATE_IS_NOBEGIN(dt))
296  strcpy(str, EARLY);
297  else if (DATE_IS_NOEND(dt))
298  strcpy(str, LATE);
299  else /* shouldn't happen */
300  elog(ERROR, "invalid argument for EncodeSpecialDate");
301 }
302 
303 
304 /*
305  * GetSQLCurrentDate -- implements CURRENT_DATE
306  */
307 DateADT
309 {
310  struct pg_tm tm;
311 
312  static int cache_year = 0;
313  static int cache_mon = 0;
314  static int cache_mday = 0;
315  static DateADT cache_date;
316 
318 
319  /*
320  * date2j involves several integer divisions; moreover, unless our session
321  * lives across local midnight, we don't really have to do it more than
322  * once. So it seems worth having a separate cache here.
323  */
324  if (tm.tm_year != cache_year ||
325  tm.tm_mon != cache_mon ||
326  tm.tm_mday != cache_mday)
327  {
329  cache_year = tm.tm_year;
330  cache_mon = tm.tm_mon;
331  cache_mday = tm.tm_mday;
332  }
333 
334  return cache_date;
335 }
336 
337 /*
338  * GetSQLCurrentTime -- implements CURRENT_TIME, CURRENT_TIME(n)
339  */
340 TimeTzADT *
342 {
343  TimeTzADT *result;
344  struct pg_tm tt,
345  *tm = &tt;
346  fsec_t fsec;
347  int tz;
348 
349  GetCurrentTimeUsec(tm, &fsec, &tz);
350 
351  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
352  tm2timetz(tm, fsec, tz, result);
353  AdjustTimeForTypmod(&(result->time), typmod);
354  return result;
355 }
356 
357 /*
358  * GetSQLLocalTime -- implements LOCALTIME, LOCALTIME(n)
359  */
360 TimeADT
362 {
363  TimeADT result;
364  struct pg_tm tt,
365  *tm = &tt;
366  fsec_t fsec;
367  int tz;
368 
369  GetCurrentTimeUsec(tm, &fsec, &tz);
370 
371  tm2time(tm, fsec, &result);
372  AdjustTimeForTypmod(&result, typmod);
373  return result;
374 }
375 
376 
377 /*
378  * Comparison functions for dates
379  */
380 
381 Datum
383 {
384  DateADT dateVal1 = PG_GETARG_DATEADT(0);
385  DateADT dateVal2 = PG_GETARG_DATEADT(1);
386 
387  PG_RETURN_BOOL(dateVal1 == dateVal2);
388 }
389 
390 Datum
392 {
393  DateADT dateVal1 = PG_GETARG_DATEADT(0);
394  DateADT dateVal2 = PG_GETARG_DATEADT(1);
395 
396  PG_RETURN_BOOL(dateVal1 != dateVal2);
397 }
398 
399 Datum
401 {
402  DateADT dateVal1 = PG_GETARG_DATEADT(0);
403  DateADT dateVal2 = PG_GETARG_DATEADT(1);
404 
405  PG_RETURN_BOOL(dateVal1 < dateVal2);
406 }
407 
408 Datum
410 {
411  DateADT dateVal1 = PG_GETARG_DATEADT(0);
412  DateADT dateVal2 = PG_GETARG_DATEADT(1);
413 
414  PG_RETURN_BOOL(dateVal1 <= dateVal2);
415 }
416 
417 Datum
419 {
420  DateADT dateVal1 = PG_GETARG_DATEADT(0);
421  DateADT dateVal2 = PG_GETARG_DATEADT(1);
422 
423  PG_RETURN_BOOL(dateVal1 > dateVal2);
424 }
425 
426 Datum
428 {
429  DateADT dateVal1 = PG_GETARG_DATEADT(0);
430  DateADT dateVal2 = PG_GETARG_DATEADT(1);
431 
432  PG_RETURN_BOOL(dateVal1 >= dateVal2);
433 }
434 
435 Datum
437 {
438  DateADT dateVal1 = PG_GETARG_DATEADT(0);
439  DateADT dateVal2 = PG_GETARG_DATEADT(1);
440 
441  if (dateVal1 < dateVal2)
442  PG_RETURN_INT32(-1);
443  else if (dateVal1 > dateVal2)
444  PG_RETURN_INT32(1);
445  PG_RETURN_INT32(0);
446 }
447 
448 Datum
450 {
452 
454  PG_RETURN_VOID();
455 }
456 
457 Datum
459 {
461 
463 }
464 
465 Datum
467 {
468  DateADT dateVal1 = PG_GETARG_DATEADT(0);
469  DateADT dateVal2 = PG_GETARG_DATEADT(1);
470 
471  PG_RETURN_DATEADT((dateVal1 > dateVal2) ? dateVal1 : dateVal2);
472 }
473 
474 Datum
476 {
477  DateADT dateVal1 = PG_GETARG_DATEADT(0);
478  DateADT dateVal2 = PG_GETARG_DATEADT(1);
479 
480  PG_RETURN_DATEADT((dateVal1 < dateVal2) ? dateVal1 : dateVal2);
481 }
482 
483 /* Compute difference between two dates in days.
484  */
485 Datum
487 {
488  DateADT dateVal1 = PG_GETARG_DATEADT(0);
489  DateADT dateVal2 = PG_GETARG_DATEADT(1);
490 
491  if (DATE_NOT_FINITE(dateVal1) || DATE_NOT_FINITE(dateVal2))
492  ereport(ERROR,
493  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
494  errmsg("cannot subtract infinite dates")));
495 
496  PG_RETURN_INT32((int32) (dateVal1 - dateVal2));
497 }
498 
499 /* Add a number of days to a date, giving a new date.
500  * Must handle both positive and negative numbers of days.
501  */
502 Datum
504 {
505  DateADT dateVal = PG_GETARG_DATEADT(0);
507  DateADT result;
508 
509  if (DATE_NOT_FINITE(dateVal))
510  PG_RETURN_DATEADT(dateVal); /* can't change infinity */
511 
512  result = dateVal + days;
513 
514  /* Check for integer overflow and out-of-allowed-range */
515  if ((days >= 0 ? (result < dateVal) : (result > dateVal)) ||
516  !IS_VALID_DATE(result))
517  ereport(ERROR,
518  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
519  errmsg("date out of range")));
520 
521  PG_RETURN_DATEADT(result);
522 }
523 
524 /* Subtract a number of days from a date, giving a new date.
525  */
526 Datum
528 {
529  DateADT dateVal = PG_GETARG_DATEADT(0);
531  DateADT result;
532 
533  if (DATE_NOT_FINITE(dateVal))
534  PG_RETURN_DATEADT(dateVal); /* can't change infinity */
535 
536  result = dateVal - days;
537 
538  /* Check for integer overflow and out-of-allowed-range */
539  if ((days >= 0 ? (result > dateVal) : (result < dateVal)) ||
540  !IS_VALID_DATE(result))
541  ereport(ERROR,
542  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
543  errmsg("date out of range")));
544 
545  PG_RETURN_DATEADT(result);
546 }
547 
548 
549 /*
550  * Promote date to timestamp.
551  *
552  * On successful conversion, *overflow is set to zero if it's not NULL.
553  *
554  * If the date is finite but out of the valid range for timestamp, then:
555  * if overflow is NULL, we throw an out-of-range error.
556  * if overflow is not NULL, we store +1 or -1 there to indicate the sign
557  * of the overflow, and return the appropriate timestamp infinity.
558  *
559  * Note: *overflow = -1 is actually not possible currently, since both
560  * datatypes have the same lower bound, Julian day zero.
561  */
562 Timestamp
563 date2timestamp_opt_overflow(DateADT dateVal, int *overflow)
564 {
565  Timestamp result;
566 
567  if (overflow)
568  *overflow = 0;
569 
570  if (DATE_IS_NOBEGIN(dateVal))
571  TIMESTAMP_NOBEGIN(result);
572  else if (DATE_IS_NOEND(dateVal))
573  TIMESTAMP_NOEND(result);
574  else
575  {
576  /*
577  * Since dates have the same minimum values as timestamps, only upper
578  * boundary need be checked for overflow.
579  */
580  if (dateVal >= (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE))
581  {
582  if (overflow)
583  {
584  *overflow = 1;
585  TIMESTAMP_NOEND(result);
586  return result;
587  }
588  else
589  {
590  ereport(ERROR,
591  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
592  errmsg("date out of range for timestamp")));
593  }
594  }
595 
596  /* date is days since 2000, timestamp is microseconds since same... */
597  result = dateVal * USECS_PER_DAY;
598  }
599 
600  return result;
601 }
602 
603 /*
604  * Promote date to timestamp, throwing error for overflow.
605  */
606 static TimestampTz
608 {
609  return date2timestamp_opt_overflow(dateVal, NULL);
610 }
611 
612 /*
613  * Promote date to timestamp with time zone.
614  *
615  * On successful conversion, *overflow is set to zero if it's not NULL.
616  *
617  * If the date is finite but out of the valid range for timestamptz, then:
618  * if overflow is NULL, we throw an out-of-range error.
619  * if overflow is not NULL, we store +1 or -1 there to indicate the sign
620  * of the overflow, and return the appropriate timestamptz infinity.
621  */
623 date2timestamptz_opt_overflow(DateADT dateVal, int *overflow)
624 {
625  TimestampTz result;
626  struct pg_tm tt,
627  *tm = &tt;
628  int tz;
629 
630  if (overflow)
631  *overflow = 0;
632 
633  if (DATE_IS_NOBEGIN(dateVal))
634  TIMESTAMP_NOBEGIN(result);
635  else if (DATE_IS_NOEND(dateVal))
636  TIMESTAMP_NOEND(result);
637  else
638  {
639  /*
640  * Since dates have the same minimum values as timestamps, only upper
641  * boundary need be checked for overflow.
642  */
643  if (dateVal >= (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE))
644  {
645  if (overflow)
646  {
647  *overflow = 1;
648  TIMESTAMP_NOEND(result);
649  return result;
650  }
651  else
652  {
653  ereport(ERROR,
654  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
655  errmsg("date out of range for timestamp")));
656  }
657  }
658 
659  j2date(dateVal + POSTGRES_EPOCH_JDATE,
660  &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
661  tm->tm_hour = 0;
662  tm->tm_min = 0;
663  tm->tm_sec = 0;
665 
666  result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC;
667 
668  /*
669  * Since it is possible to go beyond allowed timestamptz range because
670  * of time zone, check for allowed timestamp range after adding tz.
671  */
672  if (!IS_VALID_TIMESTAMP(result))
673  {
674  if (overflow)
675  {
676  if (result < MIN_TIMESTAMP)
677  {
678  *overflow = -1;
679  TIMESTAMP_NOBEGIN(result);
680  }
681  else
682  {
683  *overflow = 1;
684  TIMESTAMP_NOEND(result);
685  }
686  }
687  else
688  {
689  ereport(ERROR,
690  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
691  errmsg("date out of range for timestamp")));
692  }
693  }
694  }
695 
696  return result;
697 }
698 
699 /*
700  * Promote date to timestamptz, throwing error for overflow.
701  */
702 static TimestampTz
704 {
705  return date2timestamptz_opt_overflow(dateVal, NULL);
706 }
707 
708 /*
709  * date2timestamp_no_overflow
710  *
711  * This is chartered to produce a double value that is numerically
712  * equivalent to the corresponding Timestamp value, if the date is in the
713  * valid range of Timestamps, but in any case not throw an overflow error.
714  * We can do this since the numerical range of double is greater than
715  * that of non-erroneous timestamps. The results are currently only
716  * used for statistical estimation purposes.
717  */
718 double
720 {
721  double result;
722 
723  if (DATE_IS_NOBEGIN(dateVal))
724  result = -DBL_MAX;
725  else if (DATE_IS_NOEND(dateVal))
726  result = DBL_MAX;
727  else
728  {
729  /* date is days since 2000, timestamp is microseconds since same... */
730  result = dateVal * (double) USECS_PER_DAY;
731  }
732 
733  return result;
734 }
735 
736 
737 /*
738  * Crosstype comparison functions for dates
739  */
740 
741 int32
743 {
744  Timestamp dt1;
745  int overflow;
746 
747  dt1 = date2timestamp_opt_overflow(dateVal, &overflow);
748  if (overflow > 0)
749  {
750  /* dt1 is larger than any finite timestamp, but less than infinity */
751  return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1;
752  }
753  Assert(overflow == 0); /* -1 case cannot occur */
754 
755  return timestamp_cmp_internal(dt1, dt2);
756 }
757 
758 Datum
760 {
761  DateADT dateVal = PG_GETARG_DATEADT(0);
763 
764  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) == 0);
765 }
766 
767 Datum
769 {
770  DateADT dateVal = PG_GETARG_DATEADT(0);
772 
773  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) != 0);
774 }
775 
776 Datum
778 {
779  DateADT dateVal = PG_GETARG_DATEADT(0);
781 
782  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) < 0);
783 }
784 
785 Datum
787 {
788  DateADT dateVal = PG_GETARG_DATEADT(0);
790 
791  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) > 0);
792 }
793 
794 Datum
796 {
797  DateADT dateVal = PG_GETARG_DATEADT(0);
799 
800  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) <= 0);
801 }
802 
803 Datum
805 {
806  DateADT dateVal = PG_GETARG_DATEADT(0);
808 
809  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) >= 0);
810 }
811 
812 Datum
814 {
815  DateADT dateVal = PG_GETARG_DATEADT(0);
817 
819 }
820 
821 int32
823 {
824  TimestampTz dt1;
825  int overflow;
826 
827  dt1 = date2timestamptz_opt_overflow(dateVal, &overflow);
828  if (overflow > 0)
829  {
830  /* dt1 is larger than any finite timestamp, but less than infinity */
831  return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1;
832  }
833  if (overflow < 0)
834  {
835  /* dt1 is less than any finite timestamp, but more than -infinity */
836  return TIMESTAMP_IS_NOBEGIN(dt2) ? +1 : -1;
837  }
838 
839  return timestamptz_cmp_internal(dt1, dt2);
840 }
841 
842 Datum
844 {
845  DateADT dateVal = PG_GETARG_DATEADT(0);
847 
848  PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt2) == 0);
849 }
850 
851 Datum
853 {
854  DateADT dateVal = PG_GETARG_DATEADT(0);
856 
857  PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt2) != 0);
858 }
859 
860 Datum
862 {
863  DateADT dateVal = PG_GETARG_DATEADT(0);
865 
867 }
868 
869 Datum
871 {
872  DateADT dateVal = PG_GETARG_DATEADT(0);
874 
876 }
877 
878 Datum
880 {
881  DateADT dateVal = PG_GETARG_DATEADT(0);
883 
884  PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt2) <= 0);
885 }
886 
887 Datum
889 {
890  DateADT dateVal = PG_GETARG_DATEADT(0);
892 
893  PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt2) >= 0);
894 }
895 
896 Datum
898 {
899  DateADT dateVal = PG_GETARG_DATEADT(0);
901 
903 }
904 
905 Datum
907 {
909  DateADT dateVal = PG_GETARG_DATEADT(1);
910 
911  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) == 0);
912 }
913 
914 Datum
916 {
918  DateADT dateVal = PG_GETARG_DATEADT(1);
919 
920  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) != 0);
921 }
922 
923 Datum
925 {
927  DateADT dateVal = PG_GETARG_DATEADT(1);
928 
929  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) > 0);
930 }
931 
932 Datum
934 {
936  DateADT dateVal = PG_GETARG_DATEADT(1);
937 
938  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) < 0);
939 }
940 
941 Datum
943 {
945  DateADT dateVal = PG_GETARG_DATEADT(1);
946 
947  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) >= 0);
948 }
949 
950 Datum
952 {
954  DateADT dateVal = PG_GETARG_DATEADT(1);
955 
956  PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) <= 0);
957 }
958 
959 Datum
961 {
963  DateADT dateVal = PG_GETARG_DATEADT(1);
964 
966 }
967 
968 Datum
970 {
972  DateADT dateVal = PG_GETARG_DATEADT(1);
973 
974  PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) == 0);
975 }
976 
977 Datum
979 {
981  DateADT dateVal = PG_GETARG_DATEADT(1);
982 
983  PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) != 0);
984 }
985 
986 Datum
988 {
990  DateADT dateVal = PG_GETARG_DATEADT(1);
991 
993 }
994 
995 Datum
997 {
999  DateADT dateVal = PG_GETARG_DATEADT(1);
1000 
1001  PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) < 0);
1002 }
1003 
1004 Datum
1006 {
1008  DateADT dateVal = PG_GETARG_DATEADT(1);
1009 
1010  PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) >= 0);
1011 }
1012 
1013 Datum
1015 {
1017  DateADT dateVal = PG_GETARG_DATEADT(1);
1018 
1019  PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) <= 0);
1020 }
1021 
1022 Datum
1024 {
1026  DateADT dateVal = PG_GETARG_DATEADT(1);
1027 
1029 }
1030 
1031 /*
1032  * in_range support function for date.
1033  *
1034  * We implement this by promoting the dates to timestamp (without time zone)
1035  * and then using the timestamp-and-interval in_range function.
1036  */
1037 Datum
1039 {
1041  DateADT base = PG_GETARG_DATEADT(1);
1042  Interval *offset = PG_GETARG_INTERVAL_P(2);
1043  bool sub = PG_GETARG_BOOL(3);
1044  bool less = PG_GETARG_BOOL(4);
1045  Timestamp valStamp;
1046  Timestamp baseStamp;
1047 
1048  /* XXX we could support out-of-range cases here, perhaps */
1049  valStamp = date2timestamp(val);
1050  baseStamp = date2timestamp(base);
1051 
1053  TimestampGetDatum(valStamp),
1054  TimestampGetDatum(baseStamp),
1055  IntervalPGetDatum(offset),
1056  BoolGetDatum(sub),
1057  BoolGetDatum(less));
1058 }
1059 
1060 
1061 /* extract_date()
1062  * Extract specified field from date type.
1063  */
1064 Datum
1066 {
1067  text *units = PG_GETARG_TEXT_PP(0);
1069  int64 intresult;
1070  int type,
1071  val;
1072  char *lowunits;
1073  int year,
1074  mon,
1075  mday;
1076 
1077  lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
1078  VARSIZE_ANY_EXHDR(units),
1079  false);
1080 
1081  type = DecodeUnits(0, lowunits, &val);
1082  if (type == UNKNOWN_FIELD)
1083  type = DecodeSpecial(0, lowunits, &val);
1084 
1085  if (DATE_NOT_FINITE(date) && (type == UNITS || type == RESERV))
1086  {
1087  switch (val)
1088  {
1089  /* Oscillating units */
1090  case DTK_DAY:
1091  case DTK_MONTH:
1092  case DTK_QUARTER:
1093  case DTK_WEEK:
1094  case DTK_DOW:
1095  case DTK_ISODOW:
1096  case DTK_DOY:
1097  PG_RETURN_NULL();
1098  break;
1099 
1100  /* Monotonically-increasing units */
1101  case DTK_YEAR:
1102  case DTK_DECADE:
1103  case DTK_CENTURY:
1104  case DTK_MILLENNIUM:
1105  case DTK_JULIAN:
1106  case DTK_ISOYEAR:
1107  case DTK_EPOCH:
1108  if (DATE_IS_NOBEGIN(date))
1110  CStringGetDatum("-Infinity"),
1112  Int32GetDatum(-1))));
1113  else
1115  CStringGetDatum("Infinity"),
1117  Int32GetDatum(-1))));
1118  default:
1119  ereport(ERROR,
1120  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1121  errmsg("unit \"%s\" not supported for type %s",
1122  lowunits, format_type_be(DATEOID))));
1123  }
1124  }
1125  else if (type == UNITS)
1126  {
1127  j2date(date + POSTGRES_EPOCH_JDATE, &year, &mon, &mday);
1128 
1129  switch (val)
1130  {
1131  case DTK_DAY:
1132  intresult = mday;
1133  break;
1134 
1135  case DTK_MONTH:
1136  intresult = mon;
1137  break;
1138 
1139  case DTK_QUARTER:
1140  intresult = (mon - 1) / 3 + 1;
1141  break;
1142 
1143  case DTK_WEEK:
1144  intresult = date2isoweek(year, mon, mday);
1145  break;
1146 
1147  case DTK_YEAR:
1148  if (year > 0)
1149  intresult = year;
1150  else
1151  /* there is no year 0, just 1 BC and 1 AD */
1152  intresult = year - 1;
1153  break;
1154 
1155  case DTK_DECADE:
1156  /* see comments in timestamp_part */
1157  if (year >= 0)
1158  intresult = year / 10;
1159  else
1160  intresult = -((8 - (year - 1)) / 10);
1161  break;
1162 
1163  case DTK_CENTURY:
1164  /* see comments in timestamp_part */
1165  if (year > 0)
1166  intresult = (year + 99) / 100;
1167  else
1168  intresult = -((99 - (year - 1)) / 100);
1169  break;
1170 
1171  case DTK_MILLENNIUM:
1172  /* see comments in timestamp_part */
1173  if (year > 0)
1174  intresult = (year + 999) / 1000;
1175  else
1176  intresult = -((999 - (year - 1)) / 1000);
1177  break;
1178 
1179  case DTK_JULIAN:
1180  intresult = date + POSTGRES_EPOCH_JDATE;
1181  break;
1182 
1183  case DTK_ISOYEAR:
1184  intresult = date2isoyear(year, mon, mday);
1185  /* Adjust BC years */
1186  if (intresult <= 0)
1187  intresult -= 1;
1188  break;
1189 
1190  case DTK_DOW:
1191  case DTK_ISODOW:
1192  intresult = j2day(date + POSTGRES_EPOCH_JDATE);
1193  if (val == DTK_ISODOW && intresult == 0)
1194  intresult = 7;
1195  break;
1196 
1197  case DTK_DOY:
1198  intresult = date2j(year, mon, mday) - date2j(year, 1, 1) + 1;
1199  break;
1200 
1201  default:
1202  ereport(ERROR,
1203  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1204  errmsg("unit \"%s\" not supported for type %s",
1205  lowunits, format_type_be(DATEOID))));
1206  intresult = 0;
1207  }
1208  }
1209  else if (type == RESERV)
1210  {
1211  switch (val)
1212  {
1213  case DTK_EPOCH:
1214  intresult = ((int64) date + POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
1215  break;
1216 
1217  default:
1218  ereport(ERROR,
1219  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1220  errmsg("unit \"%s\" not supported for type %s",
1221  lowunits, format_type_be(DATEOID))));
1222  intresult = 0;
1223  }
1224  }
1225  else
1226  {
1227  ereport(ERROR,
1228  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1229  errmsg("unit \"%s\" not recognized for type %s",
1230  lowunits, format_type_be(DATEOID))));
1231  intresult = 0;
1232  }
1233 
1234  PG_RETURN_NUMERIC(int64_to_numeric(intresult));
1235 }
1236 
1237 
1238 /* Add an interval to a date, giving a new date.
1239  * Must handle both positive and negative intervals.
1240  *
1241  * We implement this by promoting the date to timestamp (without time zone)
1242  * and then using the timestamp plus interval function.
1243  */
1244 Datum
1246 {
1247  DateADT dateVal = PG_GETARG_DATEADT(0);
1248  Interval *span = PG_GETARG_INTERVAL_P(1);
1249  Timestamp dateStamp;
1250 
1251  dateStamp = date2timestamp(dateVal);
1252 
1254  TimestampGetDatum(dateStamp),
1255  PointerGetDatum(span));
1256 }
1257 
1258 /* Subtract an interval from a date, giving a new date.
1259  * Must handle both positive and negative intervals.
1260  *
1261  * We implement this by promoting the date to timestamp (without time zone)
1262  * and then using the timestamp minus interval function.
1263  */
1264 Datum
1266 {
1267  DateADT dateVal = PG_GETARG_DATEADT(0);
1268  Interval *span = PG_GETARG_INTERVAL_P(1);
1269  Timestamp dateStamp;
1270 
1271  dateStamp = date2timestamp(dateVal);
1272 
1274  TimestampGetDatum(dateStamp),
1275  PointerGetDatum(span));
1276 }
1277 
1278 /* date_timestamp()
1279  * Convert date to timestamp data type.
1280  */
1281 Datum
1283 {
1284  DateADT dateVal = PG_GETARG_DATEADT(0);
1285  Timestamp result;
1286 
1287  result = date2timestamp(dateVal);
1288 
1289  PG_RETURN_TIMESTAMP(result);
1290 }
1291 
1292 /* timestamp_date()
1293  * Convert timestamp to date data type.
1294  */
1295 Datum
1297 {
1299  DateADT result;
1300  struct pg_tm tt,
1301  *tm = &tt;
1302  fsec_t fsec;
1303 
1305  DATE_NOBEGIN(result);
1306  else if (TIMESTAMP_IS_NOEND(timestamp))
1307  DATE_NOEND(result);
1308  else
1309  {
1310  if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
1311  ereport(ERROR,
1312  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1313  errmsg("timestamp out of range")));
1314 
1316  }
1317 
1318  PG_RETURN_DATEADT(result);
1319 }
1320 
1321 
1322 /* date_timestamptz()
1323  * Convert date to timestamp with time zone data type.
1324  */
1325 Datum
1327 {
1328  DateADT dateVal = PG_GETARG_DATEADT(0);
1329  TimestampTz result;
1330 
1331  result = date2timestamptz(dateVal);
1332 
1333  PG_RETURN_TIMESTAMP(result);
1334 }
1335 
1336 
1337 /* timestamptz_date()
1338  * Convert timestamp with time zone to date data type.
1339  */
1340 Datum
1342 {
1344  DateADT result;
1345  struct pg_tm tt,
1346  *tm = &tt;
1347  fsec_t fsec;
1348  int tz;
1349 
1351  DATE_NOBEGIN(result);
1352  else if (TIMESTAMP_IS_NOEND(timestamp))
1353  DATE_NOEND(result);
1354  else
1355  {
1356  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
1357  ereport(ERROR,
1358  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1359  errmsg("timestamp out of range")));
1360 
1362  }
1363 
1364  PG_RETURN_DATEADT(result);
1365 }
1366 
1367 
1368 /*****************************************************************************
1369  * Time ADT
1370  *****************************************************************************/
1371 
1372 Datum
1374 {
1375  char *str = PG_GETARG_CSTRING(0);
1376 #ifdef NOT_USED
1377  Oid typelem = PG_GETARG_OID(1);
1378 #endif
1379  int32 typmod = PG_GETARG_INT32(2);
1380  Node *escontext = fcinfo->context;
1381  TimeADT result;
1382  fsec_t fsec;
1383  struct pg_tm tt,
1384  *tm = &tt;
1385  int tz;
1386  int nf;
1387  int dterr;
1388  char workbuf[MAXDATELEN + 1];
1389  char *field[MAXDATEFIELDS];
1390  int dtype;
1391  int ftype[MAXDATEFIELDS];
1392  DateTimeErrorExtra extra;
1393 
1394  dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
1395  field, ftype, MAXDATEFIELDS, &nf);
1396  if (dterr == 0)
1397  dterr = DecodeTimeOnly(field, ftype, nf,
1398  &dtype, tm, &fsec, &tz, &extra);
1399  if (dterr != 0)
1400  {
1401  DateTimeParseError(dterr, &extra, str, "time", escontext);
1402  PG_RETURN_NULL();
1403  }
1404 
1405  tm2time(tm, fsec, &result);
1406  AdjustTimeForTypmod(&result, typmod);
1407 
1408  PG_RETURN_TIMEADT(result);
1409 }
1410 
1411 /* tm2time()
1412  * Convert a tm structure to a time data type.
1413  */
1414 int
1415 tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
1416 {
1417  *result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec)
1418  * USECS_PER_SEC) + fsec;
1419  return 0;
1420 }
1421 
1422 /* time_overflows()
1423  * Check to see if a broken-down time-of-day is out of range.
1424  */
1425 bool
1426 time_overflows(int hour, int min, int sec, fsec_t fsec)
1427 {
1428  /* Range-check the fields individually. */
1429  if (hour < 0 || hour > HOURS_PER_DAY ||
1430  min < 0 || min >= MINS_PER_HOUR ||
1431  sec < 0 || sec > SECS_PER_MINUTE ||
1432  fsec < 0 || fsec > USECS_PER_SEC)
1433  return true;
1434 
1435  /*
1436  * Because we allow, eg, hour = 24 or sec = 60, we must check separately
1437  * that the total time value doesn't exceed 24:00:00.
1438  */
1439  if ((((((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
1440  + sec) * USECS_PER_SEC) + fsec) > USECS_PER_DAY)
1441  return true;
1442 
1443  return false;
1444 }
1445 
1446 /* float_time_overflows()
1447  * Same, when we have seconds + fractional seconds as one "double" value.
1448  */
1449 bool
1450 float_time_overflows(int hour, int min, double sec)
1451 {
1452  /* Range-check the fields individually. */
1453  if (hour < 0 || hour > HOURS_PER_DAY ||
1454  min < 0 || min >= MINS_PER_HOUR)
1455  return true;
1456 
1457  /*
1458  * "sec", being double, requires extra care. Cope with NaN, and round off
1459  * before applying the range check to avoid unexpected errors due to
1460  * imprecise input. (We assume rint() behaves sanely with infinities.)
1461  */
1462  if (isnan(sec))
1463  return true;
1464  sec = rint(sec * USECS_PER_SEC);
1465  if (sec < 0 || sec > SECS_PER_MINUTE * USECS_PER_SEC)
1466  return true;
1467 
1468  /*
1469  * Because we allow, eg, hour = 24 or sec = 60, we must check separately
1470  * that the total time value doesn't exceed 24:00:00. This must match the
1471  * way that callers will convert the fields to a time.
1472  */
1473  if (((((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
1474  * USECS_PER_SEC) + (int64) sec) > USECS_PER_DAY)
1475  return true;
1476 
1477  return false;
1478 }
1479 
1480 
1481 /* time2tm()
1482  * Convert time data type to POSIX time structure.
1483  *
1484  * Note that only the hour/min/sec/fractional-sec fields are filled in.
1485  */
1486 int
1487 time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
1488 {
1489  tm->tm_hour = time / USECS_PER_HOUR;
1490  time -= tm->tm_hour * USECS_PER_HOUR;
1491  tm->tm_min = time / USECS_PER_MINUTE;
1492  time -= tm->tm_min * USECS_PER_MINUTE;
1493  tm->tm_sec = time / USECS_PER_SEC;
1494  time -= tm->tm_sec * USECS_PER_SEC;
1495  *fsec = time;
1496  return 0;
1497 }
1498 
1499 Datum
1501 {
1502  TimeADT time = PG_GETARG_TIMEADT(0);
1503  char *result;
1504  struct pg_tm tt,
1505  *tm = &tt;
1506  fsec_t fsec;
1507  char buf[MAXDATELEN + 1];
1508 
1509  time2tm(time, tm, &fsec);
1510  EncodeTimeOnly(tm, fsec, false, 0, DateStyle, buf);
1511 
1512  result = pstrdup(buf);
1513  PG_RETURN_CSTRING(result);
1514 }
1515 
1516 /*
1517  * time_recv - converts external binary format to time
1518  */
1519 Datum
1521 {
1523 
1524 #ifdef NOT_USED
1525  Oid typelem = PG_GETARG_OID(1);
1526 #endif
1527  int32 typmod = PG_GETARG_INT32(2);
1528  TimeADT result;
1529 
1530  result = pq_getmsgint64(buf);
1531 
1532  if (result < INT64CONST(0) || result > USECS_PER_DAY)
1533  ereport(ERROR,
1534  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1535  errmsg("time out of range")));
1536 
1537  AdjustTimeForTypmod(&result, typmod);
1538 
1539  PG_RETURN_TIMEADT(result);
1540 }
1541 
1542 /*
1543  * time_send - converts time to binary format
1544  */
1545 Datum
1547 {
1548  TimeADT time = PG_GETARG_TIMEADT(0);
1550 
1551  pq_begintypsend(&buf);
1552  pq_sendint64(&buf, time);
1554 }
1555 
1556 Datum
1558 {
1560 
1561  PG_RETURN_INT32(anytime_typmodin(false, ta));
1562 }
1563 
1564 Datum
1566 {
1567  int32 typmod = PG_GETARG_INT32(0);
1568 
1569  PG_RETURN_CSTRING(anytime_typmodout(false, typmod));
1570 }
1571 
1572 /*
1573  * make_time - time constructor
1574  */
1575 Datum
1577 {
1578  int tm_hour = PG_GETARG_INT32(0);
1579  int tm_min = PG_GETARG_INT32(1);
1580  double sec = PG_GETARG_FLOAT8(2);
1581  TimeADT time;
1582 
1583  /* Check for time overflow */
1584  if (float_time_overflows(tm_hour, tm_min, sec))
1585  ereport(ERROR,
1586  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
1587  errmsg("time field value out of range: %d:%02d:%02g",
1588  tm_hour, tm_min, sec)));
1589 
1590  /* This should match tm2time */
1591  time = (((tm_hour * MINS_PER_HOUR + tm_min) * SECS_PER_MINUTE)
1592  * USECS_PER_SEC) + (int64) rint(sec * USECS_PER_SEC);
1593 
1594  PG_RETURN_TIMEADT(time);
1595 }
1596 
1597 
1598 /* time_support()
1599  *
1600  * Planner support function for the time_scale() and timetz_scale()
1601  * length coercion functions (we need not distinguish them here).
1602  */
1603 Datum
1605 {
1606  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1607  Node *ret = NULL;
1608 
1609  if (IsA(rawreq, SupportRequestSimplify))
1610  {
1612 
1613  ret = TemporalSimplify(MAX_TIME_PRECISION, (Node *) req->fcall);
1614  }
1615 
1616  PG_RETURN_POINTER(ret);
1617 }
1618 
1619 /* time_scale()
1620  * Adjust time type for specified scale factor.
1621  * Used by PostgreSQL type system to stuff columns.
1622  */
1623 Datum
1625 {
1626  TimeADT time = PG_GETARG_TIMEADT(0);
1627  int32 typmod = PG_GETARG_INT32(1);
1628  TimeADT result;
1629 
1630  result = time;
1631  AdjustTimeForTypmod(&result, typmod);
1632 
1633  PG_RETURN_TIMEADT(result);
1634 }
1635 
1636 /* AdjustTimeForTypmod()
1637  * Force the precision of the time value to a specified value.
1638  * Uses *exactly* the same code as in AdjustTimestampForTypmod()
1639  * but we make a separate copy because those types do not
1640  * have a fundamental tie together but rather a coincidence of
1641  * implementation. - thomas
1642  */
1643 void
1645 {
1646  static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {
1647  INT64CONST(1000000),
1648  INT64CONST(100000),
1649  INT64CONST(10000),
1650  INT64CONST(1000),
1651  INT64CONST(100),
1652  INT64CONST(10),
1653  INT64CONST(1)
1654  };
1655 
1656  static const int64 TimeOffsets[MAX_TIME_PRECISION + 1] = {
1657  INT64CONST(500000),
1658  INT64CONST(50000),
1659  INT64CONST(5000),
1660  INT64CONST(500),
1661  INT64CONST(50),
1662  INT64CONST(5),
1663  INT64CONST(0)
1664  };
1665 
1666  if (typmod >= 0 && typmod <= MAX_TIME_PRECISION)
1667  {
1668  if (*time >= INT64CONST(0))
1669  *time = ((*time + TimeOffsets[typmod]) / TimeScales[typmod]) *
1670  TimeScales[typmod];
1671  else
1672  *time = -((((-*time) + TimeOffsets[typmod]) / TimeScales[typmod]) *
1673  TimeScales[typmod]);
1674  }
1675 }
1676 
1677 
1678 Datum
1680 {
1681  TimeADT time1 = PG_GETARG_TIMEADT(0);
1682  TimeADT time2 = PG_GETARG_TIMEADT(1);
1683 
1684  PG_RETURN_BOOL(time1 == time2);
1685 }
1686 
1687 Datum
1689 {
1690  TimeADT time1 = PG_GETARG_TIMEADT(0);
1691  TimeADT time2 = PG_GETARG_TIMEADT(1);
1692 
1693  PG_RETURN_BOOL(time1 != time2);
1694 }
1695 
1696 Datum
1698 {
1699  TimeADT time1 = PG_GETARG_TIMEADT(0);
1700  TimeADT time2 = PG_GETARG_TIMEADT(1);
1701 
1702  PG_RETURN_BOOL(time1 < time2);
1703 }
1704 
1705 Datum
1707 {
1708  TimeADT time1 = PG_GETARG_TIMEADT(0);
1709  TimeADT time2 = PG_GETARG_TIMEADT(1);
1710 
1711  PG_RETURN_BOOL(time1 <= time2);
1712 }
1713 
1714 Datum
1716 {
1717  TimeADT time1 = PG_GETARG_TIMEADT(0);
1718  TimeADT time2 = PG_GETARG_TIMEADT(1);
1719 
1720  PG_RETURN_BOOL(time1 > time2);
1721 }
1722 
1723 Datum
1725 {
1726  TimeADT time1 = PG_GETARG_TIMEADT(0);
1727  TimeADT time2 = PG_GETARG_TIMEADT(1);
1728 
1729  PG_RETURN_BOOL(time1 >= time2);
1730 }
1731 
1732 Datum
1734 {
1735  TimeADT time1 = PG_GETARG_TIMEADT(0);
1736  TimeADT time2 = PG_GETARG_TIMEADT(1);
1737 
1738  if (time1 < time2)
1739  PG_RETURN_INT32(-1);
1740  if (time1 > time2)
1741  PG_RETURN_INT32(1);
1742  PG_RETURN_INT32(0);
1743 }
1744 
1745 Datum
1747 {
1748  return hashint8(fcinfo);
1749 }
1750 
1751 Datum
1753 {
1754  return hashint8extended(fcinfo);
1755 }
1756 
1757 Datum
1759 {
1760  TimeADT time1 = PG_GETARG_TIMEADT(0);
1761  TimeADT time2 = PG_GETARG_TIMEADT(1);
1762 
1763  PG_RETURN_TIMEADT((time1 > time2) ? time1 : time2);
1764 }
1765 
1766 Datum
1768 {
1769  TimeADT time1 = PG_GETARG_TIMEADT(0);
1770  TimeADT time2 = PG_GETARG_TIMEADT(1);
1771 
1772  PG_RETURN_TIMEADT((time1 < time2) ? time1 : time2);
1773 }
1774 
1775 /* overlaps_time() --- implements the SQL OVERLAPS operator.
1776  *
1777  * Algorithm is per SQL spec. This is much harder than you'd think
1778  * because the spec requires us to deliver a non-null answer in some cases
1779  * where some of the inputs are null.
1780  */
1781 Datum
1783 {
1784  /*
1785  * The arguments are TimeADT, but we leave them as generic Datums to avoid
1786  * dereferencing nulls (TimeADT is pass-by-reference!)
1787  */
1788  Datum ts1 = PG_GETARG_DATUM(0);
1789  Datum te1 = PG_GETARG_DATUM(1);
1790  Datum ts2 = PG_GETARG_DATUM(2);
1791  Datum te2 = PG_GETARG_DATUM(3);
1792  bool ts1IsNull = PG_ARGISNULL(0);
1793  bool te1IsNull = PG_ARGISNULL(1);
1794  bool ts2IsNull = PG_ARGISNULL(2);
1795  bool te2IsNull = PG_ARGISNULL(3);
1796 
1797 #define TIMEADT_GT(t1,t2) \
1798  (DatumGetTimeADT(t1) > DatumGetTimeADT(t2))
1799 #define TIMEADT_LT(t1,t2) \
1800  (DatumGetTimeADT(t1) < DatumGetTimeADT(t2))
1801 
1802  /*
1803  * If both endpoints of interval 1 are null, the result is null (unknown).
1804  * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
1805  * take ts1 as the lesser endpoint.
1806  */
1807  if (ts1IsNull)
1808  {
1809  if (te1IsNull)
1810  PG_RETURN_NULL();
1811  /* swap null for non-null */
1812  ts1 = te1;
1813  te1IsNull = true;
1814  }
1815  else if (!te1IsNull)
1816  {
1817  if (TIMEADT_GT(ts1, te1))
1818  {
1819  Datum tt = ts1;
1820 
1821  ts1 = te1;
1822  te1 = tt;
1823  }
1824  }
1825 
1826  /* Likewise for interval 2. */
1827  if (ts2IsNull)
1828  {
1829  if (te2IsNull)
1830  PG_RETURN_NULL();
1831  /* swap null for non-null */
1832  ts2 = te2;
1833  te2IsNull = true;
1834  }
1835  else if (!te2IsNull)
1836  {
1837  if (TIMEADT_GT(ts2, te2))
1838  {
1839  Datum tt = ts2;
1840 
1841  ts2 = te2;
1842  te2 = tt;
1843  }
1844  }
1845 
1846  /*
1847  * At this point neither ts1 nor ts2 is null, so we can consider three
1848  * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
1849  */
1850  if (TIMEADT_GT(ts1, ts2))
1851  {
1852  /*
1853  * This case is ts1 < te2 OR te1 < te2, which may look redundant but
1854  * in the presence of nulls it's not quite completely so.
1855  */
1856  if (te2IsNull)
1857  PG_RETURN_NULL();
1858  if (TIMEADT_LT(ts1, te2))
1859  PG_RETURN_BOOL(true);
1860  if (te1IsNull)
1861  PG_RETURN_NULL();
1862 
1863  /*
1864  * If te1 is not null then we had ts1 <= te1 above, and we just found
1865  * ts1 >= te2, hence te1 >= te2.
1866  */
1867  PG_RETURN_BOOL(false);
1868  }
1869  else if (TIMEADT_LT(ts1, ts2))
1870  {
1871  /* This case is ts2 < te1 OR te2 < te1 */
1872  if (te1IsNull)
1873  PG_RETURN_NULL();
1874  if (TIMEADT_LT(ts2, te1))
1875  PG_RETURN_BOOL(true);
1876  if (te2IsNull)
1877  PG_RETURN_NULL();
1878 
1879  /*
1880  * If te2 is not null then we had ts2 <= te2 above, and we just found
1881  * ts2 >= te1, hence te2 >= te1.
1882  */
1883  PG_RETURN_BOOL(false);
1884  }
1885  else
1886  {
1887  /*
1888  * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
1889  * rather silly way of saying "true if both are nonnull, else null".
1890  */
1891  if (te1IsNull || te2IsNull)
1892  PG_RETURN_NULL();
1893  PG_RETURN_BOOL(true);
1894  }
1895 
1896 #undef TIMEADT_GT
1897 #undef TIMEADT_LT
1898 }
1899 
1900 /* timestamp_time()
1901  * Convert timestamp to time data type.
1902  */
1903 Datum
1905 {
1907  TimeADT result;
1908  struct pg_tm tt,
1909  *tm = &tt;
1910  fsec_t fsec;
1911 
1913  PG_RETURN_NULL();
1914 
1915  if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
1916  ereport(ERROR,
1917  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1918  errmsg("timestamp out of range")));
1919 
1920  /*
1921  * Could also do this with time = (timestamp / USECS_PER_DAY *
1922  * USECS_PER_DAY) - timestamp;
1923  */
1924  result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
1925  USECS_PER_SEC) + fsec;
1926 
1927  PG_RETURN_TIMEADT(result);
1928 }
1929 
1930 /* timestamptz_time()
1931  * Convert timestamptz to time data type.
1932  */
1933 Datum
1935 {
1937  TimeADT result;
1938  struct pg_tm tt,
1939  *tm = &tt;
1940  int tz;
1941  fsec_t fsec;
1942 
1944  PG_RETURN_NULL();
1945 
1946  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
1947  ereport(ERROR,
1948  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1949  errmsg("timestamp out of range")));
1950 
1951  /*
1952  * Could also do this with time = (timestamp / USECS_PER_DAY *
1953  * USECS_PER_DAY) - timestamp;
1954  */
1955  result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
1956  USECS_PER_SEC) + fsec;
1957 
1958  PG_RETURN_TIMEADT(result);
1959 }
1960 
1961 /* datetime_timestamp()
1962  * Convert date and time to timestamp data type.
1963  */
1964 Datum
1966 {
1968  TimeADT time = PG_GETARG_TIMEADT(1);
1969  Timestamp result;
1970 
1971  result = date2timestamp(date);
1972  if (!TIMESTAMP_NOT_FINITE(result))
1973  {
1974  result += time;
1975  if (!IS_VALID_TIMESTAMP(result))
1976  ereport(ERROR,
1977  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1978  errmsg("timestamp out of range")));
1979  }
1980 
1981  PG_RETURN_TIMESTAMP(result);
1982 }
1983 
1984 /* time_interval()
1985  * Convert time to interval data type.
1986  */
1987 Datum
1989 {
1990  TimeADT time = PG_GETARG_TIMEADT(0);
1991  Interval *result;
1992 
1993  result = (Interval *) palloc(sizeof(Interval));
1994 
1995  result->time = time;
1996  result->day = 0;
1997  result->month = 0;
1998 
1999  PG_RETURN_INTERVAL_P(result);
2000 }
2001 
2002 /* interval_time()
2003  * Convert interval to time data type.
2004  *
2005  * This is defined as producing the fractional-day portion of the interval.
2006  * Therefore, we can just ignore the months field. It is not real clear
2007  * what to do with negative intervals, but we choose to subtract the floor,
2008  * so that, say, '-2 hours' becomes '22:00:00'.
2009  */
2010 Datum
2012 {
2013  Interval *span = PG_GETARG_INTERVAL_P(0);
2014  TimeADT result;
2015  int64 days;
2016 
2017  result = span->time;
2018  if (result >= USECS_PER_DAY)
2019  {
2020  days = result / USECS_PER_DAY;
2021  result -= days * USECS_PER_DAY;
2022  }
2023  else if (result < 0)
2024  {
2025  days = (-result + USECS_PER_DAY - 1) / USECS_PER_DAY;
2026  result += days * USECS_PER_DAY;
2027  }
2028 
2029  PG_RETURN_TIMEADT(result);
2030 }
2031 
2032 /* time_mi_time()
2033  * Subtract two times to produce an interval.
2034  */
2035 Datum
2037 {
2038  TimeADT time1 = PG_GETARG_TIMEADT(0);
2039  TimeADT time2 = PG_GETARG_TIMEADT(1);
2040  Interval *result;
2041 
2042  result = (Interval *) palloc(sizeof(Interval));
2043 
2044  result->month = 0;
2045  result->day = 0;
2046  result->time = time1 - time2;
2047 
2048  PG_RETURN_INTERVAL_P(result);
2049 }
2050 
2051 /* time_pl_interval()
2052  * Add interval to time.
2053  */
2054 Datum
2056 {
2057  TimeADT time = PG_GETARG_TIMEADT(0);
2058  Interval *span = PG_GETARG_INTERVAL_P(1);
2059  TimeADT result;
2060 
2061  result = time + span->time;
2062  result -= result / USECS_PER_DAY * USECS_PER_DAY;
2063  if (result < INT64CONST(0))
2064  result += USECS_PER_DAY;
2065 
2066  PG_RETURN_TIMEADT(result);
2067 }
2068 
2069 /* time_mi_interval()
2070  * Subtract interval from time.
2071  */
2072 Datum
2074 {
2075  TimeADT time = PG_GETARG_TIMEADT(0);
2076  Interval *span = PG_GETARG_INTERVAL_P(1);
2077  TimeADT result;
2078 
2079  result = time - span->time;
2080  result -= result / USECS_PER_DAY * USECS_PER_DAY;
2081  if (result < INT64CONST(0))
2082  result += USECS_PER_DAY;
2083 
2084  PG_RETURN_TIMEADT(result);
2085 }
2086 
2087 /*
2088  * in_range support function for time.
2089  */
2090 Datum
2092 {
2094  TimeADT base = PG_GETARG_TIMEADT(1);
2095  Interval *offset = PG_GETARG_INTERVAL_P(2);
2096  bool sub = PG_GETARG_BOOL(3);
2097  bool less = PG_GETARG_BOOL(4);
2098  TimeADT sum;
2099 
2100  /*
2101  * Like time_pl_interval/time_mi_interval, we disregard the month and day
2102  * fields of the offset. So our test for negative should too.
2103  */
2104  if (offset->time < 0)
2105  ereport(ERROR,
2106  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2107  errmsg("invalid preceding or following size in window function")));
2108 
2109  /*
2110  * We can't use time_pl_interval/time_mi_interval here, because their
2111  * wraparound behavior would give wrong (or at least undesirable) answers.
2112  * Fortunately the equivalent non-wrapping behavior is trivial, especially
2113  * since we don't worry about integer overflow.
2114  */
2115  if (sub)
2116  sum = base - offset->time;
2117  else
2118  sum = base + offset->time;
2119 
2120  if (less)
2121  PG_RETURN_BOOL(val <= sum);
2122  else
2123  PG_RETURN_BOOL(val >= sum);
2124 }
2125 
2126 
2127 /* time_part() and extract_time()
2128  * Extract specified field from time type.
2129  */
2130 static Datum
2132 {
2133  text *units = PG_GETARG_TEXT_PP(0);
2134  TimeADT time = PG_GETARG_TIMEADT(1);
2135  int64 intresult;
2136  int type,
2137  val;
2138  char *lowunits;
2139 
2140  lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
2141  VARSIZE_ANY_EXHDR(units),
2142  false);
2143 
2144  type = DecodeUnits(0, lowunits, &val);
2145  if (type == UNKNOWN_FIELD)
2146  type = DecodeSpecial(0, lowunits, &val);
2147 
2148  if (type == UNITS)
2149  {
2150  fsec_t fsec;
2151  struct pg_tm tt,
2152  *tm = &tt;
2153 
2154  time2tm(time, tm, &fsec);
2155 
2156  switch (val)
2157  {
2158  case DTK_MICROSEC:
2159  intresult = tm->tm_sec * INT64CONST(1000000) + fsec;
2160  break;
2161 
2162  case DTK_MILLISEC:
2163  if (retnumeric)
2164  /*---
2165  * tm->tm_sec * 1000 + fsec / 1000
2166  * = (tm->tm_sec * 1'000'000 + fsec) / 1000
2167  */
2168  PG_RETURN_NUMERIC(int64_div_fast_to_numeric(tm->tm_sec * INT64CONST(1000000) + fsec, 3));
2169  else
2170  PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + fsec / 1000.0);
2171  break;
2172 
2173  case DTK_SECOND:
2174  if (retnumeric)
2175  /*---
2176  * tm->tm_sec + fsec / 1'000'000
2177  * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
2178  */
2179  PG_RETURN_NUMERIC(int64_div_fast_to_numeric(tm->tm_sec * INT64CONST(1000000) + fsec, 6));
2180  else
2181  PG_RETURN_FLOAT8(tm->tm_sec + fsec / 1000000.0);
2182  break;
2183 
2184  case DTK_MINUTE:
2185  intresult = tm->tm_min;
2186  break;
2187 
2188  case DTK_HOUR:
2189  intresult = tm->tm_hour;
2190  break;
2191 
2192  case DTK_TZ:
2193  case DTK_TZ_MINUTE:
2194  case DTK_TZ_HOUR:
2195  case DTK_DAY:
2196  case DTK_MONTH:
2197  case DTK_QUARTER:
2198  case DTK_YEAR:
2199  case DTK_DECADE:
2200  case DTK_CENTURY:
2201  case DTK_MILLENNIUM:
2202  case DTK_ISOYEAR:
2203  default:
2204  ereport(ERROR,
2205  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2206  errmsg("unit \"%s\" not supported for type %s",
2207  lowunits, format_type_be(TIMEOID))));
2208  intresult = 0;
2209  }
2210  }
2211  else if (type == RESERV && val == DTK_EPOCH)
2212  {
2213  if (retnumeric)
2215  else
2216  PG_RETURN_FLOAT8(time / 1000000.0);
2217  }
2218  else
2219  {
2220  ereport(ERROR,
2221  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2222  errmsg("unit \"%s\" not recognized for type %s",
2223  lowunits, format_type_be(TIMEOID))));
2224  intresult = 0;
2225  }
2226 
2227  if (retnumeric)
2228  PG_RETURN_NUMERIC(int64_to_numeric(intresult));
2229  else
2230  PG_RETURN_FLOAT8(intresult);
2231 }
2232 
2233 Datum
2235 {
2236  return time_part_common(fcinfo, false);
2237 }
2238 
2239 Datum
2241 {
2242  return time_part_common(fcinfo, true);
2243 }
2244 
2245 
2246 /*****************************************************************************
2247  * Time With Time Zone ADT
2248  *****************************************************************************/
2249 
2250 /* tm2timetz()
2251  * Convert a tm structure to a time data type.
2252  */
2253 int
2254 tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
2255 {
2256  result->time = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
2257  USECS_PER_SEC) + fsec;
2258  result->zone = tz;
2259 
2260  return 0;
2261 }
2262 
2263 Datum
2265 {
2266  char *str = PG_GETARG_CSTRING(0);
2267 #ifdef NOT_USED
2268  Oid typelem = PG_GETARG_OID(1);
2269 #endif
2270  int32 typmod = PG_GETARG_INT32(2);
2271  Node *escontext = fcinfo->context;
2272  TimeTzADT *result;
2273  fsec_t fsec;
2274  struct pg_tm tt,
2275  *tm = &tt;
2276  int tz;
2277  int nf;
2278  int dterr;
2279  char workbuf[MAXDATELEN + 1];
2280  char *field[MAXDATEFIELDS];
2281  int dtype;
2282  int ftype[MAXDATEFIELDS];
2283  DateTimeErrorExtra extra;
2284 
2285  dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
2286  field, ftype, MAXDATEFIELDS, &nf);
2287  if (dterr == 0)
2288  dterr = DecodeTimeOnly(field, ftype, nf,
2289  &dtype, tm, &fsec, &tz, &extra);
2290  if (dterr != 0)
2291  {
2292  DateTimeParseError(dterr, &extra, str, "time with time zone",
2293  escontext);
2294  PG_RETURN_NULL();
2295  }
2296 
2297  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2298  tm2timetz(tm, fsec, tz, result);
2299  AdjustTimeForTypmod(&(result->time), typmod);
2300 
2301  PG_RETURN_TIMETZADT_P(result);
2302 }
2303 
2304 Datum
2306 {
2307  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2308  char *result;
2309  struct pg_tm tt,
2310  *tm = &tt;
2311  fsec_t fsec;
2312  int tz;
2313  char buf[MAXDATELEN + 1];
2314 
2315  timetz2tm(time, tm, &fsec, &tz);
2316  EncodeTimeOnly(tm, fsec, true, tz, DateStyle, buf);
2317 
2318  result = pstrdup(buf);
2319  PG_RETURN_CSTRING(result);
2320 }
2321 
2322 /*
2323  * timetz_recv - converts external binary format to timetz
2324  */
2325 Datum
2327 {
2329 
2330 #ifdef NOT_USED
2331  Oid typelem = PG_GETARG_OID(1);
2332 #endif
2333  int32 typmod = PG_GETARG_INT32(2);
2334  TimeTzADT *result;
2335 
2336  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2337 
2338  result->time = pq_getmsgint64(buf);
2339 
2340  if (result->time < INT64CONST(0) || result->time > USECS_PER_DAY)
2341  ereport(ERROR,
2342  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2343  errmsg("time out of range")));
2344 
2345  result->zone = pq_getmsgint(buf, sizeof(result->zone));
2346 
2347  /* Check for sane GMT displacement; see notes in datatype/timestamp.h */
2348  if (result->zone <= -TZDISP_LIMIT || result->zone >= TZDISP_LIMIT)
2349  ereport(ERROR,
2350  (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
2351  errmsg("time zone displacement out of range")));
2352 
2353  AdjustTimeForTypmod(&(result->time), typmod);
2354 
2355  PG_RETURN_TIMETZADT_P(result);
2356 }
2357 
2358 /*
2359  * timetz_send - converts timetz to binary format
2360  */
2361 Datum
2363 {
2364  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2366 
2367  pq_begintypsend(&buf);
2368  pq_sendint64(&buf, time->time);
2369  pq_sendint32(&buf, time->zone);
2371 }
2372 
2373 Datum
2375 {
2377 
2378  PG_RETURN_INT32(anytime_typmodin(true, ta));
2379 }
2380 
2381 Datum
2383 {
2384  int32 typmod = PG_GETARG_INT32(0);
2385 
2386  PG_RETURN_CSTRING(anytime_typmodout(true, typmod));
2387 }
2388 
2389 
2390 /* timetz2tm()
2391  * Convert TIME WITH TIME ZONE data type to POSIX time structure.
2392  */
2393 int
2394 timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
2395 {
2396  TimeOffset trem = time->time;
2397 
2398  tm->tm_hour = trem / USECS_PER_HOUR;
2399  trem -= tm->tm_hour * USECS_PER_HOUR;
2400  tm->tm_min = trem / USECS_PER_MINUTE;
2401  trem -= tm->tm_min * USECS_PER_MINUTE;
2402  tm->tm_sec = trem / USECS_PER_SEC;
2403  *fsec = trem - tm->tm_sec * USECS_PER_SEC;
2404 
2405  if (tzp != NULL)
2406  *tzp = time->zone;
2407 
2408  return 0;
2409 }
2410 
2411 /* timetz_scale()
2412  * Adjust time type for specified scale factor.
2413  * Used by PostgreSQL type system to stuff columns.
2414  */
2415 Datum
2417 {
2418  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2419  int32 typmod = PG_GETARG_INT32(1);
2420  TimeTzADT *result;
2421 
2422  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2423 
2424  result->time = time->time;
2425  result->zone = time->zone;
2426 
2427  AdjustTimeForTypmod(&(result->time), typmod);
2428 
2429  PG_RETURN_TIMETZADT_P(result);
2430 }
2431 
2432 
2433 static int
2435 {
2436  TimeOffset t1,
2437  t2;
2438 
2439  /* Primary sort is by true (GMT-equivalent) time */
2440  t1 = time1->time + (time1->zone * USECS_PER_SEC);
2441  t2 = time2->time + (time2->zone * USECS_PER_SEC);
2442 
2443  if (t1 > t2)
2444  return 1;
2445  if (t1 < t2)
2446  return -1;
2447 
2448  /*
2449  * If same GMT time, sort by timezone; we only want to say that two
2450  * timetz's are equal if both the time and zone parts are equal.
2451  */
2452  if (time1->zone > time2->zone)
2453  return 1;
2454  if (time1->zone < time2->zone)
2455  return -1;
2456 
2457  return 0;
2458 }
2459 
2460 Datum
2462 {
2463  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2464  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2465 
2466  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) == 0);
2467 }
2468 
2469 Datum
2471 {
2472  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2473  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2474 
2475  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) != 0);
2476 }
2477 
2478 Datum
2480 {
2481  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2482  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2483 
2484  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) < 0);
2485 }
2486 
2487 Datum
2489 {
2490  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2491  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2492 
2493  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) <= 0);
2494 }
2495 
2496 Datum
2498 {
2499  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2500  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2501 
2502  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);
2503 }
2504 
2505 Datum
2507 {
2508  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2509  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2510 
2511  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);
2512 }
2513 
2514 Datum
2516 {
2517  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2518  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2519 
2520  PG_RETURN_INT32(timetz_cmp_internal(time1, time2));
2521 }
2522 
2523 Datum
2525 {
2527  uint32 thash;
2528 
2529  /*
2530  * To avoid any problems with padding bytes in the struct, we figure the
2531  * field hashes separately and XOR them.
2532  */
2534  Int64GetDatumFast(key->time)));
2535  thash ^= DatumGetUInt32(hash_uint32(key->zone));
2536  PG_RETURN_UINT32(thash);
2537 }
2538 
2539 Datum
2541 {
2543  Datum seed = PG_GETARG_DATUM(1);
2544  uint64 thash;
2545 
2546  /* Same approach as timetz_hash */
2548  Int64GetDatumFast(key->time),
2549  seed));
2550  thash ^= DatumGetUInt64(hash_uint32_extended(key->zone,
2551  DatumGetInt64(seed)));
2552  PG_RETURN_UINT64(thash);
2553 }
2554 
2555 Datum
2557 {
2558  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2559  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2560  TimeTzADT *result;
2561 
2562  if (timetz_cmp_internal(time1, time2) > 0)
2563  result = time1;
2564  else
2565  result = time2;
2566  PG_RETURN_TIMETZADT_P(result);
2567 }
2568 
2569 Datum
2571 {
2572  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2573  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2574  TimeTzADT *result;
2575 
2576  if (timetz_cmp_internal(time1, time2) < 0)
2577  result = time1;
2578  else
2579  result = time2;
2580  PG_RETURN_TIMETZADT_P(result);
2581 }
2582 
2583 /* timetz_pl_interval()
2584  * Add interval to timetz.
2585  */
2586 Datum
2588 {
2589  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2590  Interval *span = PG_GETARG_INTERVAL_P(1);
2591  TimeTzADT *result;
2592 
2593  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2594 
2595  result->time = time->time + span->time;
2596  result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
2597  if (result->time < INT64CONST(0))
2598  result->time += USECS_PER_DAY;
2599 
2600  result->zone = time->zone;
2601 
2602  PG_RETURN_TIMETZADT_P(result);
2603 }
2604 
2605 /* timetz_mi_interval()
2606  * Subtract interval from timetz.
2607  */
2608 Datum
2610 {
2611  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2612  Interval *span = PG_GETARG_INTERVAL_P(1);
2613  TimeTzADT *result;
2614 
2615  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2616 
2617  result->time = time->time - span->time;
2618  result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
2619  if (result->time < INT64CONST(0))
2620  result->time += USECS_PER_DAY;
2621 
2622  result->zone = time->zone;
2623 
2624  PG_RETURN_TIMETZADT_P(result);
2625 }
2626 
2627 /*
2628  * in_range support function for timetz.
2629  */
2630 Datum
2632 {
2634  TimeTzADT *base = PG_GETARG_TIMETZADT_P(1);
2635  Interval *offset = PG_GETARG_INTERVAL_P(2);
2636  bool sub = PG_GETARG_BOOL(3);
2637  bool less = PG_GETARG_BOOL(4);
2638  TimeTzADT sum;
2639 
2640  /*
2641  * Like timetz_pl_interval/timetz_mi_interval, we disregard the month and
2642  * day fields of the offset. So our test for negative should too.
2643  */
2644  if (offset->time < 0)
2645  ereport(ERROR,
2646  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2647  errmsg("invalid preceding or following size in window function")));
2648 
2649  /*
2650  * We can't use timetz_pl_interval/timetz_mi_interval here, because their
2651  * wraparound behavior would give wrong (or at least undesirable) answers.
2652  * Fortunately the equivalent non-wrapping behavior is trivial, especially
2653  * since we don't worry about integer overflow.
2654  */
2655  if (sub)
2656  sum.time = base->time - offset->time;
2657  else
2658  sum.time = base->time + offset->time;
2659  sum.zone = base->zone;
2660 
2661  if (less)
2662  PG_RETURN_BOOL(timetz_cmp_internal(val, &sum) <= 0);
2663  else
2664  PG_RETURN_BOOL(timetz_cmp_internal(val, &sum) >= 0);
2665 }
2666 
2667 /* overlaps_timetz() --- implements the SQL OVERLAPS operator.
2668  *
2669  * Algorithm is per SQL spec. This is much harder than you'd think
2670  * because the spec requires us to deliver a non-null answer in some cases
2671  * where some of the inputs are null.
2672  */
2673 Datum
2675 {
2676  /*
2677  * The arguments are TimeTzADT *, but we leave them as generic Datums for
2678  * convenience of notation --- and to avoid dereferencing nulls.
2679  */
2680  Datum ts1 = PG_GETARG_DATUM(0);
2681  Datum te1 = PG_GETARG_DATUM(1);
2682  Datum ts2 = PG_GETARG_DATUM(2);
2683  Datum te2 = PG_GETARG_DATUM(3);
2684  bool ts1IsNull = PG_ARGISNULL(0);
2685  bool te1IsNull = PG_ARGISNULL(1);
2686  bool ts2IsNull = PG_ARGISNULL(2);
2687  bool te2IsNull = PG_ARGISNULL(3);
2688 
2689 #define TIMETZ_GT(t1,t2) \
2690  DatumGetBool(DirectFunctionCall2(timetz_gt,t1,t2))
2691 #define TIMETZ_LT(t1,t2) \
2692  DatumGetBool(DirectFunctionCall2(timetz_lt,t1,t2))
2693 
2694  /*
2695  * If both endpoints of interval 1 are null, the result is null (unknown).
2696  * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
2697  * take ts1 as the lesser endpoint.
2698  */
2699  if (ts1IsNull)
2700  {
2701  if (te1IsNull)
2702  PG_RETURN_NULL();
2703  /* swap null for non-null */
2704  ts1 = te1;
2705  te1IsNull = true;
2706  }
2707  else if (!te1IsNull)
2708  {
2709  if (TIMETZ_GT(ts1, te1))
2710  {
2711  Datum tt = ts1;
2712 
2713  ts1 = te1;
2714  te1 = tt;
2715  }
2716  }
2717 
2718  /* Likewise for interval 2. */
2719  if (ts2IsNull)
2720  {
2721  if (te2IsNull)
2722  PG_RETURN_NULL();
2723  /* swap null for non-null */
2724  ts2 = te2;
2725  te2IsNull = true;
2726  }
2727  else if (!te2IsNull)
2728  {
2729  if (TIMETZ_GT(ts2, te2))
2730  {
2731  Datum tt = ts2;
2732 
2733  ts2 = te2;
2734  te2 = tt;
2735  }
2736  }
2737 
2738  /*
2739  * At this point neither ts1 nor ts2 is null, so we can consider three
2740  * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
2741  */
2742  if (TIMETZ_GT(ts1, ts2))
2743  {
2744  /*
2745  * This case is ts1 < te2 OR te1 < te2, which may look redundant but
2746  * in the presence of nulls it's not quite completely so.
2747  */
2748  if (te2IsNull)
2749  PG_RETURN_NULL();
2750  if (TIMETZ_LT(ts1, te2))
2751  PG_RETURN_BOOL(true);
2752  if (te1IsNull)
2753  PG_RETURN_NULL();
2754 
2755  /*
2756  * If te1 is not null then we had ts1 <= te1 above, and we just found
2757  * ts1 >= te2, hence te1 >= te2.
2758  */
2759  PG_RETURN_BOOL(false);
2760  }
2761  else if (TIMETZ_LT(ts1, ts2))
2762  {
2763  /* This case is ts2 < te1 OR te2 < te1 */
2764  if (te1IsNull)
2765  PG_RETURN_NULL();
2766  if (TIMETZ_LT(ts2, te1))
2767  PG_RETURN_BOOL(true);
2768  if (te2IsNull)
2769  PG_RETURN_NULL();
2770 
2771  /*
2772  * If te2 is not null then we had ts2 <= te2 above, and we just found
2773  * ts2 >= te1, hence te2 >= te1.
2774  */
2775  PG_RETURN_BOOL(false);
2776  }
2777  else
2778  {
2779  /*
2780  * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
2781  * rather silly way of saying "true if both are nonnull, else null".
2782  */
2783  if (te1IsNull || te2IsNull)
2784  PG_RETURN_NULL();
2785  PG_RETURN_BOOL(true);
2786  }
2787 
2788 #undef TIMETZ_GT
2789 #undef TIMETZ_LT
2790 }
2791 
2792 
2793 Datum
2795 {
2796  TimeTzADT *timetz = PG_GETARG_TIMETZADT_P(0);
2797  TimeADT result;
2798 
2799  /* swallow the time zone and just return the time */
2800  result = timetz->time;
2801 
2802  PG_RETURN_TIMEADT(result);
2803 }
2804 
2805 
2806 Datum
2808 {
2809  TimeADT time = PG_GETARG_TIMEADT(0);
2810  TimeTzADT *result;
2811  struct pg_tm tt,
2812  *tm = &tt;
2813  fsec_t fsec;
2814  int tz;
2815 
2817  time2tm(time, tm, &fsec);
2819 
2820  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2821 
2822  result->time = time;
2823  result->zone = tz;
2824 
2825  PG_RETURN_TIMETZADT_P(result);
2826 }
2827 
2828 
2829 /* timestamptz_timetz()
2830  * Convert timestamp to timetz data type.
2831  */
2832 Datum
2834 {
2836  TimeTzADT *result;
2837  struct pg_tm tt,
2838  *tm = &tt;
2839  int tz;
2840  fsec_t fsec;
2841 
2843  PG_RETURN_NULL();
2844 
2845  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
2846  ereport(ERROR,
2847  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2848  errmsg("timestamp out of range")));
2849 
2850  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2851 
2852  tm2timetz(tm, fsec, tz, result);
2853 
2854  PG_RETURN_TIMETZADT_P(result);
2855 }
2856 
2857 
2858 /* datetimetz_timestamptz()
2859  * Convert date and timetz to timestamp with time zone data type.
2860  * Timestamp is stored in GMT, so add the time zone
2861  * stored with the timetz to the result.
2862  * - thomas 2000-03-10
2863  */
2864 Datum
2866 {
2868  TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
2869  TimestampTz result;
2870 
2871  if (DATE_IS_NOBEGIN(date))
2872  TIMESTAMP_NOBEGIN(result);
2873  else if (DATE_IS_NOEND(date))
2874  TIMESTAMP_NOEND(result);
2875  else
2876  {
2877  /*
2878  * Date's range is wider than timestamp's, so check for boundaries.
2879  * Since dates have the same minimum values as timestamps, only upper
2880  * boundary need be checked for overflow.
2881  */
2883  ereport(ERROR,
2884  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2885  errmsg("date out of range for timestamp")));
2886  result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;
2887 
2888  /*
2889  * Since it is possible to go beyond allowed timestamptz range because
2890  * of time zone, check for allowed timestamp range after adding tz.
2891  */
2892  if (!IS_VALID_TIMESTAMP(result))
2893  ereport(ERROR,
2894  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2895  errmsg("date out of range for timestamp")));
2896  }
2897 
2898  PG_RETURN_TIMESTAMP(result);
2899 }
2900 
2901 
2902 /* timetz_part() and extract_timetz()
2903  * Extract specified field from time type.
2904  */
2905 static Datum
2907 {
2908  text *units = PG_GETARG_TEXT_PP(0);
2909  TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
2910  int64 intresult;
2911  int type,
2912  val;
2913  char *lowunits;
2914 
2915  lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
2916  VARSIZE_ANY_EXHDR(units),
2917  false);
2918 
2919  type = DecodeUnits(0, lowunits, &val);
2920  if (type == UNKNOWN_FIELD)
2921  type = DecodeSpecial(0, lowunits, &val);
2922 
2923  if (type == UNITS)
2924  {
2925  int tz;
2926  fsec_t fsec;
2927  struct pg_tm tt,
2928  *tm = &tt;
2929 
2930  timetz2tm(time, tm, &fsec, &tz);
2931 
2932  switch (val)
2933  {
2934  case DTK_TZ:
2935  intresult = -tz;
2936  break;
2937 
2938  case DTK_TZ_MINUTE:
2939  intresult = (-tz / SECS_PER_MINUTE) % MINS_PER_HOUR;
2940  break;
2941 
2942  case DTK_TZ_HOUR:
2943  intresult = -tz / SECS_PER_HOUR;
2944  break;
2945 
2946  case DTK_MICROSEC:
2947  intresult = tm->tm_sec * INT64CONST(1000000) + fsec;
2948  break;
2949 
2950  case DTK_MILLISEC:
2951  if (retnumeric)
2952  /*---
2953  * tm->tm_sec * 1000 + fsec / 1000
2954  * = (tm->tm_sec * 1'000'000 + fsec) / 1000
2955  */
2956  PG_RETURN_NUMERIC(int64_div_fast_to_numeric(tm->tm_sec * INT64CONST(1000000) + fsec, 3));
2957  else
2958  PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + fsec / 1000.0);
2959  break;
2960 
2961  case DTK_SECOND:
2962  if (retnumeric)
2963  /*---
2964  * tm->tm_sec + fsec / 1'000'000
2965  * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
2966  */
2967  PG_RETURN_NUMERIC(int64_div_fast_to_numeric(tm->tm_sec * INT64CONST(1000000) + fsec, 6));
2968  else
2969  PG_RETURN_FLOAT8(tm->tm_sec + fsec / 1000000.0);
2970  break;
2971 
2972  case DTK_MINUTE:
2973  intresult = tm->tm_min;
2974  break;
2975 
2976  case DTK_HOUR:
2977  intresult = tm->tm_hour;
2978  break;
2979 
2980  case DTK_DAY:
2981  case DTK_MONTH:
2982  case DTK_QUARTER:
2983  case DTK_YEAR:
2984  case DTK_DECADE:
2985  case DTK_CENTURY:
2986  case DTK_MILLENNIUM:
2987  default:
2988  ereport(ERROR,
2989  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2990  errmsg("unit \"%s\" not supported for type %s",
2991  lowunits, format_type_be(TIMETZOID))));
2992  intresult = 0;
2993  }
2994  }
2995  else if (type == RESERV && val == DTK_EPOCH)
2996  {
2997  if (retnumeric)
2998  /*---
2999  * time->time / 1'000'000 + time->zone
3000  * = (time->time + time->zone * 1'000'000) / 1'000'000
3001  */
3002  PG_RETURN_NUMERIC(int64_div_fast_to_numeric(time->time + time->zone * INT64CONST(1000000), 6));
3003  else
3004  PG_RETURN_FLOAT8(time->time / 1000000.0 + time->zone);
3005  }
3006  else
3007  {
3008  ereport(ERROR,
3009  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3010  errmsg("unit \"%s\" not recognized for type %s",
3011  lowunits, format_type_be(TIMETZOID))));
3012  intresult = 0;
3013  }
3014 
3015  if (retnumeric)
3016  PG_RETURN_NUMERIC(int64_to_numeric(intresult));
3017  else
3018  PG_RETURN_FLOAT8(intresult);
3019 }
3020 
3021 
3022 Datum
3024 {
3025  return timetz_part_common(fcinfo, false);
3026 }
3027 
3028 Datum
3030 {
3031  return timetz_part_common(fcinfo, true);
3032 }
3033 
3034 /* timetz_zone()
3035  * Encode time with time zone type with specified time zone.
3036  * Applies DST rules as of the transaction start time.
3037  */
3038 Datum
3040 {
3041  text *zone = PG_GETARG_TEXT_PP(0);
3043  TimeTzADT *result;
3044  int tz;
3045  char tzname[TZ_STRLEN_MAX + 1];
3046  int type,
3047  val;
3048  pg_tz *tzp;
3049 
3050  /*
3051  * Look up the requested timezone.
3052  */
3053  text_to_cstring_buffer(zone, tzname, sizeof(tzname));
3054 
3055  type = DecodeTimezoneName(tzname, &val, &tzp);
3056 
3057  if (type == TZNAME_FIXED_OFFSET)
3058  {
3059  /* fixed-offset abbreviation */
3060  tz = -val;
3061  }
3062  else if (type == TZNAME_DYNTZ)
3063  {
3064  /* dynamic-offset abbreviation, resolve using transaction start time */
3066  int isdst;
3067 
3068  tz = DetermineTimeZoneAbbrevOffsetTS(now, tzname, tzp, &isdst);
3069  }
3070  else
3071  {
3072  /* Get the offset-from-GMT that is valid now for the zone name */
3074  struct pg_tm tm;
3075  fsec_t fsec;
3076 
3077  if (timestamp2tm(now, &tz, &tm, &fsec, NULL, tzp) != 0)
3078  ereport(ERROR,
3079  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3080  errmsg("timestamp out of range")));
3081  }
3082 
3083  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
3084 
3085  result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
3086  while (result->time < INT64CONST(0))
3087  result->time += USECS_PER_DAY;
3088  while (result->time >= USECS_PER_DAY)
3089  result->time -= USECS_PER_DAY;
3090 
3091  result->zone = tz;
3092 
3093  PG_RETURN_TIMETZADT_P(result);
3094 }
3095 
3096 /* timetz_izone()
3097  * Encode time with time zone type with specified time interval as time zone.
3098  */
3099 Datum
3101 {
3103  TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
3104  TimeTzADT *result;
3105  int tz;
3106 
3107  if (zone->month != 0 || zone->day != 0)
3108  ereport(ERROR,
3109  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3110  errmsg("interval time zone \"%s\" must not include months or days",
3112  PointerGetDatum(zone))))));
3113 
3114  tz = -(zone->time / USECS_PER_SEC);
3115 
3116  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
3117 
3118  result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
3119  while (result->time < INT64CONST(0))
3120  result->time += USECS_PER_DAY;
3121  while (result->time >= USECS_PER_DAY)
3122  result->time -= USECS_PER_DAY;
3123 
3124  result->zone = tz;
3125 
3126  PG_RETURN_TIMETZADT_P(result);
3127 }
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
int32 * ArrayGetIntegerTypmods(ArrayType *arr, int *n)
Definition: arrayutils.c:254
int DetermineTimeZoneAbbrevOffsetTS(TimestampTz ts, const char *abbr, pg_tz *tzp, int *isdst)
Definition: datetime.c:1786
int DecodeUnits(int field, const char *lowtoken, int *val)
Definition: datetime.c:3922
int DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:1866
int j2day(int date)
Definition: datetime.c:346
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition: datetime.c:756
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1587
void DateTimeParseError(int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, Node *escontext)
Definition: datetime.c:3967
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:4187
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2499
int DecodeSpecial(int field, const char *lowtoken, int *val)
Definition: datetime.c:3139
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:313
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:368
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4102
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:980
int date2j(int year, int month, int day)
Definition: datetime.c:288
void GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: datetime.c:389
const char *const days[]
Definition: datetime.c:86
int DecodeTimezoneName(const char *tzname, int *offset, pg_tz **tz)
Definition: datetime.c:3181
Node * TemporalSimplify(int32 max_precis, Node *node)
Definition: datetime.c:4715
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4232
Numeric int64_div_fast_to_numeric(int64 val1, int log10val2)
Definition: numeric.c:4253
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:627
Datum interval_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:958
int timestamp_cmp_internal(Timestamp dt1, Timestamp dt2)
Definition: timestamp.c:2125
Datum in_range_timestamp_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3470
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:2083
Datum timestamp_pl_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:2914
int date2isoweek(int year, int mon, int mday)
Definition: timestamp.c:4510
Datum timestamp_mi_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:2993
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1830
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1547
int date2isoyear(int year, int mon, int mday)
Definition: timestamp.c:4565
unsigned int uint32
Definition: c.h:490
signed int int32
Definition: c.h:478
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
#define SECS_PER_HOUR
Definition: timestamp.h:126
#define IS_VALID_DATE(d)
Definition: timestamp.h:236
int32 fsec_t
Definition: timestamp.h:41
#define TIMESTAMP_NOBEGIN(j)
Definition: timestamp.h:158
#define USECS_PER_HOUR
Definition: timestamp.h:131
#define TIMESTAMP_END_JULIAN
Definition: timestamp.h:227
#define MINS_PER_HOUR
Definition: timestamp.h:128
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:201
#define TZDISP_LIMIT
Definition: timestamp.h:143
#define IS_VALID_TIMESTAMP(t)
Definition: timestamp.h:241
#define SECS_PER_MINUTE
Definition: timestamp.h:127
#define USECS_PER_DAY
Definition: timestamp.h:130
#define USECS_PER_SEC
Definition: timestamp.h:133
#define HOURS_PER_DAY
Definition: timestamp.h:117
#define TIMESTAMP_IS_NOEND(j)
Definition: timestamp.h:166
#define USECS_PER_MINUTE
Definition: timestamp.h:132
#define TIMESTAMP_IS_NOBEGIN(j)
Definition: timestamp.h:161
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:208
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:168
#define SECS_PER_DAY
Definition: timestamp.h:125
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:209
#define TIMESTAMP_NOEND(j)
Definition: timestamp.h:163
#define MIN_TIMESTAMP
Definition: timestamp.h:230
int64 TimeOffset
Definition: timestamp.h:40
Datum timestamp_eq_date(PG_FUNCTION_ARGS)
Definition: date.c:906
int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
Definition: date.c:742
Datum date_send(PG_FUNCTION_ARGS)
Definition: date.c:230
Datum timetz_izone(PG_FUNCTION_ARGS)
Definition: date.c:3100
int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: date.c:2394
Datum timestamp_ne_date(PG_FUNCTION_ARGS)
Definition: date.c:915
Datum date_ne_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:852
Datum date_sortsupport(PG_FUNCTION_ARGS)
Definition: date.c:449
Datum date_cmp(PG_FUNCTION_ARGS)
Definition: date.c:436
Datum date_le(PG_FUNCTION_ARGS)
Definition: date.c:409
Datum time_part(PG_FUNCTION_ARGS)
Definition: date.c:2234
Datum time_eq(PG_FUNCTION_ARGS)
Definition: date.c:1679
Datum timetz_send(PG_FUNCTION_ARGS)
Definition: date.c:2362
Datum timetztypmodout(PG_FUNCTION_ARGS)
Definition: date.c:2382
#define TIMETZ_GT(t1, t2)
Datum timestamp_ge_date(PG_FUNCTION_ARGS)
Definition: date.c:951
Datum timetz_pl_interval(PG_FUNCTION_ARGS)
Definition: date.c:2587
Datum timetz_smaller(PG_FUNCTION_ARGS)
Definition: date.c:2570
Datum timetypmodin(PG_FUNCTION_ARGS)
Definition: date.c:1557
Datum date_lt_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:861
Datum make_time(PG_FUNCTION_ARGS)
Definition: date.c:1576
Datum date_larger(PG_FUNCTION_ARGS)
Definition: date.c:466
TimeTzADT * GetSQLCurrentTime(int32 typmod)
Definition: date.c:341
Datum in_range_time_interval(PG_FUNCTION_ARGS)
Definition: date.c:2091
Datum date_gt_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:870
Datum date_lt_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:777
Datum timetz_ne(PG_FUNCTION_ARGS)
Definition: date.c:2470
Datum time_interval(PG_FUNCTION_ARGS)
Definition: date.c:1988
Datum date_eq(PG_FUNCTION_ARGS)
Definition: date.c:382
Datum timetz_larger(PG_FUNCTION_ARGS)
Definition: date.c:2556
Datum time_le(PG_FUNCTION_ARGS)
Definition: date.c:1706
Datum timetz_part(PG_FUNCTION_ARGS)
Definition: date.c:3023
Datum in_range_timetz_interval(PG_FUNCTION_ARGS)
Definition: date.c:2631
Datum extract_time(PG_FUNCTION_ARGS)
Definition: date.c:2240
Datum interval_time(PG_FUNCTION_ARGS)
Definition: date.c:2011
Datum date_mi_interval(PG_FUNCTION_ARGS)
Definition: date.c:1265
Datum date_eq_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:843
bool float_time_overflows(int hour, int min, double sec)
Definition: date.c:1450
Datum timetz_gt(PG_FUNCTION_ARGS)
Definition: date.c:2497
Datum timestamp_gt_date(PG_FUNCTION_ARGS)
Definition: date.c:933
Datum date_finite(PG_FUNCTION_ARGS)
Definition: date.c:458
Datum in_range_date_interval(PG_FUNCTION_ARGS)
Definition: date.c:1038
Datum time_cmp(PG_FUNCTION_ARGS)
Definition: date.c:1733
Datum timestamp_time(PG_FUNCTION_ARGS)
Definition: date.c:1904
static char * anytime_typmodout(bool istz, int32 typmod)
Definition: date.c:92
Datum time_mi_time(PG_FUNCTION_ARGS)
Definition: date.c:2036
Datum time_ge(PG_FUNCTION_ARGS)
Definition: date.c:1724
int32 anytime_typmod_check(bool istz, int32 typmod)
Definition: date.c:70
#define TIMEADT_GT(t1, t2)
Datum datetime_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:1965
static Datum timetz_part_common(PG_FUNCTION_ARGS, bool retnumeric)
Definition: date.c:2906
Datum date_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:1326
Datum date_ne_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:768
Datum timestamptz_ge_date(PG_FUNCTION_ARGS)
Definition: date.c:1014
Datum date_eq_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:759
int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
Definition: date.c:1415
Datum timetz_ge(PG_FUNCTION_ARGS)
Definition: date.c:2506
Datum timestamp_lt_date(PG_FUNCTION_ARGS)
Definition: date.c:924
Datum timestamptz_lt_date(PG_FUNCTION_ARGS)
Definition: date.c:987
Datum timetz_cmp(PG_FUNCTION_ARGS)
Definition: date.c:2515
TimeADT GetSQLLocalTime(int32 typmod)
Definition: date.c:361
Datum timetztypmodin(PG_FUNCTION_ARGS)
Definition: date.c:2374
Datum timetz_recv(PG_FUNCTION_ARGS)
Definition: date.c:2326
static TimestampTz date2timestamptz(DateADT dateVal)
Definition: date.c:703
Datum time_recv(PG_FUNCTION_ARGS)
Definition: date.c:1520
Datum time_mi_interval(PG_FUNCTION_ARGS)
Definition: date.c:2073
Datum time_support(PG_FUNCTION_ARGS)
Definition: date.c:1604
int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
Definition: date.c:2254
Datum date_out(PG_FUNCTION_ARGS)
Definition: date.c:183
Datum timetz_time(PG_FUNCTION_ARGS)
Definition: date.c:2794
Datum timetz_in(PG_FUNCTION_ARGS)
Definition: date.c:2264
Datum time_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2807
Datum time_lt(PG_FUNCTION_ARGS)
Definition: date.c:1697
Datum date_in(PG_FUNCTION_ARGS)
Definition: date.c:112
Datum date_gt(PG_FUNCTION_ARGS)
Definition: date.c:418
bool time_overflows(int hour, int min, int sec, fsec_t fsec)
Definition: date.c:1426
Datum timetz_mi_interval(PG_FUNCTION_ARGS)
Definition: date.c:2609
Datum extract_timetz(PG_FUNCTION_ARGS)
Definition: date.c:3029
Datum date_ge_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:804
static int32 anytime_typmodin(bool istz, ArrayType *ta)
Definition: date.c:49
Datum date_mii(PG_FUNCTION_ARGS)
Definition: date.c:527
Datum date_pl_interval(PG_FUNCTION_ARGS)
Definition: date.c:1245
Datum overlaps_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2674
static Datum time_part_common(PG_FUNCTION_ARGS, bool retnumeric)
Definition: date.c:2131
Datum time_gt(PG_FUNCTION_ARGS)
Definition: date.c:1715
Datum date_recv(PG_FUNCTION_ARGS)
Definition: date.c:208
Datum timetz_lt(PG_FUNCTION_ARGS)
Definition: date.c:2479
Datum time_out(PG_FUNCTION_ARGS)
Definition: date.c:1500
Datum date_cmp_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:813
Datum time_hash(PG_FUNCTION_ARGS)
Definition: date.c:1746
Datum time_larger(PG_FUNCTION_ARGS)
Definition: date.c:1758
#define TIMETZ_LT(t1, t2)
Datum time_smaller(PG_FUNCTION_ARGS)
Definition: date.c:1767
Datum time_ne(PG_FUNCTION_ARGS)
Definition: date.c:1688
DateADT GetSQLCurrentDate(void)
Definition: date.c:308
Datum timetz_eq(PG_FUNCTION_ARGS)
Definition: date.c:2461
Datum date_gt_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:786
Datum timestamptz_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2833
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition: date.c:1644
Datum date_le_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:879
Datum date_pli(PG_FUNCTION_ARGS)
Definition: date.c:503
Datum extract_date(PG_FUNCTION_ARGS)
Definition: date.c:1065
Datum timestamptz_date(PG_FUNCTION_ARGS)
Definition: date.c:1341
Datum timetz_le(PG_FUNCTION_ARGS)
Definition: date.c:2488
Datum date_lt(PG_FUNCTION_ARGS)
Definition: date.c:400
Datum timetz_hash(PG_FUNCTION_ARGS)
Definition: date.c:2524
static TimestampTz date2timestamp(DateADT dateVal)
Definition: date.c:607
static int timetz_cmp_internal(TimeTzADT *time1, TimeTzADT *time2)
Definition: date.c:2434
Datum timestamptz_gt_date(PG_FUNCTION_ARGS)
Definition: date.c:996
Datum timestamp_date(PG_FUNCTION_ARGS)
Definition: date.c:1296
Datum date_ge(PG_FUNCTION_ARGS)
Definition: date.c:427
Datum time_in(PG_FUNCTION_ARGS)
Definition: date.c:1373
Datum time_hash_extended(PG_FUNCTION_ARGS)
Definition: date.c:1752
Datum time_pl_interval(PG_FUNCTION_ARGS)
Definition: date.c:2055
TimestampTz date2timestamptz_opt_overflow(DateADT dateVal, int *overflow)
Definition: date.c:623
Datum datetimetz_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:2865
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
Definition: date.c:1487
Datum timestamptz_ne_date(PG_FUNCTION_ARGS)
Definition: date.c:978
Datum date_smaller(PG_FUNCTION_ARGS)
Definition: date.c:475
void EncodeSpecialDate(DateADT dt, char *str)
Definition: date.c:293
Datum timestamp_le_date(PG_FUNCTION_ARGS)
Definition: date.c:942
Datum timetypmodout(PG_FUNCTION_ARGS)
Definition: date.c:1565
Datum timestamptz_eq_date(PG_FUNCTION_ARGS)
Definition: date.c:969
Datum timetz_scale(PG_FUNCTION_ARGS)
Definition: date.c:2416
Datum timestamptz_cmp_date(PG_FUNCTION_ARGS)
Definition: date.c:1023
Datum date_ge_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:888
Datum timetz_hash_extended(PG_FUNCTION_ARGS)
Definition: date.c:2540
Datum timetz_zone(PG_FUNCTION_ARGS)
Definition: date.c:3039
Datum date_cmp_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:897
Timestamp date2timestamp_opt_overflow(DateADT dateVal, int *overflow)
Definition: date.c:563
int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
Definition: date.c:822
double date2timestamp_no_overflow(DateADT dateVal)
Definition: date.c:719
Datum make_date(PG_FUNCTION_ARGS)
Definition: date.c:244
Datum date_le_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:795
Datum time_send(PG_FUNCTION_ARGS)
Definition: date.c:1546
Datum date_mi(PG_FUNCTION_ARGS)
Definition: date.c:486
Datum timestamp_cmp_date(PG_FUNCTION_ARGS)
Definition: date.c:960
Datum date_ne(PG_FUNCTION_ARGS)
Definition: date.c:391
Datum time_scale(PG_FUNCTION_ARGS)
Definition: date.c:1624
Datum timestamptz_time(PG_FUNCTION_ARGS)
Definition: date.c:1934
#define TIMEADT_LT(t1, t2)
Datum timetz_out(PG_FUNCTION_ARGS)
Definition: date.c:2305
Datum overlaps_time(PG_FUNCTION_ARGS)
Definition: date.c:1782
Datum date_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:1282
Datum timestamptz_le_date(PG_FUNCTION_ARGS)
Definition: date.c:1005
#define DATE_IS_NOEND(j)
Definition: date.h:42
#define PG_RETURN_TIMETZADT_P(x)
Definition: date.h:95
#define PG_RETURN_DATEADT(x)
Definition: date.h:93
#define DATE_IS_NOBEGIN(j)
Definition: date.h:40
#define DATE_NOT_FINITE(j)
Definition: date.h:43
#define DATE_NOEND(j)
Definition: date.h:41
#define PG_GETARG_TIMEADT(n)
Definition: date.h:90
#define PG_RETURN_TIMEADT(x)
Definition: date.h:94
int32 DateADT
Definition: date.h:23
#define DATE_NOBEGIN(j)
Definition: date.h:39
#define MAX_TIME_PRECISION
Definition: date.h:45
int64 TimeADT
Definition: date.h:25
#define PG_GETARG_TIMETZADT_P(n)
Definition: date.h:91
#define PG_GETARG_DATEADT(n)
Definition: date.h:89
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:355
#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_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:369
#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 DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5)
Definition: fmgr.h:650
#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:339
int DateStyle
Definition: globals.c:119
static Datum hash_uint32(uint32 k)
Definition: hashfn.h:43
static Datum hash_uint32_extended(uint32 k, uint64 seed)
Definition: hashfn.h:49
Datum hashint8extended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:105
Datum hashint8(PG_FUNCTION_ARGS)
Definition: hashfunc.c:85
#define MAXDATEFIELDS
Definition: datetime.h:202
#define DTK_EPOCH
Definition: datetime.h:152
#define UNKNOWN_FIELD
Definition: datetime.h:124
#define DTK_DECADE
Definition: datetime.h:168
#define DTK_SECOND
Definition: datetime.h:160
#define DTK_QUARTER
Definition: datetime.h:166
#define DTK_JULIAN
Definition: datetime.h:173
#define DTK_TZ_HOUR
Definition: datetime.h:177
#define DTK_TZ_MINUTE
Definition: datetime.h:178
#define DTK_LATE
Definition: datetime.h:151
#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 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 EARLY
Definition: datetime.h:39
#define DTK_HOUR
Definition: datetime.h:162
#define DTK_WEEK
Definition: datetime.h:164
#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 DTK_MINUTE
Definition: datetime.h:161
#define UNITS
Definition: datetime.h:107
long val
Definition: informix.c:664
Assert(fmt[strlen(fmt) - 1] !='\n')
static struct pg_tm tm
Definition: localtime.c:104
char * pstrdup(const char *in)
Definition: mcxt.c:1644
void * palloc(Size size)
Definition: mcxt.c:1226
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:60
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:79
while(p+4<=pend)
static char * buf
Definition: pg_test_fsync.c:67
#define TZ_STRLEN_MAX
Definition: pgtime.h:54
PGDLLIMPORT pg_tz * session_timezone
Definition: pgtz.c:28
long date
Definition: pgtypes_date.h:9
int64 timestamp
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:222
static uint64 DatumGetUInt64(Datum X)
Definition: postgres.h:419
#define Int64GetDatumFast(X)
Definition: postgres.h:554
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:385
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 BoolGetDatum(bool X)
Definition: postgres.h:102
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
#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:418
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:329
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:456
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:349
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:153
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
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:44
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
Definition: date.h:28
TimeADT time
Definition: date.h:29
int32 zone
Definition: date.h:30
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
int tm_sec
Definition: pgtime.h:36
int tm_year
Definition: pgtime.h:41
Definition: pgtz.h:66
Definition: c.h:671
Definition: zic.c:94
int ssup_datum_int32_cmp(Datum x, Datum y, SortSupport ssup)
Definition: tuplesort.c:3204
#define timestamptz_cmp_internal(dt1, dt2)
Definition: timestamp.h:131
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_INTERVAL_P(x)
Definition: timestamp.h:69
#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:246
TimestampTz GetCurrentTransactionStartTimestamp(void)
Definition: xact.c:855