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 15:15:32 Functions: 71.6 % 141 101 40 97 4 40 99 2
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           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
      49 CBC          34 : anytime_typmod_check(bool istz, int32 typmod)
      50                 : {
      51 GIC          34 :     if (typmod < 0)
      52 UIC           0 :         ereport(ERROR,
      53                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      54 ECB             :                  errmsg("TIME(%d)%s precision must not be negative",
      55                 :                         typmod, (istz ? " WITH TIME ZONE" : ""))));
      56 GIC          34 :     if (typmod > MAX_TIME_PRECISION)
      57                 :     {
      58               6 :         ereport(WARNING,
      59                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      60 ECB             :                  errmsg("TIME(%d)%s precision reduced to maximum allowed, %d",
      61 EUB             :                         typmod, (istz ? " WITH TIME ZONE" : ""),
      62                 :                         MAX_TIME_PRECISION)));
      63 GIC           6 :         typmod = MAX_TIME_PRECISION;
      64                 :     }
      65 ECB             : 
      66 GIC          34 :     return typmod;
      67                 : }
      68                 : 
      69                 : static int32
      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)
      82 UNC           0 :         ereport(ERROR,
      83                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      84                 :                  errmsg("invalid type modifier")));
      85                 : 
      86 GNC          22 :     return anytime_typmod_check(istz, tl[0]);
      87                 : }
      88                 : 
      89                 : /* common code for timetypmodout and timetztypmodout */
      90 ECB             : static char *
      91 GIC          10 : anytime_typmodout(bool istz, int32 typmod)
      92 ECB             : {
      93 GIC          10 :     const char *tz = istz ? " with time zone" : " without time zone";
      94 ECB             : 
      95 CBC          10 :     if (typmod >= 0)
      96 GIC          10 :         return psprintf("(%d)%s", (int) typmod, tz);
      97 EUB             :     else
      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                 :  */
     110 ECB             : Datum
     111 GIC        3155 : date_in(PG_FUNCTION_ARGS)
     112 ECB             : {
     113 CBC        3155 :     char       *str = PG_GETARG_CSTRING(0);
     114 GNC        3155 :     Node       *escontext = fcinfo->context;
     115                 :     DateADT     date;
     116                 :     fsec_t      fsec;
     117                 :     struct pg_tm tt,
     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                 : 
     128 GIC        3155 :     dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
     129 ECB             :                           field, ftype, MAXDATEFIELDS, &nf);
     130 GIC        3155 :     if (dterr == 0)
     131 GNC        3155 :         dterr = DecodeDateTime(field, ftype, nf,
     132                 :                                &dtype, tm, &fsec, &tzp, &extra);
     133 CBC        3155 :     if (dterr != 0)
     134                 :     {
     135 GNC         147 :         DateTimeParseError(dterr, &extra, str, "date", escontext);
     136               6 :         PG_RETURN_NULL();
     137                 :     }
     138 ECB             : 
     139 GIC        3008 :     switch (dtype)
     140 ECB             :     {
     141 CBC        2900 :         case DTK_DATE:
     142 GIC        2900 :             break;
     143                 : 
     144 CBC           3 :         case DTK_EPOCH:
     145 GIC           3 :             GetEpochTime(tm);
     146 CBC           3 :             break;
     147 ECB             : 
     148 GIC          78 :         case DTK_LATE:
     149 CBC          78 :             DATE_NOEND(date);
     150              78 :             PG_RETURN_DATEADT(date);
     151 ECB             : 
     152 GIC          27 :         case DTK_EARLY:
     153 CBC          27 :             DATE_NOBEGIN(date);
     154              27 :             PG_RETURN_DATEADT(date);
     155 ECB             : 
     156 UIC           0 :         default:
     157 UNC           0 :             DateTimeParseError(DTERR_BAD_FORMAT, &extra, str, "date", escontext);
     158               0 :             PG_RETURN_NULL();
     159 ECB             :     }
     160                 : 
     161 EUB             :     /* Prevent overflow in Julian-day routines */
     162 GBC        2903 :     if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
     163 GNC           6 :         ereturn(escontext, (Datum) 0,
     164                 :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
     165                 :                  errmsg("date out of range: \"%s\"", str)));
     166                 : 
     167 CBC        2897 :     date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
     168 ECB             : 
     169                 :     /* Now check for just-out-of-range dates */
     170 GIC        2897 :     if (!IS_VALID_DATE(date))
     171 GNC           6 :         ereturn(escontext, (Datum) 0,
     172 ECB             :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
     173                 :                  errmsg("date out of range: \"%s\"", str)));
     174                 : 
     175 CBC        2891 :     PG_RETURN_DATEADT(date);
     176 ECB             : }
     177                 : 
     178                 : /* date_out()
     179                 :  * Given internal format date, convert to text string.
     180                 :  */
     181                 : Datum
     182 GIC        4327 : date_out(PG_FUNCTION_ARGS)
     183                 : {
     184            4327 :     DateADT     date = PG_GETARG_DATEADT(0);
     185                 :     char       *result;
     186                 :     struct pg_tm tt,
     187 CBC        4327 :                *tm = &tt;
     188                 :     char        buf[MAXDATELEN + 1];
     189 ECB             : 
     190 GIC        4327 :     if (DATE_NOT_FINITE(date))
     191              18 :         EncodeSpecialDate(date, buf);
     192 ECB             :     else
     193                 :     {
     194 GIC        4309 :         j2date(date + POSTGRES_EPOCH_JDATE,
     195 ECB             :                &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
     196 CBC        4309 :         EncodeDateOnly(tm, DateStyle, buf);
     197                 :     }
     198                 : 
     199            4327 :     result = pstrdup(buf);
     200 GIC        4327 :     PG_RETURN_CSTRING(result);
     201 ECB             : }
     202                 : 
     203                 : /*
     204                 :  *      date_recv           - converts external binary format to date
     205                 :  */
     206                 : Datum
     207 UIC           0 : date_recv(PG_FUNCTION_ARGS)
     208                 : {
     209               0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     210                 :     DateADT     result;
     211                 : 
     212 UBC           0 :     result = (DateADT) pq_getmsgint(buf, sizeof(DateADT));
     213                 : 
     214 EUB             :     /* Limit to the same range that date_in() accepts. */
     215 UIC           0 :     if (DATE_NOT_FINITE(result))
     216                 :          /* ok */ ;
     217 UBC           0 :     else if (!IS_VALID_DATE(result))
     218 UIC           0 :         ereport(ERROR,
     219                 :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
     220 EUB             :                  errmsg("date out of range")));
     221                 : 
     222 UBC           0 :     PG_RETURN_DATEADT(result);
     223 EUB             : }
     224                 : 
     225                 : /*
     226                 :  *      date_send           - converts date to binary format
     227                 :  */
     228                 : Datum
     229 UIC           0 : date_send(PG_FUNCTION_ARGS)
     230                 : {
     231               0 :     DateADT     date = PG_GETARG_DATEADT(0);
     232                 :     StringInfoData buf;
     233                 : 
     234 UBC           0 :     pq_begintypsend(&buf);
     235 UIC           0 :     pq_sendint32(&buf, date);
     236 UBC           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     237                 : }
     238                 : 
     239 EUB             : /*
     240                 :  *      make_date           - date constructor
     241                 :  */
     242                 : Datum
     243 GIC          18 : make_date(PG_FUNCTION_ARGS)
     244                 : {
     245                 :     struct pg_tm tm;
     246                 :     DateADT     date;
     247                 :     int         dterr;
     248 CBC          18 :     bool        bc = false;
     249                 : 
     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);
     253 ECB             : 
     254                 :     /* Handle negative years as BC */
     255 CBC          18 :     if (tm.tm_year < 0)
     256 ECB             :     {
     257 CBC           3 :         bc = true;
     258 GIC           3 :         tm.tm_year = -tm.tm_year;
     259                 :     }
     260 ECB             : 
     261 GIC          18 :     dterr = ValidateDate(DTK_DATE_M, false, false, bc, &tm);
     262 ECB             : 
     263 CBC          18 :     if (dterr != 0)
     264 GIC          12 :         ereport(ERROR,
     265                 :                 (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
     266 ECB             :                  errmsg("date field value out of range: %d-%02d-%02d",
     267                 :                         tm.tm_year, tm.tm_mon, tm.tm_mday)));
     268                 : 
     269                 :     /* Prevent overflow in Julian-day routines */
     270 GIC           6 :     if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
     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)));
     275 ECB             : 
     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 */
     279 GIC           6 :     if (!IS_VALID_DATE(date))
     280 UIC           0 :         ereport(ERROR,
     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                 : 
     285 GBC           6 :     PG_RETURN_DATEADT(date);
     286                 : }
     287                 : 
     288                 : /*
     289                 :  * Convert reserved date values to string.
     290 ECB             :  */
     291                 : void
     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))
     297 CBC          15 :         strcpy(str, LATE);
     298                 :     else                        /* shouldn't happen */
     299 LBC           0 :         elog(ERROR, "invalid argument for EncodeSpecialDate");
     300 CBC          30 : }
     301 ECB             : 
     302                 : 
     303                 : /*
     304                 :  * current_date -- implements CURRENT_DATE
     305                 :  */
     306                 : Datum
     307 GNC          13 : current_date(PG_FUNCTION_ARGS)
     308                 : {
     309                 :     struct pg_tm tm;
     310                 : 
     311                 :     static int  cache_year = 0;
     312 ECB             :     static int  cache_mon = 0;
     313                 :     static int  cache_mday = 0;
     314                 :     static DateADT cache_date;
     315                 : 
     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
     321 ECB             :      * once.  So it seems worth having a separate cache here.
     322                 :      */
     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;
     328 CBC          10 :         cache_year = tm.tm_year;
     329              10 :         cache_mon = tm.tm_mon;
     330              10 :         cache_mday = tm.tm_mday;
     331                 :     }
     332 ECB             : 
     333 GNC          13 :     return DateADTGetDatum(cache_date);
     334 ECB             : }
     335                 : 
     336                 : /*
     337                 :  * current_time -- implements CURRENT_TIME, CURRENT_TIME(n)
     338                 :  */
     339                 : Datum
     340 GNC          12 : current_time(PG_FUNCTION_ARGS)
     341                 : {
     342                 :     TimeTzADT  *result;
     343                 :     struct pg_tm tt,
     344 GIC          12 :                *tm = &tt;
     345 ECB             :     fsec_t      fsec;
     346                 :     int         tz;
     347 GNC          12 :     int32       typmod = -1;
     348                 : 
     349              12 :     if (!PG_ARGISNULL(0))
     350               6 :         typmod = anytime_typmod_check(true, PG_GETARG_INT32(0));
     351                 : 
     352 GIC          12 :     GetCurrentTimeUsec(tm, &fsec, &tz);
     353 ECB             : 
     354 GIC          12 :     result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
     355              12 :     tm2timetz(tm, fsec, tz, result);
     356 CBC          12 :     AdjustTimeForTypmod(&(result->time), typmod);
     357                 : 
     358 GNC          12 :     return TimeTzADTPGetDatum(result);
     359 ECB             : }
     360                 : 
     361                 : /*
     362                 :  * sql_localtime -- implements LOCALTIME, LOCALTIME(n)
     363                 :  */
     364                 : Datum
     365 GNC          12 : sql_localtime(PG_FUNCTION_ARGS)
     366 ECB             : {
     367                 :     TimeADT     result;
     368                 :     struct pg_tm tt,
     369 GIC          12 :                *tm = &tt;
     370                 :     fsec_t      fsec;
     371                 :     int         tz;
     372 GNC          12 :     int32       typmod = -1;
     373                 : 
     374              12 :     if (!PG_ARGISNULL(0))
     375               6 :         typmod = anytime_typmod_check(false, PG_GETARG_INT32(0));
     376                 : 
     377 GIC          12 :     GetCurrentTimeUsec(tm, &fsec, &tz);
     378                 : 
     379 CBC          12 :     tm2time(tm, fsec, &result);
     380 GIC          12 :     AdjustTimeForTypmod(&result, typmod);
     381                 : 
     382 GNC          12 :     return TimeADTGetDatum(result);
     383                 : }
     384 ECB             : 
     385                 : 
     386                 : /*
     387                 :  * Comparison functions for dates
     388                 :  */
     389                 : 
     390                 : Datum
     391 GIC       24586 : date_eq(PG_FUNCTION_ARGS)
     392 ECB             : {
     393 GIC       24586 :     DateADT     dateVal1 = PG_GETARG_DATEADT(0);
     394 CBC       24586 :     DateADT     dateVal2 = PG_GETARG_DATEADT(1);
     395 ECB             : 
     396 GIC       24586 :     PG_RETURN_BOOL(dateVal1 == dateVal2);
     397 ECB             : }
     398                 : 
     399                 : Datum
     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);
     406 ECB             : }
     407                 : 
     408                 : Datum
     409 CBC       44005 : date_lt(PG_FUNCTION_ARGS)
     410                 : {
     411           44005 :     DateADT     dateVal1 = PG_GETARG_DATEADT(0);
     412 GIC       44005 :     DateADT     dateVal2 = PG_GETARG_DATEADT(1);
     413                 : 
     414           44005 :     PG_RETURN_BOOL(dateVal1 < dateVal2);
     415 EUB             : }
     416                 : 
     417                 : Datum
     418 GBC        3387 : date_le(PG_FUNCTION_ARGS)
     419                 : {
     420            3387 :     DateADT     dateVal1 = PG_GETARG_DATEADT(0);
     421 GIC        3387 :     DateADT     dateVal2 = PG_GETARG_DATEADT(1);
     422                 : 
     423            3387 :     PG_RETURN_BOOL(dateVal1 <= dateVal2);
     424 ECB             : }
     425                 : 
     426                 : Datum
     427 CBC        4185 : date_gt(PG_FUNCTION_ARGS)
     428                 : {
     429            4185 :     DateADT     dateVal1 = PG_GETARG_DATEADT(0);
     430 GIC        4185 :     DateADT     dateVal2 = PG_GETARG_DATEADT(1);
     431                 : 
     432            4185 :     PG_RETURN_BOOL(dateVal1 > dateVal2);
     433 ECB             : }
     434                 : 
     435                 : Datum
     436 CBC        3206 : date_ge(PG_FUNCTION_ARGS)
     437                 : {
     438            3206 :     DateADT     dateVal1 = PG_GETARG_DATEADT(0);
     439 GIC        3206 :     DateADT     dateVal2 = PG_GETARG_DATEADT(1);
     440                 : 
     441            3206 :     PG_RETURN_BOOL(dateVal1 >= dateVal2);
     442 ECB             : }
     443                 : 
     444                 : Datum
     445 CBC        3674 : date_cmp(PG_FUNCTION_ARGS)
     446                 : {
     447            3674 :     DateADT     dateVal1 = PG_GETARG_DATEADT(0);
     448 GIC        3674 :     DateADT     dateVal2 = PG_GETARG_DATEADT(1);
     449                 : 
     450            3674 :     if (dateVal1 < dateVal2)
     451 CBC        1958 :         PG_RETURN_INT32(-1);
     452 GIC        1716 :     else if (dateVal1 > dateVal2)
     453 CBC        1596 :         PG_RETURN_INT32(1);
     454             120 :     PG_RETURN_INT32(0);
     455                 : }
     456 ECB             : 
     457                 : Datum
     458 GIC         284 : date_sortsupport(PG_FUNCTION_ARGS)
     459                 : {
     460 CBC         284 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     461                 : 
     462             284 :     ssup->comparator = ssup_datum_int32_cmp;
     463             284 :     PG_RETURN_VOID();
     464                 : }
     465 ECB             : 
     466                 : Datum
     467 CBC           9 : date_finite(PG_FUNCTION_ARGS)
     468 ECB             : {
     469 CBC           9 :     DateADT     date = PG_GETARG_DATEADT(0);
     470                 : 
     471 GIC           9 :     PG_RETURN_BOOL(!DATE_NOT_FINITE(date));
     472                 : }
     473 ECB             : 
     474                 : Datum
     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                 : 
     480 GIC           8 :     PG_RETURN_DATEADT((dateVal1 > dateVal2) ? dateVal1 : dateVal2);
     481                 : }
     482 ECB             : 
     483                 : Datum
     484 LBC           0 : date_smaller(PG_FUNCTION_ARGS)
     485                 : {
     486               0 :     DateADT     dateVal1 = PG_GETARG_DATEADT(0);
     487 UIC           0 :     DateADT     dateVal2 = PG_GETARG_DATEADT(1);
     488                 : 
     489               0 :     PG_RETURN_DATEADT((dateVal1 < dateVal2) ? dateVal1 : dateVal2);
     490 ECB             : }
     491                 : 
     492                 : /* Compute difference between two dates in days.
     493                 :  */
     494                 : Datum
     495 CBC        1763 : date_mi(PG_FUNCTION_ARGS)
     496                 : {
     497 GIC        1763 :     DateADT     dateVal1 = PG_GETARG_DATEADT(0);
     498            1763 :     DateADT     dateVal2 = PG_GETARG_DATEADT(1);
     499 EUB             : 
     500 GIC        1763 :     if (DATE_NOT_FINITE(dateVal1) || DATE_NOT_FINITE(dateVal2))
     501 UBC           0 :         ereport(ERROR,
     502 EUB             :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
     503                 :                  errmsg("cannot subtract infinite dates")));
     504                 : 
     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.
     510 ECB             :  */
     511                 : Datum
     512 CBC        1023 : date_pli(PG_FUNCTION_ARGS)
     513 ECB             : {
     514 GIC        1023 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     515 CBC        1023 :     int32       days = PG_GETARG_INT32(1);
     516 EUB             :     DateADT     result;
     517                 : 
     518 GIC        1023 :     if (DATE_NOT_FINITE(dateVal))
     519 UIC           0 :         PG_RETURN_DATEADT(dateVal); /* can't change infinity */
     520 ECB             : 
     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))
     526 UIC           0 :         ereport(ERROR,
     527 ECB             :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
     528                 :                  errmsg("date out of range")));
     529                 : 
     530 CBC        1023 :     PG_RETURN_DATEADT(result);
     531                 : }
     532                 : 
     533 ECB             : /* Subtract a number of days from a date, giving a new date.
     534 EUB             :  */
     535                 : Datum
     536 CBC          18 : date_mii(PG_FUNCTION_ARGS)
     537                 : {
     538 GIC          18 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     539 CBC          18 :     int32       days = PG_GETARG_INT32(1);
     540 ECB             :     DateADT     result;
     541 EUB             : 
     542 GIC          18 :     if (DATE_NOT_FINITE(dateVal))
     543 UIC           0 :         PG_RETURN_DATEADT(dateVal); /* can't change infinity */
     544                 : 
     545 CBC          18 :     result = dateVal - days;
     546                 : 
     547                 :     /* Check for integer overflow and out-of-allowed-range */
     548 GIC          18 :     if ((days >= 0 ? (result > dateVal) : (result < dateVal)) ||
     549              18 :         !IS_VALID_DATE(result))
     550 UIC           0 :         ereport(ERROR,
     551 ECB             :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
     552                 :                  errmsg("date out of range")));
     553                 : 
     554 CBC          18 :     PG_RETURN_DATEADT(result);
     555                 : }
     556                 : 
     557 ECB             : 
     558 EUB             : /*
     559                 :  * Promote date to timestamp.
     560 ECB             :  *
     561                 :  * On successful conversion, *overflow is set to zero if it's not NULL.
     562                 :  *
     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.
     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
     569 ECB             :  * datatypes have the same lower bound, Julian day zero.
     570                 :  */
     571                 : Timestamp
     572 GIC        2121 : date2timestamp_opt_overflow(DateADT dateVal, int *overflow)
     573                 : {
     574                 :     Timestamp   result;
     575                 : 
     576            2121 :     if (overflow)
     577              63 :         *overflow = 0;
     578                 : 
     579            2121 :     if (DATE_IS_NOBEGIN(dateVal))
     580 UIC           0 :         TIMESTAMP_NOBEGIN(result);
     581 GIC        2121 :     else if (DATE_IS_NOEND(dateVal))
     582 UIC           0 :         TIMESTAMP_NOEND(result);
     583                 :     else
     584                 :     {
     585                 :         /*
     586                 :          * Since dates have the same minimum values as timestamps, only upper
     587 ECB             :          * boundary need be checked for overflow.
     588                 :          */
     589 GIC        2121 :         if (dateVal >= (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE))
     590                 :         {
     591 CBC          12 :             if (overflow)
     592 ECB             :             {
     593 GIC           9 :                 *overflow = 1;
     594 CBC           9 :                 TIMESTAMP_NOEND(result);
     595 GBC           9 :                 return result;
     596 ECB             :             }
     597 EUB             :             else
     598                 :             {
     599 GIC           3 :                 ereport(ERROR,
     600                 :                         (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
     601                 :                          errmsg("date out of range for timestamp")));
     602                 :             }
     603                 :         }
     604 ECB             : 
     605                 :         /* date is days since 2000, timestamp is microseconds since same... */
     606 CBC        2109 :         result = dateVal * USECS_PER_DAY;
     607                 :     }
     608 ECB             : 
     609 CBC        2109 :     return result;
     610 ECB             : }
     611                 : 
     612                 : /*
     613                 :  * Promote date to timestamp, throwing error for overflow.
     614                 :  */
     615                 : static TimestampTz
     616 GIC        2058 : date2timestamp(DateADT dateVal)
     617                 : {
     618            2058 :     return date2timestamp_opt_overflow(dateVal, NULL);
     619                 : }
     620                 : 
     621 ECB             : /*
     622                 :  * Promote date to timestamp with time zone.
     623                 :  *
     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                 :  */
     631                 : TimestampTz
     632 GIC         136 : date2timestamptz_opt_overflow(DateADT dateVal, int *overflow)
     633 ECB             : {
     634                 :     TimestampTz result;
     635                 :     struct pg_tm tt,
     636 GIC         136 :                *tm = &tt;
     637                 :     int         tz;
     638                 : 
     639             136 :     if (overflow)
     640              48 :         *overflow = 0;
     641                 : 
     642             136 :     if (DATE_IS_NOBEGIN(dateVal))
     643 UIC           0 :         TIMESTAMP_NOBEGIN(result);
     644 GIC         136 :     else if (DATE_IS_NOEND(dateVal))
     645 UIC           0 :         TIMESTAMP_NOEND(result);
     646                 :     else
     647 ECB             :     {
     648                 :         /*
     649                 :          * Since dates have the same minimum values as timestamps, only upper
     650                 :          * boundary need be checked for overflow.
     651                 :          */
     652 GIC         136 :         if (dateVal >= (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE))
     653                 :         {
     654 CBC           9 :             if (overflow)
     655 ECB             :             {
     656 GIC           6 :                 *overflow = 1;
     657 CBC           6 :                 TIMESTAMP_NOEND(result);
     658 GBC           6 :                 return result;
     659 ECB             :             }
     660 EUB             :             else
     661                 :             {
     662 GIC           3 :                 ereport(ERROR,
     663                 :                         (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
     664                 :                          errmsg("date out of range for timestamp")));
     665                 :             }
     666                 :         }
     667 ECB             : 
     668 GIC         127 :         j2date(dateVal + POSTGRES_EPOCH_JDATE,
     669 ECB             :                &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
     670 GIC         127 :         tm->tm_hour = 0;
     671 CBC         127 :         tm->tm_min = 0;
     672             127 :         tm->tm_sec = 0;
     673             127 :         tz = DetermineTimeZoneOffset(tm, session_timezone);
     674                 : 
     675 GIC         127 :         result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC;
     676                 : 
     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                 :          */
     681 GIC         127 :         if (!IS_VALID_TIMESTAMP(result))
     682                 :         {
     683 CBC           9 :             if (overflow)
     684                 :             {
     685               6 :                 if (result < MIN_TIMESTAMP)
     686 ECB             :                 {
     687 CBC           6 :                     *overflow = -1;
     688               6 :                     TIMESTAMP_NOBEGIN(result);
     689                 :                 }
     690 ECB             :                 else
     691                 :                 {
     692 UIC           0 :                     *overflow = 1;
     693               0 :                     TIMESTAMP_NOEND(result);
     694                 :                 }
     695                 :             }
     696 ECB             :             else
     697                 :             {
     698 CBC           3 :                 ereport(ERROR,
     699                 :                         (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
     700 ECB             :                          errmsg("date out of range for timestamp")));
     701                 :             }
     702                 :         }
     703                 :     }
     704                 : 
     705 GIC         124 :     return result;
     706                 : }
     707 EUB             : 
     708                 : /*
     709                 :  * Promote date to timestamptz, throwing error for overflow.
     710                 :  */
     711                 : static TimestampTz
     712 GIC          88 : date2timestamptz(DateADT dateVal)
     713 ECB             : {
     714 GIC          88 :     return date2timestamptz_opt_overflow(dateVal, NULL);
     715                 : }
     716                 : 
     717                 : /*
     718                 :  * date2timestamp_no_overflow
     719                 :  *
     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
     728 UIC           0 : date2timestamp_no_overflow(DateADT dateVal)
     729 ECB             : {
     730                 :     double      result;
     731                 : 
     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;
     743 EUB             : }
     744                 : 
     745                 : 
     746                 : /*
     747                 :  * Crosstype comparison functions for dates
     748                 :  */
     749                 : 
     750                 : int32
     751 GIC          63 : date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
     752                 : {
     753                 :     Timestamp   dt1;
     754 EUB             :     int         overflow;
     755                 : 
     756 GIC          63 :     dt1 = date2timestamp_opt_overflow(dateVal, &overflow);
     757 GBC          63 :     if (overflow > 0)
     758                 :     {
     759                 :         /* dt1 is larger than any finite timestamp, but less than infinity */
     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                 : }
     766 ECB             : 
     767                 : Datum
     768 UIC           0 : date_eq_timestamp(PG_FUNCTION_ARGS)
     769                 : {
     770               0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     771 LBC           0 :     Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
     772 ECB             : 
     773 UIC           0 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) == 0);
     774                 : }
     775 ECB             : 
     776                 : Datum
     777 LBC           0 : date_ne_timestamp(PG_FUNCTION_ARGS)
     778                 : {
     779               0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     780 UIC           0 :     Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
     781                 : 
     782               0 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) != 0);
     783 EUB             : }
     784                 : 
     785                 : Datum
     786 UBC           0 : date_lt_timestamp(PG_FUNCTION_ARGS)
     787                 : {
     788               0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     789 UIC           0 :     Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
     790                 : 
     791               0 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) < 0);
     792 EUB             : }
     793                 : 
     794                 : Datum
     795 GBC           3 : date_gt_timestamp(PG_FUNCTION_ARGS)
     796                 : {
     797               3 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     798 GIC           3 :     Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
     799                 : 
     800               3 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) > 0);
     801 EUB             : }
     802                 : 
     803                 : Datum
     804 UBC           0 : date_le_timestamp(PG_FUNCTION_ARGS)
     805                 : {
     806               0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     807 UIC           0 :     Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
     808                 : 
     809               0 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) <= 0);
     810 ECB             : }
     811                 : 
     812                 : Datum
     813 LBC           0 : date_ge_timestamp(PG_FUNCTION_ARGS)
     814                 : {
     815               0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     816 UIC           0 :     Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
     817                 : 
     818               0 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt2) >= 0);
     819 EUB             : }
     820                 : 
     821                 : Datum
     822 UBC           0 : date_cmp_timestamp(PG_FUNCTION_ARGS)
     823                 : {
     824               0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     825 UIC           0 :     Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
     826                 : 
     827               0 :     PG_RETURN_INT32(date_cmp_timestamp_internal(dateVal, dt2));
     828 EUB             : }
     829                 : 
     830                 : int32
     831 GBC          48 : date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
     832                 : {
     833 EUB             :     TimestampTz dt1;
     834                 :     int         overflow;
     835                 : 
     836 GIC          48 :     dt1 = date2timestamptz_opt_overflow(dateVal, &overflow);
     837 GBC          48 :     if (overflow > 0)
     838                 :     {
     839 EUB             :         /* dt1 is larger than any finite timestamp, but less than infinity */
     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 */
     845 GIC           6 :         return TIMESTAMP_IS_NOBEGIN(dt2) ? +1 : -1;
     846 ECB             :     }
     847                 : 
     848 GIC          36 :     return timestamptz_cmp_internal(dt1, dt2);
     849                 : }
     850                 : 
     851 ECB             : Datum
     852 LBC           0 : date_eq_timestamptz(PG_FUNCTION_ARGS)
     853                 : {
     854 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     855 LBC           0 :     TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
     856                 : 
     857               0 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt2) == 0);
     858                 : }
     859                 : 
     860 ECB             : Datum
     861 UIC           0 : date_ne_timestamptz(PG_FUNCTION_ARGS)
     862                 : {
     863 LBC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     864 UIC           0 :     TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
     865                 : 
     866               0 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt2) != 0);
     867 EUB             : }
     868                 : 
     869                 : Datum
     870 GBC           3 : date_lt_timestamptz(PG_FUNCTION_ARGS)
     871                 : {
     872               3 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     873 GIC           3 :     TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
     874                 : 
     875               3 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt2) < 0);
     876 EUB             : }
     877                 : 
     878                 : Datum
     879 GBC           3 : date_gt_timestamptz(PG_FUNCTION_ARGS)
     880                 : {
     881               3 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     882 GIC           3 :     TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
     883                 : 
     884               3 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt2) > 0);
     885 ECB             : }
     886                 : 
     887                 : Datum
     888 LBC           0 : date_le_timestamptz(PG_FUNCTION_ARGS)
     889                 : {
     890               0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     891 UIC           0 :     TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
     892                 : 
     893               0 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt2) <= 0);
     894 ECB             : }
     895                 : 
     896                 : Datum
     897 LBC           0 : date_ge_timestamptz(PG_FUNCTION_ARGS)
     898                 : {
     899               0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     900 UIC           0 :     TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
     901                 : 
     902               0 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt2) >= 0);
     903 EUB             : }
     904                 : 
     905                 : Datum
     906 UBC           0 : date_cmp_timestamptz(PG_FUNCTION_ARGS)
     907                 : {
     908               0 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
     909 UIC           0 :     TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
     910                 : 
     911               0 :     PG_RETURN_INT32(date_cmp_timestamptz_internal(dateVal, dt2));
     912 EUB             : }
     913                 : 
     914                 : Datum
     915 UBC           0 : timestamp_eq_date(PG_FUNCTION_ARGS)
     916                 : {
     917               0 :     Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
     918 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
     919                 : 
     920               0 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) == 0);
     921 EUB             : }
     922                 : 
     923                 : Datum
     924 UBC           0 : timestamp_ne_date(PG_FUNCTION_ARGS)
     925                 : {
     926               0 :     Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
     927 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
     928                 : 
     929               0 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) != 0);
     930 EUB             : }
     931                 : 
     932                 : Datum
     933 UBC           0 : timestamp_lt_date(PG_FUNCTION_ARGS)
     934                 : {
     935               0 :     Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
     936 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
     937                 : 
     938               0 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) > 0);
     939 EUB             : }
     940                 : 
     941                 : Datum
     942 GBC           3 : timestamp_gt_date(PG_FUNCTION_ARGS)
     943                 : {
     944               3 :     Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
     945 GIC           3 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
     946                 : 
     947               3 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) < 0);
     948 EUB             : }
     949                 : 
     950                 : Datum
     951 UBC           0 : timestamp_le_date(PG_FUNCTION_ARGS)
     952                 : {
     953               0 :     Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
     954 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
     955                 : 
     956               0 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) >= 0);
     957 ECB             : }
     958                 : 
     959                 : Datum
     960 LBC           0 : timestamp_ge_date(PG_FUNCTION_ARGS)
     961                 : {
     962               0 :     Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
     963 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
     964                 : 
     965               0 :     PG_RETURN_BOOL(date_cmp_timestamp_internal(dateVal, dt1) <= 0);
     966 EUB             : }
     967                 : 
     968                 : Datum
     969 UBC           0 : timestamp_cmp_date(PG_FUNCTION_ARGS)
     970                 : {
     971               0 :     Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
     972 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
     973                 : 
     974               0 :     PG_RETURN_INT32(-date_cmp_timestamp_internal(dateVal, dt1));
     975 EUB             : }
     976                 : 
     977                 : Datum
     978 UBC           0 : timestamptz_eq_date(PG_FUNCTION_ARGS)
     979                 : {
     980               0 :     TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
     981 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
     982                 : 
     983               0 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) == 0);
     984 EUB             : }
     985                 : 
     986                 : Datum
     987 UBC           0 : timestamptz_ne_date(PG_FUNCTION_ARGS)
     988                 : {
     989               0 :     TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
     990 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
     991                 : 
     992               0 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) != 0);
     993 EUB             : }
     994                 : 
     995                 : Datum
     996 UBC           0 : timestamptz_lt_date(PG_FUNCTION_ARGS)
     997                 : {
     998               0 :     TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
     999 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
    1000                 : 
    1001               0 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) > 0);
    1002 EUB             : }
    1003                 : 
    1004                 : Datum
    1005 GBC           3 : timestamptz_gt_date(PG_FUNCTION_ARGS)
    1006                 : {
    1007               3 :     TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
    1008 GIC           3 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
    1009                 : 
    1010               3 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) < 0);
    1011 EUB             : }
    1012                 : 
    1013                 : Datum
    1014 UBC           0 : timestamptz_le_date(PG_FUNCTION_ARGS)
    1015                 : {
    1016               0 :     TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
    1017 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
    1018                 : 
    1019               0 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) >= 0);
    1020 ECB             : }
    1021                 : 
    1022                 : Datum
    1023 CBC           3 : timestamptz_ge_date(PG_FUNCTION_ARGS)
    1024                 : {
    1025               3 :     TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
    1026 GIC           3 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
    1027                 : 
    1028               3 :     PG_RETURN_BOOL(date_cmp_timestamptz_internal(dateVal, dt1) <= 0);
    1029 EUB             : }
    1030                 : 
    1031                 : Datum
    1032 UBC           0 : timestamptz_cmp_date(PG_FUNCTION_ARGS)
    1033                 : {
    1034               0 :     TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
    1035 UIC           0 :     DateADT     dateVal = PG_GETARG_DATEADT(1);
    1036                 : 
    1037               0 :     PG_RETURN_INT32(-date_cmp_timestamptz_internal(dateVal, dt1));
    1038 ECB             : }
    1039                 : 
    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
    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);
    1051 GIC         669 :     Interval   *offset = PG_GETARG_INTERVAL_P(2);
    1052 GBC         669 :     bool        sub = PG_GETARG_BOOL(3);
    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,
    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                 :  */
    1073                 : Datum
    1074 CBC         339 : extract_date(PG_FUNCTION_ARGS)
    1075                 : {
    1076             339 :     text       *units = PG_GETARG_TEXT_PP(0);
    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);
    1089 ECB             : 
    1090 GIC         339 :     type = DecodeUnits(0, lowunits, &val);
    1091 CBC         339 :     if (type == UNKNOWN_FIELD)
    1092              57 :         type = DecodeSpecial(0, lowunits, &val);
    1093                 : 
    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:
    1101 ECB             :             case DTK_QUARTER:
    1102                 :             case DTK_WEEK:
    1103                 :             case DTK_DOW:
    1104                 :             case DTK_ISODOW:
    1105                 :             case DTK_DOY:
    1106 CBC          27 :                 PG_RETURN_NULL();
    1107 ECB             :                 break;
    1108                 : 
    1109                 :                 /* Monotonically-increasing units */
    1110 GIC          27 :             case DTK_YEAR:
    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:
    1117 GIC          27 :                 if (DATE_IS_NOBEGIN(date))
    1118               3 :                     PG_RETURN_NUMERIC(DatumGetNumeric(DirectFunctionCall3(numeric_in,
    1119                 :                                                                           CStringGetDatum("-Infinity"),
    1120                 :                                                                           ObjectIdGetDatum(InvalidOid),
    1121 ECB             :                                                                           Int32GetDatum(-1))));
    1122                 :                 else
    1123 GIC          24 :                     PG_RETURN_NUMERIC(DatumGetNumeric(DirectFunctionCall3(numeric_in,
    1124                 :                                                                           CStringGetDatum("Infinity"),
    1125 ECB             :                                                                           ObjectIdGetDatum(InvalidOid),
    1126                 :                                                                           Int32GetDatum(-1))));
    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))));
    1132 ECB             :         }
    1133                 :     }
    1134 GIC         285 :     else if (type == UNITS)
    1135                 :     {
    1136             276 :         j2date(date + POSTGRES_EPOCH_JDATE, &year, &mon, &mday);
    1137                 : 
    1138 CBC         276 :         switch (val)
    1139                 :         {
    1140 GIC           3 :             case DTK_DAY:
    1141               3 :                 intresult = mday;
    1142 GBC           3 :                 break;
    1143 EUB             : 
    1144 GIC          45 :             case DTK_MONTH:
    1145              45 :                 intresult = mon;
    1146              45 :                 break;
    1147                 : 
    1148               3 :             case DTK_QUARTER:
    1149 CBC           3 :                 intresult = (mon - 1) / 3 + 1;
    1150 GIC           3 :                 break;
    1151 ECB             : 
    1152 GIC           3 :             case DTK_WEEK:
    1153 CBC           3 :                 intresult = date2isoweek(year, mon, mday);
    1154 GIC           3 :                 break;
    1155 ECB             : 
    1156 CBC          93 :             case DTK_YEAR:
    1157              93 :                 if (year > 0)
    1158 GIC          90 :                     intresult = year;
    1159 ECB             :                 else
    1160                 :                     /* there is no year 0, just 1 BC and 1 AD */
    1161 CBC           3 :                     intresult = year - 1;
    1162 GIC          93 :                 break;
    1163 ECB             : 
    1164 CBC          24 :             case DTK_DECADE:
    1165 ECB             :                 /* see comments in timestamp_part */
    1166 GIC          24 :                 if (year >= 0)
    1167 CBC          15 :                     intresult = year / 10;
    1168 ECB             :                 else
    1169 CBC           9 :                     intresult = -((8 - (year - 1)) / 10);
    1170 GIC          24 :                 break;
    1171 ECB             : 
    1172 CBC          33 :             case DTK_CENTURY:
    1173 ECB             :                 /* see comments in timestamp_part */
    1174 GIC          33 :                 if (year > 0)
    1175              24 :                     intresult = (year + 99) / 100;
    1176 ECB             :                 else
    1177 CBC           9 :                     intresult = -((99 - (year - 1)) / 100);
    1178 GIC          33 :                 break;
    1179 ECB             : 
    1180 GIC          24 :             case DTK_MILLENNIUM:
    1181 ECB             :                 /* see comments in timestamp_part */
    1182 CBC          24 :                 if (year > 0)
    1183 GIC          21 :                     intresult = (year + 999) / 1000;
    1184 ECB             :                 else
    1185 CBC           3 :                     intresult = -((999 - (year - 1)) / 1000);
    1186 GIC          24 :                 break;
    1187 ECB             : 
    1188 GIC           3 :             case DTK_JULIAN:
    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)
    1196 GIC           3 :                     intresult -= 1;
    1197 CBC           6 :                 break;
    1198 ECB             : 
    1199 GIC          12 :             case DTK_DOW:
    1200 ECB             :             case DTK_ISODOW:
    1201 CBC          12 :                 intresult = j2day(date + POSTGRES_EPOCH_JDATE);
    1202 GIC          12 :                 if (val == DTK_ISODOW && intresult == 0)
    1203 CBC           3 :                     intresult = 7;
    1204              12 :                 break;
    1205 ECB             : 
    1206 GIC           3 :             case DTK_DOY:
    1207 CBC           3 :                 intresult = date2j(year, mon, mday) - date2j(year, 1, 1) + 1;
    1208               3 :                 break;
    1209                 : 
    1210              24 :             default:
    1211              24 :                 ereport(ERROR,
    1212 ECB             :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1213                 :                          errmsg("unit \"%s\" not supported for type %s",
    1214                 :                                 lowunits, format_type_be(DATEOID))));
    1215                 :                 intresult = 0;
    1216                 :         }
    1217                 :     }
    1218 CBC           9 :     else if (type == RESERV)
    1219 ECB             :     {
    1220 GIC           6 :         switch (val)
    1221 ECB             :         {
    1222 CBC           6 :             case DTK_EPOCH:
    1223               6 :                 intresult = ((int64) date + POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
    1224 GIC           6 :                 break;
    1225 ECB             : 
    1226 LBC           0 :             default:
    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                 :         }
    1233 ECB             :     }
    1234                 :     else
    1235                 :     {
    1236 GIC           3 :         ereport(ERROR,
    1237 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1238                 :                  errmsg("unit \"%s\" not recognized for type %s",
    1239                 :                         lowunits, format_type_be(DATEOID))));
    1240                 :         intresult = 0;
    1241 EUB             :     }
    1242                 : 
    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)
    1251 ECB             :  * and then using the timestamp plus interval function.
    1252                 :  */
    1253                 : Datum
    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);
    1258 ECB             :     Timestamp   dateStamp;
    1259                 : 
    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.
    1269 ECB             :  *
    1270                 :  * We implement this by promoting the date to timestamp (without time zone)
    1271                 :  * and then using the timestamp minus interval function.
    1272                 :  */
    1273                 : Datum
    1274 GIC           6 : date_mi_interval(PG_FUNCTION_ARGS)
    1275 ECB             : {
    1276 GIC           6 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
    1277 CBC           6 :     Interval   *span = PG_GETARG_INTERVAL_P(1);
    1278                 :     Timestamp   dateStamp;
    1279                 : 
    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.
    1289 ECB             :  */
    1290                 : Datum
    1291 CBC         696 : date_timestamp(PG_FUNCTION_ARGS)
    1292 ECB             : {
    1293 GIC         696 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
    1294                 :     Timestamp   result;
    1295 ECB             : 
    1296 GIC         696 :     result = date2timestamp(dateVal);
    1297 ECB             : 
    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)
    1306 ECB             : {
    1307 GIC        1970 :     Timestamp   timestamp = PG_GETARG_TIMESTAMP(0);
    1308 ECB             :     DateADT     result;
    1309                 :     struct pg_tm tt,
    1310 GIC        1970 :                *tm = &tt;
    1311 ECB             :     fsec_t      fsec;
    1312                 : 
    1313 CBC        1970 :     if (TIMESTAMP_IS_NOBEGIN(timestamp))
    1314 UIC           0 :         DATE_NOBEGIN(result);
    1315 GIC        1970 :     else if (TIMESTAMP_IS_NOEND(timestamp))
    1316 UIC           0 :         DATE_NOEND(result);
    1317                 :     else
    1318                 :     {
    1319 GIC        1970 :         if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
    1320 LBC           0 :             ereport(ERROR,
    1321                 :                     (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    1322 ECB             :                      errmsg("timestamp out of range")));
    1323                 : 
    1324 GIC        1970 :         result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
    1325 ECB             :     }
    1326                 : 
    1327 GIC        1970 :     PG_RETURN_DATEADT(result);
    1328 ECB             : }
    1329 EUB             : 
    1330 ECB             : 
    1331 EUB             : /* date_timestamptz()
    1332                 :  * Convert date to timestamp with time zone data type.
    1333                 :  */
    1334 ECB             : Datum
    1335 GBC          88 : date_timestamptz(PG_FUNCTION_ARGS)
    1336                 : {
    1337 GIC          88 :     DateADT     dateVal = PG_GETARG_DATEADT(0);
    1338                 :     TimestampTz result;
    1339 ECB             : 
    1340 GIC          88 :     result = date2timestamptz(dateVal);
    1341                 : 
    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
    1350            1941 : timestamptz_date(PG_FUNCTION_ARGS)
    1351                 : {
    1352            1941 :     TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
    1353                 :     DateADT     result;
    1354                 :     struct pg_tm tt,
    1355            1941 :                *tm = &tt;
    1356                 :     fsec_t      fsec;
    1357 ECB             :     int         tz;
    1358                 : 
    1359 GIC        1941 :     if (TIMESTAMP_IS_NOBEGIN(timestamp))
    1360 UIC           0 :         DATE_NOBEGIN(result);
    1361 GIC        1941 :     else if (TIMESTAMP_IS_NOEND(timestamp))
    1362 UIC           0 :         DATE_NOEND(result);
    1363                 :     else
    1364                 :     {
    1365 CBC        1941 :         if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
    1366 UIC           0 :             ereport(ERROR,
    1367 ECB             :                     (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    1368                 :                      errmsg("timestamp out of range")));
    1369                 : 
    1370 CBC        1941 :         result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
    1371                 :     }
    1372                 : 
    1373 GIC        1941 :     PG_RETURN_DATEADT(result);
    1374 ECB             : }
    1375 EUB             : 
    1376 ECB             : 
    1377 EUB             : /*****************************************************************************
    1378                 :  *   Time ADT
    1379                 :  *****************************************************************************/
    1380 ECB             : 
    1381 EUB             : Datum
    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);
    1387 ECB             : #endif
    1388 GIC         984 :     int32       typmod = PG_GETARG_INT32(2);
    1389 GNC         984 :     Node       *escontext = fcinfo->context;
    1390                 :     TimeADT     result;
    1391                 :     fsec_t      fsec;
    1392                 :     struct pg_tm tt,
    1393 GIC         984 :                *tm = &tt;
    1394                 :     int         tz;
    1395                 :     int         nf;
    1396                 :     int         dterr;
    1397 ECB             :     char        workbuf[MAXDATELEN + 1];
    1398                 :     char       *field[MAXDATEFIELDS];
    1399                 :     int         dtype;
    1400                 :     int         ftype[MAXDATEFIELDS];
    1401                 :     DateTimeErrorExtra extra;
    1402                 : 
    1403 GIC         984 :     dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
    1404 ECB             :                           field, ftype, MAXDATEFIELDS, &nf);
    1405 CBC         984 :     if (dterr == 0)
    1406 GNC         984 :         dterr = DecodeTimeOnly(field, ftype, nf,
    1407                 :                                &dtype, tm, &fsec, &tz, &extra);
    1408 GIC         984 :     if (dterr != 0)
    1409                 :     {
    1410 GNC          27 :         DateTimeParseError(dterr, &extra, str, "time", escontext);
    1411              12 :         PG_RETURN_NULL();
    1412                 :     }
    1413 ECB             : 
    1414 GIC         957 :     tm2time(tm, fsec, &result);
    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                 :  */
    1423 ECB             : int
    1424 GIC        1227 : tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
    1425 ECB             : {
    1426 CBC        1227 :     *result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec)
    1427 GIC        1227 :                * USECS_PER_SEC) + fsec;
    1428 CBC        1227 :     return 0;
    1429                 : }
    1430 ECB             : 
    1431                 : /* time_overflows()
    1432                 :  * Check to see if a broken-down time-of-day is out of range.
    1433                 :  */
    1434                 : bool
    1435 CBC       30577 : time_overflows(int hour, int min, int sec, fsec_t fsec)
    1436                 : {
    1437 ECB             :     /* Range-check the fields individually. */
    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                 : 
    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                 :      */
    1448 CBC       30559 :     if ((((((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
    1449 GIC       30559 :            + sec) * USECS_PER_SEC) + fsec) > USECS_PER_DAY)
    1450              18 :         return true;
    1451                 : 
    1452           30541 :     return false;
    1453                 : }
    1454                 : 
    1455 ECB             : /* float_time_overflows()
    1456                 :  * Same, when we have seconds + fractional seconds as one "double" value.
    1457                 :  */
    1458                 : bool
    1459 CBC         111 : float_time_overflows(int hour, int min, double sec)
    1460 ECB             : {
    1461                 :     /* Range-check the fields individually. */
    1462 CBC         111 :     if (hour < 0 || hour > HOURS_PER_DAY ||
    1463 GIC         111 :         min < 0 || min >= MINS_PER_HOUR)
    1464 UIC           0 :         return true;
    1465                 : 
    1466                 :     /*
    1467                 :      * "sec", being double, requires extra care.  Cope with NaN, and round off
    1468 ECB             :      * before applying the range check to avoid unexpected errors due to
    1469                 :      * imprecise input.  (We assume rint() behaves sanely with infinities.)
    1470                 :      */
    1471 GIC         111 :     if (isnan(sec))
    1472 LBC           0 :         return true;
    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
    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                 :      */
    1482 CBC         108 :     if (((((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
    1483             108 :           * USECS_PER_SEC) + (int64) sec) > USECS_PER_DAY)
    1484 GBC           3 :         return true;
    1485                 : 
    1486 GIC         105 :     return false;
    1487                 : }
    1488                 : 
    1489                 : 
    1490                 : /* time2tm()
    1491 ECB             :  * Convert time data type to POSIX time structure.
    1492 EUB             :  *
    1493 ECB             :  * Note that only the hour/min/sec/fractional-sec fields are filled in.
    1494                 :  */
    1495                 : int
    1496 GIC        2744 : time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
    1497                 : {
    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;
    1502 CBC        2744 :     tm->tm_sec = time / USECS_PER_SEC;
    1503            2744 :     time -= tm->tm_sec * USECS_PER_SEC;
    1504            2744 :     *fsec = time;
    1505 GIC        2744 :     return 0;
    1506 ECB             : }
    1507                 : 
    1508                 : Datum
    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,
    1514            2630 :                *tm = &tt;
    1515                 :     fsec_t      fsec;
    1516 ECB             :     char        buf[MAXDATELEN + 1];
    1517                 : 
    1518 CBC        2630 :     time2tm(time, tm, &fsec);
    1519            2630 :     EncodeTimeOnly(tm, fsec, false, 0, DateStyle, buf);
    1520 ECB             : 
    1521 CBC        2630 :     result = pstrdup(buf);
    1522            2630 :     PG_RETURN_CSTRING(result);
    1523 ECB             : }
    1524                 : 
    1525                 : /*
    1526                 :  *      time_recv           - converts external binary format to time
    1527                 :  */
    1528                 : Datum
    1529 LBC           0 : time_recv(PG_FUNCTION_ARGS)
    1530                 : {
    1531               0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
    1532                 : 
    1533                 : #ifdef NOT_USED
    1534 ECB             :     Oid         typelem = PG_GETARG_OID(1);
    1535                 : #endif
    1536 UIC           0 :     int32       typmod = PG_GETARG_INT32(2);
    1537                 :     TimeADT     result;
    1538 ECB             : 
    1539 LBC           0 :     result = pq_getmsgint64(buf);
    1540                 : 
    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                 : 
    1546 UIC           0 :     AdjustTimeForTypmod(&result, typmod);
    1547                 : 
    1548               0 :     PG_RETURN_TIMEADT(result);
    1549 EUB             : }
    1550                 : 
    1551                 : /*
    1552                 :  *      time_send           - converts time to binary format
    1553                 :  */
    1554                 : Datum
    1555 UIC           0 : time_send(PG_FUNCTION_ARGS)
    1556 EUB             : {
    1557 UIC           0 :     TimeADT     time = PG_GETARG_TIMEADT(0);
    1558                 :     StringInfoData buf;
    1559 EUB             : 
    1560 UIC           0 :     pq_begintypsend(&buf);
    1561 UBC           0 :     pq_sendint64(&buf, time);
    1562               0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
    1563                 : }
    1564                 : 
    1565                 : Datum
    1566 GBC          11 : timetypmodin(PG_FUNCTION_ARGS)
    1567                 : {
    1568              11 :     ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
    1569                 : 
    1570 GIC          11 :     PG_RETURN_INT32(anytime_typmodin(false, ta));
    1571                 : }
    1572                 : 
    1573                 : Datum
    1574               5 : timetypmodout(PG_FUNCTION_ARGS)
    1575 EUB             : {
    1576 GIC           5 :     int32       typmod = PG_GETARG_INT32(0);
    1577 EUB             : 
    1578 GIC           5 :     PG_RETURN_CSTRING(anytime_typmodout(false, typmod));
    1579                 : }
    1580 EUB             : 
    1581                 : /*
    1582                 :  *      make_time           - time constructor
    1583                 :  */
    1584                 : Datum
    1585 GIC           9 : make_time(PG_FUNCTION_ARGS)
    1586 ECB             : {
    1587 GIC           9 :     int         tm_hour = PG_GETARG_INT32(0);
    1588 CBC           9 :     int         tm_min = PG_GETARG_INT32(1);
    1589 GIC           9 :     double      sec = PG_GETARG_FLOAT8(2);
    1590 ECB             :     TimeADT     time;
    1591                 : 
    1592                 :     /* Check for time overflow */
    1593 GIC           9 :     if (float_time_overflows(tm_hour, tm_min, sec))
    1594 CBC           6 :         ereport(ERROR,
    1595                 :                 (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
    1596 ECB             :                  errmsg("time field value out of range: %d:%02d:%02g",
    1597                 :                         tm_hour, tm_min, sec)));
    1598                 : 
    1599                 :     /* This should match tm2time */
    1600 GIC           3 :     time = (((tm_hour * MINS_PER_HOUR + tm_min) * SECS_PER_MINUTE)
    1601               3 :             * USECS_PER_SEC) + (int64) rint(sec * USECS_PER_SEC);
    1602                 : 
    1603               3 :     PG_RETURN_TIMEADT(time);
    1604                 : }
    1605 ECB             : 
    1606                 : 
    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
    1613 CBC          12 : time_support(PG_FUNCTION_ARGS)
    1614 ECB             : {
    1615 GIC          12 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
    1616              12 :     Node       *ret = NULL;
    1617                 : 
    1618              12 :     if (IsA(rawreq, SupportRequestSimplify))
    1619                 :     {
    1620 CBC           6 :         SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
    1621 ECB             : 
    1622 GIC           6 :         ret = TemporalSimplify(MAX_TIME_PRECISION, (Node *) req->fcall);
    1623 ECB             :     }
    1624                 : 
    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
    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;
    1638 ECB             : 
    1639 GIC          33 :     result = time;
    1640 CBC          33 :     AdjustTimeForTypmod(&result, typmod);
    1641                 : 
    1642              33 :     PG_RETURN_TIMEADT(result);
    1643                 : }
    1644                 : 
    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
    1653 CBC        2618 : AdjustTimeForTypmod(TimeADT *time, int32 typmod)
    1654                 : {
    1655 ECB             :     static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {
    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                 : 
    1675 GIC        2618 :     if (typmod >= 0 && typmod <= MAX_TIME_PRECISION)
    1676                 :     {
    1677              84 :         if (*time >= INT64CONST(0))
    1678              84 :             *time = ((*time + TimeOffsets[typmod]) / TimeScales[typmod]) *
    1679              84 :                 TimeScales[typmod];
    1680                 :         else
    1681 UIC           0 :             *time = -((((-*time) + TimeOffsets[typmod]) / TimeScales[typmod]) *
    1682               0 :                       TimeScales[typmod]);
    1683                 :     }
    1684 GIC        2618 : }
    1685                 : 
    1686                 : 
    1687                 : Datum
    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                 : }
    1695 ECB             : 
    1696                 : Datum
    1697 LBC           0 : time_ne(PG_FUNCTION_ARGS)
    1698 ECB             : {
    1699 LBC           0 :     TimeADT     time1 = PG_GETARG_TIMEADT(0);
    1700 UIC           0 :     TimeADT     time2 = PG_GETARG_TIMEADT(1);
    1701 EUB             : 
    1702 UBC           0 :     PG_RETURN_BOOL(time1 != time2);
    1703                 : }
    1704 ECB             : 
    1705                 : Datum
    1706 GIC       47578 : time_lt(PG_FUNCTION_ARGS)
    1707                 : {
    1708 CBC       47578 :     TimeADT     time1 = PG_GETARG_TIMEADT(0);
    1709 GIC       47578 :     TimeADT     time2 = PG_GETARG_TIMEADT(1);
    1710 ECB             : 
    1711 CBC       47578 :     PG_RETURN_BOOL(time1 < time2);
    1712                 : }
    1713 ECB             : 
    1714                 : Datum
    1715 GIC        4362 : time_le(PG_FUNCTION_ARGS)
    1716                 : {
    1717 GBC        4362 :     TimeADT     time1 = PG_GETARG_TIMEADT(0);
    1718 GIC        4362 :     TimeADT     time2 = PG_GETARG_TIMEADT(1);
    1719 EUB             : 
    1720 GBC        4362 :     PG_RETURN_BOOL(time1 <= time2);
    1721                 : }
    1722 EUB             : 
    1723                 : Datum
    1724 GIC        5982 : time_gt(PG_FUNCTION_ARGS)
    1725                 : {
    1726 CBC        5982 :     TimeADT     time1 = PG_GETARG_TIMEADT(0);
    1727 GIC        5982 :     TimeADT     time2 = PG_GETARG_TIMEADT(1);
    1728 ECB             : 
    1729 CBC        5982 :     PG_RETURN_BOOL(time1 > time2);
    1730                 : }
    1731 ECB             : 
    1732                 : Datum
    1733 GIC        3447 : time_ge(PG_FUNCTION_ARGS)
    1734                 : {
    1735 CBC        3447 :     TimeADT     time1 = PG_GETARG_TIMEADT(0);
    1736 GIC        3447 :     TimeADT     time2 = PG_GETARG_TIMEADT(1);
    1737 ECB             : 
    1738 CBC        3447 :     PG_RETURN_BOOL(time1 >= time2);
    1739                 : }
    1740 ECB             : 
    1741                 : Datum
    1742 GIC       11296 : time_cmp(PG_FUNCTION_ARGS)
    1743                 : {
    1744 CBC       11296 :     TimeADT     time1 = PG_GETARG_TIMEADT(0);
    1745 GIC       11296 :     TimeADT     time2 = PG_GETARG_TIMEADT(1);
    1746 ECB             : 
    1747 CBC       11296 :     if (time1 < time2)
    1748 GIC        5198 :         PG_RETURN_INT32(-1);
    1749 CBC        6098 :     if (time1 > time2)
    1750 GIC        5011 :         PG_RETURN_INT32(1);
    1751            1087 :     PG_RETURN_INT32(0);
    1752                 : }
    1753 ECB             : 
    1754                 : Datum
    1755 CBC        1131 : time_hash(PG_FUNCTION_ARGS)
    1756 ECB             : {
    1757 GIC        1131 :     return hashint8(fcinfo);
    1758 ECB             : }
    1759                 : 
    1760                 : Datum
    1761 GIC          30 : time_hash_extended(PG_FUNCTION_ARGS)
    1762 ECB             : {
    1763 GIC          30 :     return hashint8extended(fcinfo);
    1764 ECB             : }
    1765                 : 
    1766                 : Datum
    1767 LBC           0 : time_larger(PG_FUNCTION_ARGS)
    1768 ECB             : {
    1769 LBC           0 :     TimeADT     time1 = PG_GETARG_TIMEADT(0);
    1770               0 :     TimeADT     time2 = PG_GETARG_TIMEADT(1);
    1771 ECB             : 
    1772 UIC           0 :     PG_RETURN_TIMEADT((time1 > time2) ? time1 : time2);
    1773                 : }
    1774                 : 
    1775 ECB             : Datum
    1776 UIC           0 : time_smaller(PG_FUNCTION_ARGS)
    1777 ECB             : {
    1778 UIC           0 :     TimeADT     time1 = PG_GETARG_TIMEADT(0);
    1779               0 :     TimeADT     time2 = PG_GETARG_TIMEADT(1);
    1780                 : 
    1781 LBC           0 :     PG_RETURN_TIMEADT((time1 < time2) ? time1 : time2);
    1782                 : }
    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
    1787 EUB             :  * because the spec requires us to deliver a non-null answer in some cases
    1788                 :  * where some of the inputs are null.
    1789                 :  */
    1790                 : Datum
    1791 GIC          12 : overlaps_time(PG_FUNCTION_ARGS)
    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!)
    1796                 :      */
    1797 GIC          12 :     Datum       ts1 = PG_GETARG_DATUM(0);
    1798 GBC          12 :     Datum       te1 = PG_GETARG_DATUM(1);
    1799              12 :     Datum       ts2 = PG_GETARG_DATUM(2);
    1800 GIC          12 :     Datum       te2 = PG_GETARG_DATUM(3);
    1801 GBC          12 :     bool        ts1IsNull = PG_ARGISNULL(0);
    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                 : 
    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                 :      */
    1816 GIC          12 :     if (ts1IsNull)
    1817 ECB             :     {
    1818 LBC           0 :         if (te1IsNull)
    1819               0 :             PG_RETURN_NULL();
    1820 ECB             :         /* swap null for non-null */
    1821 LBC           0 :         ts1 = te1;
    1822               0 :         te1IsNull = true;
    1823 ECB             :     }
    1824 CBC          12 :     else if (!te1IsNull)
    1825                 :     {
    1826 GIC          12 :         if (TIMEADT_GT(ts1, te1))
    1827                 :         {
    1828 UIC           0 :             Datum       tt = ts1;
    1829                 : 
    1830               0 :             ts1 = te1;
    1831               0 :             te1 = tt;
    1832                 :         }
    1833                 :     }
    1834                 : 
    1835                 :     /* Likewise for interval 2. */
    1836 CBC          12 :     if (ts2IsNull)
    1837                 :     {
    1838 UBC           0 :         if (te2IsNull)
    1839               0 :             PG_RETURN_NULL();
    1840                 :         /* swap null for non-null */
    1841               0 :         ts2 = te2;
    1842               0 :         te2IsNull = true;
    1843                 :     }
    1844 CBC          12 :     else if (!te2IsNull)
    1845                 :     {
    1846              12 :         if (TIMEADT_GT(ts2, te2))
    1847                 :         {
    1848 UBC           0 :             Datum       tt = ts2;
    1849                 : 
    1850               0 :             ts2 = te2;
    1851               0 :             te2 = tt;
    1852                 :         }
    1853                 :     }
    1854                 : 
    1855                 :     /*
    1856 ECB             :      * At this point neither ts1 nor ts2 is null, so we can consider three
    1857                 :      * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
    1858 EUB             :      */
    1859 GBC          12 :     if (TIMEADT_GT(ts1, ts2))
    1860                 :     {
    1861 EUB             :         /*
    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.
    1864 ECB             :          */
    1865 UIC           0 :         if (te2IsNull)
    1866 LBC           0 :             PG_RETURN_NULL();
    1867 UIC           0 :         if (TIMEADT_LT(ts1, te2))
    1868 UBC           0 :             PG_RETURN_BOOL(true);
    1869 UIC           0 :         if (te1IsNull)
    1870 UBC           0 :             PG_RETURN_NULL();
    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                 :          */
    1876 UIC           0 :         PG_RETURN_BOOL(false);
    1877                 :     }
    1878 GIC          12 :     else if (TIMEADT_LT(ts1, ts2))
    1879 ECB             :     {
    1880                 :         /* This case is ts2 < te1 OR te2 < te1 */
    1881 GIC          12 :         if (te1IsNull)
    1882 UIC           0 :             PG_RETURN_NULL();
    1883 GIC          12 :         if (TIMEADT_LT(ts2, te1))
    1884               6 :             PG_RETURN_BOOL(true);
    1885 GBC           6 :         if (te2IsNull)
    1886 UBC           0 :             PG_RETURN_NULL();
    1887 EUB             : 
    1888                 :         /*
    1889                 :          * If te2 is not null then we had ts2 <= te2 above, and we just found
    1890                 :          * ts2 >= te1, hence te2 >= te1.
    1891                 :          */
    1892 GIC           6 :         PG_RETURN_BOOL(false);
    1893                 :     }
    1894                 :     else
    1895                 :     {
    1896 EUB             :         /*
    1897                 :          * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
    1898 ECB             :          * rather silly way of saying "true if both are nonnull, else null".
    1899                 :          */
    1900 UIC           0 :         if (te1IsNull || te2IsNull)
    1901 LBC           0 :             PG_RETURN_NULL();
    1902 UBC           0 :         PG_RETURN_BOOL(true);
    1903 ECB             :     }
    1904                 : 
    1905                 : #undef TIMEADT_GT
    1906 EUB             : #undef TIMEADT_LT
    1907                 : }
    1908                 : 
    1909                 : /* timestamp_time()
    1910                 :  * Convert timestamp to time data type.
    1911                 :  */
    1912 ECB             : Datum
    1913 GIC           3 : timestamp_time(PG_FUNCTION_ARGS)
    1914                 : {
    1915               3 :     Timestamp   timestamp = PG_GETARG_TIMESTAMP(0);
    1916                 :     TimeADT     result;
    1917                 :     struct pg_tm tt,
    1918               3 :                *tm = &tt;
    1919                 :     fsec_t      fsec;
    1920 EUB             : 
    1921 GBC           3 :     if (TIMESTAMP_NOT_FINITE(timestamp))
    1922 UBC           0 :         PG_RETURN_NULL();
    1923                 : 
    1924 GIC           3 :     if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
    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                 :      */
    1933 CBC           3 :     result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
    1934 GIC           3 :               USECS_PER_SEC) + fsec;
    1935 ECB             : 
    1936 GIC           3 :     PG_RETURN_TIMEADT(result);
    1937                 : }
    1938 ECB             : 
    1939                 : /* timestamptz_time()
    1940                 :  * Convert timestamptz to time data type.
    1941                 :  */
    1942 EUB             : Datum
    1943 GIC           6 : timestamptz_time(PG_FUNCTION_ARGS)
    1944 ECB             : {
    1945 GBC           6 :     TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
    1946                 :     TimeADT     result;
    1947                 :     struct pg_tm tt,
    1948 GIC           6 :                *tm = &tt;
    1949                 :     int         tz;
    1950                 :     fsec_t      fsec;
    1951                 : 
    1952               6 :     if (TIMESTAMP_NOT_FINITE(timestamp))
    1953 LBC           0 :         PG_RETURN_NULL();
    1954 ECB             : 
    1955 GIC           6 :     if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
    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;
    1963 ECB             :      */
    1964 GIC           6 :     result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
    1965 CBC           6 :               USECS_PER_SEC) + fsec;
    1966                 : 
    1967 GIC           6 :     PG_RETURN_TIMEADT(result);
    1968 ECB             : }
    1969                 : 
    1970                 : /* datetime_timestamp()
    1971                 :  * Convert date and time to timestamp data type.
    1972                 :  */
    1973 EUB             : Datum
    1974 GIC          15 : datetime_timestamp(PG_FUNCTION_ARGS)
    1975 ECB             : {
    1976 GBC          15 :     DateADT     date = PG_GETARG_DATEADT(0);
    1977 GIC          15 :     TimeADT     time = PG_GETARG_TIMEADT(1);
    1978                 :     Timestamp   result;
    1979                 : 
    1980              15 :     result = date2timestamp(date);
    1981              15 :     if (!TIMESTAMP_NOT_FINITE(result))
    1982                 :     {
    1983              15 :         result += time;
    1984 CBC          15 :         if (!IS_VALID_TIMESTAMP(result))
    1985 LBC           0 :             ereport(ERROR,
    1986                 :                     (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    1987 ECB             :                      errmsg("timestamp out of range")));
    1988                 :     }
    1989                 : 
    1990 GIC          15 :     PG_RETURN_TIMESTAMP(result);
    1991                 : }
    1992                 : 
    1993                 : /* time_interval()
    1994 ECB             :  * Convert time to interval data type.
    1995                 :  */
    1996                 : Datum
    1997 CBC           6 : time_interval(PG_FUNCTION_ARGS)
    1998                 : {
    1999 GIC           6 :     TimeADT     time = PG_GETARG_TIMEADT(0);
    2000 ECB             :     Interval   *result;
    2001                 : 
    2002 GIC           6 :     result = (Interval *) palloc(sizeof(Interval));
    2003 ECB             : 
    2004 CBC           6 :     result->time = time;
    2005 GBC           6 :     result->day = 0;
    2006 GIC           6 :     result->month = 0;
    2007                 : 
    2008               6 :     PG_RETURN_INTERVAL_P(result);
    2009                 : }
    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,
    2017                 :  * so that, say, '-2 hours' becomes '22:00:00'.
    2018                 :  */
    2019                 : Datum
    2020 GIC           3 : interval_time(PG_FUNCTION_ARGS)
    2021                 : {
    2022 CBC           3 :     Interval   *span = PG_GETARG_INTERVAL_P(0);
    2023                 :     TimeADT     result;
    2024 ECB             :     int64       days;
    2025                 : 
    2026 CBC           3 :     result = span->time;
    2027 GIC           3 :     if (result >= USECS_PER_DAY)
    2028 ECB             :     {
    2029 UIC           0 :         days = result / USECS_PER_DAY;
    2030               0 :         result -= days * USECS_PER_DAY;
    2031                 :     }
    2032 GIC           3 :     else if (result < 0)
    2033                 :     {
    2034 UIC           0 :         days = (-result + USECS_PER_DAY - 1) / USECS_PER_DAY;
    2035               0 :         result += days * USECS_PER_DAY;
    2036                 :     }
    2037                 : 
    2038 GIC           3 :     PG_RETURN_TIMEADT(result);
    2039                 : }
    2040 ECB             : 
    2041                 : /* time_mi_time()
    2042                 :  * Subtract two times to produce an interval.
    2043                 :  */
    2044                 : Datum
    2045 GIC        3265 : time_mi_time(PG_FUNCTION_ARGS)
    2046 ECB             : {
    2047 CBC        3265 :     TimeADT     time1 = PG_GETARG_TIMEADT(0);
    2048 GIC        3265 :     TimeADT     time2 = PG_GETARG_TIMEADT(1);
    2049 EUB             :     Interval   *result;
    2050                 : 
    2051 GIC        3265 :     result = (Interval *) palloc(sizeof(Interval));
    2052 ECB             : 
    2053 GIC        3265 :     result->month = 0;
    2054 GBC        3265 :     result->day = 0;
    2055            3265 :     result->time = time1 - time2;
    2056                 : 
    2057 GIC        3265 :     PG_RETURN_INTERVAL_P(result);
    2058 ECB             : }
    2059                 : 
    2060                 : /* time_pl_interval()
    2061                 :  * Add interval to time.
    2062                 :  */
    2063                 : Datum
    2064 GIC        1017 : time_pl_interval(PG_FUNCTION_ARGS)
    2065 ECB             : {
    2066 GIC        1017 :     TimeADT     time = PG_GETARG_TIMEADT(0);
    2067 CBC        1017 :     Interval   *span = PG_GETARG_INTERVAL_P(1);
    2068 ECB             :     TimeADT     result;
    2069                 : 
    2070 GIC        1017 :     result = time + span->time;
    2071 CBC        1017 :     result -= result / USECS_PER_DAY * USECS_PER_DAY;
    2072 GIC        1017 :     if (result < INT64CONST(0))
    2073 LBC           0 :         result += USECS_PER_DAY;
    2074 ECB             : 
    2075 CBC        1017 :     PG_RETURN_TIMEADT(result);
    2076                 : }
    2077 ECB             : 
    2078                 : /* time_mi_interval()
    2079                 :  * Subtract interval from time.
    2080                 :  */
    2081                 : Datum
    2082 GIC           3 : time_mi_interval(PG_FUNCTION_ARGS)
    2083                 : {
    2084 CBC           3 :     TimeADT     time = PG_GETARG_TIMEADT(0);
    2085 GIC           3 :     Interval   *span = PG_GETARG_INTERVAL_P(1);
    2086 ECB             :     TimeADT     result;
    2087                 : 
    2088 GIC           3 :     result = time - span->time;
    2089               3 :     result -= result / USECS_PER_DAY * USECS_PER_DAY;
    2090 CBC           3 :     if (result < INT64CONST(0))
    2091               3 :         result += USECS_PER_DAY;
    2092 ECB             : 
    2093 GBC           3 :     PG_RETURN_TIMEADT(result);
    2094                 : }
    2095 ECB             : 
    2096                 : /*
    2097                 :  * in_range support function for time.
    2098                 :  */
    2099                 : Datum
    2100 GIC         210 : in_range_time_interval(PG_FUNCTION_ARGS)
    2101                 : {
    2102 CBC         210 :     TimeADT     val = PG_GETARG_TIMEADT(0);
    2103 GIC         210 :     TimeADT     base = PG_GETARG_TIMEADT(1);
    2104 CBC         210 :     Interval   *offset = PG_GETARG_INTERVAL_P(2);
    2105             210 :     bool        sub = PG_GETARG_BOOL(3);
    2106 GIC         210 :     bool        less = PG_GETARG_BOOL(4);
    2107                 :     TimeADT     sum;
    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                 :      */
    2113 CBC         210 :     if (offset->time < 0)
    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
    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                 :      */
    2124 CBC         210 :     if (sub)
    2125             105 :         sum = base - offset->time;
    2126 ECB             :     else
    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);
    2133 ECB             : }
    2134 EUB             : 
    2135                 : 
    2136                 : /* time_part() and extract_time()
    2137                 :  * Extract specified field from time type.
    2138                 :  */
    2139                 : static Datum
    2140 GIC          39 : time_part_common(PG_FUNCTION_ARGS, bool retnumeric)
    2141                 : {
    2142              39 :     text       *units = PG_GETARG_TEXT_PP(0);
    2143              39 :     TimeADT     time = PG_GETARG_TIMEADT(1);
    2144 ECB             :     int64       intresult;
    2145                 :     int         type,
    2146                 :                 val;
    2147                 :     char       *lowunits;
    2148                 : 
    2149 CBC          39 :     lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
    2150              39 :                                             VARSIZE_ANY_EXHDR(units),
    2151                 :                                             false);
    2152 ECB             : 
    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;
    2160 ECB             :         struct pg_tm tt,
    2161 GIC          30 :                    *tm = &tt;
    2162 ECB             : 
    2163 CBC          30 :         time2tm(time, tm, &fsec);
    2164                 : 
    2165 GIC          30 :         switch (val)
    2166                 :         {
    2167               6 :             case DTK_MICROSEC:
    2168               6 :                 intresult = tm->tm_sec * INT64CONST(1000000) + fsec;
    2169 CBC           6 :                 break;
    2170 ECB             : 
    2171 GIC           6 :             case DTK_MILLISEC:
    2172               6 :                 if (retnumeric)
    2173 ECB             :                     /*---
    2174                 :                      * tm->tm_sec * 1000 + fsec / 1000
    2175                 :                      * = (tm->tm_sec * 1'000'000 + fsec) / 1000
    2176                 :                      */
    2177 CBC          12 :                     PG_RETURN_NUMERIC(int64_div_fast_to_numeric(tm->tm_sec * INT64CONST(1000000) + fsec, 3));
    2178                 :                 else
    2179 GIC           3 :                     PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + fsec / 1000.0);
    2180                 :                 break;
    2181 ECB             : 
    2182 GIC           6 :             case DTK_SECOND:
    2183 CBC           6 :                 if (retnumeric)
    2184                 :                     /*---
    2185 ECB             :                      * tm->tm_sec + fsec / 1'000'000
    2186                 :                      * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
    2187                 :                      */
    2188 CBC           3 :                     PG_RETURN_NUMERIC(int64_div_fast_to_numeric(tm->tm_sec * INT64CONST(1000000) + fsec, 6));
    2189 ECB             :                 else
    2190 GIC           3 :                     PG_RETURN_FLOAT8(tm->tm_sec + fsec / 1000000.0);
    2191 ECB             :                 break;
    2192                 : 
    2193 GIC           3 :             case DTK_MINUTE:
    2194               3 :                 intresult = tm->tm_min;
    2195               3 :                 break;
    2196                 : 
    2197 CBC           3 :             case DTK_HOUR:
    2198 GIC           3 :                 intresult = tm->tm_hour;
    2199 CBC           3 :                 break;
    2200                 : 
    2201 GIC           6 :             case DTK_TZ:
    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:
    2213 CBC           6 :                 ereport(ERROR,
    2214 ECB             :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2215                 :                          errmsg("unit \"%s\" not supported for type %s",
    2216                 :                                 lowunits, format_type_be(TIMEOID))));
    2217                 :                 intresult = 0;
    2218                 :         }
    2219                 :     }
    2220 GIC           9 :     else if (type == RESERV && val == DTK_EPOCH)
    2221 ECB             :     {
    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                 :     {
    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))));
    2233 ECB             :         intresult = 0;
    2234                 :     }
    2235                 : 
    2236 GIC          12 :     if (retnumeric)
    2237               9 :         PG_RETURN_NUMERIC(int64_to_numeric(intresult));
    2238                 :     else
    2239               3 :         PG_RETURN_FLOAT8(intresult);
    2240 ECB             : }
    2241                 : 
    2242                 : Datum
    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                 : {
    2251 GIC          27 :     return time_part_common(fcinfo, true);
    2252                 : }
    2253                 : 
    2254                 : 
    2255                 : /*****************************************************************************
    2256 ECB             :  *   Time With Time Zone ADT
    2257                 :  *****************************************************************************/
    2258                 : 
    2259                 : /* tm2timetz()
    2260                 :  * Convert a tm structure to a time data type.
    2261                 :  */
    2262                 : int
    2263 CBC        1328 : tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
    2264                 : {
    2265            1328 :     result->time = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
    2266 GIC        1328 :                     USECS_PER_SEC) + fsec;
    2267            1328 :     result->zone = tz;
    2268                 : 
    2269 CBC        1328 :     return 0;
    2270                 : }
    2271 ECB             : 
    2272                 : Datum
    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
    2279             989 :     int32       typmod = PG_GETARG_INT32(2);
    2280 GNC         989 :     Node       *escontext = fcinfo->context;
    2281                 :     TimeTzADT  *result;
    2282                 :     fsec_t      fsec;
    2283 ECB             :     struct pg_tm tt,
    2284 GIC         989 :                *tm = &tt;
    2285 ECB             :     int         tz;
    2286                 :     int         nf;
    2287                 :     int         dterr;
    2288                 :     char        workbuf[MAXDATELEN + 1];
    2289                 :     char       *field[MAXDATEFIELDS];
    2290                 :     int         dtype;
    2291                 :     int         ftype[MAXDATEFIELDS];
    2292                 :     DateTimeErrorExtra extra;
    2293                 : 
    2294 CBC         989 :     dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
    2295                 :                           field, ftype, MAXDATEFIELDS, &nf);
    2296             989 :     if (dterr == 0)
    2297 GNC         989 :         dterr = DecodeTimeOnly(field, ftype, nf,
    2298                 :                                &dtype, tm, &fsec, &tz, &extra);
    2299 GIC         989 :     if (dterr != 0)
    2300                 :     {
    2301 GNC          36 :         DateTimeParseError(dterr, &extra, str, "time with time zone",
    2302                 :                            escontext);
    2303              12 :         PG_RETURN_NULL();
    2304                 :     }
    2305 ECB             : 
    2306 CBC         953 :     result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
    2307 GIC         953 :     tm2timetz(tm, fsec, tz, result);
    2308             953 :     AdjustTimeForTypmod(&(result->time), typmod);
    2309                 : 
    2310 CBC         953 :     PG_RETURN_TIMETZADT_P(result);
    2311                 : }
    2312                 : 
    2313                 : Datum
    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,
    2319            2746 :                *tm = &tt;
    2320 ECB             :     fsec_t      fsec;
    2321                 :     int         tz;
    2322                 :     char        buf[MAXDATELEN + 1];
    2323                 : 
    2324 GIC        2746 :     timetz2tm(time, tm, &fsec, &tz);
    2325 CBC        2746 :     EncodeTimeOnly(tm, fsec, true, tz, DateStyle, buf);
    2326                 : 
    2327            2746 :     result = pstrdup(buf);
    2328 GIC        2746 :     PG_RETURN_CSTRING(result);
    2329 ECB             : }
    2330                 : 
    2331                 : /*
    2332                 :  *      timetz_recv         - converts external binary format to timetz
    2333                 :  */
    2334                 : Datum
    2335 UIC           0 : timetz_recv(PG_FUNCTION_ARGS)
    2336 ECB             : {
    2337 UIC           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
    2338                 : 
    2339                 : #ifdef NOT_USED
    2340 ECB             :     Oid         typelem = PG_GETARG_OID(1);
    2341                 : #endif
    2342 LBC           0 :     int32       typmod = PG_GETARG_INT32(2);
    2343                 :     TimeTzADT  *result;
    2344                 : 
    2345               0 :     result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
    2346                 : 
    2347 UIC           0 :     result->time = pq_getmsgint64(buf);
    2348                 : 
    2349               0 :     if (result->time < INT64CONST(0) || result->time > USECS_PER_DAY)
    2350 LBC           0 :         ereport(ERROR,
    2351 ECB             :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2352                 :                  errmsg("time out of range")));
    2353                 : 
    2354 LBC           0 :     result->zone = pq_getmsgint(buf, sizeof(result->zone));
    2355                 : 
    2356                 :     /* Check for sane GMT displacement; see notes in datatype/timestamp.h */
    2357 UIC           0 :     if (result->zone <= -TZDISP_LIMIT || result->zone >= TZDISP_LIMIT)
    2358               0 :         ereport(ERROR,
    2359                 :                 (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
    2360                 :                  errmsg("time zone displacement out of range")));
    2361 EUB             : 
    2362 UIC           0 :     AdjustTimeForTypmod(&(result->time), typmod);
    2363 EUB             : 
    2364 UIC           0 :     PG_RETURN_TIMETZADT_P(result);
    2365                 : }
    2366                 : 
    2367                 : /*
    2368 EUB             :  *      timetz_send         - converts timetz to binary format
    2369                 :  */
    2370                 : Datum
    2371 UBC           0 : timetz_send(PG_FUNCTION_ARGS)
    2372                 : {
    2373               0 :     TimeTzADT  *time = PG_GETARG_TIMETZADT_P(0);
    2374                 :     StringInfoData buf;
    2375 EUB             : 
    2376 UBC           0 :     pq_begintypsend(&buf);
    2377 UIC           0 :     pq_sendint64(&buf, time->time);
    2378               0 :     pq_sendint32(&buf, time->zone);
    2379               0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
    2380 EUB             : }
    2381                 : 
    2382                 : Datum
    2383 GBC          11 : timetztypmodin(PG_FUNCTION_ARGS)
    2384 EUB             : {
    2385 GIC          11 :     ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
    2386                 : 
    2387              11 :     PG_RETURN_INT32(anytime_typmodin(true, ta));
    2388 EUB             : }
    2389                 : 
    2390                 : Datum
    2391 GIC           5 : timetztypmodout(PG_FUNCTION_ARGS)
    2392                 : {
    2393               5 :     int32       typmod = PG_GETARG_INT32(0);
    2394                 : 
    2395               5 :     PG_RETURN_CSTRING(anytime_typmodout(true, typmod));
    2396                 : }
    2397 EUB             : 
    2398                 : 
    2399                 : /* timetz2tm()
    2400                 :  * Convert TIME WITH TIME ZONE data type to POSIX time structure.
    2401                 :  */
    2402                 : int
    2403 GBC        2842 : timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
    2404 EUB             : {
    2405 GBC        2842 :     TimeOffset  trem = time->time;
    2406                 : 
    2407 GIC        2842 :     tm->tm_hour = trem / USECS_PER_HOUR;
    2408            2842 :     trem -= tm->tm_hour * USECS_PER_HOUR;
    2409 CBC        2842 :     tm->tm_min = trem / USECS_PER_MINUTE;
    2410 GIC        2842 :     trem -= tm->tm_min * USECS_PER_MINUTE;
    2411 CBC        2842 :     tm->tm_sec = trem / USECS_PER_SEC;
    2412 GIC        2842 :     *fsec = trem - tm->tm_sec * USECS_PER_SEC;
    2413 ECB             : 
    2414 GIC        2842 :     if (tzp != NULL)
    2415            2842 :         *tzp = time->zone;
    2416                 : 
    2417 CBC        2842 :     return 0;
    2418                 : }
    2419 ECB             : 
    2420                 : /* timetz_scale()
    2421                 :  * Adjust time type for specified scale factor.
    2422                 :  * Used by PostgreSQL type system to stuff columns.
    2423                 :  */
    2424                 : Datum
    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);
    2429 ECB             :     TimeTzADT  *result;
    2430                 : 
    2431 CBC          39 :     result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
    2432                 : 
    2433              39 :     result->time = time->time;
    2434              39 :     result->zone = time->zone;
    2435 ECB             : 
    2436 CBC          39 :     AdjustTimeForTypmod(&(result->time), typmod);
    2437 ECB             : 
    2438 CBC          39 :     PG_RETURN_TIMETZADT_P(result);
    2439                 : }
    2440 ECB             : 
    2441                 : 
    2442                 : static int
    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 */
    2449 GIC       98233 :     t1 = time1->time + (time1->zone * USECS_PER_SEC);
    2450           98233 :     t2 = time2->time + (time2->zone * USECS_PER_SEC);
    2451 ECB             : 
    2452 GIC       98233 :     if (t1 > t2)
    2453 CBC       47160 :         return 1;
    2454           51073 :     if (t1 < t2)
    2455 GIC       46359 :         return -1;
    2456                 : 
    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                 :      */
    2461 GIC        4714 :     if (time1->zone > time2->zone)
    2462 CBC           9 :         return 1;
    2463 GIC        4705 :     if (time1->zone < time2->zone)
    2464 CBC           9 :         return -1;
    2465                 : 
    2466 GIC        4696 :     return 0;
    2467                 : }
    2468                 : 
    2469 ECB             : Datum
    2470 GIC       14809 : timetz_eq(PG_FUNCTION_ARGS)
    2471                 : {
    2472           14809 :     TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);
    2473           14809 :     TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);
    2474                 : 
    2475 CBC       14809 :     PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) == 0);
    2476 ECB             : }
    2477                 : 
    2478                 : Datum
    2479 LBC           0 : timetz_ne(PG_FUNCTION_ARGS)
    2480 ECB             : {
    2481 LBC           0 :     TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);
    2482 UIC           0 :     TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);
    2483                 : 
    2484               0 :     PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) != 0);
    2485                 : }
    2486                 : 
    2487 ECB             : Datum
    2488 CBC       69651 : timetz_lt(PG_FUNCTION_ARGS)
    2489 ECB             : {
    2490 CBC       69651 :     TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);
    2491 GIC       69651 :     TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);
    2492 ECB             : 
    2493 GIC       69651 :     PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) < 0);
    2494                 : }
    2495                 : 
    2496 ECB             : Datum
    2497 GIC        3492 : timetz_le(PG_FUNCTION_ARGS)
    2498 ECB             : {
    2499 CBC        3492 :     TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);
    2500 GIC        3492 :     TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);
    2501 ECB             : 
    2502 GIC        3492 :     PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) <= 0);
    2503                 : }
    2504                 : 
    2505 EUB             : Datum
    2506 GIC        3858 : timetz_gt(PG_FUNCTION_ARGS)
    2507 EUB             : {
    2508 GBC        3858 :     TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);
    2509 GIC        3858 :     TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);
    2510 EUB             : 
    2511 GIC        3858 :     PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);
    2512                 : }
    2513                 : 
    2514 ECB             : Datum
    2515 GIC        3318 : timetz_ge(PG_FUNCTION_ARGS)
    2516 ECB             : {
    2517 CBC        3318 :     TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);
    2518 GIC        3318 :     TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);
    2519 ECB             : 
    2520 GIC        3318 :     PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);
    2521                 : }
    2522                 : 
    2523 ECB             : Datum
    2524 GIC        2895 : timetz_cmp(PG_FUNCTION_ARGS)
    2525 ECB             : {
    2526 CBC        2895 :     TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);
    2527 GIC        2895 :     TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);
    2528 ECB             : 
    2529 GIC        2895 :     PG_RETURN_INT32(timetz_cmp_internal(time1, time2));
    2530                 : }
    2531                 : 
    2532 ECB             : Datum
    2533 GIC        1131 : timetz_hash(PG_FUNCTION_ARGS)
    2534 ECB             : {
    2535 CBC        1131 :     TimeTzADT  *key = PG_GETARG_TIMETZADT_P(0);
    2536                 :     uint32      thash;
    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                 :      */
    2542 GIC        1131 :     thash = DatumGetUInt32(DirectFunctionCall1(hashint8,
    2543 ECB             :                                                Int64GetDatumFast(key->time)));
    2544 CBC        1131 :     thash ^= DatumGetUInt32(hash_uint32(key->zone));
    2545 GIC        1131 :     PG_RETURN_UINT32(thash);
    2546 ECB             : }
    2547                 : 
    2548                 : Datum
    2549 GIC          30 : timetz_hash_extended(PG_FUNCTION_ARGS)
    2550 ECB             : {
    2551 GIC          30 :     TimeTzADT  *key = PG_GETARG_TIMETZADT_P(0);
    2552 CBC          30 :     Datum       seed = PG_GETARG_DATUM(1);
    2553 ECB             :     uint64      thash;
    2554                 : 
    2555                 :     /* Same approach as timetz_hash */
    2556 GIC          30 :     thash = DatumGetUInt64(DirectFunctionCall2(hashint8extended,
    2557                 :                                                Int64GetDatumFast(key->time),
    2558                 :                                                seed));
    2559 CBC          30 :     thash ^= DatumGetUInt64(hash_uint32_extended(key->zone,
    2560 GIC          30 :                                                  DatumGetInt64(seed)));
    2561 CBC          30 :     PG_RETURN_UINT64(thash);
    2562                 : }
    2563                 : 
    2564                 : Datum
    2565 UIC           0 : timetz_larger(PG_FUNCTION_ARGS)
    2566                 : {
    2567               0 :     TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);
    2568 LBC           0 :     TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);
    2569                 :     TimeTzADT  *result;
    2570 ECB             : 
    2571 LBC           0 :     if (timetz_cmp_internal(time1, time2) > 0)
    2572 UIC           0 :         result = time1;
    2573                 :     else
    2574               0 :         result = time2;
    2575 LBC           0 :     PG_RETURN_TIMETZADT_P(result);
    2576                 : }
    2577 ECB             : 
    2578                 : Datum
    2579 UIC           0 : timetz_smaller(PG_FUNCTION_ARGS)
    2580                 : {
    2581               0 :     TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);
    2582 LBC           0 :     TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);
    2583                 :     TimeTzADT  *result;
    2584                 : 
    2585               0 :     if (timetz_cmp_internal(time1, time2) < 0)
    2586               0 :         result = time1;
    2587 ECB             :     else
    2588 UIC           0 :         result = time2;
    2589               0 :     PG_RETURN_TIMETZADT_P(result);
    2590                 : }
    2591 EUB             : 
    2592                 : /* timetz_pl_interval()
    2593                 :  * Add interval to timetz.
    2594                 :  */
    2595                 : Datum
    2596 GIC         993 : timetz_pl_interval(PG_FUNCTION_ARGS)
    2597 EUB             : {
    2598 GBC         993 :     TimeTzADT  *time = PG_GETARG_TIMETZADT_P(0);
    2599 GIC         993 :     Interval   *span = PG_GETARG_INTERVAL_P(1);
    2600 EUB             :     TimeTzADT  *result;
    2601                 : 
    2602 GIC         993 :     result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
    2603                 : 
    2604             993 :     result->time = time->time + span->time;
    2605 GBC         993 :     result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
    2606 GIC         993 :     if (result->time < INT64CONST(0))
    2607 UBC           0 :         result->time += USECS_PER_DAY;
    2608 EUB             : 
    2609 GIC         993 :     result->zone = time->zone;
    2610                 : 
    2611 GBC         993 :     PG_RETURN_TIMETZADT_P(result);
    2612 EUB             : }
    2613                 : 
    2614                 : /* timetz_mi_interval()
    2615                 :  * Subtract interval from timetz.
    2616                 :  */
    2617                 : Datum
    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);
    2622 ECB             :     TimeTzADT  *result;
    2623                 : 
    2624 CBC           3 :     result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
    2625 ECB             : 
    2626 GIC           3 :     result->time = time->time - span->time;
    2627               3 :     result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
    2628 CBC           3 :     if (result->time < INT64CONST(0))
    2629 GIC           3 :         result->time += USECS_PER_DAY;
    2630 ECB             : 
    2631 CBC           3 :     result->zone = time->zone;
    2632 ECB             : 
    2633 GBC           3 :     PG_RETURN_TIMETZADT_P(result);
    2634                 : }
    2635 ECB             : 
    2636                 : /*
    2637                 :  * in_range support function for timetz.
    2638                 :  */
    2639                 : Datum
    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);
    2644 CBC         210 :     Interval   *offset = PG_GETARG_INTERVAL_P(2);
    2645 GIC         210 :     bool        sub = PG_GETARG_BOOL(3);
    2646 CBC         210 :     bool        less = PG_GETARG_BOOL(4);
    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                 :      */
    2653 CBC         210 :     if (offset->time < 0)
    2654 LBC           0 :         ereport(ERROR,
    2655 ECB             :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
    2656                 :                  errmsg("invalid preceding or following size in window function")));
    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                 :      */
    2664 GIC         210 :     if (sub)
    2665             105 :         sum.time = base->time - offset->time;
    2666 ECB             :     else
    2667 GIC         105 :         sum.time = base->time + offset->time;
    2668 CBC         210 :     sum.zone = base->zone;
    2669 ECB             : 
    2670 CBC         210 :     if (less)
    2671             105 :         PG_RETURN_BOOL(timetz_cmp_internal(val, &sum) <= 0);
    2672 ECB             :     else
    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
    2679 ECB             :  * because the spec requires us to deliver a non-null answer in some cases
    2680 EUB             :  * where some of the inputs are null.
    2681                 :  */
    2682                 : Datum
    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);
    2690 LBC           0 :     Datum       te1 = PG_GETARG_DATUM(1);
    2691               0 :     Datum       ts2 = PG_GETARG_DATUM(2);
    2692 UIC           0 :     Datum       te2 = PG_GETARG_DATUM(3);
    2693 LBC           0 :     bool        ts1IsNull = PG_ARGISNULL(0);
    2694               0 :     bool        te1IsNull = PG_ARGISNULL(1);
    2695 UIC           0 :     bool        ts2IsNull = PG_ARGISNULL(2);
    2696 LBC           0 :     bool        te2IsNull = PG_ARGISNULL(3);
    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                 :      */
    2708 UIC           0 :     if (ts1IsNull)
    2709 EUB             :     {
    2710 UIC           0 :         if (te1IsNull)
    2711               0 :             PG_RETURN_NULL();
    2712                 :         /* swap null for non-null */
    2713               0 :         ts1 = te1;
    2714               0 :         te1IsNull = true;
    2715 EUB             :     }
    2716 UBC           0 :     else if (!te1IsNull)
    2717 EUB             :     {
    2718 UBC           0 :         if (TIMETZ_GT(ts1, te1))
    2719 EUB             :         {
    2720 UBC           0 :             Datum       tt = ts1;
    2721 EUB             : 
    2722 UBC           0 :             ts1 = te1;
    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 */
    2733               0 :         ts2 = te2;
    2734 UBC           0 :         te2IsNull = true;
    2735                 :     }
    2736               0 :     else if (!te2IsNull)
    2737 EUB             :     {
    2738 UIC           0 :         if (TIMETZ_GT(ts2, te2))
    2739 EUB             :         {
    2740 UBC           0 :             Datum       tt = ts2;
    2741                 : 
    2742               0 :             ts2 = te2;
    2743 UIC           0 :             te2 = tt;
    2744 EUB             :         }
    2745                 :     }
    2746                 : 
    2747                 :     /*
    2748                 :      * At this point neither ts1 nor ts2 is null, so we can consider three
    2749                 :      * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
    2750                 :      */
    2751 UIC           0 :     if (TIMETZ_GT(ts1, ts2))
    2752                 :     {
    2753                 :         /*
    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.
    2756                 :          */
    2757 UBC           0 :         if (te2IsNull)
    2758 UIC           0 :             PG_RETURN_NULL();
    2759 UBC           0 :         if (TIMETZ_LT(ts1, te2))
    2760               0 :             PG_RETURN_BOOL(true);
    2761 UIC           0 :         if (te1IsNull)
    2762 UBC           0 :             PG_RETURN_NULL();
    2763                 : 
    2764 EUB             :         /*
    2765                 :          * If te1 is not null then we had ts1 <= te1 above, and we just found
    2766                 :          * ts1 >= te2, hence te1 >= te2.
    2767                 :          */
    2768 UBC           0 :         PG_RETURN_BOOL(false);
    2769 EUB             :     }
    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);
    2777 UBC           0 :         if (te2IsNull)
    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.
    2783 EUB             :          */
    2784 UBC           0 :         PG_RETURN_BOOL(false);
    2785 EUB             :     }
    2786                 :     else
    2787                 :     {
    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                 :          */
    2792 UIC           0 :         if (te1IsNull || te2IsNull)
    2793               0 :             PG_RETURN_NULL();
    2794 UBC           0 :         PG_RETURN_BOOL(true);
    2795                 :     }
    2796 EUB             : 
    2797                 : #undef TIMETZ_GT
    2798                 : #undef TIMETZ_LT
    2799                 : }
    2800                 : 
    2801                 : 
    2802                 : Datum
    2803 GBC           3 : timetz_time(PG_FUNCTION_ARGS)
    2804 EUB             : {
    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;
    2810 EUB             : 
    2811 GIC           3 :     PG_RETURN_TIMEADT(result);
    2812                 : }
    2813                 : 
    2814                 : 
    2815                 : Datum
    2816              54 : time_timetz(PG_FUNCTION_ARGS)
    2817                 : {
    2818 GBC          54 :     TimeADT     time = PG_GETARG_TIMEADT(0);
    2819 EUB             :     TimeTzADT  *result;
    2820                 :     struct pg_tm tt,
    2821 GIC          54 :                *tm = &tt;
    2822                 :     fsec_t      fsec;
    2823                 :     int         tz;
    2824                 : 
    2825              54 :     GetCurrentDateTime(tm);
    2826              54 :     time2tm(time, tm, &fsec);
    2827              54 :     tz = DetermineTimeZoneOffset(tm, session_timezone);
    2828                 : 
    2829 CBC          54 :     result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
    2830                 : 
    2831              54 :     result->time = time;
    2832 GIC          54 :     result->zone = tz;
    2833                 : 
    2834              54 :     PG_RETURN_TIMETZADT_P(result);
    2835 ECB             : }
    2836                 : 
    2837                 : 
    2838                 : /* timestamptz_timetz()
    2839                 :  * Convert timestamp to timetz data type.
    2840                 :  */
    2841                 : Datum
    2842 CBC           9 : timestamptz_timetz(PG_FUNCTION_ARGS)
    2843                 : {
    2844               9 :     TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
    2845                 :     TimeTzADT  *result;
    2846                 :     struct pg_tm tt,
    2847               9 :                *tm = &tt;
    2848                 :     int         tz;
    2849                 :     fsec_t      fsec;
    2850                 : 
    2851               9 :     if (TIMESTAMP_NOT_FINITE(timestamp))
    2852 LBC           0 :         PG_RETURN_NULL();
    2853 ECB             : 
    2854 GIC           9 :     if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
    2855 LBC           0 :         ereport(ERROR,
    2856                 :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2857 ECB             :                  errmsg("timestamp out of range")));
    2858                 : 
    2859 GIC           9 :     result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
    2860 ECB             : 
    2861 GIC           9 :     tm2timetz(tm, fsec, tz, result);
    2862                 : 
    2863               9 :     PG_RETURN_TIMETZADT_P(result);
    2864                 : }
    2865                 : 
    2866                 : 
    2867                 : /* datetimetz_timestamptz()
    2868 ECB             :  * Convert date and timetz to timestamp with time zone data type.
    2869                 :  * Timestamp is stored in GMT, so add the time zone
    2870                 :  * stored with the timetz to the result.
    2871                 :  * - thomas 2000-03-10
    2872                 :  */
    2873                 : Datum
    2874 GIC          27 : datetimetz_timestamptz(PG_FUNCTION_ARGS)
    2875                 : {
    2876              27 :     DateADT     date = PG_GETARG_DATEADT(0);
    2877 CBC          27 :     TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);
    2878 EUB             :     TimestampTz result;
    2879                 : 
    2880 CBC          27 :     if (DATE_IS_NOBEGIN(date))
    2881 UBC           0 :         TIMESTAMP_NOBEGIN(result);
    2882 GIC          27 :     else if (DATE_IS_NOEND(date))
    2883 UIC           0 :         TIMESTAMP_NOEND(result);
    2884                 :     else
    2885 ECB             :     {
    2886                 :         /*
    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                 :          */
    2891 GIC          27 :         if (date >= (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE))
    2892 UIC           0 :             ereport(ERROR,
    2893                 :                     (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2894                 :                      errmsg("date out of range for timestamp")));
    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.
    2900 ECB             :          */
    2901 GIC          27 :         if (!IS_VALID_TIMESTAMP(result))
    2902 LBC           0 :             ereport(ERROR,
    2903 ECB             :                     (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2904                 :                      errmsg("date out of range for timestamp")));
    2905                 :     }
    2906                 : 
    2907 GBC          27 :     PG_RETURN_TIMESTAMP(result);
    2908 ECB             : }
    2909 EUB             : 
    2910                 : 
    2911                 : /* timetz_part() and extract_timetz()
    2912                 :  * Extract specified field from time type.
    2913                 :  */
    2914                 : static Datum
    2915 GIC          45 : timetz_part_common(PG_FUNCTION_ARGS, bool retnumeric)
    2916                 : {
    2917 CBC          45 :     text       *units = PG_GETARG_TEXT_PP(0);
    2918 GBC          45 :     TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);
    2919                 :     int64       intresult;
    2920                 :     int         type,
    2921 ECB             :                 val;
    2922                 :     char       *lowunits;
    2923                 : 
    2924 GIC          45 :     lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
    2925              45 :                                             VARSIZE_ANY_EXHDR(units),
    2926                 :                                             false);
    2927 ECB             : 
    2928 GBC          45 :     type = DecodeUnits(0, lowunits, &val);
    2929 GIC          45 :     if (type == UNKNOWN_FIELD)
    2930               9 :         type = DecodeSpecial(0, lowunits, &val);
    2931                 : 
    2932              45 :     if (type == UNITS)
    2933 ECB             :     {
    2934                 :         int         tz;
    2935                 :         fsec_t      fsec;
    2936                 :         struct pg_tm tt,
    2937 GIC          36 :                    *tm = &tt;
    2938                 : 
    2939              36 :         timetz2tm(time, tm, &fsec, &tz);
    2940                 : 
    2941 CBC          36 :         switch (val)
    2942                 :         {
    2943               3 :             case DTK_TZ:
    2944               3 :                 intresult = -tz;
    2945 GIC           3 :                 break;
    2946                 : 
    2947               3 :             case DTK_TZ_MINUTE:
    2948               3 :                 intresult = (-tz / SECS_PER_MINUTE) % MINS_PER_HOUR;
    2949               3 :                 break;
    2950 ECB             : 
    2951 CBC           3 :             case DTK_TZ_HOUR:
    2952 GIC           3 :                 intresult = -tz / SECS_PER_HOUR;
    2953               3 :                 break;
    2954 ECB             : 
    2955 CBC           6 :             case DTK_MICROSEC:
    2956               6 :                 intresult = tm->tm_sec * INT64CONST(1000000) + fsec;
    2957 GIC           6 :                 break;
    2958 ECB             : 
    2959 GIC           6 :             case DTK_MILLISEC:
    2960               6 :                 if (retnumeric)
    2961                 :                     /*---
    2962                 :                      * tm->tm_sec * 1000 + fsec / 1000
    2963 ECB             :                      * = (tm->tm_sec * 1'000'000 + fsec) / 1000
    2964                 :                      */
    2965 CBC          12 :                     PG_RETURN_NUMERIC(int64_div_fast_to_numeric(tm->tm_sec * INT64CONST(1000000) + fsec, 3));
    2966                 :                 else
    2967               3 :                     PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + fsec / 1000.0);
    2968                 :                 break;
    2969 ECB             : 
    2970 CBC           6 :             case DTK_SECOND:
    2971               6 :                 if (retnumeric)
    2972                 :                     /*---
    2973 ECB             :                      * tm->tm_sec + fsec / 1'000'000
    2974                 :                      * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
    2975                 :                      */
    2976 GIC           3 :                     PG_RETURN_NUMERIC(int64_div_fast_to_numeric(tm->tm_sec * INT64CONST(1000000) + fsec, 6));
    2977 ECB             :                 else
    2978 CBC           3 :                     PG_RETURN_FLOAT8(tm->tm_sec + fsec / 1000000.0);
    2979 ECB             :                 break;
    2980                 : 
    2981 CBC           3 :             case DTK_MINUTE:
    2982               3 :                 intresult = tm->tm_min;
    2983               3 :                 break;
    2984                 : 
    2985               3 :             case DTK_HOUR:
    2986               3 :                 intresult = tm->tm_hour;
    2987 GIC           3 :                 break;
    2988                 : 
    2989               3 :             case DTK_DAY:
    2990                 :             case DTK_MONTH:
    2991 ECB             :             case DTK_QUARTER:
    2992                 :             case DTK_YEAR:
    2993                 :             case DTK_DECADE:
    2994                 :             case DTK_CENTURY:
    2995                 :             case DTK_MILLENNIUM:
    2996                 :             default:
    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;
    3002 ECB             :         }
    3003                 :     }
    3004 CBC           9 :     else if (type == RESERV && val == DTK_EPOCH)
    3005                 :     {
    3006 GIC           6 :         if (retnumeric)
    3007 ECB             :             /*---
    3008                 :              * time->time / 1'000'000 + time->zone
    3009                 :              * = (time->time + time->zone * 1'000'000) / 1'000'000
    3010                 :              */
    3011 CBC           3 :             PG_RETURN_NUMERIC(int64_div_fast_to_numeric(time->time + time->zone * INT64CONST(1000000), 6));
    3012 ECB             :         else
    3013 CBC           3 :             PG_RETURN_FLOAT8(time->time / 1000000.0 + time->zone);
    3014                 :     }
    3015 ECB             :     else
    3016                 :     {
    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                 :     }
    3023 ECB             : 
    3024 GIC          21 :     if (retnumeric)
    3025              18 :         PG_RETURN_NUMERIC(int64_to_numeric(intresult));
    3026                 :     else
    3027               3 :         PG_RETURN_FLOAT8(intresult);
    3028                 : }
    3029                 : 
    3030 ECB             : 
    3031                 : Datum
    3032 CBC          12 : timetz_part(PG_FUNCTION_ARGS)
    3033                 : {
    3034 GIC          12 :     return timetz_part_common(fcinfo, false);
    3035                 : }
    3036                 : 
    3037 ECB             : Datum
    3038 GIC          33 : extract_timetz(PG_FUNCTION_ARGS)
    3039 ECB             : {
    3040 GIC          33 :     return timetz_part_common(fcinfo, true);
    3041                 : }
    3042                 : 
    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
    3048 UIC           0 : timetz_zone(PG_FUNCTION_ARGS)
    3049                 : {
    3050 LBC           0 :     text       *zone = PG_GETARG_TEXT_PP(0);
    3051               0 :     TimeTzADT  *t = PG_GETARG_TIMETZADT_P(1);
    3052                 :     TimeTzADT  *result;
    3053 ECB             :     int         tz;
    3054                 :     char        tzname[TZ_STRLEN_MAX + 1];
    3055                 :     int         type,
    3056                 :                 val;
    3057                 :     pg_tz      *tzp;
    3058                 : 
    3059                 :     /*
    3060                 :      * Look up the requested timezone.
    3061                 :      */
    3062 UIC           0 :     text_to_cstring_buffer(zone, tzname, sizeof(tzname));
    3063                 : 
    3064 UNC           0 :     type = DecodeTimezoneName(tzname, &val, &tzp);
    3065 EUB             : 
    3066 UNC           0 :     if (type == TZNAME_FIXED_OFFSET)
    3067                 :     {
    3068                 :         /* fixed-offset abbreviation */
    3069 UIC           0 :         tz = -val;
    3070                 :     }
    3071 UNC           0 :     else if (type == TZNAME_DYNTZ)
    3072                 :     {
    3073                 :         /* dynamic-offset abbreviation, resolve using transaction start time */
    3074 UIC           0 :         TimestampTz now = GetCurrentTransactionStartTimestamp();
    3075                 :         int         isdst;
    3076                 : 
    3077 UBC           0 :         tz = DetermineTimeZoneAbbrevOffsetTS(now, tzname, tzp, &isdst);
    3078                 :     }
    3079 EUB             :     else
    3080                 :     {
    3081                 :         /* Get the offset-from-GMT that is valid now for the zone name */
    3082 UNC           0 :         TimestampTz now = GetCurrentTransactionStartTimestamp();
    3083                 :         struct pg_tm tm;
    3084                 :         fsec_t      fsec;
    3085 EUB             : 
    3086 UNC           0 :         if (timestamp2tm(now, &tz, &tm, &fsec, NULL, tzp) != 0)
    3087 UBC           0 :             ereport(ERROR,
    3088                 :                     (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    3089                 :                      errmsg("timestamp out of range")));
    3090 EUB             :     }
    3091                 : 
    3092 UIC           0 :     result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
    3093                 : 
    3094               0 :     result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
    3095 UBC           0 :     while (result->time < INT64CONST(0))
    3096 UIC           0 :         result->time += USECS_PER_DAY;
    3097 UBC           0 :     while (result->time >= USECS_PER_DAY)
    3098               0 :         result->time -= USECS_PER_DAY;
    3099 EUB             : 
    3100 UBC           0 :     result->zone = tz;
    3101 EUB             : 
    3102 UIC           0 :     PG_RETURN_TIMETZADT_P(result);
    3103 EUB             : }
    3104                 : 
    3105                 : /* timetz_izone()
    3106                 :  * Encode time with time zone type with specified time interval as time zone.
    3107                 :  */
    3108                 : Datum
    3109 UIC           0 : timetz_izone(PG_FUNCTION_ARGS)
    3110                 : {
    3111               0 :     Interval   *zone = PG_GETARG_INTERVAL_P(0);
    3112 UBC           0 :     TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);
    3113                 :     TimeTzADT  *result;
    3114 EUB             :     int         tz;
    3115                 : 
    3116 UIC           0 :     if (zone->month != 0 || zone->day != 0)
    3117               0 :         ereport(ERROR,
    3118                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3119 EUB             :                  errmsg("interval time zone \"%s\" must not include months or days",
    3120                 :                         DatumGetCString(DirectFunctionCall1(interval_out,
    3121                 :                                                             PointerGetDatum(zone))))));
    3122                 : 
    3123 UIC           0 :     tz = -(zone->time / USECS_PER_SEC);
    3124                 : 
    3125               0 :     result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
    3126 EUB             : 
    3127 UIC           0 :     result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
    3128 UBC           0 :     while (result->time < INT64CONST(0))
    3129 UIC           0 :         result->time += USECS_PER_DAY;
    3130 UBC           0 :     while (result->time >= USECS_PER_DAY)
    3131               0 :         result->time -= USECS_PER_DAY;
    3132 EUB             : 
    3133 UBC           0 :     result->zone = tz;
    3134 EUB             : 
    3135 UIC           0 :     PG_RETURN_TIMETZADT_P(result);
    3136 EUB             : }
        

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