LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - date.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 71.2 % 1172 834 9 65 183 81 58 486 30 260 189 493 10 16
Current Date: 2023-04-08 17:13:01 Functions: 71.6 % 141 101 40 97 4 40 99 2
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 0.0 % 5 0 5
Legend: Lines: hit not hit (60,120] days: 100.0 % 2 2 2
(120,180] days: 90.3 % 31 28 3 28
(180,240] days: 0.0 % 1 0 1
(240..) days: 71.0 % 1133 804 65 183 81 58 486 260 188 493
Function coverage date bins:
(120,180] days: 100.0 % 4 4 4
(240..) days: 35.1 % 276 97 40 97 40 99

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

Generated by: LCOV version v1.16-55-g56c0a2a