LCOV - differential code coverage report
Current view: top level - src/interfaces/ecpg/pgtypeslib - interval.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DUB
Current: Differential Code Coverage HEAD vs 15 Lines: 33.1 % 602 199 2 401 199 2
Current Date: 2023-04-08 17:13:01 Functions: 73.7 % 19 14 5 1 13
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (180,240] days: 0.0 % 2 0 2
Legend: Lines: hit not hit (240..) days: 33.2 % 600 199 401 199
Function coverage date bins:
(240..) days: 73.7 % 19 14 5 1 13

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /* src/interfaces/ecpg/pgtypeslib/interval.c */
                                  2                 : 
                                  3                 : #include "postgres_fe.h"
                                  4                 : 
                                  5                 : #include <time.h>
                                  6                 : #include <math.h>
                                  7                 : #include <limits.h>
                                  8                 : 
                                  9                 : #ifdef __FAST_MATH__
                                 10                 : #error -ffast-math is known to break this code
                                 11                 : #endif
                                 12                 : 
                                 13                 : #include "common/string.h"
                                 14                 : #include "dt.h"
                                 15                 : #include "pgtypes_error.h"
                                 16                 : #include "pgtypes_interval.h"
                                 17                 : #include "pgtypeslib_extern.h"
                                 18                 : 
                                 19                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c
                                 20                 :  * and changed struct pg_tm to struct tm
                                 21                 :  */
                                 22                 : static void
 2118 tgl                        23 CBC          38 : AdjustFractSeconds(double frac, struct /* pg_ */ tm *tm, fsec_t *fsec, int scale)
                                 24                 : {
                                 25                 :     int         sec;
                                 26                 : 
 5247 meskes                     27              38 :     if (frac == 0)
                                 28              38 :         return;
 5050 bruce                      29 UBC           0 :     frac *= scale;
                                 30               0 :     sec = (int) frac;
 5247 meskes                     31               0 :     tm->tm_sec += sec;
 5050 bruce                      32               0 :     frac -= sec;
                                 33               0 :     *fsec += rint(frac * 1000000);
                                 34                 : }
                                 35                 : 
                                 36                 : 
                                 37                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c
                                 38                 :  * and changed struct pg_tm to struct tm
                                 39                 :  */
                                 40                 : static void
 2118 tgl                        41               0 : AdjustFractDays(double frac, struct /* pg_ */ tm *tm, fsec_t *fsec, int scale)
                                 42                 : {
                                 43                 :     int         extra_days;
                                 44                 : 
 5247 meskes                     45               0 :     if (frac == 0)
                                 46               0 :         return;
 5050 bruce                      47               0 :     frac *= scale;
                                 48               0 :     extra_days = (int) frac;
 5247 meskes                     49               0 :     tm->tm_mday += extra_days;
 5050 bruce                      50               0 :     frac -= extra_days;
 5247 meskes                     51               0 :     AdjustFractSeconds(frac, tm, fsec, SECS_PER_DAY);
                                 52                 : }
                                 53                 : 
                                 54                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c */
                                 55                 : static int
 1986 peter_e                    56               0 : ParseISO8601Number(const char *str, char **endptr, int *ipart, double *fpart)
                                 57                 : {
                                 58                 :     double      val;
                                 59                 : 
 5247 meskes                     60               0 :     if (!(isdigit((unsigned char) *str) || *str == '-' || *str == '.'))
                                 61               0 :         return DTERR_BAD_FORMAT;
                                 62               0 :     errno = 0;
                                 63               0 :     val = strtod(str, endptr);
                                 64                 :     /* did we not see anything that looks like a double? */
                                 65               0 :     if (*endptr == str || errno != 0)
                                 66               0 :         return DTERR_BAD_FORMAT;
                                 67                 :     /* watch out for overflow */
                                 68               0 :     if (val < INT_MIN || val > INT_MAX)
                                 69               0 :         return DTERR_FIELD_OVERFLOW;
                                 70                 :     /* be very sure we truncate towards zero (cf dtrunc()) */
                                 71               0 :     if (val >= 0)
                                 72               0 :         *ipart = (int) floor(val);
                                 73                 :     else
                                 74               0 :         *ipart = (int) -floor(-val);
                                 75               0 :     *fpart = val - *ipart;
                                 76               0 :     return 0;
                                 77                 : }
                                 78                 : 
                                 79                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c */
                                 80                 : static int
 1986 peter_e                    81               0 : ISO8601IntegerWidth(const char *fieldstart)
                                 82                 : {
                                 83                 :     /* We might have had a leading '-' */
 5247 meskes                     84               0 :     if (*fieldstart == '-')
                                 85               0 :         fieldstart++;
                                 86               0 :     return strspn(fieldstart, "0123456789");
                                 87                 : }
                                 88                 : 
                                 89                 : 
                                 90                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c
                                 91                 :  * and changed struct pg_tm to struct tm
                                 92                 :  */
                                 93                 : static inline void
 2118 tgl                        94 CBC          30 : ClearPgTm(struct /* pg_ */ tm *tm, fsec_t *fsec)
                                 95                 : {
 5247 meskes                     96              30 :     tm->tm_year = 0;
 5050 bruce                      97              30 :     tm->tm_mon = 0;
 5247 meskes                     98              30 :     tm->tm_mday = 0;
                                 99              30 :     tm->tm_hour = 0;
 5050 bruce                     100              30 :     tm->tm_min = 0;
                                101              30 :     tm->tm_sec = 0;
                                102              30 :     *fsec = 0;
 5247 meskes                    103              30 : }
                                104                 : 
                                105                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c
                                106                 :  *
                                107                 :  * * changed struct pg_tm to struct tm
                                108                 :  *
                                109                 :  * * Made the function static
                                110                 :  */
                                111                 : static int
                                112               1 : DecodeISO8601Interval(char *str,
                                113                 :                       int *dtype, struct /* pg_ */ tm *tm, fsec_t *fsec)
                                114                 : {
 5050 bruce                     115               1 :     bool        datepart = true;
                                116               1 :     bool        havefield = false;
                                117                 : 
 5247 meskes                    118               1 :     *dtype = DTK_DELTA;
                                119               1 :     ClearPgTm(tm, fsec);
                                120                 : 
                                121               1 :     if (strlen(str) < 2 || str[0] != 'P')
                                122               1 :         return DTERR_BAD_FORMAT;
                                123                 : 
 5247 meskes                    124 UBC           0 :     str++;
                                125               0 :     while (*str)
                                126                 :     {
                                127                 :         char       *fieldstart;
                                128                 :         int         val;
                                129                 :         double      fval;
                                130                 :         char        unit;
                                131                 :         int         dterr;
                                132                 : 
 5050 bruce                     133               0 :         if (*str == 'T')        /* T indicates the beginning of the time part */
                                134                 :         {
 5247 meskes                    135               0 :             datepart = false;
                                136               0 :             havefield = false;
                                137               0 :             str++;
                                138               0 :             continue;
                                139                 :         }
                                140                 : 
                                141               0 :         fieldstart = str;
                                142               0 :         dterr = ParseISO8601Number(str, &str, &val, &fval);
                                143               0 :         if (dterr)
                                144               0 :             return dterr;
                                145                 : 
                                146                 :         /*
                                147                 :          * Note: we could step off the end of the string here.  Code below
                                148                 :          * *must* exit the loop if unit == '\0'.
                                149                 :          */
                                150               0 :         unit = *str++;
                                151                 : 
                                152               0 :         if (datepart)
                                153                 :         {
 5050 bruce                     154               0 :             switch (unit)       /* before T: Y M W D */
                                155                 :             {
 5247 meskes                    156               0 :                 case 'Y':
                                157               0 :                     tm->tm_year += val;
  614 bruce                     158               0 :                     tm->tm_mon += rint(fval * MONTHS_PER_YEAR);
 5247 meskes                    159               0 :                     break;
                                160               0 :                 case 'M':
                                161               0 :                     tm->tm_mon += val;
                                162               0 :                     AdjustFractDays(fval, tm, fsec, DAYS_PER_MONTH);
                                163               0 :                     break;
                                164               0 :                 case 'W':
                                165               0 :                     tm->tm_mday += val * 7;
                                166               0 :                     AdjustFractDays(fval, tm, fsec, 7);
                                167               0 :                     break;
                                168               0 :                 case 'D':
                                169               0 :                     tm->tm_mday += val;
                                170               0 :                     AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
                                171               0 :                     break;
 5050 bruce                     172               0 :                 case 'T':       /* ISO 8601 4.4.3.3 Alternative Format / Basic */
                                173                 :                 case '\0':
 5247 meskes                    174               0 :                     if (ISO8601IntegerWidth(fieldstart) == 8 && !havefield)
                                175                 :                     {
                                176               0 :                         tm->tm_year += val / 10000;
 5050 bruce                     177               0 :                         tm->tm_mon += (val / 100) % 100;
 5247 meskes                    178               0 :                         tm->tm_mday += val % 100;
                                179               0 :                         AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
                                180               0 :                         if (unit == '\0')
                                181               0 :                             return 0;
                                182               0 :                         datepart = false;
                                183               0 :                         havefield = false;
                                184               0 :                         continue;
                                185                 :                     }
                                186                 :                     /* Else fall through to extended alternative format */
                                187                 :                     /* FALLTHROUGH */
                                188                 :                 case '-':       /* ISO 8601 4.4.3.3 Alternative Format,
                                189                 :                                  * Extended */
                                190               0 :                     if (havefield)
                                191               0 :                         return DTERR_BAD_FORMAT;
                                192                 : 
                                193               0 :                     tm->tm_year += val;
  614 bruce                     194               0 :                     tm->tm_mon += rint(fval * MONTHS_PER_YEAR);
 5247 meskes                    195               0 :                     if (unit == '\0')
                                196               0 :                         return 0;
                                197               0 :                     if (unit == 'T')
                                198                 :                     {
                                199               0 :                         datepart = false;
                                200               0 :                         havefield = false;
                                201               0 :                         continue;
                                202                 :                     }
                                203                 : 
                                204               0 :                     dterr = ParseISO8601Number(str, &str, &val, &fval);
                                205               0 :                     if (dterr)
                                206               0 :                         return dterr;
 5050 bruce                     207               0 :                     tm->tm_mon += val;
 5247 meskes                    208               0 :                     AdjustFractDays(fval, tm, fsec, DAYS_PER_MONTH);
                                209               0 :                     if (*str == '\0')
                                210               0 :                         return 0;
                                211               0 :                     if (*str == 'T')
                                212                 :                     {
                                213               0 :                         datepart = false;
                                214               0 :                         havefield = false;
                                215               0 :                         continue;
                                216                 :                     }
                                217               0 :                     if (*str != '-')
                                218               0 :                         return DTERR_BAD_FORMAT;
                                219               0 :                     str++;
                                220                 : 
                                221               0 :                     dterr = ParseISO8601Number(str, &str, &val, &fval);
                                222               0 :                     if (dterr)
                                223               0 :                         return dterr;
                                224               0 :                     tm->tm_mday += val;
                                225               0 :                     AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
                                226               0 :                     if (*str == '\0')
                                227               0 :                         return 0;
                                228               0 :                     if (*str == 'T')
                                229                 :                     {
                                230               0 :                         datepart = false;
                                231               0 :                         havefield = false;
                                232               0 :                         continue;
                                233                 :                     }
                                234               0 :                     return DTERR_BAD_FORMAT;
                                235               0 :                 default:
                                236                 :                     /* not a valid date unit suffix */
                                237               0 :                     return DTERR_BAD_FORMAT;
                                238                 :             }
                                239                 :         }
                                240                 :         else
                                241                 :         {
 5050 bruce                     242               0 :             switch (unit)       /* after T: H M S */
                                243                 :             {
 5247 meskes                    244               0 :                 case 'H':
                                245               0 :                     tm->tm_hour += val;
                                246               0 :                     AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
                                247               0 :                     break;
                                248               0 :                 case 'M':
                                249               0 :                     tm->tm_min += val;
                                250               0 :                     AdjustFractSeconds(fval, tm, fsec, SECS_PER_MINUTE);
                                251               0 :                     break;
                                252               0 :                 case 'S':
                                253               0 :                     tm->tm_sec += val;
                                254               0 :                     AdjustFractSeconds(fval, tm, fsec, 1);
                                255               0 :                     break;
 5050 bruce                     256               0 :                 case '\0':      /* ISO 8601 4.4.3.3 Alternative Format */
                                257               0 :                     if (ISO8601IntegerWidth(fieldstart) == 6 && !havefield)
                                258                 :                     {
 5247 meskes                    259               0 :                         tm->tm_hour += val / 10000;
 5050 bruce                     260               0 :                         tm->tm_min += (val / 100) % 100;
                                261               0 :                         tm->tm_sec += val % 100;
 5247 meskes                    262               0 :                         AdjustFractSeconds(fval, tm, fsec, 1);
                                263               0 :                         return 0;
                                264                 :                     }
                                265                 :                     /* Else fall through to extended alternative format */
                                266                 :                     /* FALLTHROUGH */
                                267                 :                 case ':':       /* ISO 8601 4.4.3.3 Alternative Format,
                                268                 :                                  * Extended */
                                269               0 :                     if (havefield)
                                270               0 :                         return DTERR_BAD_FORMAT;
                                271                 : 
                                272               0 :                     tm->tm_hour += val;
                                273               0 :                     AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
                                274               0 :                     if (unit == '\0')
                                275               0 :                         return 0;
                                276                 : 
                                277               0 :                     dterr = ParseISO8601Number(str, &str, &val, &fval);
                                278               0 :                     if (dterr)
                                279               0 :                         return dterr;
 5050 bruce                     280               0 :                     tm->tm_min += val;
 5247 meskes                    281               0 :                     AdjustFractSeconds(fval, tm, fsec, SECS_PER_MINUTE);
                                282               0 :                     if (*str == '\0')
                                283               0 :                         return 0;
                                284               0 :                     if (*str != ':')
                                285               0 :                         return DTERR_BAD_FORMAT;
                                286               0 :                     str++;
                                287                 : 
                                288               0 :                     dterr = ParseISO8601Number(str, &str, &val, &fval);
                                289               0 :                     if (dterr)
                                290               0 :                         return dterr;
 5050 bruce                     291               0 :                     tm->tm_sec += val;
 5247 meskes                    292               0 :                     AdjustFractSeconds(fval, tm, fsec, 1);
                                293               0 :                     if (*str == '\0')
                                294               0 :                         return 0;
                                295               0 :                     return DTERR_BAD_FORMAT;
                                296                 : 
                                297               0 :                 default:
                                298                 :                     /* not a valid time unit suffix */
                                299               0 :                     return DTERR_BAD_FORMAT;
                                300                 :             }
                                301                 :         }
                                302                 : 
                                303               0 :         havefield = true;
                                304                 :     }
                                305                 : 
                                306               0 :     return 0;
                                307                 : }
                                308                 : 
                                309                 : 
                                310                 : 
                                311                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c
                                312                 :  * with 3 exceptions
                                313                 :  *
                                314                 :  *  * changed struct pg_tm to struct tm
                                315                 :  *
                                316                 :  *  * ECPG code called this without a 'range' parameter
                                317                 :  *    removed 'int range' from the argument list and
                                318                 :  *    places where DecodeTime is called; and added
                                319                 :  *       int range = INTERVAL_FULL_RANGE;
                                320                 :  *
                                321                 :  *  * ECPG seems not to have a global IntervalStyle
                                322                 :  *    so added
                                323                 :  *      int IntervalStyle = INTSTYLE_POSTGRES;
                                324                 :  */
                                325                 : int
 2118 tgl                       326 CBC          29 : DecodeInterval(char **field, int *ftype, int nf,    /* int range, */
                                327                 :                int *dtype, struct /* pg_ */ tm *tm, fsec_t *fsec)
                                328                 : {
 5050 bruce                     329              29 :     int         IntervalStyle = INTSTYLE_POSTGRES_VERBOSE;
                                330              29 :     int         range = INTERVAL_FULL_RANGE;
 2062 peter_e                   331              29 :     bool        is_before = false;
                                332                 :     char       *cp;
 7315 meskes                    333              29 :     int         fmask = 0,
                                334                 :                 tmask,
                                335                 :                 type;
                                336                 :     int         i;
                                337                 :     int         dterr;
                                338                 :     int         val;
                                339                 :     double      fval;
                                340                 : 
                                341              29 :     *dtype = DTK_DELTA;
                                342              29 :     type = IGNORE_DTF;
 5050 bruce                     343              29 :     ClearPgTm(tm, fsec);
                                344                 : 
                                345                 :     /* read through list backwards to pick up units before values */
 7315 meskes                    346             117 :     for (i = nf - 1; i >= 0; i--)
                                347                 :     {
                                348              89 :         switch (ftype[i])
                                349                 :         {
                                350               1 :             case DTK_TIME:
 5050 bruce                     351               1 :                 dterr = DecodeTime(field[i],    /* range, */
                                352                 :                                    &tmask, tm, fsec);
 5247 meskes                    353               1 :                 if (dterr)
 5247 meskes                    354 UBC           0 :                     return dterr;
 7315 meskes                    355 CBC           1 :                 type = DTK_DAY;
                                356               1 :                 break;
                                357                 : 
 7315 meskes                    358 UBC           0 :             case DTK_TZ:
                                359                 : 
                                360                 :                 /*
                                361                 :                  * Timezone is a token with a leading sign character and at
                                362                 :                  * least one digit; there could be ':', '.', '-' embedded in
                                363                 :                  * it as well.
                                364                 :                  */
 2036 peter_e                   365               0 :                 Assert(*field[i] == '-' || *field[i] == '+');
                                366                 : 
                                367                 :                 /*
                                368                 :                  * Try for hh:mm or hh:mm:ss.  If not, fall through to
                                369                 :                  * DTK_NUMBER case, which can handle signed float numbers and
                                370                 :                  * signed year-month values.
                                371                 :                  */
 5247 meskes                    372               0 :                 if (strchr(field[i] + 1, ':') != NULL &&
 5050 bruce                     373               0 :                     DecodeTime(field[i] + 1,    /* INTERVAL_FULL_RANGE, */
                                374                 :                                &tmask, tm, fsec) == 0)
                                375                 :                 {
 7315 meskes                    376               0 :                     if (*field[i] == '-')
                                377                 :                     {
                                378                 :                         /* flip the sign on all fields */
                                379               0 :                         tm->tm_hour = -tm->tm_hour;
                                380               0 :                         tm->tm_min = -tm->tm_min;
                                381               0 :                         tm->tm_sec = -tm->tm_sec;
                                382               0 :                         *fsec = -(*fsec);
                                383                 :                     }
                                384                 : 
                                385                 :                     /*
                                386                 :                      * Set the next type to be a day, if units are not
                                387                 :                      * specified. This handles the case of '1 +02:03' since we
                                388                 :                      * are reading right to left.
                                389                 :                      */
                                390               0 :                     type = DTK_DAY;
                                391               0 :                     tmask = DTK_M(TZ);
                                392               0 :                     break;
                                393                 :                 }
                                394                 :                 /* FALL THROUGH */
                                395                 : 
                                396                 :             case DTK_DATE:
                                397                 :             case DTK_NUMBER:
 5247 meskes                    398 CBC          44 :                 if (type == IGNORE_DTF)
                                399                 :                 {
                                400                 :                     /* use typmod to decide what rightmost field is */
                                401                 :                     switch (range)
                                402                 :                     {
 5247 meskes                    403 UBC           0 :                         case INTERVAL_MASK(YEAR):
                                404               0 :                             type = DTK_YEAR;
                                405               0 :                             break;
                                406               0 :                         case INTERVAL_MASK(MONTH):
                                407                 :                         case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
                                408               0 :                             type = DTK_MONTH;
                                409               0 :                             break;
                                410               0 :                         case INTERVAL_MASK(DAY):
                                411               0 :                             type = DTK_DAY;
                                412               0 :                             break;
                                413               0 :                         case INTERVAL_MASK(HOUR):
                                414                 :                         case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
                                415                 :                         case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
                                416                 :                         case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
                                417               0 :                             type = DTK_HOUR;
                                418               0 :                             break;
                                419               0 :                         case INTERVAL_MASK(MINUTE):
                                420                 :                         case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
                                421               0 :                             type = DTK_MINUTE;
                                422               0 :                             break;
                                423               0 :                         case INTERVAL_MASK(SECOND):
                                424                 :                         case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
                                425                 :                         case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
                                426               0 :                             type = DTK_SECOND;
                                427               0 :                             break;
                                428               0 :                         default:
                                429               0 :                             type = DTK_SECOND;
                                430               0 :                             break;
                                431                 :                     }
                                432                 :                 }
                                433                 : 
 5247 meskes                    434 CBC          44 :                 errno = 0;
 2542 tgl                       435              44 :                 val = strtoint(field[i], &cp, 10);
 5247 meskes                    436              44 :                 if (errno == ERANGE)
 5247 meskes                    437 UBC           0 :                     return DTERR_FIELD_OVERFLOW;
                                438                 : 
 5247 meskes                    439 CBC          44 :                 if (*cp == '-')
                                440                 :                 {
                                441                 :                     /* SQL "years-months" syntax */
                                442                 :                     int         val2;
                                443                 : 
 2542 tgl                       444 UBC           0 :                     val2 = strtoint(cp + 1, &cp, 10);
 5247 meskes                    445               0 :                     if (errno == ERANGE || val2 < 0 || val2 >= MONTHS_PER_YEAR)
                                446               0 :                         return DTERR_FIELD_OVERFLOW;
                                447               0 :                     if (*cp != '\0')
                                448               0 :                         return DTERR_BAD_FORMAT;
                                449               0 :                     type = DTK_MONTH;
                                450               0 :                     if (*field[i] == '-')
                                451               0 :                         val2 = -val2;
                                452               0 :                     val = val * MONTHS_PER_YEAR + val2;
                                453               0 :                     fval = 0;
                                454                 :                 }
 5247 meskes                    455 CBC          44 :                 else if (*cp == '.')
                                456                 :                 {
 5247 meskes                    457 UBC           0 :                     errno = 0;
 7315                           458               0 :                     fval = strtod(cp, &cp);
 5247                           459               0 :                     if (*cp != '\0' || errno != 0)
                                460               0 :                         return DTERR_BAD_FORMAT;
                                461                 : 
                                462               0 :                     if (*field[i] == '-')
 6529 bruce                     463               0 :                         fval = -fval;
                                464                 :                 }
 7315 meskes                    465 CBC          44 :                 else if (*cp == '\0')
                                466              44 :                     fval = 0;
                                467                 :                 else
 5247 meskes                    468 UBC           0 :                     return DTERR_BAD_FORMAT;
                                469                 : 
 7315 meskes                    470 CBC          44 :                 tmask = 0;      /* DTK_M(type); */
                                471                 : 
                                472                 :                 switch (type)
                                473                 :                 {
 7315 meskes                    474 UBC           0 :                     case DTK_MICROSEC:
 5247                           475               0 :                         *fsec += rint(val + fval);
                                476               0 :                         tmask = DTK_M(MICROSECOND);
 7315                           477               0 :                         break;
                                478                 : 
                                479               0 :                     case DTK_MILLISEC:
 5247                           480               0 :                         *fsec += rint((val + fval) * 1000);
                                481               0 :                         tmask = DTK_M(MILLISECOND);
 7315                           482               0 :                         break;
                                483                 : 
 7315 meskes                    484 CBC           5 :                     case DTK_SECOND:
                                485               5 :                         tm->tm_sec += val;
 5247                           486               5 :                         *fsec += rint(fval * 1000000);
                                487                 : 
                                488                 :                         /*
                                489                 :                          * If any subseconds were specified, consider this
                                490                 :                          * microsecond and millisecond input as well.
                                491                 :                          */
                                492               5 :                         if (fval == 0)
                                493               5 :                             tmask = DTK_M(SECOND);
                                494                 :                         else
 5247 meskes                    495 UBC           0 :                             tmask = DTK_ALL_SECS_M;
 7315 meskes                    496 CBC           5 :                         break;
                                497                 : 
                                498               7 :                     case DTK_MINUTE:
                                499               7 :                         tm->tm_min += val;
 5247                           500               7 :                         AdjustFractSeconds(fval, tm, fsec, SECS_PER_MINUTE);
 7315                           501               7 :                         tmask = DTK_M(MINUTE);
                                502               7 :                         break;
                                503                 : 
                                504              25 :                     case DTK_HOUR:
                                505              25 :                         tm->tm_hour += val;
 5247                           506              25 :                         AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
 7315                           507              25 :                         tmask = DTK_M(HOUR);
 5247                           508              25 :                         type = DTK_DAY;
 7315                           509              25 :                         break;
                                510                 : 
                                511               6 :                     case DTK_DAY:
                                512               6 :                         tm->tm_mday += val;
 5247                           513               6 :                         AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
 6529 bruce                     514               6 :                         tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY);
 7315 meskes                    515               6 :                         break;
                                516                 : 
 7315 meskes                    517 UBC           0 :                     case DTK_WEEK:
                                518               0 :                         tm->tm_mday += val * 7;
 5247                           519               0 :                         AdjustFractDays(fval, tm, fsec, 7);
 6529 bruce                     520               0 :                         tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY);
 7315 meskes                    521               0 :                         break;
                                522                 : 
                                523               0 :                     case DTK_MONTH:
                                524               0 :                         tm->tm_mon += val;
 5247                           525               0 :                         AdjustFractDays(fval, tm, fsec, DAYS_PER_MONTH);
 7315                           526               0 :                         tmask = DTK_M(MONTH);
                                527               0 :                         break;
                                528                 : 
 7315 meskes                    529 CBC           1 :                     case DTK_YEAR:
                                530               1 :                         tm->tm_year += val;
  614 bruce                     531               1 :                         tm->tm_mon += rint(fval * MONTHS_PER_YEAR);
 6529                           532               1 :                         tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR);
 7315 meskes                    533               1 :                         break;
                                534                 : 
 7315 meskes                    535 UBC           0 :                     case DTK_DECADE:
                                536               0 :                         tm->tm_year += val * 10;
  614 bruce                     537               0 :                         tm->tm_mon += rint(fval * MONTHS_PER_YEAR * 10);
 6529                           538               0 :                         tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR);
 7315 meskes                    539               0 :                         break;
                                540                 : 
                                541               0 :                     case DTK_CENTURY:
                                542               0 :                         tm->tm_year += val * 100;
  614 bruce                     543               0 :                         tm->tm_mon += rint(fval * MONTHS_PER_YEAR * 100);
 6529                           544               0 :                         tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR);
 7315 meskes                    545               0 :                         break;
                                546                 : 
                                547               0 :                     case DTK_MILLENNIUM:
                                548               0 :                         tm->tm_year += val * 1000;
  614 bruce                     549               0 :                         tm->tm_mon += rint(fval * MONTHS_PER_YEAR * 1000);
 6529                           550               0 :                         tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR);
 7315 meskes                    551               0 :                         break;
                                552                 : 
                                553               0 :                     default:
 5247                           554               0 :                         return DTERR_BAD_FORMAT;
                                555                 :                 }
 7315 meskes                    556 CBC          44 :                 break;
                                557                 : 
                                558              44 :             case DTK_STRING:
                                559                 :             case DTK_SPECIAL:
                                560              44 :                 type = DecodeUnits(i, field[i], &val);
                                561              44 :                 if (type == IGNORE_DTF)
 7315 meskes                    562 UBC           0 :                     continue;
                                563                 : 
 7315 meskes                    564 CBC          44 :                 tmask = 0;      /* DTK_M(type); */
                                565                 :                 switch (type)
                                566                 :                 {
                                567              43 :                     case UNITS:
                                568              43 :                         type = val;
                                569              43 :                         break;
                                570                 : 
 7315 meskes                    571 UBC           0 :                     case AGO:
 2062 peter_e                   572               0 :                         is_before = true;
 7315 meskes                    573               0 :                         type = val;
                                574               0 :                         break;
                                575                 : 
                                576               0 :                     case RESERV:
 4633 tgl                       577               0 :                         tmask = (DTK_DATE_M | DTK_TIME_M);
 7315 meskes                    578               0 :                         *dtype = val;
                                579               0 :                         break;
                                580                 : 
 7315 meskes                    581 CBC           1 :                     default:
 5247                           582               1 :                         return DTERR_BAD_FORMAT;
                                583                 :                 }
 7315                           584              43 :                 break;
                                585                 : 
 7315 meskes                    586 UBC           0 :             default:
 5247                           587               0 :                 return DTERR_BAD_FORMAT;
                                588                 :         }
                                589                 : 
 7315 meskes                    590 CBC          88 :         if (tmask & fmask)
 5247 meskes                    591 UBC           0 :             return DTERR_BAD_FORMAT;
 7315 meskes                    592 CBC          88 :         fmask |= tmask;
                                593                 :     }
                                594                 : 
                                595                 :     /* ensure that at least one time field has been found */
 5247                           596              28 :     if (fmask == 0)
 5247 meskes                    597 UBC           0 :         return DTERR_BAD_FORMAT;
                                598                 : 
                                599                 :     /* ensure fractional seconds are fractional */
 7315 meskes                    600 CBC          28 :     if (*fsec != 0)
                                601                 :     {
                                602                 :         int         sec;
                                603                 : 
 6393 bruce                     604 UBC           0 :         sec = *fsec / USECS_PER_SEC;
                                605               0 :         *fsec -= sec * USECS_PER_SEC;
 7315 meskes                    606               0 :         tm->tm_sec += sec;
                                607                 :     }
                                608                 : 
                                609                 :     /*----------
                                610                 :      * The SQL standard defines the interval literal
                                611                 :      *   '-1 1:00:00'
                                612                 :      * to mean "negative 1 days and negative 1 hours", while Postgres
                                613                 :      * traditionally treats this as meaning "negative 1 days and positive
                                614                 :      * 1 hours".  In SQL_STANDARD intervalstyle, we apply the leading sign
                                615                 :      * to all fields if there are no other explicit signs.
                                616                 :      *
                                617                 :      * We leave the signs alone if there are additional explicit signs.
                                618                 :      * This protects us against misinterpreting postgres-style dump output,
                                619                 :      * since the postgres-style output code has always put an explicit sign on
                                620                 :      * all fields following a negative field.  But note that SQL-spec output
                                621                 :      * is ambiguous and can be misinterpreted on load!  (So it's best practice
                                622                 :      * to dump in postgres style, not SQL style.)
                                623                 :      *----------
                                624                 :      */
 5247 meskes                    625 CBC          28 :     if (IntervalStyle == INTSTYLE_SQL_STANDARD && *field[0] == '-')
                                626                 :     {
                                627                 :         /* Check for additional explicit signs */
 5050 bruce                     628 UBC           0 :         bool        more_signs = false;
                                629                 : 
 5247 meskes                    630               0 :         for (i = 1; i < nf; i++)
                                631                 :         {
                                632               0 :             if (*field[i] == '-' || *field[i] == '+')
                                633                 :             {
                                634               0 :                 more_signs = true;
                                635               0 :                 break;
                                636                 :             }
                                637                 :         }
                                638                 : 
                                639               0 :         if (!more_signs)
                                640                 :         {
                                641                 :             /*
                                642                 :              * Rather than re-determining which field was field[0], just force
                                643                 :              * 'em all negative.
                                644                 :              */
                                645               0 :             if (*fsec > 0)
                                646               0 :                 *fsec = -(*fsec);
                                647               0 :             if (tm->tm_sec > 0)
                                648               0 :                 tm->tm_sec = -tm->tm_sec;
                                649               0 :             if (tm->tm_min > 0)
                                650               0 :                 tm->tm_min = -tm->tm_min;
                                651               0 :             if (tm->tm_hour > 0)
                                652               0 :                 tm->tm_hour = -tm->tm_hour;
                                653               0 :             if (tm->tm_mday > 0)
                                654               0 :                 tm->tm_mday = -tm->tm_mday;
                                655               0 :             if (tm->tm_mon > 0)
                                656               0 :                 tm->tm_mon = -tm->tm_mon;
                                657               0 :             if (tm->tm_year > 0)
                                658               0 :                 tm->tm_year = -tm->tm_year;
                                659                 :         }
                                660                 :     }
                                661                 : 
                                662                 :     /* finally, AGO negates everything */
 7315 meskes                    663 CBC          28 :     if (is_before)
                                664                 :     {
 7315 meskes                    665 UBC           0 :         *fsec = -(*fsec);
 5247                           666               0 :         tm->tm_sec = -tm->tm_sec;
                                667               0 :         tm->tm_min = -tm->tm_min;
                                668               0 :         tm->tm_hour = -tm->tm_hour;
                                669               0 :         tm->tm_mday = -tm->tm_mday;
                                670               0 :         tm->tm_mon = -tm->tm_mon;
                                671               0 :         tm->tm_year = -tm->tm_year;
                                672                 :     }
                                673                 : 
 5247 meskes                    674 CBC          28 :     return 0;
                                675                 : }
                                676                 : 
                                677                 : 
                                678                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c */
                                679                 : static char *
                                680             265 : AddVerboseIntPart(char *cp, int value, const char *units,
                                681                 :                   bool *is_zero, bool *is_before)
                                682                 : {
                                683             265 :     if (value == 0)
                                684             192 :         return cp;
                                685                 :     /* first nonzero value sets is_before */
                                686              73 :     if (*is_zero)
                                687                 :     {
                                688              53 :         *is_before = (value < 0);
                                689              53 :         value = abs(value);
                                690                 :     }
                                691              20 :     else if (*is_before)
 5247 meskes                    692 UBC           0 :         value = -value;
  708 bruce                     693 CBC          73 :     sprintf(cp, " %d %s%s", value, units, (value == 1) ? "" : "s");
 2062 peter_e                   694              73 :     *is_zero = false;
 5247 meskes                    695              73 :     return cp + strlen(cp);
                                696                 : }
                                697                 : 
                                698                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c */
                                699                 : static char *
 5247 meskes                    700 UBC           0 : AddPostgresIntPart(char *cp, int value, const char *units,
                                701                 :                    bool *is_zero, bool *is_before)
                                702                 : {
                                703               0 :     if (value == 0)
                                704               0 :         return cp;
                                705               0 :     sprintf(cp, "%s%s%d %s%s",
                                706               0 :             (!*is_zero) ? " " : "",
                                707               0 :             (*is_before && value > 0) ? "+" : "",
                                708                 :             value,
                                709                 :             units,
                                710                 :             (value != 1) ? "s" : "");
                                711                 : 
                                712                 :     /*
                                713                 :      * Each nonzero field sets is_before for (only) the next one.  This is a
                                714                 :      * tad bizarre but it's how it worked before...
                                715                 :      */
                                716               0 :     *is_before = (value < 0);
 2062 peter_e                   717               0 :     *is_zero = false;
 5247 meskes                    718               0 :     return cp + strlen(cp);
                                719                 : }
                                720                 : 
                                721                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c */
                                722                 : static char *
                                723               0 : AddISO8601IntPart(char *cp, int value, char units)
                                724                 : {
                                725               0 :     if (value == 0)
                                726               0 :         return cp;
                                727               0 :     sprintf(cp, "%d%c", value, units);
                                728               0 :     return cp + strlen(cp);
                                729                 : }
                                730                 : 
                                731                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c */
                                732                 : static void
 5247 meskes                    733 CBC           9 : AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros)
                                734                 : {
                                735               9 :     if (fsec == 0)
                                736                 :     {
                                737               9 :         if (fillzeros)
 5247 meskes                    738 UBC           0 :             sprintf(cp, "%02d", abs(sec));
                                739                 :         else
 5247 meskes                    740 CBC           9 :             sprintf(cp, "%d", abs(sec));
                                741                 :     }
                                742                 :     else
                                743                 :     {
 5247 meskes                    744 UBC           0 :         if (fillzeros)
  184 peter                     745 UNC           0 :             sprintf(cp, "%02d.%0*d", abs(sec), precision, abs(fsec));
                                746                 :         else
                                747               0 :             sprintf(cp, "%d.%0*d", abs(sec), precision, abs(fsec));
 5247 meskes                    748 UBC           0 :         TrimTrailingZeros(cp);
                                749                 :     }
 5247 meskes                    750 CBC           9 : }
                                751                 : 
                                752                 : 
                                753                 : /* copy&pasted from .../src/backend/utils/adt/datetime.c
                                754                 :  *
                                755                 :  * Change pg_tm to tm
                                756                 :  */
                                757                 : 
                                758                 : void
 2118 tgl                       759              53 : EncodeInterval(struct /* pg_ */ tm *tm, fsec_t fsec, int style, char *str)
                                760                 : {
 7315 meskes                    761              53 :     char       *cp = str;
 5247                           762              53 :     int         year = tm->tm_year;
 5050 bruce                     763              53 :     int         mon = tm->tm_mon;
 5247 meskes                    764              53 :     int         mday = tm->tm_mday;
                                765              53 :     int         hour = tm->tm_hour;
 5050 bruce                     766              53 :     int         min = tm->tm_min;
                                767              53 :     int         sec = tm->tm_sec;
 2062 peter_e                   768              53 :     bool        is_before = false;
                                769              53 :     bool        is_zero = true;
                                770                 : 
                                771                 :     /*
                                772                 :      * The sign of year and month are guaranteed to match, since they are
                                773                 :      * stored internally as "month". But we'll need to check for is_before and
                                774                 :      * is_zero when determining the signs of day and hour/minute/seconds
                                775                 :      * fields.
                                776                 :      */
 7315 meskes                    777              53 :     switch (style)
                                778                 :     {
                                779                 :             /* SQL Standard interval format */
 5247 meskes                    780 UBC           0 :         case INTSTYLE_SQL_STANDARD:
                                781                 :             {
 5050 bruce                     782               0 :                 bool        has_negative = year < 0 || mon < 0 ||
                                783               0 :                 mday < 0 || hour < 0 ||
                                784               0 :                 min < 0 || sec < 0 || fsec < 0;
                                785               0 :                 bool        has_positive = year > 0 || mon > 0 ||
                                786               0 :                 mday > 0 || hour > 0 ||
                                787               0 :                 min > 0 || sec > 0 || fsec > 0;
                                788               0 :                 bool        has_year_month = year != 0 || mon != 0;
                                789               0 :                 bool        has_day_time = mday != 0 || hour != 0 ||
                                790               0 :                 min != 0 || sec != 0 || fsec != 0;
                                791               0 :                 bool        has_day = mday != 0;
                                792               0 :                 bool        sql_standard_value = !(has_negative && has_positive) &&
                                793               0 :                 !(has_year_month && has_day_time);
                                794                 : 
                                795                 :                 /*
                                796                 :                  * SQL Standard wants only 1 "<sign>" preceding the whole
                                797                 :                  * interval ... but can't do that if mixed signs.
                                798                 :                  */
 5247 meskes                    799               0 :                 if (has_negative && sql_standard_value)
                                800                 :                 {
                                801               0 :                     *cp++ = '-';
                                802               0 :                     year = -year;
 5050 bruce                     803               0 :                     mon = -mon;
 5247 meskes                    804               0 :                     mday = -mday;
                                805               0 :                     hour = -hour;
 5050 bruce                     806               0 :                     min = -min;
                                807               0 :                     sec = -sec;
 5247 meskes                    808               0 :                     fsec = -fsec;
                                809                 :                 }
                                810                 : 
                                811               0 :                 if (!has_negative && !has_positive)
                                812                 :                 {
                                813               0 :                     sprintf(cp, "0");
                                814                 :                 }
                                815               0 :                 else if (!sql_standard_value)
                                816                 :                 {
                                817                 :                     /*
                                818                 :                      * For non sql-standard interval values, force outputting
                                819                 :                      * the signs to avoid ambiguities with intervals with
                                820                 :                      * mixed sign components.
                                821                 :                      */
 5050 bruce                     822               0 :                     char        year_sign = (year < 0 || mon < 0) ? '-' : '+';
                                823               0 :                     char        day_sign = (mday < 0) ? '-' : '+';
                                824               0 :                     char        sec_sign = (hour < 0 || min < 0 ||
                                825               0 :                                             sec < 0 || fsec < 0) ? '-' : '+';
                                826                 : 
 5247 meskes                    827               0 :                     sprintf(cp, "%c%d-%d %c%d %c%d:%02d:",
                                828                 :                             year_sign, abs(year), abs(mon),
                                829                 :                             day_sign, abs(mday),
                                830                 :                             sec_sign, abs(hour), abs(min));
 7315                           831               0 :                     cp += strlen(cp);
 5247                           832               0 :                     AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
                                833                 :                 }
                                834               0 :                 else if (has_year_month)
                                835                 :                 {
                                836               0 :                     sprintf(cp, "%d-%d", year, mon);
                                837                 :                 }
                                838               0 :                 else if (has_day)
                                839                 :                 {
                                840               0 :                     sprintf(cp, "%d %d:%02d:", mday, hour, min);
 7315                           841               0 :                     cp += strlen(cp);
 5247                           842               0 :                     AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
                                843                 :                 }
                                844                 :                 else
                                845                 :                 {
                                846               0 :                     sprintf(cp, "%d:%02d:", hour, min);
 7315                           847               0 :                     cp += strlen(cp);
 5247                           848               0 :                     AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
                                849                 :                 }
                                850                 :             }
 7315                           851               0 :             break;
                                852                 : 
                                853                 :             /* ISO 8601 "time-intervals by duration only" */
 5247                           854               0 :         case INTSTYLE_ISO_8601:
                                855                 :             /* special-case zero to avoid printing nothing */
                                856               0 :             if (year == 0 && mon == 0 && mday == 0 &&
 5050 bruce                     857               0 :                 hour == 0 && min == 0 && sec == 0 && fsec == 0)
                                858                 :             {
 5247 meskes                    859               0 :                 sprintf(cp, "PT0S");
                                860               0 :                 break;
                                861                 :             }
                                862               0 :             *cp++ = 'P';
                                863               0 :             cp = AddISO8601IntPart(cp, year, 'Y');
 5050 bruce                     864               0 :             cp = AddISO8601IntPart(cp, mon, 'M');
 5247 meskes                    865               0 :             cp = AddISO8601IntPart(cp, mday, 'D');
                                866               0 :             if (hour != 0 || min != 0 || sec != 0 || fsec != 0)
                                867               0 :                 *cp++ = 'T';
                                868               0 :             cp = AddISO8601IntPart(cp, hour, 'H');
 5050 bruce                     869               0 :             cp = AddISO8601IntPart(cp, min, 'M');
 5247 meskes                    870               0 :             if (sec != 0 || fsec != 0)
                                871                 :             {
                                872               0 :                 if (sec < 0 || fsec < 0)
                                873               0 :                     *cp++ = '-';
                                874               0 :                 AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
 7315                           875               0 :                 cp += strlen(cp);
 5247                           876               0 :                 *cp++ = 'S';
 4966                           877               0 :                 *cp = '\0';
                                878                 :             }
 5247                           879               0 :             break;
                                880                 : 
                                881                 :             /* Compatible with postgresql < 8.4 when DateStyle = 'iso' */
                                882               0 :         case INTSTYLE_POSTGRES:
                                883               0 :             cp = AddPostgresIntPart(cp, year, "year", &is_zero, &is_before);
                                884               0 :             cp = AddPostgresIntPart(cp, mon, "mon", &is_zero, &is_before);
                                885               0 :             cp = AddPostgresIntPart(cp, mday, "day", &is_zero, &is_before);
                                886               0 :             if (is_zero || hour != 0 || min != 0 || sec != 0 || fsec != 0)
                                887                 :             {
 5050 bruce                     888               0 :                 bool        minus = (hour < 0 || min < 0 || sec < 0 || fsec < 0);
                                889                 : 
 5247 meskes                    890               0 :                 sprintf(cp, "%s%s%02d:%02d:",
                                891               0 :                         is_zero ? "" : " ",
                                892               0 :                         (minus ? "-" : (is_before ? "+" : "")),
                                893                 :                         abs(hour), abs(min));
 7315                           894               0 :                 cp += strlen(cp);
 5247                           895               0 :                 AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
                                896                 :             }
                                897               0 :             break;
                                898                 : 
                                899                 :             /* Compatible with postgresql < 8.4 when DateStyle != 'iso' */
 5247 meskes                    900 CBC          53 :         case INTSTYLE_POSTGRES_VERBOSE:
                                901                 :         default:
                                902              53 :             strcpy(cp, "@");
                                903              53 :             cp++;
                                904              53 :             cp = AddVerboseIntPart(cp, year, "year", &is_zero, &is_before);
                                905              53 :             cp = AddVerboseIntPart(cp, mon, "mon", &is_zero, &is_before);
                                906              53 :             cp = AddVerboseIntPart(cp, mday, "day", &is_zero, &is_before);
                                907              53 :             cp = AddVerboseIntPart(cp, hour, "hour", &is_zero, &is_before);
                                908              53 :             cp = AddVerboseIntPart(cp, min, "min", &is_zero, &is_before);
                                909              53 :             if (sec != 0 || fsec != 0)
                                910                 :             {
                                911               9 :                 *cp++ = ' ';
                                912               9 :                 if (sec < 0 || (sec == 0 && fsec < 0))
                                913                 :                 {
 5247 meskes                    914 UBC           0 :                     if (is_zero)
 2062 peter_e                   915               0 :                         is_before = true;
 5247 meskes                    916               0 :                     else if (!is_before)
                                917               0 :                         *cp++ = '-';
                                918                 :                 }
 5247 meskes                    919 CBC           9 :                 else if (is_before)
 5247 meskes                    920 UBC           0 :                     *cp++ = '-';
 5247 meskes                    921 CBC           9 :                 AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
 7315                           922               9 :                 cp += strlen(cp);
                                923                 :                 /* We output "ago", not negatives, so use abs(). */
 5247                           924               9 :                 sprintf(cp, " sec%s",
                                925               9 :                         (abs(sec) != 1 || fsec != 0) ? "s" : "");
 2062 peter_e                   926               9 :                 is_zero = false;
                                927                 :             }
                                928                 :             /* identically zero? then put in a unitless zero... */
 5247 meskes                    929              53 :             if (is_zero)
 5247 meskes                    930 UBC           0 :                 strcat(cp, " 0");
 5247 meskes                    931 CBC          53 :             if (is_before)
 5247 meskes                    932 UBC           0 :                 strcat(cp, " ago");
 7315 meskes                    933 CBC          53 :             break;
                                934                 :     }
 2036 peter_e                   935              53 : }
                                936                 : 
                                937                 : 
                                938                 : /* interval2tm()
                                939                 :  * Convert an interval data type to a tm structure.
                                940                 :  */
                                941                 : static int
 2118 tgl                       942              53 : interval2tm(interval span, struct tm *tm, fsec_t *fsec)
                                943                 : {
                                944                 :     int64       time;
                                945                 : 
 7315 meskes                    946              53 :     if (span.month != 0)
                                947                 :     {
 6471 bruce                     948               2 :         tm->tm_year = span.month / MONTHS_PER_YEAR;
                                949               2 :         tm->tm_mon = span.month % MONTHS_PER_YEAR;
                                950                 :     }
                                951                 :     else
                                952                 :     {
 7315 meskes                    953              51 :         tm->tm_year = 0;
                                954              51 :         tm->tm_mon = 0;
                                955                 :     }
                                956                 : 
                                957              53 :     time = span.time;
                                958                 : 
 6393 bruce                     959              53 :     tm->tm_mday = time / USECS_PER_DAY;
                                960              53 :     time -= tm->tm_mday * USECS_PER_DAY;
                                961              53 :     tm->tm_hour = time / USECS_PER_HOUR;
                                962              53 :     time -= tm->tm_hour * USECS_PER_HOUR;
                                963              53 :     tm->tm_min = time / USECS_PER_MINUTE;
                                964              53 :     time -= tm->tm_min * USECS_PER_MINUTE;
                                965              53 :     tm->tm_sec = time / USECS_PER_SEC;
                                966              53 :     *fsec = time - (tm->tm_sec * USECS_PER_SEC);
                                967                 : 
 7315 meskes                    968              53 :     return 0;
                                969                 : }                               /* interval2tm() */
                                970                 : 
                                971                 : static int
 2118 tgl                       972              28 : tm2interval(struct tm *tm, fsec_t fsec, interval * span)
                                973                 : {
 3260 bruce                     974              28 :     if ((double) tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon > INT_MAX ||
                                975              28 :         (double) tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon < INT_MIN)
 3356 bruce                     976 UBC           0 :         return -1;
 6471 bruce                     977 CBC          28 :     span->month = tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon;
                                978              28 :     span->time = (((((((tm->tm_mday * INT64CONST(24)) +
 6385                           979              28 :                        tm->tm_hour) * INT64CONST(60)) +
                                980              28 :                      tm->tm_min) * INT64CONST(60)) +
                                981              28 :                    tm->tm_sec) * USECS_PER_SEC) + fsec;
                                982                 : 
 7315 meskes                    983              28 :     return 0;
                                984                 : }                               /* tm2interval() */
                                985                 : 
                                986                 : interval *
 6051                           987              16 : PGTYPESinterval_new(void)
                                988                 : {
                                989                 :     interval   *result;
                                990                 : 
                                991              16 :     result = (interval *) pgtypes_alloc(sizeof(interval));
                                992                 :     /* result can be NULL if we run out of memory */
                                993              16 :     return result;
                                994                 : }
                                995                 : 
                                996                 : void
 6031 bruce                     997              13 : PGTYPESinterval_free(interval * intvl)
                                998                 : {
 6051 meskes                    999              13 :     free(intvl);
                               1000              13 : }
                               1001                 : 
                               1002                 : interval *
 7313                          1003              29 : PGTYPESinterval_from_asc(char *str, char **endptr)
                               1004                 : {
 7152                          1005              29 :     interval   *result = NULL;
                               1006                 :     fsec_t      fsec;
                               1007                 :     struct tm   tt,
 7315                          1008              29 :                *tm = &tt;
                               1009                 :     int         dtype;
                               1010                 :     int         nf;
                               1011                 :     char       *field[MAXDATEFIELDS];
                               1012                 :     int         ftype[MAXDATEFIELDS];
                               1013                 :     char        lowstr[MAXDATELEN + MAXDATEFIELDS];
                               1014                 :     char       *realptr;
 7188 bruce                    1015              29 :     char      **ptr = (endptr != NULL) ? endptr : &realptr;
                               1016                 : 
 7315 meskes                   1017              29 :     tm->tm_year = 0;
                               1018              29 :     tm->tm_mon = 0;
                               1019              29 :     tm->tm_mday = 0;
                               1020              29 :     tm->tm_hour = 0;
                               1021              29 :     tm->tm_min = 0;
                               1022              29 :     tm->tm_sec = 0;
                               1023              29 :     fsec = 0;
                               1024                 : 
 3338 noah                     1025              29 :     if (strlen(str) > MAXDATELEN)
                               1026                 :     {
 7315 meskes                   1027 UBC           0 :         errno = PGTYPES_INTVL_BAD_INTERVAL;
                               1028               0 :         return NULL;
                               1029                 :     }
                               1030                 : 
 5072 meskes                   1031 CBC          58 :     if (ParseDateTime(str, lowstr, field, ftype, &nf, ptr) != 0 ||
 5247                          1032              30 :         (DecodeInterval(field, ftype, nf, &dtype, tm, &fsec) != 0 &&
                               1033               1 :          DecodeISO8601Interval(str, &dtype, tm, &fsec) != 0))
                               1034                 :     {
 7315                          1035               1 :         errno = PGTYPES_INTVL_BAD_INTERVAL;
                               1036               1 :         return NULL;
                               1037                 :     }
                               1038                 : 
 7152                          1039              28 :     result = (interval *) pgtypes_alloc(sizeof(interval));
 7315                          1040              28 :     if (!result)
 7315 meskes                   1041 UBC           0 :         return NULL;
                               1042                 : 
 7315 meskes                   1043 CBC          28 :     if (dtype != DTK_DELTA)
                               1044                 :     {
 7315 meskes                   1045 UBC           0 :         errno = PGTYPES_INTVL_BAD_INTERVAL;
 6852                          1046               0 :         free(result);
 7315                          1047               0 :         return NULL;
                               1048                 :     }
                               1049                 : 
 7315 meskes                   1050 CBC          28 :     if (tm2interval(tm, fsec, result) != 0)
                               1051                 :     {
 7315 meskes                   1052 UBC           0 :         errno = PGTYPES_INTVL_BAD_INTERVAL;
 6852                          1053               0 :         free(result);
 7315                          1054               0 :         return NULL;
                               1055                 :     }
                               1056                 : 
 6151 meskes                   1057 CBC          28 :     errno = 0;
 7315                          1058              28 :     return result;
                               1059                 : }
                               1060                 : 
                               1061                 : char *
 6385 bruce                    1062              53 : PGTYPESinterval_to_asc(interval * span)
                               1063                 : {
                               1064                 :     struct tm   tt,
 7315 meskes                   1065              53 :                *tm = &tt;
                               1066                 :     fsec_t      fsec;
                               1067                 :     char        buf[MAXDATELEN + 1];
 5050 bruce                    1068              53 :     int         IntervalStyle = INTSTYLE_POSTGRES_VERBOSE;
                               1069                 : 
 7315 meskes                   1070              53 :     if (interval2tm(*span, tm, &fsec) != 0)
                               1071                 :     {
 7315 meskes                   1072 UBC           0 :         errno = PGTYPES_INTVL_BAD_INTERVAL;
                               1073               0 :         return NULL;
                               1074                 :     }
                               1075                 : 
 2036 peter_e                  1076 CBC          53 :     EncodeInterval(tm, fsec, IntervalStyle, buf);
                               1077                 : 
 7188 bruce                    1078              53 :     return pgtypes_strdup(buf);
                               1079                 : }
                               1080                 : 
                               1081                 : int
 6060 meskes                   1082              17 : PGTYPESinterval_copy(interval * intvlsrc, interval * intvldest)
                               1083                 : {
                               1084              17 :     intvldest->time = intvlsrc->time;
                               1085              17 :     intvldest->month = intvlsrc->month;
                               1086                 : 
 7315                          1087              17 :     return 0;
                               1088                 : }
        

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