LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - formatting.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 80.5 % 2312 1861 69 127 208 47 158 965 95 643 225 977 21 114
Current Date: 2023-04-08 15:15:32 Functions: 95.3 % 64 61 3 58 3 3 56 5
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /* -----------------------------------------------------------------------
       2                 :  * formatting.c
       3                 :  *
       4                 :  * src/backend/utils/adt/formatting.c
       5                 :  *
       6                 :  *
       7                 :  *   Portions Copyright (c) 1999-2023, PostgreSQL Global Development Group
       8                 :  *
       9                 :  *
      10                 :  *   TO_CHAR(); TO_TIMESTAMP(); TO_DATE(); TO_NUMBER();
      11                 :  *
      12                 :  *   The PostgreSQL routines for a timestamp/int/float/numeric formatting,
      13                 :  *   inspired by the Oracle TO_CHAR() / TO_DATE() / TO_NUMBER() routines.
      14                 :  *
      15                 :  *
      16                 :  *   Cache & Memory:
      17                 :  *  Routines use (itself) internal cache for format pictures.
      18                 :  *
      19                 :  *  The cache uses a static buffer and is persistent across transactions.  If
      20                 :  *  the format-picture is bigger than the cache buffer, the parser is called
      21                 :  *  always.
      22                 :  *
      23                 :  *   NOTE for Number version:
      24                 :  *  All in this version is implemented as keywords ( => not used
      25                 :  *  suffixes), because a format picture is for *one* item (number)
      26                 :  *  only. It not is as a timestamp version, where each keyword (can)
      27                 :  *  has suffix.
      28                 :  *
      29                 :  *   NOTE for Timestamp routines:
      30                 :  *  In this module the POSIX 'struct tm' type is *not* used, but rather
      31                 :  *  PgSQL type, which has tm_mon based on one (*non* zero) and
      32                 :  *  year *not* based on 1900, but is used full year number.
      33                 :  *  Module supports AD / BC / AM / PM.
      34                 :  *
      35                 :  *  Supported types for to_char():
      36                 :  *
      37                 :  *      Timestamp, Numeric, int4, int8, float4, float8
      38                 :  *
      39                 :  *  Supported types for reverse conversion:
      40                 :  *
      41                 :  *      Timestamp   - to_timestamp()
      42                 :  *      Date        - to_date()
      43                 :  *      Numeric     - to_number()
      44                 :  *
      45                 :  *
      46                 :  *  Karel Zak
      47                 :  *
      48                 :  * TODO
      49                 :  *  - better number building (formatting) / parsing, now it isn't
      50                 :  *        ideal code
      51                 :  *  - use Assert()
      52                 :  *  - add support for roman number to standard number conversion
      53                 :  *  - add support for number spelling
      54                 :  *  - add support for string to string formatting (we must be better
      55                 :  *    than Oracle :-),
      56                 :  *      to_char('Hello', 'X X X X X') -> 'H e l l o'
      57                 :  *
      58                 :  * -----------------------------------------------------------------------
      59                 :  */
      60                 : 
      61                 : #ifdef DEBUG_TO_FROM_CHAR
      62                 : #define DEBUG_elog_output   DEBUG3
      63                 : #endif
      64                 : 
      65                 : #include "postgres.h"
      66                 : 
      67                 : #include <ctype.h>
      68                 : #include <unistd.h>
      69                 : #include <math.h>
      70                 : #include <float.h>
      71                 : #include <limits.h>
      72                 : #include <wctype.h>
      73                 : 
      74                 : #ifdef USE_ICU
      75                 : #include <unicode/ustring.h>
      76                 : #endif
      77                 : 
      78                 : #include "catalog/pg_collation.h"
      79                 : #include "catalog/pg_type.h"
      80                 : #include "mb/pg_wchar.h"
      81                 : #include "nodes/miscnodes.h"
      82                 : #include "parser/scansup.h"
      83                 : #include "utils/builtins.h"
      84                 : #include "utils/date.h"
      85                 : #include "utils/datetime.h"
      86                 : #include "utils/float.h"
      87                 : #include "utils/formatting.h"
      88                 : #include "utils/memutils.h"
      89                 : #include "utils/numeric.h"
      90                 : #include "utils/pg_locale.h"
      91                 : #include "varatt.h"
      92                 : 
      93                 : 
      94                 : /* ----------
      95                 :  * Routines flags
      96                 :  * ----------
      97                 :  */
      98                 : #define DCH_FLAG        0x1     /* DATE-TIME flag   */
      99                 : #define NUM_FLAG        0x2     /* NUMBER flag  */
     100                 : #define STD_FLAG        0x4     /* STANDARD flag    */
     101                 : 
     102                 : /* ----------
     103                 :  * KeyWord Index (ascii from position 32 (' ') to 126 (~))
     104                 :  * ----------
     105                 :  */
     106                 : #define KeyWord_INDEX_SIZE      ('~' - ' ')
     107                 : #define KeyWord_INDEX_FILTER(_c)    ((_c) <= ' ' || (_c) >= '~' ? 0 : 1)
     108                 : 
     109                 : /* ----------
     110                 :  * Maximal length of one node
     111                 :  * ----------
     112                 :  */
     113                 : #define DCH_MAX_ITEM_SIZ       12   /* max localized day name       */
     114                 : #define NUM_MAX_ITEM_SIZ        8   /* roman number (RN has 15 chars)   */
     115                 : 
     116                 : 
     117                 : /* ----------
     118                 :  * Format parser structs
     119                 :  * ----------
     120                 :  */
     121                 : typedef struct
     122                 : {
     123                 :     const char *name;           /* suffix string        */
     124                 :     int         len,            /* suffix length        */
     125                 :                 id,             /* used in node->suffix */
     126                 :                 type;           /* prefix / postfix     */
     127                 : } KeySuffix;
     128                 : 
     129                 : /* ----------
     130                 :  * FromCharDateMode
     131                 :  * ----------
     132                 :  *
     133                 :  * This value is used to nominate one of several distinct (and mutually
     134                 :  * exclusive) date conventions that a keyword can belong to.
     135                 :  */
     136                 : typedef enum
     137                 : {
     138                 :     FROM_CHAR_DATE_NONE = 0,    /* Value does not affect date mode. */
     139                 :     FROM_CHAR_DATE_GREGORIAN,   /* Gregorian (day, month, year) style date */
     140                 :     FROM_CHAR_DATE_ISOWEEK      /* ISO 8601 week date */
     141                 : } FromCharDateMode;
     142                 : 
     143                 : typedef struct
     144                 : {
     145                 :     const char *name;
     146                 :     int         len;
     147                 :     int         id;
     148                 :     bool        is_digit;
     149                 :     FromCharDateMode date_mode;
     150                 : } KeyWord;
     151                 : 
     152                 : typedef struct
     153                 : {
     154                 :     uint8       type;           /* NODE_TYPE_XXX, see below */
     155                 :     char        character[MAX_MULTIBYTE_CHAR_LEN + 1];  /* if type is CHAR */
     156                 :     uint8       suffix;         /* keyword prefix/suffix code, if any */
     157                 :     const KeyWord *key;         /* if type is ACTION */
     158                 : } FormatNode;
     159                 : 
     160                 : #define NODE_TYPE_END       1
     161                 : #define NODE_TYPE_ACTION    2
     162                 : #define NODE_TYPE_CHAR      3
     163                 : #define NODE_TYPE_SEPARATOR 4
     164                 : #define NODE_TYPE_SPACE     5
     165                 : 
     166                 : #define SUFFTYPE_PREFIX     1
     167                 : #define SUFFTYPE_POSTFIX    2
     168                 : 
     169                 : #define CLOCK_24_HOUR       0
     170                 : #define CLOCK_12_HOUR       1
     171                 : 
     172                 : 
     173                 : /* ----------
     174                 :  * Full months
     175                 :  * ----------
     176                 :  */
     177                 : static const char *const months_full[] = {
     178                 :     "January", "February", "March", "April", "May", "June", "July",
     179                 :     "August", "September", "October", "November", "December", NULL
     180                 : };
     181                 : 
     182                 : static const char *const days_short[] = {
     183                 :     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
     184                 : };
     185                 : 
     186                 : /* ----------
     187                 :  * AD / BC
     188                 :  * ----------
     189                 :  *  There is no 0 AD.  Years go from 1 BC to 1 AD, so we make it
     190                 :  *  positive and map year == -1 to year zero, and shift all negative
     191                 :  *  years up one.  For interval years, we just return the year.
     192                 :  */
     193                 : #define ADJUST_YEAR(year, is_interval)  ((is_interval) ? (year) : ((year) <= 0 ? -((year) - 1) : (year)))
     194                 : 
     195                 : #define A_D_STR     "A.D."
     196                 : #define a_d_STR     "a.d."
     197                 : #define AD_STR      "AD"
     198                 : #define ad_STR      "ad"
     199                 : 
     200                 : #define B_C_STR     "B.C."
     201                 : #define b_c_STR     "b.c."
     202                 : #define BC_STR      "BC"
     203                 : #define bc_STR      "bc"
     204                 : 
     205                 : /*
     206                 :  * AD / BC strings for seq_search.
     207                 :  *
     208                 :  * These are given in two variants, a long form with periods and a standard
     209                 :  * form without.
     210                 :  *
     211                 :  * The array is laid out such that matches for AD have an even index, and
     212                 :  * matches for BC have an odd index.  So the boolean value for BC is given by
     213                 :  * taking the array index of the match, modulo 2.
     214                 :  */
     215                 : static const char *const adbc_strings[] = {ad_STR, bc_STR, AD_STR, BC_STR, NULL};
     216                 : static const char *const adbc_strings_long[] = {a_d_STR, b_c_STR, A_D_STR, B_C_STR, NULL};
     217                 : 
     218                 : /* ----------
     219                 :  * AM / PM
     220                 :  * ----------
     221                 :  */
     222                 : #define A_M_STR     "A.M."
     223                 : #define a_m_STR     "a.m."
     224                 : #define AM_STR      "AM"
     225                 : #define am_STR      "am"
     226                 : 
     227                 : #define P_M_STR     "P.M."
     228                 : #define p_m_STR     "p.m."
     229                 : #define PM_STR      "PM"
     230                 : #define pm_STR      "pm"
     231                 : 
     232                 : /*
     233                 :  * AM / PM strings for seq_search.
     234                 :  *
     235                 :  * These are given in two variants, a long form with periods and a standard
     236                 :  * form without.
     237                 :  *
     238                 :  * The array is laid out such that matches for AM have an even index, and
     239                 :  * matches for PM have an odd index.  So the boolean value for PM is given by
     240                 :  * taking the array index of the match, modulo 2.
     241                 :  */
     242                 : static const char *const ampm_strings[] = {am_STR, pm_STR, AM_STR, PM_STR, NULL};
     243                 : static const char *const ampm_strings_long[] = {a_m_STR, p_m_STR, A_M_STR, P_M_STR, NULL};
     244                 : 
     245                 : /* ----------
     246                 :  * Months in roman-numeral
     247                 :  * (Must be in reverse order for seq_search (in FROM_CHAR), because
     248                 :  *  'VIII' must have higher precedence than 'V')
     249                 :  * ----------
     250                 :  */
     251                 : static const char *const rm_months_upper[] =
     252                 : {"XII", "XI", "X", "IX", "VIII", "VII", "VI", "V", "IV", "III", "II", "I", NULL};
     253                 : 
     254                 : static const char *const rm_months_lower[] =
     255                 : {"xii", "xi", "x", "ix", "viii", "vii", "vi", "v", "iv", "iii", "ii", "i", NULL};
     256                 : 
     257                 : /* ----------
     258                 :  * Roman numbers
     259                 :  * ----------
     260                 :  */
     261                 : static const char *const rm1[] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", NULL};
     262                 : static const char *const rm10[] = {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", NULL};
     263                 : static const char *const rm100[] = {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", NULL};
     264                 : 
     265                 : /* ----------
     266                 :  * Ordinal postfixes
     267                 :  * ----------
     268                 :  */
     269                 : static const char *const numTH[] = {"ST", "ND", "RD", "TH", NULL};
     270                 : static const char *const numth[] = {"st", "nd", "rd", "th", NULL};
     271                 : 
     272                 : /* ----------
     273                 :  * Flags & Options:
     274                 :  * ----------
     275                 :  */
     276                 : #define TH_UPPER        1
     277                 : #define TH_LOWER        2
     278                 : 
     279                 : /* ----------
     280                 :  * Number description struct
     281                 :  * ----------
     282                 :  */
     283                 : typedef struct
     284                 : {
     285                 :     int         pre,            /* (count) numbers before decimal */
     286                 :                 post,           /* (count) numbers after decimal  */
     287                 :                 lsign,          /* want locales sign          */
     288                 :                 flag,           /* number parameters          */
     289                 :                 pre_lsign_num,  /* tmp value for lsign        */
     290                 :                 multi,          /* multiplier for 'V'         */
     291                 :                 zero_start,     /* position of first zero     */
     292                 :                 zero_end,       /* position of last zero      */
     293                 :                 need_locale;    /* needs it locale        */
     294                 : } NUMDesc;
     295                 : 
     296                 : /* ----------
     297                 :  * Flags for NUMBER version
     298                 :  * ----------
     299                 :  */
     300                 : #define NUM_F_DECIMAL       (1 << 1)
     301                 : #define NUM_F_LDECIMAL      (1 << 2)
     302                 : #define NUM_F_ZERO          (1 << 3)
     303                 : #define NUM_F_BLANK         (1 << 4)
     304                 : #define NUM_F_FILLMODE      (1 << 5)
     305                 : #define NUM_F_LSIGN         (1 << 6)
     306                 : #define NUM_F_BRACKET       (1 << 7)
     307                 : #define NUM_F_MINUS         (1 << 8)
     308                 : #define NUM_F_PLUS          (1 << 9)
     309                 : #define NUM_F_ROMAN         (1 << 10)
     310                 : #define NUM_F_MULTI         (1 << 11)
     311                 : #define NUM_F_PLUS_POST     (1 << 12)
     312                 : #define NUM_F_MINUS_POST    (1 << 13)
     313                 : #define NUM_F_EEEE          (1 << 14)
     314                 : 
     315                 : #define NUM_LSIGN_PRE   (-1)
     316                 : #define NUM_LSIGN_POST  1
     317                 : #define NUM_LSIGN_NONE  0
     318                 : 
     319                 : /* ----------
     320                 :  * Tests
     321                 :  * ----------
     322                 :  */
     323                 : #define IS_DECIMAL(_f)  ((_f)->flag & NUM_F_DECIMAL)
     324                 : #define IS_LDECIMAL(_f) ((_f)->flag & NUM_F_LDECIMAL)
     325                 : #define IS_ZERO(_f) ((_f)->flag & NUM_F_ZERO)
     326                 : #define IS_BLANK(_f)    ((_f)->flag & NUM_F_BLANK)
     327                 : #define IS_FILLMODE(_f) ((_f)->flag & NUM_F_FILLMODE)
     328                 : #define IS_BRACKET(_f)  ((_f)->flag & NUM_F_BRACKET)
     329                 : #define IS_MINUS(_f)    ((_f)->flag & NUM_F_MINUS)
     330                 : #define IS_LSIGN(_f)    ((_f)->flag & NUM_F_LSIGN)
     331                 : #define IS_PLUS(_f) ((_f)->flag & NUM_F_PLUS)
     332                 : #define IS_ROMAN(_f)    ((_f)->flag & NUM_F_ROMAN)
     333                 : #define IS_MULTI(_f)    ((_f)->flag & NUM_F_MULTI)
     334                 : #define IS_EEEE(_f)     ((_f)->flag & NUM_F_EEEE)
     335                 : 
     336                 : /* ----------
     337                 :  * Format picture cache
     338                 :  *
     339                 :  * We will cache datetime format pictures up to DCH_CACHE_SIZE bytes long;
     340                 :  * likewise number format pictures up to NUM_CACHE_SIZE bytes long.
     341                 :  *
     342                 :  * For simplicity, the cache entries are fixed-size, so they allow for the
     343                 :  * worst case of a FormatNode for each byte in the picture string.
     344                 :  *
     345                 :  * The CACHE_SIZE constants are computed to make sizeof(DCHCacheEntry) and
     346                 :  * sizeof(NUMCacheEntry) be powers of 2, or just less than that, so that
     347                 :  * we don't waste too much space by palloc'ing them individually.  Be sure
     348                 :  * to adjust those macros if you add fields to those structs.
     349                 :  *
     350                 :  * The max number of entries in each cache is DCH_CACHE_ENTRIES
     351                 :  * resp. NUM_CACHE_ENTRIES.
     352                 :  * ----------
     353                 :  */
     354                 : #define DCH_CACHE_OVERHEAD \
     355                 :     MAXALIGN(sizeof(bool) + sizeof(int))
     356                 : #define NUM_CACHE_OVERHEAD \
     357                 :     MAXALIGN(sizeof(bool) + sizeof(int) + sizeof(NUMDesc))
     358                 : 
     359                 : #define DCH_CACHE_SIZE \
     360                 :     ((2048 - DCH_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
     361                 : #define NUM_CACHE_SIZE \
     362                 :     ((1024 - NUM_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
     363                 : 
     364                 : #define DCH_CACHE_ENTRIES   20
     365                 : #define NUM_CACHE_ENTRIES   20
     366                 : 
     367                 : typedef struct
     368                 : {
     369                 :     FormatNode  format[DCH_CACHE_SIZE + 1];
     370                 :     char        str[DCH_CACHE_SIZE + 1];
     371                 :     bool        std;
     372                 :     bool        valid;
     373                 :     int         age;
     374                 : } DCHCacheEntry;
     375                 : 
     376                 : typedef struct
     377                 : {
     378                 :     FormatNode  format[NUM_CACHE_SIZE + 1];
     379                 :     char        str[NUM_CACHE_SIZE + 1];
     380                 :     bool        valid;
     381                 :     int         age;
     382                 :     NUMDesc     Num;
     383                 : } NUMCacheEntry;
     384                 : 
     385                 : /* global cache for date/time format pictures */
     386                 : static DCHCacheEntry *DCHCache[DCH_CACHE_ENTRIES];
     387                 : static int  n_DCHCache = 0;     /* current number of entries */
     388                 : static int  DCHCounter = 0;     /* aging-event counter */
     389                 : 
     390                 : /* global cache for number format pictures */
     391                 : static NUMCacheEntry *NUMCache[NUM_CACHE_ENTRIES];
     392                 : static int  n_NUMCache = 0;     /* current number of entries */
     393                 : static int  NUMCounter = 0;     /* aging-event counter */
     394                 : 
     395                 : /* ----------
     396                 :  * For char->date/time conversion
     397                 :  * ----------
     398                 :  */
     399                 : typedef struct
     400                 : {
     401                 :     FromCharDateMode mode;
     402                 :     int         hh,
     403                 :                 pm,
     404                 :                 mi,
     405                 :                 ss,
     406                 :                 ssss,
     407                 :                 d,              /* stored as 1-7, Sunday = 1, 0 means missing */
     408                 :                 dd,
     409                 :                 ddd,
     410                 :                 mm,
     411                 :                 ms,
     412                 :                 year,
     413                 :                 bc,
     414                 :                 ww,
     415                 :                 w,
     416                 :                 cc,
     417                 :                 j,
     418                 :                 us,
     419                 :                 yysz,           /* is it YY or YYYY ? */
     420                 :                 clock,          /* 12 or 24 hour clock? */
     421                 :                 tzsign,         /* +1, -1 or 0 if timezone info is absent */
     422                 :                 tzh,
     423                 :                 tzm,
     424                 :                 ff;             /* fractional precision */
     425                 : } TmFromChar;
     426                 : 
     427                 : #define ZERO_tmfc(_X) memset(_X, 0, sizeof(TmFromChar))
     428                 : 
     429                 : /* ----------
     430                 :  * Debug
     431                 :  * ----------
     432                 :  */
     433                 : #ifdef DEBUG_TO_FROM_CHAR
     434                 : #define DEBUG_TMFC(_X) \
     435                 :         elog(DEBUG_elog_output, "TMFC:\nmode %d\nhh %d\npm %d\nmi %d\nss %d\nssss %d\nd %d\ndd %d\nddd %d\nmm %d\nms: %d\nyear %d\nbc %d\nww %d\nw %d\ncc %d\nj %d\nus: %d\nyysz: %d\nclock: %d", \
     436                 :             (_X)->mode, (_X)->hh, (_X)->pm, (_X)->mi, (_X)->ss, (_X)->ssss, \
     437                 :             (_X)->d, (_X)->dd, (_X)->ddd, (_X)->mm, (_X)->ms, (_X)->year, \
     438                 :             (_X)->bc, (_X)->ww, (_X)->w, (_X)->cc, (_X)->j, (_X)->us, \
     439                 :             (_X)->yysz, (_X)->clock)
     440                 : #define DEBUG_TM(_X) \
     441                 :         elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\
     442                 :             (_X)->tm_sec, (_X)->tm_year,\
     443                 :             (_X)->tm_min, (_X)->tm_wday, (_X)->tm_hour, (_X)->tm_yday,\
     444                 :             (_X)->tm_mday, (_X)->tm_isdst, (_X)->tm_mon)
     445                 : #else
     446                 : #define DEBUG_TMFC(_X)
     447                 : #define DEBUG_TM(_X)
     448                 : #endif
     449                 : 
     450                 : /* ----------
     451                 :  * Datetime to char conversion
     452                 :  *
     453                 :  * To support intervals as well as timestamps, we use a custom "tm" struct
     454                 :  * that is almost like struct pg_tm, but has a 64-bit tm_hour field.
     455                 :  * We omit the tm_isdst and tm_zone fields, which are not used here.
     456                 :  * ----------
     457                 :  */
     458                 : struct fmt_tm
     459                 : {
     460                 :     int         tm_sec;
     461                 :     int         tm_min;
     462                 :     int64       tm_hour;
     463                 :     int         tm_mday;
     464                 :     int         tm_mon;
     465                 :     int         tm_year;
     466                 :     int         tm_wday;
     467                 :     int         tm_yday;
     468                 :     long int    tm_gmtoff;
     469                 : };
     470                 : 
     471                 : typedef struct TmToChar
     472                 : {
     473                 :     struct fmt_tm tm;           /* almost the classic 'tm' struct */
     474                 :     fsec_t      fsec;           /* fractional seconds */
     475                 :     const char *tzn;            /* timezone */
     476                 : } TmToChar;
     477                 : 
     478                 : #define tmtcTm(_X)  (&(_X)->tm)
     479                 : #define tmtcTzn(_X) ((_X)->tzn)
     480                 : #define tmtcFsec(_X)    ((_X)->fsec)
     481                 : 
     482                 : /* Note: this is used to copy pg_tm to fmt_tm, so not quite a bitwise copy */
     483                 : #define COPY_tm(_DST, _SRC) \
     484                 : do {    \
     485                 :     (_DST)->tm_sec = (_SRC)->tm_sec; \
     486                 :     (_DST)->tm_min = (_SRC)->tm_min; \
     487                 :     (_DST)->tm_hour = (_SRC)->tm_hour; \
     488                 :     (_DST)->tm_mday = (_SRC)->tm_mday; \
     489                 :     (_DST)->tm_mon = (_SRC)->tm_mon; \
     490                 :     (_DST)->tm_year = (_SRC)->tm_year; \
     491                 :     (_DST)->tm_wday = (_SRC)->tm_wday; \
     492                 :     (_DST)->tm_yday = (_SRC)->tm_yday; \
     493                 :     (_DST)->tm_gmtoff = (_SRC)->tm_gmtoff; \
     494                 : } while(0)
     495                 : 
     496                 : /* Caution: this is used to zero both pg_tm and fmt_tm structs */
     497                 : #define ZERO_tm(_X) \
     498                 : do {    \
     499                 :     memset(_X, 0, sizeof(*(_X))); \
     500                 :     (_X)->tm_mday = (_X)->tm_mon = 1; \
     501                 : } while(0)
     502                 : 
     503                 : #define ZERO_tmtc(_X) \
     504                 : do { \
     505                 :     ZERO_tm( tmtcTm(_X) ); \
     506                 :     tmtcFsec(_X) = 0; \
     507                 :     tmtcTzn(_X) = NULL; \
     508                 : } while(0)
     509                 : 
     510                 : /*
     511                 :  *  to_char(time) appears to to_char() as an interval, so this check
     512                 :  *  is really for interval and time data types.
     513                 :  */
     514                 : #define INVALID_FOR_INTERVAL  \
     515                 : do { \
     516                 :     if (is_interval) \
     517                 :         ereport(ERROR, \
     518                 :                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT), \
     519                 :                  errmsg("invalid format specification for an interval value"), \
     520                 :                  errhint("Intervals are not tied to specific calendar dates."))); \
     521                 : } while(0)
     522                 : 
     523                 : /*****************************************************************************
     524                 :  *          KeyWord definitions
     525                 :  *****************************************************************************/
     526                 : 
     527                 : /* ----------
     528                 :  * Suffixes (FormatNode.suffix is an OR of these codes)
     529                 :  * ----------
     530                 :  */
     531                 : #define DCH_S_FM    0x01
     532                 : #define DCH_S_TH    0x02
     533                 : #define DCH_S_th    0x04
     534                 : #define DCH_S_SP    0x08
     535                 : #define DCH_S_TM    0x10
     536                 : 
     537                 : /* ----------
     538                 :  * Suffix tests
     539                 :  * ----------
     540                 :  */
     541                 : #define S_THth(_s)  ((((_s) & DCH_S_TH) || ((_s) & DCH_S_th)) ? 1 : 0)
     542                 : #define S_TH(_s)    (((_s) & DCH_S_TH) ? 1 : 0)
     543                 : #define S_th(_s)    (((_s) & DCH_S_th) ? 1 : 0)
     544                 : #define S_TH_TYPE(_s)   (((_s) & DCH_S_TH) ? TH_UPPER : TH_LOWER)
     545                 : 
     546                 : /* Oracle toggles FM behavior, we don't; see docs. */
     547                 : #define S_FM(_s)    (((_s) & DCH_S_FM) ? 1 : 0)
     548                 : #define S_SP(_s)    (((_s) & DCH_S_SP) ? 1 : 0)
     549                 : #define S_TM(_s)    (((_s) & DCH_S_TM) ? 1 : 0)
     550                 : 
     551                 : /* ----------
     552                 :  * Suffixes definition for DATE-TIME TO/FROM CHAR
     553                 :  * ----------
     554                 :  */
     555                 : #define TM_SUFFIX_LEN   2
     556                 : 
     557                 : static const KeySuffix DCH_suff[] = {
     558                 :     {"FM", 2, DCH_S_FM, SUFFTYPE_PREFIX},
     559                 :     {"fm", 2, DCH_S_FM, SUFFTYPE_PREFIX},
     560                 :     {"TM", TM_SUFFIX_LEN, DCH_S_TM, SUFFTYPE_PREFIX},
     561                 :     {"tm", 2, DCH_S_TM, SUFFTYPE_PREFIX},
     562                 :     {"TH", 2, DCH_S_TH, SUFFTYPE_POSTFIX},
     563                 :     {"th", 2, DCH_S_th, SUFFTYPE_POSTFIX},
     564                 :     {"SP", 2, DCH_S_SP, SUFFTYPE_POSTFIX},
     565                 :     /* last */
     566                 :     {NULL, 0, 0, 0}
     567                 : };
     568                 : 
     569                 : 
     570                 : /* ----------
     571                 :  * Format-pictures (KeyWord).
     572                 :  *
     573                 :  * The KeyWord field; alphabetic sorted, *BUT* strings alike is sorted
     574                 :  *        complicated -to-> easy:
     575                 :  *
     576                 :  *  (example: "DDD","DD","Day","D" )
     577                 :  *
     578                 :  * (this specific sort needs the algorithm for sequential search for strings,
     579                 :  * which not has exact end; -> How keyword is in "HH12blabla" ? - "HH"
     580                 :  * or "HH12"? You must first try "HH12", because "HH" is in string, but
     581                 :  * it is not good.
     582                 :  *
     583                 :  * (!)
     584                 :  *   - Position for the keyword is similar as position in the enum DCH/NUM_poz.
     585                 :  * (!)
     586                 :  *
     587                 :  * For fast search is used the 'int index[]', index is ascii table from position
     588                 :  * 32 (' ') to 126 (~), in this index is DCH_ / NUM_ enums for each ASCII
     589                 :  * position or -1 if char is not used in the KeyWord. Search example for
     590                 :  * string "MM":
     591                 :  *  1)  see in index to index['M' - 32],
     592                 :  *  2)  take keywords position (enum DCH_MI) from index
     593                 :  *  3)  run sequential search in keywords[] from this position
     594                 :  *
     595                 :  * ----------
     596                 :  */
     597                 : 
     598                 : typedef enum
     599                 : {
     600                 :     DCH_A_D,
     601                 :     DCH_A_M,
     602                 :     DCH_AD,
     603                 :     DCH_AM,
     604                 :     DCH_B_C,
     605                 :     DCH_BC,
     606                 :     DCH_CC,
     607                 :     DCH_DAY,
     608                 :     DCH_DDD,
     609                 :     DCH_DD,
     610                 :     DCH_DY,
     611                 :     DCH_Day,
     612                 :     DCH_Dy,
     613                 :     DCH_D,
     614                 :     DCH_FF1,
     615                 :     DCH_FF2,
     616                 :     DCH_FF3,
     617                 :     DCH_FF4,
     618                 :     DCH_FF5,
     619                 :     DCH_FF6,
     620                 :     DCH_FX,                     /* global suffix */
     621                 :     DCH_HH24,
     622                 :     DCH_HH12,
     623                 :     DCH_HH,
     624                 :     DCH_IDDD,
     625                 :     DCH_ID,
     626                 :     DCH_IW,
     627                 :     DCH_IYYY,
     628                 :     DCH_IYY,
     629                 :     DCH_IY,
     630                 :     DCH_I,
     631                 :     DCH_J,
     632                 :     DCH_MI,
     633                 :     DCH_MM,
     634                 :     DCH_MONTH,
     635                 :     DCH_MON,
     636                 :     DCH_MS,
     637                 :     DCH_Month,
     638                 :     DCH_Mon,
     639                 :     DCH_OF,
     640                 :     DCH_P_M,
     641                 :     DCH_PM,
     642                 :     DCH_Q,
     643                 :     DCH_RM,
     644                 :     DCH_SSSSS,
     645                 :     DCH_SSSS,
     646                 :     DCH_SS,
     647                 :     DCH_TZH,
     648                 :     DCH_TZM,
     649                 :     DCH_TZ,
     650                 :     DCH_US,
     651                 :     DCH_WW,
     652                 :     DCH_W,
     653                 :     DCH_Y_YYY,
     654                 :     DCH_YYYY,
     655                 :     DCH_YYY,
     656                 :     DCH_YY,
     657                 :     DCH_Y,
     658                 :     DCH_a_d,
     659                 :     DCH_a_m,
     660                 :     DCH_ad,
     661                 :     DCH_am,
     662                 :     DCH_b_c,
     663                 :     DCH_bc,
     664                 :     DCH_cc,
     665                 :     DCH_day,
     666                 :     DCH_ddd,
     667                 :     DCH_dd,
     668                 :     DCH_dy,
     669                 :     DCH_d,
     670                 :     DCH_ff1,
     671                 :     DCH_ff2,
     672                 :     DCH_ff3,
     673                 :     DCH_ff4,
     674                 :     DCH_ff5,
     675                 :     DCH_ff6,
     676                 :     DCH_fx,
     677                 :     DCH_hh24,
     678                 :     DCH_hh12,
     679                 :     DCH_hh,
     680                 :     DCH_iddd,
     681                 :     DCH_id,
     682                 :     DCH_iw,
     683                 :     DCH_iyyy,
     684                 :     DCH_iyy,
     685                 :     DCH_iy,
     686                 :     DCH_i,
     687                 :     DCH_j,
     688                 :     DCH_mi,
     689                 :     DCH_mm,
     690                 :     DCH_month,
     691                 :     DCH_mon,
     692                 :     DCH_ms,
     693                 :     DCH_of,
     694                 :     DCH_p_m,
     695                 :     DCH_pm,
     696                 :     DCH_q,
     697                 :     DCH_rm,
     698                 :     DCH_sssss,
     699                 :     DCH_ssss,
     700                 :     DCH_ss,
     701                 :     DCH_tzh,
     702                 :     DCH_tzm,
     703                 :     DCH_tz,
     704                 :     DCH_us,
     705                 :     DCH_ww,
     706                 :     DCH_w,
     707                 :     DCH_y_yyy,
     708                 :     DCH_yyyy,
     709                 :     DCH_yyy,
     710                 :     DCH_yy,
     711                 :     DCH_y,
     712                 : 
     713                 :     /* last */
     714                 :     _DCH_last_
     715                 : }           DCH_poz;
     716                 : 
     717                 : typedef enum
     718                 : {
     719                 :     NUM_COMMA,
     720                 :     NUM_DEC,
     721                 :     NUM_0,
     722                 :     NUM_9,
     723                 :     NUM_B,
     724                 :     NUM_C,
     725                 :     NUM_D,
     726                 :     NUM_E,
     727                 :     NUM_FM,
     728                 :     NUM_G,
     729                 :     NUM_L,
     730                 :     NUM_MI,
     731                 :     NUM_PL,
     732                 :     NUM_PR,
     733                 :     NUM_RN,
     734                 :     NUM_SG,
     735                 :     NUM_SP,
     736                 :     NUM_S,
     737                 :     NUM_TH,
     738                 :     NUM_V,
     739                 :     NUM_b,
     740                 :     NUM_c,
     741                 :     NUM_d,
     742                 :     NUM_e,
     743                 :     NUM_fm,
     744                 :     NUM_g,
     745                 :     NUM_l,
     746                 :     NUM_mi,
     747                 :     NUM_pl,
     748                 :     NUM_pr,
     749                 :     NUM_rn,
     750                 :     NUM_sg,
     751                 :     NUM_sp,
     752                 :     NUM_s,
     753                 :     NUM_th,
     754                 :     NUM_v,
     755                 : 
     756                 :     /* last */
     757                 :     _NUM_last_
     758                 : }           NUM_poz;
     759                 : 
     760                 : /* ----------
     761                 :  * KeyWords for DATE-TIME version
     762                 :  * ----------
     763                 :  */
     764                 : static const KeyWord DCH_keywords[] = {
     765                 : /*  name, len, id, is_digit, date_mode */
     766                 :     {"A.D.", 4, DCH_A_D, false, FROM_CHAR_DATE_NONE}, /* A */
     767                 :     {"A.M.", 4, DCH_A_M, false, FROM_CHAR_DATE_NONE},
     768                 :     {"AD", 2, DCH_AD, false, FROM_CHAR_DATE_NONE},
     769                 :     {"AM", 2, DCH_AM, false, FROM_CHAR_DATE_NONE},
     770                 :     {"B.C.", 4, DCH_B_C, false, FROM_CHAR_DATE_NONE}, /* B */
     771                 :     {"BC", 2, DCH_BC, false, FROM_CHAR_DATE_NONE},
     772                 :     {"CC", 2, DCH_CC, true, FROM_CHAR_DATE_NONE}, /* C */
     773                 :     {"DAY", 3, DCH_DAY, false, FROM_CHAR_DATE_NONE},  /* D */
     774                 :     {"DDD", 3, DCH_DDD, true, FROM_CHAR_DATE_GREGORIAN},
     775                 :     {"DD", 2, DCH_DD, true, FROM_CHAR_DATE_GREGORIAN},
     776                 :     {"DY", 2, DCH_DY, false, FROM_CHAR_DATE_NONE},
     777                 :     {"Day", 3, DCH_Day, false, FROM_CHAR_DATE_NONE},
     778                 :     {"Dy", 2, DCH_Dy, false, FROM_CHAR_DATE_NONE},
     779                 :     {"D", 1, DCH_D, true, FROM_CHAR_DATE_GREGORIAN},
     780                 :     {"FF1", 3, DCH_FF1, false, FROM_CHAR_DATE_NONE},  /* F */
     781                 :     {"FF2", 3, DCH_FF2, false, FROM_CHAR_DATE_NONE},
     782                 :     {"FF3", 3, DCH_FF3, false, FROM_CHAR_DATE_NONE},
     783                 :     {"FF4", 3, DCH_FF4, false, FROM_CHAR_DATE_NONE},
     784                 :     {"FF5", 3, DCH_FF5, false, FROM_CHAR_DATE_NONE},
     785                 :     {"FF6", 3, DCH_FF6, false, FROM_CHAR_DATE_NONE},
     786                 :     {"FX", 2, DCH_FX, false, FROM_CHAR_DATE_NONE},
     787                 :     {"HH24", 4, DCH_HH24, true, FROM_CHAR_DATE_NONE}, /* H */
     788                 :     {"HH12", 4, DCH_HH12, true, FROM_CHAR_DATE_NONE},
     789                 :     {"HH", 2, DCH_HH, true, FROM_CHAR_DATE_NONE},
     790                 :     {"IDDD", 4, DCH_IDDD, true, FROM_CHAR_DATE_ISOWEEK},  /* I */
     791                 :     {"ID", 2, DCH_ID, true, FROM_CHAR_DATE_ISOWEEK},
     792                 :     {"IW", 2, DCH_IW, true, FROM_CHAR_DATE_ISOWEEK},
     793                 :     {"IYYY", 4, DCH_IYYY, true, FROM_CHAR_DATE_ISOWEEK},
     794                 :     {"IYY", 3, DCH_IYY, true, FROM_CHAR_DATE_ISOWEEK},
     795                 :     {"IY", 2, DCH_IY, true, FROM_CHAR_DATE_ISOWEEK},
     796                 :     {"I", 1, DCH_I, true, FROM_CHAR_DATE_ISOWEEK},
     797                 :     {"J", 1, DCH_J, true, FROM_CHAR_DATE_NONE}, /* J */
     798                 :     {"MI", 2, DCH_MI, true, FROM_CHAR_DATE_NONE}, /* M */
     799                 :     {"MM", 2, DCH_MM, true, FROM_CHAR_DATE_GREGORIAN},
     800                 :     {"MONTH", 5, DCH_MONTH, false, FROM_CHAR_DATE_GREGORIAN},
     801                 :     {"MON", 3, DCH_MON, false, FROM_CHAR_DATE_GREGORIAN},
     802                 :     {"MS", 2, DCH_MS, true, FROM_CHAR_DATE_NONE},
     803                 :     {"Month", 5, DCH_Month, false, FROM_CHAR_DATE_GREGORIAN},
     804                 :     {"Mon", 3, DCH_Mon, false, FROM_CHAR_DATE_GREGORIAN},
     805                 :     {"OF", 2, DCH_OF, false, FROM_CHAR_DATE_NONE},    /* O */
     806                 :     {"P.M.", 4, DCH_P_M, false, FROM_CHAR_DATE_NONE}, /* P */
     807                 :     {"PM", 2, DCH_PM, false, FROM_CHAR_DATE_NONE},
     808                 :     {"Q", 1, DCH_Q, true, FROM_CHAR_DATE_NONE}, /* Q */
     809                 :     {"RM", 2, DCH_RM, false, FROM_CHAR_DATE_GREGORIAN}, /* R */
     810                 :     {"SSSSS", 5, DCH_SSSS, true, FROM_CHAR_DATE_NONE},    /* S */
     811                 :     {"SSSS", 4, DCH_SSSS, true, FROM_CHAR_DATE_NONE},
     812                 :     {"SS", 2, DCH_SS, true, FROM_CHAR_DATE_NONE},
     813                 :     {"TZH", 3, DCH_TZH, false, FROM_CHAR_DATE_NONE},  /* T */
     814                 :     {"TZM", 3, DCH_TZM, true, FROM_CHAR_DATE_NONE},
     815                 :     {"TZ", 2, DCH_TZ, false, FROM_CHAR_DATE_NONE},
     816                 :     {"US", 2, DCH_US, true, FROM_CHAR_DATE_NONE}, /* U */
     817                 :     {"WW", 2, DCH_WW, true, FROM_CHAR_DATE_GREGORIAN},    /* W */
     818                 :     {"W", 1, DCH_W, true, FROM_CHAR_DATE_GREGORIAN},
     819                 :     {"Y,YYY", 5, DCH_Y_YYY, true, FROM_CHAR_DATE_GREGORIAN},  /* Y */
     820                 :     {"YYYY", 4, DCH_YYYY, true, FROM_CHAR_DATE_GREGORIAN},
     821                 :     {"YYY", 3, DCH_YYY, true, FROM_CHAR_DATE_GREGORIAN},
     822                 :     {"YY", 2, DCH_YY, true, FROM_CHAR_DATE_GREGORIAN},
     823                 :     {"Y", 1, DCH_Y, true, FROM_CHAR_DATE_GREGORIAN},
     824                 :     {"a.d.", 4, DCH_a_d, false, FROM_CHAR_DATE_NONE}, /* a */
     825                 :     {"a.m.", 4, DCH_a_m, false, FROM_CHAR_DATE_NONE},
     826                 :     {"ad", 2, DCH_ad, false, FROM_CHAR_DATE_NONE},
     827                 :     {"am", 2, DCH_am, false, FROM_CHAR_DATE_NONE},
     828                 :     {"b.c.", 4, DCH_b_c, false, FROM_CHAR_DATE_NONE}, /* b */
     829                 :     {"bc", 2, DCH_bc, false, FROM_CHAR_DATE_NONE},
     830                 :     {"cc", 2, DCH_CC, true, FROM_CHAR_DATE_NONE}, /* c */
     831                 :     {"day", 3, DCH_day, false, FROM_CHAR_DATE_NONE},  /* d */
     832                 :     {"ddd", 3, DCH_DDD, true, FROM_CHAR_DATE_GREGORIAN},
     833                 :     {"dd", 2, DCH_DD, true, FROM_CHAR_DATE_GREGORIAN},
     834                 :     {"dy", 2, DCH_dy, false, FROM_CHAR_DATE_NONE},
     835                 :     {"d", 1, DCH_D, true, FROM_CHAR_DATE_GREGORIAN},
     836                 :     {"ff1", 3, DCH_FF1, false, FROM_CHAR_DATE_NONE},  /* f */
     837                 :     {"ff2", 3, DCH_FF2, false, FROM_CHAR_DATE_NONE},
     838                 :     {"ff3", 3, DCH_FF3, false, FROM_CHAR_DATE_NONE},
     839                 :     {"ff4", 3, DCH_FF4, false, FROM_CHAR_DATE_NONE},
     840                 :     {"ff5", 3, DCH_FF5, false, FROM_CHAR_DATE_NONE},
     841                 :     {"ff6", 3, DCH_FF6, false, FROM_CHAR_DATE_NONE},
     842                 :     {"fx", 2, DCH_FX, false, FROM_CHAR_DATE_NONE},
     843                 :     {"hh24", 4, DCH_HH24, true, FROM_CHAR_DATE_NONE}, /* h */
     844                 :     {"hh12", 4, DCH_HH12, true, FROM_CHAR_DATE_NONE},
     845                 :     {"hh", 2, DCH_HH, true, FROM_CHAR_DATE_NONE},
     846                 :     {"iddd", 4, DCH_IDDD, true, FROM_CHAR_DATE_ISOWEEK},  /* i */
     847                 :     {"id", 2, DCH_ID, true, FROM_CHAR_DATE_ISOWEEK},
     848                 :     {"iw", 2, DCH_IW, true, FROM_CHAR_DATE_ISOWEEK},
     849                 :     {"iyyy", 4, DCH_IYYY, true, FROM_CHAR_DATE_ISOWEEK},
     850                 :     {"iyy", 3, DCH_IYY, true, FROM_CHAR_DATE_ISOWEEK},
     851                 :     {"iy", 2, DCH_IY, true, FROM_CHAR_DATE_ISOWEEK},
     852                 :     {"i", 1, DCH_I, true, FROM_CHAR_DATE_ISOWEEK},
     853                 :     {"j", 1, DCH_J, true, FROM_CHAR_DATE_NONE}, /* j */
     854                 :     {"mi", 2, DCH_MI, true, FROM_CHAR_DATE_NONE}, /* m */
     855                 :     {"mm", 2, DCH_MM, true, FROM_CHAR_DATE_GREGORIAN},
     856                 :     {"month", 5, DCH_month, false, FROM_CHAR_DATE_GREGORIAN},
     857                 :     {"mon", 3, DCH_mon, false, FROM_CHAR_DATE_GREGORIAN},
     858                 :     {"ms", 2, DCH_MS, true, FROM_CHAR_DATE_NONE},
     859                 :     {"of", 2, DCH_OF, false, FROM_CHAR_DATE_NONE},    /* o */
     860                 :     {"p.m.", 4, DCH_p_m, false, FROM_CHAR_DATE_NONE}, /* p */
     861                 :     {"pm", 2, DCH_pm, false, FROM_CHAR_DATE_NONE},
     862                 :     {"q", 1, DCH_Q, true, FROM_CHAR_DATE_NONE}, /* q */
     863                 :     {"rm", 2, DCH_rm, false, FROM_CHAR_DATE_GREGORIAN}, /* r */
     864                 :     {"sssss", 5, DCH_SSSS, true, FROM_CHAR_DATE_NONE},    /* s */
     865                 :     {"ssss", 4, DCH_SSSS, true, FROM_CHAR_DATE_NONE},
     866                 :     {"ss", 2, DCH_SS, true, FROM_CHAR_DATE_NONE},
     867                 :     {"tzh", 3, DCH_TZH, false, FROM_CHAR_DATE_NONE},  /* t */
     868                 :     {"tzm", 3, DCH_TZM, true, FROM_CHAR_DATE_NONE},
     869                 :     {"tz", 2, DCH_tz, false, FROM_CHAR_DATE_NONE},
     870                 :     {"us", 2, DCH_US, true, FROM_CHAR_DATE_NONE}, /* u */
     871                 :     {"ww", 2, DCH_WW, true, FROM_CHAR_DATE_GREGORIAN},    /* w */
     872                 :     {"w", 1, DCH_W, true, FROM_CHAR_DATE_GREGORIAN},
     873                 :     {"y,yyy", 5, DCH_Y_YYY, true, FROM_CHAR_DATE_GREGORIAN},  /* y */
     874                 :     {"yyyy", 4, DCH_YYYY, true, FROM_CHAR_DATE_GREGORIAN},
     875                 :     {"yyy", 3, DCH_YYY, true, FROM_CHAR_DATE_GREGORIAN},
     876                 :     {"yy", 2, DCH_YY, true, FROM_CHAR_DATE_GREGORIAN},
     877                 :     {"y", 1, DCH_Y, true, FROM_CHAR_DATE_GREGORIAN},
     878                 : 
     879                 :     /* last */
     880                 :     {NULL, 0, 0, 0, 0}
     881                 : };
     882                 : 
     883                 : /* ----------
     884                 :  * KeyWords for NUMBER version
     885                 :  *
     886                 :  * The is_digit and date_mode fields are not relevant here.
     887                 :  * ----------
     888                 :  */
     889                 : static const KeyWord NUM_keywords[] = {
     890                 : /*  name, len, id           is in Index */
     891                 :     {",", 1, NUM_COMMA},      /* , */
     892                 :     {".", 1, NUM_DEC},            /* . */
     893                 :     {"0", 1, NUM_0},          /* 0 */
     894                 :     {"9", 1, NUM_9},          /* 9 */
     895                 :     {"B", 1, NUM_B},          /* B */
     896                 :     {"C", 1, NUM_C},          /* C */
     897                 :     {"D", 1, NUM_D},          /* D */
     898                 :     {"EEEE", 4, NUM_E},           /* E */
     899                 :     {"FM", 2, NUM_FM},            /* F */
     900                 :     {"G", 1, NUM_G},          /* G */
     901                 :     {"L", 1, NUM_L},          /* L */
     902                 :     {"MI", 2, NUM_MI},            /* M */
     903                 :     {"PL", 2, NUM_PL},            /* P */
     904                 :     {"PR", 2, NUM_PR},
     905                 :     {"RN", 2, NUM_RN},            /* R */
     906                 :     {"SG", 2, NUM_SG},            /* S */
     907                 :     {"SP", 2, NUM_SP},
     908                 :     {"S", 1, NUM_S},
     909                 :     {"TH", 2, NUM_TH},            /* T */
     910                 :     {"V", 1, NUM_V},          /* V */
     911                 :     {"b", 1, NUM_B},          /* b */
     912                 :     {"c", 1, NUM_C},          /* c */
     913                 :     {"d", 1, NUM_D},          /* d */
     914                 :     {"eeee", 4, NUM_E},           /* e */
     915                 :     {"fm", 2, NUM_FM},            /* f */
     916                 :     {"g", 1, NUM_G},          /* g */
     917                 :     {"l", 1, NUM_L},          /* l */
     918                 :     {"mi", 2, NUM_MI},            /* m */
     919                 :     {"pl", 2, NUM_PL},            /* p */
     920                 :     {"pr", 2, NUM_PR},
     921                 :     {"rn", 2, NUM_rn},            /* r */
     922                 :     {"sg", 2, NUM_SG},            /* s */
     923                 :     {"sp", 2, NUM_SP},
     924                 :     {"s", 1, NUM_S},
     925                 :     {"th", 2, NUM_th},            /* t */
     926                 :     {"v", 1, NUM_V},          /* v */
     927                 : 
     928                 :     /* last */
     929                 :     {NULL, 0, 0}
     930                 : };
     931                 : 
     932                 : 
     933                 : /* ----------
     934                 :  * KeyWords index for DATE-TIME version
     935                 :  * ----------
     936                 :  */
     937                 : static const int DCH_index[KeyWord_INDEX_SIZE] = {
     938                 : /*
     939                 : 0   1   2   3   4   5   6   7   8   9
     940                 : */
     941                 :     /*---- first 0..31 chars are skipped ----*/
     942                 : 
     943                 :     -1, -1, -1, -1, -1, -1, -1, -1,
     944                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     945                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     946                 :     -1, -1, -1, -1, -1, DCH_A_D, DCH_B_C, DCH_CC, DCH_DAY, -1,
     947                 :     DCH_FF1, -1, DCH_HH24, DCH_IDDD, DCH_J, -1, -1, DCH_MI, -1, DCH_OF,
     948                 :     DCH_P_M, DCH_Q, DCH_RM, DCH_SSSSS, DCH_TZH, DCH_US, -1, DCH_WW, -1, DCH_Y_YYY,
     949                 :     -1, -1, -1, -1, -1, -1, -1, DCH_a_d, DCH_b_c, DCH_cc,
     950                 :     DCH_day, -1, DCH_ff1, -1, DCH_hh24, DCH_iddd, DCH_j, -1, -1, DCH_mi,
     951                 :     -1, DCH_of, DCH_p_m, DCH_q, DCH_rm, DCH_sssss, DCH_tzh, DCH_us, -1, DCH_ww,
     952                 :     -1, DCH_y_yyy, -1, -1, -1, -1
     953                 : 
     954                 :     /*---- chars over 126 are skipped ----*/
     955                 : };
     956                 : 
     957                 : /* ----------
     958                 :  * KeyWords index for NUMBER version
     959                 :  * ----------
     960                 :  */
     961                 : static const int NUM_index[KeyWord_INDEX_SIZE] = {
     962                 : /*
     963                 : 0   1   2   3   4   5   6   7   8   9
     964                 : */
     965                 :     /*---- first 0..31 chars are skipped ----*/
     966                 : 
     967                 :     -1, -1, -1, -1, -1, -1, -1, -1,
     968                 :     -1, -1, -1, -1, NUM_COMMA, -1, NUM_DEC, -1, NUM_0, -1,
     969                 :     -1, -1, -1, -1, -1, -1, -1, NUM_9, -1, -1,
     970                 :     -1, -1, -1, -1, -1, -1, NUM_B, NUM_C, NUM_D, NUM_E,
     971                 :     NUM_FM, NUM_G, -1, -1, -1, -1, NUM_L, NUM_MI, -1, -1,
     972                 :     NUM_PL, -1, NUM_RN, NUM_SG, NUM_TH, -1, NUM_V, -1, -1, -1,
     973                 :     -1, -1, -1, -1, -1, -1, -1, -1, NUM_b, NUM_c,
     974                 :     NUM_d, NUM_e, NUM_fm, NUM_g, -1, -1, -1, -1, NUM_l, NUM_mi,
     975                 :     -1, -1, NUM_pl, -1, NUM_rn, NUM_sg, NUM_th, -1, NUM_v, -1,
     976                 :     -1, -1, -1, -1, -1, -1
     977                 : 
     978                 :     /*---- chars over 126 are skipped ----*/
     979                 : };
     980                 : 
     981                 : /* ----------
     982                 :  * Number processor struct
     983                 :  * ----------
     984                 :  */
     985                 : typedef struct NUMProc
     986                 : {
     987                 :     bool        is_to_char;
     988                 :     NUMDesc    *Num;            /* number description       */
     989                 : 
     990                 :     int         sign,           /* '-' or '+'           */
     991                 :                 sign_wrote,     /* was sign write       */
     992                 :                 num_count,      /* number of write digits   */
     993                 :                 num_in,         /* is inside number     */
     994                 :                 num_curr,       /* current position in number   */
     995                 :                 out_pre_spaces, /* spaces before first digit    */
     996                 : 
     997                 :                 read_dec,       /* to_number - was read dec. point  */
     998                 :                 read_post,      /* to_number - number of dec. digit */
     999                 :                 read_pre;       /* to_number - number non-dec. digit */
    1000                 : 
    1001                 :     char       *number,         /* string with number   */
    1002                 :                *number_p,       /* pointer to current number position */
    1003                 :                *inout,          /* in / out buffer  */
    1004                 :                *inout_p,        /* pointer to current inout position */
    1005                 :                *last_relevant,  /* last relevant number after decimal point */
    1006                 : 
    1007                 :                *L_negative_sign,    /* Locale */
    1008                 :                *L_positive_sign,
    1009                 :                *decimal,
    1010                 :                *L_thousands_sep,
    1011                 :                *L_currency_symbol;
    1012                 : } NUMProc;
    1013                 : 
    1014                 : /* Return flags for DCH_from_char() */
    1015                 : #define DCH_DATED   0x01
    1016                 : #define DCH_TIMED   0x02
    1017                 : #define DCH_ZONED   0x04
    1018                 : 
    1019                 : /* ----------
    1020                 :  * Functions
    1021                 :  * ----------
    1022                 :  */
    1023                 : static const KeyWord *index_seq_search(const char *str, const KeyWord *kw,
    1024                 :                                        const int *index);
    1025                 : static const KeySuffix *suff_search(const char *str, const KeySuffix *suf, int type);
    1026                 : static bool is_separator_char(const char *str);
    1027                 : static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);
    1028                 : static void parse_format(FormatNode *node, const char *str, const KeyWord *kw,
    1029                 :                          const KeySuffix *suf, const int *index, uint32 flags, NUMDesc *Num);
    1030                 : 
    1031                 : static void DCH_to_char(FormatNode *node, bool is_interval,
    1032                 :                         TmToChar *in, char *out, Oid collid);
    1033                 : static void DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
    1034                 :                           Oid collid, bool std, Node *escontext);
    1035                 : 
    1036                 : #ifdef DEBUG_TO_FROM_CHAR
    1037                 : static void dump_index(const KeyWord *k, const int *index);
    1038                 : static void dump_node(FormatNode *node, int max);
    1039                 : #endif
    1040                 : 
    1041                 : static const char *get_th(char *num, int type);
    1042                 : static char *str_numth(char *dest, char *num, int type);
    1043                 : static int  adjust_partial_year_to_2020(int year);
    1044                 : static int  strspace_len(const char *str);
    1045                 : static bool from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode,
    1046                 :                                Node *escontext);
    1047                 : static bool from_char_set_int(int *dest, const int value, const FormatNode *node,
    1048                 :                               Node *escontext);
    1049                 : static int  from_char_parse_int_len(int *dest, const char **src, const int len,
    1050                 :                                     FormatNode *node, Node *escontext);
    1051 ECB             : static int  from_char_parse_int(int *dest, const char **src, FormatNode *node,
    1052                 :                                 Node *escontext);
    1053                 : static int  seq_search_ascii(const char *name, const char *const *array, int *len);
    1054                 : static int  seq_search_localized(const char *name, char **array, int *len,
    1055                 :                                  Oid collid);
    1056                 : static bool from_char_seq_search(int *dest, const char **src,
    1057                 :                                  const char *const *array,
    1058                 :                                  char **localized_array, Oid collid,
    1059                 :                                  FormatNode *node, Node *escontext);
    1060                 : static bool do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
    1061                 :                             struct pg_tm *tm, fsec_t *fsec, int *fprec,
    1062                 :                             uint32 *flags, Node *escontext);
    1063 EUB             : static char *fill_str(char *str, int c, int max);
    1064 ECB             : static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree);
    1065                 : static char *int_to_roman(int number);
    1066                 : static void NUM_prepare_locale(NUMProc *Np);
    1067                 : static char *get_last_relevant_decnum(char *num);
    1068                 : static void NUM_numpart_from_char(NUMProc *Np, int id, int input_len);
    1069                 : static void NUM_numpart_to_char(NUMProc *Np, int id);
    1070                 : static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
    1071                 :                            char *number, int input_len, int to_char_out_pre_spaces,
    1072                 :                            int sign, bool is_to_char, Oid collid);
    1073                 : static DCHCacheEntry *DCH_cache_getnew(const char *str, bool std);
    1074                 : static DCHCacheEntry *DCH_cache_search(const char *str, bool std);
    1075                 : static DCHCacheEntry *DCH_cache_fetch(const char *str, bool std);
    1076                 : static NUMCacheEntry *NUM_cache_getnew(const char *str);
    1077                 : static NUMCacheEntry *NUM_cache_search(const char *str);
    1078                 : static NUMCacheEntry *NUM_cache_fetch(const char *str);
    1079                 : 
    1080                 : 
    1081                 : /* ----------
    1082                 :  * Fast sequential search, use index for data selection which
    1083                 :  * go to seq. cycle (it is very fast for unwanted strings)
    1084                 :  * (can't be used binary search in format parsing)
    1085                 :  * ----------
    1086                 :  */
    1087                 : static const KeyWord *
    1088 GIC       13155 : index_seq_search(const char *str, const KeyWord *kw, const int *index)
    1089 ECB             : {
    1090                 :     int         poz;
    1091                 : 
    1092 CBC       13155 :     if (!KeyWord_INDEX_FILTER(*str))
    1093 GIC        3269 :         return NULL;
    1094                 : 
    1095            9886 :     if ((poz = *(index + (*str - ' '))) > -1)
    1096                 :     {
    1097            8943 :         const KeyWord *k = kw + poz;
    1098                 : 
    1099                 :         do
    1100 ECB             :         {
    1101 GIC       12090 :             if (strncmp(str, k->name, k->len) == 0)
    1102 CBC        8886 :                 return k;
    1103 GBC        3204 :             k++;
    1104 GIC        3204 :             if (!k->name)
    1105 LBC           0 :                 return NULL;
    1106 GBC        3204 :         } while (*str == *k->name);
    1107                 :     }
    1108 GIC        1000 :     return NULL;
    1109                 : }
    1110 ECB             : 
    1111                 : static const KeySuffix *
    1112 CBC        5124 : suff_search(const char *str, const KeySuffix *suf, int type)
    1113 ECB             : {
    1114 EUB             :     const KeySuffix *s;
    1115                 : 
    1116 GIC       39528 :     for (s = suf; s->name != NULL; s++)
    1117 ECB             :     {
    1118 GIC       34629 :         if (s->type != type)
    1119 GBC       16314 :             continue;
    1120 EUB             : 
    1121 GIC       18315 :         if (strncmp(str, s->name, s->len) == 0)
    1122 CBC         225 :             return s;
    1123 ECB             :     }
    1124 GIC        4899 :     return NULL;
    1125 ECB             : }
    1126                 : 
    1127                 : static bool
    1128 CBC        3000 : is_separator_char(const char *str)
    1129 ECB             : {
    1130 EUB             :     /* ASCII printable character, but not letter or digit */
    1131 GIC        2179 :     return (*str > 0x20 && *str < 0x7F &&
    1132            2179 :             !(*str >= 'A' && *str <= 'Z') &&
    1133 CBC        7232 :             !(*str >= 'a' && *str <= 'z') &&
    1134 GIC        2053 :             !(*str >= '0' && *str <= '9'));
    1135 ECB             : }
    1136                 : 
    1137                 : /* ----------
    1138                 :  * Prepare NUMDesc (number description struct) via FormatNode struct
    1139                 :  * ----------
    1140                 :  */
    1141                 : static void
    1142 GIC        6945 : NUMDesc_prepare(NUMDesc *num, FormatNode *n)
    1143 ECB             : {
    1144 CBC        6945 :     if (n->type != NODE_TYPE_ACTION)
    1145 UIC           0 :         return;
    1146 EUB             : 
    1147 GBC        6945 :     if (IS_EEEE(num) && n->key->id != NUM_E)
    1148 UBC           0 :         ereport(ERROR,
    1149 EUB             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    1150                 :                  errmsg("\"EEEE\" must be the last pattern used")));
    1151 ECB             : 
    1152 CBC        6945 :     switch (n->key->id)
    1153 ECB             :     {
    1154 GIC        6051 :         case NUM_9:
    1155 CBC        6051 :             if (IS_BRACKET(num))
    1156 LBC           0 :                 ereport(ERROR,
    1157 EUB             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1158                 :                          errmsg("\"9\" must be ahead of \"PR\"")));
    1159 GIC        6051 :             if (IS_MULTI(num))
    1160 ECB             :             {
    1161 UBC           0 :                 ++num->multi;
    1162 UIC           0 :                 break;
    1163                 :             }
    1164 CBC        6051 :             if (IS_DECIMAL(num))
    1165            2038 :                 ++num->post;
    1166                 :             else
    1167            4013 :                 ++num->pre;
    1168            6051 :             break;
    1169 ECB             : 
    1170 GIC         260 :         case NUM_0:
    1171 CBC         260 :             if (IS_BRACKET(num))
    1172 LBC           0 :                 ereport(ERROR,
    1173 EUB             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1174                 :                          errmsg("\"0\" must be ahead of \"PR\"")));
    1175 GIC         260 :             if (!IS_ZERO(num) && !IS_DECIMAL(num))
    1176 ECB             :             {
    1177 GBC          55 :                 num->flag |= NUM_F_ZERO;
    1178 GIC          55 :                 num->zero_start = num->pre + 1;
    1179                 :             }
    1180 CBC         260 :             if (!IS_DECIMAL(num))
    1181 GIC         176 :                 ++num->pre;
    1182 ECB             :             else
    1183 CBC          84 :                 ++num->post;
    1184 ECB             : 
    1185 CBC         260 :             num->zero_end = num->pre + num->post;
    1186 GIC         260 :             break;
    1187 ECB             : 
    1188 UIC           0 :         case NUM_B:
    1189 LBC           0 :             if (num->pre == 0 && num->post == 0 && (!IS_ZERO(num)))
    1190               0 :                 num->flag |= NUM_F_BLANK;
    1191               0 :             break;
    1192                 : 
    1193 CBC          18 :         case NUM_D:
    1194 GIC          18 :             num->flag |= NUM_F_LDECIMAL;
    1195 CBC          18 :             num->need_locale = true;
    1196 ECB             :             /* FALLTHROUGH */
    1197 GBC         198 :         case NUM_DEC:
    1198 GIC         198 :             if (IS_DECIMAL(num))
    1199 UIC           0 :                 ereport(ERROR,
    1200 ECB             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1201                 :                          errmsg("multiple decimal points")));
    1202 CBC         198 :             if (IS_MULTI(num))
    1203 LBC           0 :                 ereport(ERROR,
    1204                 :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1205 EUB             :                          errmsg("cannot use \"V\" and decimal point together")));
    1206 GBC         198 :             num->flag |= NUM_F_DECIMAL;
    1207             198 :             break;
    1208                 : 
    1209 GIC         121 :         case NUM_FM:
    1210 GBC         121 :             num->flag |= NUM_F_FILLMODE;
    1211             121 :             break;
    1212 EUB             : 
    1213 GBC         101 :         case NUM_S:
    1214 GIC         101 :             if (IS_LSIGN(num))
    1215 LBC           0 :                 ereport(ERROR,
    1216 ECB             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1217 EUB             :                          errmsg("cannot use \"S\" twice")));
    1218 GIC         101 :             if (IS_PLUS(num) || IS_MINUS(num) || IS_BRACKET(num))
    1219 UIC           0 :                 ereport(ERROR,
    1220 ECB             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1221                 :                          errmsg("cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together")));
    1222 CBC         101 :             if (!IS_DECIMAL(num))
    1223                 :             {
    1224              84 :                 num->lsign = NUM_LSIGN_PRE;
    1225              84 :                 num->pre_lsign_num = num->pre;
    1226 GBC          84 :                 num->need_locale = true;
    1227 GIC          84 :                 num->flag |= NUM_F_LSIGN;
    1228                 :             }
    1229 CBC          17 :             else if (num->lsign == NUM_LSIGN_NONE)
    1230 ECB             :             {
    1231 GIC          17 :                 num->lsign = NUM_LSIGN_POST;
    1232 GBC          17 :                 num->need_locale = true;
    1233 GIC          17 :                 num->flag |= NUM_F_LSIGN;
    1234 EUB             :             }
    1235 GBC         101 :             break;
    1236                 : 
    1237 CBC          15 :         case NUM_MI:
    1238 GIC          15 :             if (IS_LSIGN(num))
    1239 LBC           0 :                 ereport(ERROR,
    1240 ECB             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1241                 :                          errmsg("cannot use \"S\" and \"MI\" together")));
    1242 GBC          15 :             num->flag |= NUM_F_MINUS;
    1243              15 :             if (IS_DECIMAL(num))
    1244               3 :                 num->flag |= NUM_F_MINUS_POST;
    1245 GIC          15 :             break;
    1246                 : 
    1247 UBC           0 :         case NUM_PL:
    1248               0 :             if (IS_LSIGN(num))
    1249 UIC           0 :                 ereport(ERROR,
    1250 ECB             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1251                 :                          errmsg("cannot use \"S\" and \"PL\" together")));
    1252 UBC           0 :             num->flag |= NUM_F_PLUS;
    1253 UIC           0 :             if (IS_DECIMAL(num))
    1254               0 :                 num->flag |= NUM_F_PLUS_POST;
    1255 LBC           0 :             break;
    1256 ECB             : 
    1257 CBC          12 :         case NUM_SG:
    1258 GBC          12 :             if (IS_LSIGN(num))
    1259 UIC           0 :                 ereport(ERROR,
    1260                 :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1261                 :                          errmsg("cannot use \"S\" and \"SG\" together")));
    1262 CBC          12 :             num->flag |= NUM_F_MINUS;
    1263              12 :             num->flag |= NUM_F_PLUS;
    1264 GIC          12 :             break;
    1265                 : 
    1266              18 :         case NUM_PR:
    1267              18 :             if (IS_LSIGN(num) || IS_PLUS(num) || IS_MINUS(num))
    1268 UIC           0 :                 ereport(ERROR,
    1269                 :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1270                 :                          errmsg("cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together")));
    1271 GIC          18 :             num->flag |= NUM_F_BRACKET;
    1272              18 :             break;
    1273                 : 
    1274 UIC           0 :         case NUM_rn:
    1275 ECB             :         case NUM_RN:
    1276 UIC           0 :             num->flag |= NUM_F_ROMAN;
    1277               0 :             break;
    1278                 : 
    1279 GIC         109 :         case NUM_L:
    1280                 :         case NUM_G:
    1281             109 :             num->need_locale = true;
    1282             109 :             break;
    1283                 : 
    1284 LBC           0 :         case NUM_V:
    1285 UIC           0 :             if (IS_DECIMAL(num))
    1286 LBC           0 :                 ereport(ERROR,
    1287                 :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1288 ECB             :                          errmsg("cannot use \"V\" and decimal point together")));
    1289 UIC           0 :             num->flag |= NUM_F_MULTI;
    1290               0 :             break;
    1291                 : 
    1292 GIC           3 :         case NUM_E:
    1293               3 :             if (IS_EEEE(num))
    1294 LBC           0 :                 ereport(ERROR,
    1295 ECB             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1296                 :                          errmsg("cannot use \"EEEE\" twice")));
    1297 CBC           3 :             if (IS_BLANK(num) || IS_FILLMODE(num) || IS_LSIGN(num) ||
    1298               3 :                 IS_BRACKET(num) || IS_MINUS(num) || IS_PLUS(num) ||
    1299               3 :                 IS_ROMAN(num) || IS_MULTI(num))
    1300 UIC           0 :                 ereport(ERROR,
    1301                 :                         (errcode(ERRCODE_SYNTAX_ERROR),
    1302                 :                          errmsg("\"EEEE\" is incompatible with other formats"),
    1303                 :                          errdetail("\"EEEE\" may only be used together with digit and decimal point patterns.")));
    1304 GIC           3 :             num->flag |= NUM_F_EEEE;
    1305 CBC           3 :             break;
    1306                 :     }
    1307 ECB             : }
    1308                 : 
    1309                 : /* ----------
    1310                 :  * Format parser, search small keywords and keyword's suffixes, and make
    1311                 :  * format-node tree.
    1312                 :  *
    1313                 :  * for DATE-TIME & NUMBER version
    1314                 :  * ----------
    1315                 :  */
    1316                 : static void
    1317 GIC         774 : parse_format(FormatNode *node, const char *str, const KeyWord *kw,
    1318                 :              const KeySuffix *suf, const int *index, uint32 flags, NUMDesc *Num)
    1319                 : {
    1320                 :     FormatNode *n;
    1321 ECB             : 
    1322                 : #ifdef DEBUG_TO_FROM_CHAR
    1323                 :     elog(DEBUG_elog_output, "to_char/number(): run parser");
    1324                 : #endif
    1325                 : 
    1326 CBC         774 :     n = node;
    1327                 : 
    1328 GIC       13926 :     while (*str)
    1329 ECB             :     {
    1330 GIC       13155 :         int         suffix = 0;
    1331 ECB             :         const KeySuffix *s;
    1332                 : 
    1333                 :         /*
    1334                 :          * Prefix
    1335                 :          */
    1336 GIC       16725 :         if ((flags & DCH_FLAG) &&
    1337            3570 :             (s = suff_search(str, suf, SUFFTYPE_PREFIX)) != NULL)
    1338                 :         {
    1339             204 :             suffix |= s->id;
    1340             204 :             if (s->len)
    1341             204 :                 str += s->len;
    1342 ECB             :         }
    1343                 : 
    1344                 :         /*
    1345                 :          * Keyword
    1346                 :          */
    1347 GIC       13155 :         if (*str && (n->key = index_seq_search(str, kw, index)) != NULL)
    1348 ECB             :         {
    1349 CBC        8886 :             n->type = NODE_TYPE_ACTION;
    1350 GIC        8886 :             n->suffix = suffix;
    1351 CBC        8886 :             if (n->key->len)
    1352 GIC        8886 :                 str += n->key->len;
    1353 ECB             : 
    1354                 :             /*
    1355                 :              * NUM version: Prepare global NUMDesc struct
    1356                 :              */
    1357 CBC        8886 :             if (flags & NUM_FLAG)
    1358            6945 :                 NUMDesc_prepare(Num, n);
    1359                 : 
    1360 ECB             :             /*
    1361                 :              * Postfix
    1362                 :              */
    1363 GIC       10440 :             if ((flags & DCH_FLAG) && *str &&
    1364            1554 :                 (s = suff_search(str, suf, SUFFTYPE_POSTFIX)) != NULL)
    1365 ECB             :             {
    1366 CBC          21 :                 n->suffix |= s->id;
    1367 GIC          21 :                 if (s->len)
    1368 CBC          21 :                     str += s->len;
    1369                 :             }
    1370 ECB             : 
    1371 CBC        8886 :             n++;
    1372                 :         }
    1373 GIC        4269 :         else if (*str)
    1374 ECB             :         {
    1375                 :             int         chlen;
    1376                 : 
    1377 CBC        4269 :             if ((flags & STD_FLAG) && *str != '"')
    1378 ECB             :             {
    1379                 :                 /*
    1380                 :                  * Standard mode, allow only following separators: "-./,':; ".
    1381                 :                  * However, we support double quotes even in standard mode
    1382                 :                  * (see below).  This is our extension of standard mode.
    1383                 :                  */
    1384 GIC         243 :                 if (strchr("-./,':; ", *str) == NULL)
    1385               3 :                     ereport(ERROR,
    1386                 :                             (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    1387                 :                              errmsg("invalid datetime format separator: \"%s\"",
    1388                 :                                     pnstrdup(str, pg_mblen(str)))));
    1389                 : 
    1390             240 :                 if (*str == ' ')
    1391              42 :                     n->type = NODE_TYPE_SPACE;
    1392 ECB             :                 else
    1393 CBC         198 :                     n->type = NODE_TYPE_SEPARATOR;
    1394 ECB             : 
    1395 GIC         240 :                 n->character[0] = *str;
    1396 CBC         240 :                 n->character[1] = '\0';
    1397             240 :                 n->key = NULL;
    1398             240 :                 n->suffix = 0;
    1399             240 :                 n++;
    1400 GIC         240 :                 str++;
    1401 ECB             :             }
    1402 GIC        4026 :             else if (*str == '"')
    1403 ECB             :             {
    1404                 :                 /*
    1405                 :                  * Process double-quoted literal string, if any
    1406                 :                  */
    1407 CBC         189 :                 str++;
    1408            2202 :                 while (*str)
    1409                 :                 {
    1410 GIC        2199 :                     if (*str == '"')
    1411                 :                     {
    1412             186 :                         str++;
    1413 CBC         186 :                         break;
    1414 ECB             :                     }
    1415                 :                     /* backslash quotes the next character, if any */
    1416 GIC        2013 :                     if (*str == '\\' && *(str + 1))
    1417             120 :                         str++;
    1418            2013 :                     chlen = pg_mblen(str);
    1419            2013 :                     n->type = NODE_TYPE_CHAR;
    1420            2013 :                     memcpy(n->character, str, chlen);
    1421            2013 :                     n->character[chlen] = '\0';
    1422            2013 :                     n->key = NULL;
    1423            2013 :                     n->suffix = 0;
    1424            2013 :                     n++;
    1425            2013 :                     str += chlen;
    1426                 :                 }
    1427                 :             }
    1428                 :             else
    1429                 :             {
    1430                 :                 /*
    1431                 :                  * Outside double-quoted strings, backslash is only special if
    1432                 :                  * it immediately precedes a double quote.
    1433                 :                  */
    1434            3837 :                 if (*str == '\\' && *(str + 1) == '"')
    1435               6 :                     str++;
    1436            3837 :                 chlen = pg_mblen(str);
    1437                 : 
    1438            3837 :                 if ((flags & DCH_FLAG) && is_separator_char(str))
    1439             475 :                     n->type = NODE_TYPE_SEPARATOR;
    1440            3362 :                 else if (isspace((unsigned char) *str))
    1441            3227 :                     n->type = NODE_TYPE_SPACE;
    1442                 :                 else
    1443             135 :                     n->type = NODE_TYPE_CHAR;
    1444                 : 
    1445            3837 :                 memcpy(n->character, str, chlen);
    1446            3837 :                 n->character[chlen] = '\0';
    1447            3837 :                 n->key = NULL;
    1448            3837 :                 n->suffix = 0;
    1449            3837 :                 n++;
    1450            3837 :                 str += chlen;
    1451                 :             }
    1452                 :         }
    1453                 :     }
    1454                 : 
    1455             771 :     n->type = NODE_TYPE_END;
    1456             771 :     n->suffix = 0;
    1457             771 : }
    1458                 : 
    1459                 : /* ----------
    1460                 :  * DEBUG: Dump the FormatNode Tree (debug)
    1461                 :  * ----------
    1462                 :  */
    1463 ECB             : #ifdef DEBUG_TO_FROM_CHAR
    1464                 : 
    1465                 : #define DUMP_THth(_suf) (S_TH(_suf) ? "TH" : (S_th(_suf) ? "th" : " "))
    1466                 : #define DUMP_FM(_suf)   (S_FM(_suf) ? "FM" : " ")
    1467                 : 
    1468                 : static void
    1469                 : dump_node(FormatNode *node, int max)
    1470 EUB             : {
    1471                 :     FormatNode *n;
    1472                 :     int         a;
    1473                 : 
    1474                 :     elog(DEBUG_elog_output, "to_from-char(): DUMP FORMAT");
    1475                 : 
    1476                 :     for (a = 0, n = node; a <= max; n++, a++)
    1477                 :     {
    1478 ECB             :         if (n->type == NODE_TYPE_ACTION)
    1479                 :             elog(DEBUG_elog_output, "%d:\t NODE_TYPE_ACTION '%s'\t(%s,%s)",
    1480                 :                  a, n->key->name, DUMP_THth(n->suffix), DUMP_FM(n->suffix));
    1481                 :         else if (n->type == NODE_TYPE_CHAR)
    1482                 :             elog(DEBUG_elog_output, "%d:\t NODE_TYPE_CHAR '%s'",
    1483                 :                  a, n->character);
    1484                 :         else if (n->type == NODE_TYPE_END)
    1485                 :         {
    1486                 :             elog(DEBUG_elog_output, "%d:\t NODE_TYPE_END", a);
    1487                 :             return;
    1488                 :         }
    1489 EUB             :         else
    1490 ECB             :             elog(DEBUG_elog_output, "%d:\t unknown NODE!", a);
    1491                 :     }
    1492                 : }
    1493                 : #endif                          /* DEBUG */
    1494                 : 
    1495                 : /*****************************************************************************
    1496                 :  *          Private utils
    1497                 :  *****************************************************************************/
    1498                 : 
    1499                 : /* ----------
    1500                 :  * Return ST/ND/RD/TH for simple (1..9) numbers
    1501                 :  * type --> 0 upper, 1 lower
    1502                 :  * ----------
    1503                 :  */
    1504                 : static const char *
    1505 GIC        1167 : get_th(char *num, int type)
    1506                 : {
    1507            1167 :     int         len = strlen(num),
    1508 ECB             :                 last;
    1509                 : 
    1510 CBC        1167 :     last = *(num + (len - 1));
    1511 GBC        1167 :     if (!isdigit((unsigned char) last))
    1512 LBC           0 :         ereport(ERROR,
    1513 ECB             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    1514                 :                  errmsg("\"%s\" is not a number", num)));
    1515                 : 
    1516                 :     /*
    1517                 :      * All "teens" (<x>1[0-9]) get 'TH/th', while <x>[02-9][123] still get
    1518                 :      * 'ST/st', 'ND/nd', 'RD/rd', respectively
    1519                 :      */
    1520 GIC        1167 :     if ((len > 1) && (num[len - 2] == '1'))
    1521              66 :         last = 0;
    1522                 : 
    1523            1167 :     switch (last)
    1524                 :     {
    1525              48 :         case '1':
    1526              48 :             if (type == TH_UPPER)
    1527              12 :                 return numTH[0];
    1528 CBC          36 :             return numth[0];
    1529 GIC          24 :         case '2':
    1530              24 :             if (type == TH_UPPER)
    1531 UIC           0 :                 return numTH[1];
    1532 GIC          24 :             return numth[1];
    1533              18 :         case '3':
    1534 CBC          18 :             if (type == TH_UPPER)
    1535               3 :                 return numTH[2];
    1536              15 :             return numth[2];
    1537            1077 :         default:
    1538 GIC        1077 :             if (type == TH_UPPER)
    1539 CBC         378 :                 return numTH[3];
    1540 GIC         699 :             return numth[3];
    1541                 :     }
    1542 EUB             : }
    1543                 : 
    1544                 : /* ----------
    1545                 :  * Convert string-number to ordinal string-number
    1546                 :  * type --> 0 upper, 1 lower
    1547                 :  * ----------
    1548 ECB             :  */
    1549 EUB             : static char *
    1550 GIC        1143 : str_numth(char *dest, char *num, int type)
    1551 ECB             : {
    1552 GIC        1143 :     if (dest != num)
    1553 UIC           0 :         strcpy(dest, num);
    1554 GIC        1143 :     strcat(dest, get_th(num, type));
    1555 CBC        1143 :     return dest;
    1556                 : }
    1557                 : 
    1558                 : /*****************************************************************************
    1559                 :  *          upper/lower/initcap functions
    1560 ECB             :  *****************************************************************************/
    1561                 : 
    1562                 : #ifdef USE_ICU
    1563                 : 
    1564                 : typedef int32_t (*ICU_Convert_Func) (UChar *dest, int32_t destCapacity,
    1565                 :                                      const UChar *src, int32_t srcLength,
    1566                 :                                      const char *locale,
    1567                 :                                      UErrorCode *pErrorCode);
    1568                 : 
    1569                 : static int32_t
    1570 GIC      588887 : icu_convert_case(ICU_Convert_Func func, pg_locale_t mylocale,
    1571                 :                  UChar **buff_dest, UChar *buff_source, int32_t len_source)
    1572                 : {
    1573                 :     UErrorCode  status;
    1574                 :     int32_t     len_dest;
    1575                 : 
    1576          588887 :     len_dest = len_source;      /* try first with same length */
    1577          588887 :     *buff_dest = palloc(len_dest * sizeof(**buff_dest));
    1578          588887 :     status = U_ZERO_ERROR;
    1579          588887 :     len_dest = func(*buff_dest, len_dest, buff_source, len_source,
    1580                 :                     mylocale->info.icu.locale, &status);
    1581          588887 :     if (status == U_BUFFER_OVERFLOW_ERROR)
    1582                 :     {
    1583                 :         /* try again with adjusted length */
    1584 UIC           0 :         pfree(*buff_dest);
    1585               0 :         *buff_dest = palloc(len_dest * sizeof(**buff_dest));
    1586               0 :         status = U_ZERO_ERROR;
    1587               0 :         len_dest = func(*buff_dest, len_dest, buff_source, len_source,
    1588                 :                         mylocale->info.icu.locale, &status);
    1589 ECB             :     }
    1590 GIC      588887 :     if (U_FAILURE(status))
    1591 UIC           0 :         ereport(ERROR,
    1592                 :                 (errmsg("case conversion failed: %s", u_errorName(status))));
    1593 CBC      588887 :     return len_dest;
    1594 EUB             : }
    1595                 : 
    1596 ECB             : static int32_t
    1597 GIC          17 : u_strToTitle_default_BI(UChar *dest, int32_t destCapacity,
    1598                 :                         const UChar *src, int32_t srcLength,
    1599                 :                         const char *locale,
    1600                 :                         UErrorCode *pErrorCode)
    1601                 : {
    1602 GBC          17 :     return u_strToTitle(dest, destCapacity, src, srcLength,
    1603                 :                         NULL, locale, pErrorCode);
    1604                 : }
    1605                 : 
    1606                 : #endif                          /* USE_ICU */
    1607                 : 
    1608                 : /*
    1609                 :  * If the system provides the needed functions for wide-character manipulation
    1610 ECB             :  * (which are all standardized by C99), then we implement upper/lower/initcap
    1611                 :  * using wide-character functions, if necessary.  Otherwise we use the
    1612                 :  * traditional <ctype.h> functions, which of course will not work as desired
    1613                 :  * in multibyte character sets.  Note that in either case we are effectively
    1614                 :  * assuming that the database character encoding matches the encoding implied
    1615                 :  * by LC_CTYPE.
    1616                 :  *
    1617                 :  * If the system provides locale_t and associated functions (which are
    1618                 :  * standardized by Open Group's XBD), we can support collations that are
    1619                 :  * neither default nor C.  The code is written to handle both combinations
    1620                 :  * of have-wide-characters and have-locale_t, though it's rather unlikely
    1621                 :  * a platform would have the latter without the former.
    1622                 :  */
    1623                 : 
    1624                 : /*
    1625                 :  * collation-aware, wide-character-aware lower function
    1626                 :  *
    1627                 :  * We pass the number of bytes so we can pass varlena and char*
    1628                 :  * to this function.  The result is a palloc'd, null-terminated string.
    1629                 :  */
    1630                 : char *
    1631 CBC       98496 : str_tolower(const char *buff, size_t nbytes, Oid collid)
    1632 ECB             : {
    1633                 :     char       *result;
    1634                 : 
    1635 GIC       98496 :     if (!buff)
    1636 UIC           0 :         return NULL;
    1637                 : 
    1638 CBC       98496 :     if (!OidIsValid(collid))
    1639                 :     {
    1640                 :         /*
    1641                 :          * This typically means that the parser could not resolve a conflict
    1642                 :          * of implicit collations, so report it that way.
    1643                 :          */
    1644 UIC           0 :         ereport(ERROR,
    1645 ECB             :                 (errcode(ERRCODE_INDETERMINATE_COLLATION),
    1646 EUB             :                  errmsg("could not determine which collation to use for %s function",
    1647                 :                         "lower()"),
    1648                 :                  errhint("Use the COLLATE clause to set the collation explicitly.")));
    1649                 :     }
    1650                 : 
    1651 ECB             :     /* C/POSIX collations use this path regardless of database encoding */
    1652 GIC       98496 :     if (lc_ctype_is_c(collid))
    1653 ECB             :     {
    1654 GIC       23057 :         result = asc_tolower(buff, nbytes);
    1655 ECB             :     }
    1656                 :     else
    1657                 :     {
    1658                 :         pg_locale_t mylocale;
    1659                 : 
    1660 GIC       75439 :         mylocale = pg_newlocale_from_collation(collid);
    1661                 : 
    1662 EUB             : #ifdef USE_ICU
    1663 GIC       75439 :         if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
    1664           75277 :         {
    1665                 :             int32_t     len_uchar;
    1666                 :             int32_t     len_conv;
    1667                 :             UChar      *buff_uchar;
    1668                 :             UChar      *buff_conv;
    1669 ECB             : 
    1670 CBC       75277 :             len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
    1671 GIC       75277 :             len_conv = icu_convert_case(u_strToLower, mylocale,
    1672 ECB             :                                         &buff_conv, buff_uchar, len_uchar);
    1673 CBC       75277 :             icu_from_uchar(&result, buff_conv, len_conv);
    1674 GIC       75277 :             pfree(buff_uchar);
    1675           75277 :             pfree(buff_conv);
    1676                 :         }
    1677                 :         else
    1678                 : #endif
    1679 EUB             :         {
    1680 GIC         162 :             if (pg_database_encoding_max_length() > 1)
    1681                 :             {
    1682                 :                 wchar_t    *workspace;
    1683                 :                 size_t      curr_char;
    1684                 :                 size_t      result_size;
    1685                 : 
    1686                 :                 /* Overflow paranoia */
    1687             162 :                 if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
    1688 UBC           0 :                     ereport(ERROR,
    1689                 :                             (errcode(ERRCODE_OUT_OF_MEMORY),
    1690                 :                              errmsg("out of memory")));
    1691 EUB             : 
    1692                 :                 /* Output workspace cannot have more codes than input bytes */
    1693 GIC         162 :                 workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
    1694                 : 
    1695 GBC         162 :                 char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
    1696                 : 
    1697 GIC         702 :                 for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
    1698                 :                 {
    1699                 : #ifdef HAVE_LOCALE_T
    1700             540 :                     if (mylocale)
    1701 CBC         540 :                         workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
    1702                 :                     else
    1703                 : #endif
    1704 UIC           0 :                         workspace[curr_char] = towlower(workspace[curr_char]);
    1705                 :                 }
    1706                 : 
    1707                 :                 /*
    1708                 :                  * Make result large enough; case change might change number
    1709                 :                  * of bytes
    1710                 :                  */
    1711 CBC         162 :                 result_size = curr_char * pg_database_encoding_max_length() + 1;
    1712 GIC         162 :                 result = palloc(result_size);
    1713                 : 
    1714             162 :                 wchar2char(result, workspace, result_size, mylocale);
    1715 CBC         162 :                 pfree(workspace);
    1716 EUB             :             }
    1717                 :             else
    1718 ECB             :             {
    1719                 :                 char       *p;
    1720                 : 
    1721 UIC           0 :                 result = pnstrdup(buff, nbytes);
    1722                 : 
    1723                 :                 /*
    1724 EUB             :                  * Note: we assume that tolower_l() will not be so broken as
    1725                 :                  * to need an isupper_l() guard test.  When using the default
    1726                 :                  * collation, we apply the traditional Postgres behavior that
    1727                 :                  * forces ASCII-style treatment of I/i, but in non-default
    1728                 :                  * collations you get exactly what the collation says.
    1729                 :                  */
    1730 UIC           0 :                 for (p = result; *p; p++)
    1731                 :                 {
    1732 ECB             : #ifdef HAVE_LOCALE_T
    1733 UIC           0 :                     if (mylocale)
    1734 LBC           0 :                         *p = tolower_l((unsigned char) *p, mylocale->info.lt);
    1735                 :                     else
    1736                 : #endif
    1737 UIC           0 :                         *p = pg_tolower((unsigned char) *p);
    1738                 :                 }
    1739                 :             }
    1740 ECB             :         }
    1741                 :     }
    1742                 : 
    1743 CBC       98496 :     return result;
    1744 ECB             : }
    1745                 : 
    1746                 : /*
    1747                 :  * collation-aware, wide-character-aware upper function
    1748                 :  *
    1749                 :  * We pass the number of bytes so we can pass varlena and char*
    1750                 :  * to this function.  The result is a palloc'd, null-terminated string.
    1751                 :  */
    1752                 : char *
    1753 CBC      521189 : str_toupper(const char *buff, size_t nbytes, Oid collid)
    1754 ECB             : {
    1755                 :     char       *result;
    1756                 : 
    1757 GIC      521189 :     if (!buff)
    1758 UIC           0 :         return NULL;
    1759                 : 
    1760 CBC      521189 :     if (!OidIsValid(collid))
    1761                 :     {
    1762                 :         /*
    1763                 :          * This typically means that the parser could not resolve a conflict
    1764                 :          * of implicit collations, so report it that way.
    1765                 :          */
    1766 UIC           0 :         ereport(ERROR,
    1767 ECB             :                 (errcode(ERRCODE_INDETERMINATE_COLLATION),
    1768 EUB             :                  errmsg("could not determine which collation to use for %s function",
    1769                 :                         "upper()"),
    1770                 :                  errhint("Use the COLLATE clause to set the collation explicitly.")));
    1771                 :     }
    1772                 : 
    1773 ECB             :     /* C/POSIX collations use this path regardless of database encoding */
    1774 GIC      521189 :     if (lc_ctype_is_c(collid))
    1775 ECB             :     {
    1776 GIC        7578 :         result = asc_toupper(buff, nbytes);
    1777 ECB             :     }
    1778                 :     else
    1779                 :     {
    1780                 :         pg_locale_t mylocale;
    1781                 : 
    1782 GIC      513611 :         mylocale = pg_newlocale_from_collation(collid);
    1783                 : 
    1784 EUB             : #ifdef USE_ICU
    1785 GIC      513611 :         if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
    1786          513593 :         {
    1787                 :             int32_t     len_uchar,
    1788                 :                         len_conv;
    1789                 :             UChar      *buff_uchar;
    1790                 :             UChar      *buff_conv;
    1791 ECB             : 
    1792 CBC      513593 :             len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
    1793 GIC      513593 :             len_conv = icu_convert_case(u_strToUpper, mylocale,
    1794 ECB             :                                         &buff_conv, buff_uchar, len_uchar);
    1795 CBC      513593 :             icu_from_uchar(&result, buff_conv, len_conv);
    1796 GIC      513593 :             pfree(buff_uchar);
    1797          513593 :             pfree(buff_conv);
    1798                 :         }
    1799                 :         else
    1800                 : #endif
    1801 EUB             :         {
    1802 GIC          18 :             if (pg_database_encoding_max_length() > 1)
    1803                 :             {
    1804                 :                 wchar_t    *workspace;
    1805                 :                 size_t      curr_char;
    1806                 :                 size_t      result_size;
    1807                 : 
    1808                 :                 /* Overflow paranoia */
    1809              18 :                 if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
    1810 UBC           0 :                     ereport(ERROR,
    1811                 :                             (errcode(ERRCODE_OUT_OF_MEMORY),
    1812                 :                              errmsg("out of memory")));
    1813 EUB             : 
    1814                 :                 /* Output workspace cannot have more codes than input bytes */
    1815 GIC          18 :                 workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
    1816                 : 
    1817 GBC          18 :                 char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
    1818                 : 
    1819 GIC          72 :                 for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
    1820                 :                 {
    1821                 : #ifdef HAVE_LOCALE_T
    1822              54 :                     if (mylocale)
    1823 CBC          54 :                         workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt);
    1824                 :                     else
    1825                 : #endif
    1826 UIC           0 :                         workspace[curr_char] = towupper(workspace[curr_char]);
    1827                 :                 }
    1828                 : 
    1829                 :                 /*
    1830                 :                  * Make result large enough; case change might change number
    1831                 :                  * of bytes
    1832                 :                  */
    1833 CBC          18 :                 result_size = curr_char * pg_database_encoding_max_length() + 1;
    1834 GIC          18 :                 result = palloc(result_size);
    1835                 : 
    1836 CBC          18 :                 wchar2char(result, workspace, result_size, mylocale);
    1837 GIC          18 :                 pfree(workspace);
    1838 ECB             :             }
    1839 EUB             :             else
    1840                 :             {
    1841 ECB             :                 char       *p;
    1842                 : 
    1843 UIC           0 :                 result = pnstrdup(buff, nbytes);
    1844                 : 
    1845                 :                 /*
    1846                 :                  * Note: we assume that toupper_l() will not be so broken as
    1847 EUB             :                  * to need an islower_l() guard test.  When using the default
    1848                 :                  * collation, we apply the traditional Postgres behavior that
    1849                 :                  * forces ASCII-style treatment of I/i, but in non-default
    1850                 :                  * collations you get exactly what the collation says.
    1851                 :                  */
    1852 UIC           0 :                 for (p = result; *p; p++)
    1853                 :                 {
    1854                 : #ifdef HAVE_LOCALE_T
    1855 LBC           0 :                     if (mylocale)
    1856 UIC           0 :                         *p = toupper_l((unsigned char) *p, mylocale->info.lt);
    1857 ECB             :                     else
    1858                 : #endif
    1859 UIC           0 :                         *p = pg_toupper((unsigned char) *p);
    1860                 :                 }
    1861                 :             }
    1862                 :         }
    1863 ECB             :     }
    1864                 : 
    1865 GIC      521189 :     return result;
    1866 ECB             : }
    1867                 : 
    1868                 : /*
    1869                 :  * collation-aware, wide-character-aware initcap function
    1870                 :  *
    1871                 :  * We pass the number of bytes so we can pass varlena and char*
    1872                 :  * to this function.  The result is a palloc'd, null-terminated string.
    1873                 :  */
    1874                 : char *
    1875 GIC          41 : str_initcap(const char *buff, size_t nbytes, Oid collid)
    1876 ECB             : {
    1877                 :     char       *result;
    1878 CBC          41 :     int         wasalnum = false;
    1879                 : 
    1880 GIC          41 :     if (!buff)
    1881 UIC           0 :         return NULL;
    1882                 : 
    1883 CBC          41 :     if (!OidIsValid(collid))
    1884                 :     {
    1885                 :         /*
    1886                 :          * This typically means that the parser could not resolve a conflict
    1887                 :          * of implicit collations, so report it that way.
    1888                 :          */
    1889 UIC           0 :         ereport(ERROR,
    1890 ECB             :                 (errcode(ERRCODE_INDETERMINATE_COLLATION),
    1891 EUB             :                  errmsg("could not determine which collation to use for %s function",
    1892                 :                         "initcap()"),
    1893                 :                  errhint("Use the COLLATE clause to set the collation explicitly.")));
    1894                 :     }
    1895                 : 
    1896 ECB             :     /* C/POSIX collations use this path regardless of database encoding */
    1897 GIC          41 :     if (lc_ctype_is_c(collid))
    1898 ECB             :     {
    1899 GIC          12 :         result = asc_initcap(buff, nbytes);
    1900 ECB             :     }
    1901                 :     else
    1902                 :     {
    1903                 :         pg_locale_t mylocale;
    1904                 : 
    1905 CBC          29 :         mylocale = pg_newlocale_from_collation(collid);
    1906 ECB             : 
    1907                 : #ifdef USE_ICU
    1908 CBC          29 :         if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
    1909              17 :         {
    1910                 :             int32_t     len_uchar,
    1911                 :                         len_conv;
    1912                 :             UChar      *buff_uchar;
    1913                 :             UChar      *buff_conv;
    1914 EUB             : 
    1915 GBC          17 :             len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
    1916 GIC          17 :             len_conv = icu_convert_case(u_strToTitle_default_BI, mylocale,
    1917 EUB             :                                         &buff_conv, buff_uchar, len_uchar);
    1918 GBC          17 :             icu_from_uchar(&result, buff_conv, len_conv);
    1919 GIC          17 :             pfree(buff_uchar);
    1920              17 :             pfree(buff_conv);
    1921                 :         }
    1922                 :         else
    1923                 : #endif
    1924                 :         {
    1925              12 :             if (pg_database_encoding_max_length() > 1)
    1926 ECB             :             {
    1927                 :                 wchar_t    *workspace;
    1928                 :                 size_t      curr_char;
    1929                 :                 size_t      result_size;
    1930                 : 
    1931                 :                 /* Overflow paranoia */
    1932 GIC          12 :                 if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
    1933 UIC           0 :                     ereport(ERROR,
    1934                 :                             (errcode(ERRCODE_OUT_OF_MEMORY),
    1935                 :                              errmsg("out of memory")));
    1936 EUB             : 
    1937                 :                 /* Output workspace cannot have more codes than input bytes */
    1938 GIC          12 :                 workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
    1939                 : 
    1940              12 :                 char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
    1941                 : 
    1942              48 :                 for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
    1943                 :                 {
    1944                 : #ifdef HAVE_LOCALE_T
    1945 GBC          36 :                     if (mylocale)
    1946                 :                     {
    1947 GIC          36 :                         if (wasalnum)
    1948 GBC          24 :                             workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
    1949                 :                         else
    1950              12 :                             workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt);
    1951              36 :                         wasalnum = iswalnum_l(workspace[curr_char], mylocale->info.lt);
    1952                 :                     }
    1953 EUB             :                     else
    1954                 : #endif
    1955                 :                     {
    1956 UIC           0 :                         if (wasalnum)
    1957               0 :                             workspace[curr_char] = towlower(workspace[curr_char]);
    1958                 :                         else
    1959 UBC           0 :                             workspace[curr_char] = towupper(workspace[curr_char]);
    1960               0 :                         wasalnum = iswalnum(workspace[curr_char]);
    1961                 :                     }
    1962 EUB             :                 }
    1963                 : 
    1964                 :                 /*
    1965                 :                  * Make result large enough; case change might change number
    1966                 :                  * of bytes
    1967                 :                  */
    1968 GIC          12 :                 result_size = curr_char * pg_database_encoding_max_length() + 1;
    1969              12 :                 result = palloc(result_size);
    1970 ECB             : 
    1971 GIC          12 :                 wchar2char(result, workspace, result_size, mylocale);
    1972              12 :                 pfree(workspace);
    1973                 :             }
    1974                 :             else
    1975                 :             {
    1976                 :                 char       *p;
    1977                 : 
    1978 UIC           0 :                 result = pnstrdup(buff, nbytes);
    1979                 : 
    1980 ECB             :                 /*
    1981                 :                  * Note: we assume that toupper_l()/tolower_l() will not be so
    1982                 :                  * broken as to need guard tests.  When using the default
    1983                 :                  * collation, we apply the traditional Postgres behavior that
    1984                 :                  * forces ASCII-style treatment of I/i, but in non-default
    1985                 :                  * collations you get exactly what the collation says.
    1986 EUB             :                  */
    1987 UIC           0 :                 for (p = result; *p; p++)
    1988 ECB             :                 {
    1989                 : #ifdef HAVE_LOCALE_T
    1990 LBC           0 :                     if (mylocale)
    1991 ECB             :                     {
    1992 UIC           0 :                         if (wasalnum)
    1993 LBC           0 :                             *p = tolower_l((unsigned char) *p, mylocale->info.lt);
    1994                 :                         else
    1995 UIC           0 :                             *p = toupper_l((unsigned char) *p, mylocale->info.lt);
    1996               0 :                         wasalnum = isalnum_l((unsigned char) *p, mylocale->info.lt);
    1997                 :                     }
    1998                 :                     else
    1999                 : #endif
    2000                 :                     {
    2001               0 :                         if (wasalnum)
    2002               0 :                             *p = pg_tolower((unsigned char) *p);
    2003 ECB             :                         else
    2004 UIC           0 :                             *p = pg_toupper((unsigned char) *p);
    2005               0 :                         wasalnum = isalnum((unsigned char) *p);
    2006                 :                     }
    2007                 :                 }
    2008 ECB             :             }
    2009 EUB             :         }
    2010                 :     }
    2011 ECB             : 
    2012 GIC          41 :     return result;
    2013 ECB             : }
    2014                 : 
    2015                 : /*
    2016                 :  * ASCII-only lower function
    2017                 :  *
    2018                 :  * We pass the number of bytes so we can pass varlena and char*
    2019                 :  * to this function.  The result is a palloc'd, null-terminated string.
    2020                 :  */
    2021                 : char *
    2022 GIC       25343 : asc_tolower(const char *buff, size_t nbytes)
    2023                 : {
    2024                 :     char       *result;
    2025                 :     char       *p;
    2026 ECB             : 
    2027 GIC       25343 :     if (!buff)
    2028 UIC           0 :         return NULL;
    2029                 : 
    2030 CBC       25343 :     result = pnstrdup(buff, nbytes);
    2031                 : 
    2032          280095 :     for (p = result; *p; p++)
    2033 GBC      254752 :         *p = pg_ascii_tolower((unsigned char) *p);
    2034                 : 
    2035 CBC       25343 :     return result;
    2036                 : }
    2037 ECB             : 
    2038                 : /*
    2039                 :  * ASCII-only upper function
    2040                 :  *
    2041                 :  * We pass the number of bytes so we can pass varlena and char*
    2042                 :  * to this function.  The result is a palloc'd, null-terminated string.
    2043                 :  */
    2044                 : char *
    2045 GIC        9864 : asc_toupper(const char *buff, size_t nbytes)
    2046 ECB             : {
    2047                 :     char       *result;
    2048 EUB             :     char       *p;
    2049                 : 
    2050 GIC        9864 :     if (!buff)
    2051 LBC           0 :         return NULL;
    2052                 : 
    2053 GIC        9864 :     result = pnstrdup(buff, nbytes);
    2054                 : 
    2055           85059 :     for (p = result; *p; p++)
    2056           75195 :         *p = pg_ascii_toupper((unsigned char) *p);
    2057 EUB             : 
    2058 GIC        9864 :     return result;
    2059 EUB             : }
    2060                 : 
    2061                 : /*
    2062                 :  * ASCII-only initcap function
    2063 ECB             :  *
    2064                 :  * We pass the number of bytes so we can pass varlena and char*
    2065                 :  * to this function.  The result is a palloc'd, null-terminated string.
    2066                 :  */
    2067                 : char *
    2068 GIC          12 : asc_initcap(const char *buff, size_t nbytes)
    2069 EUB             : {
    2070                 :     char       *result;
    2071                 :     char       *p;
    2072 GIC          12 :     int         wasalnum = false;
    2073                 : 
    2074              12 :     if (!buff)
    2075 LBC           0 :         return NULL;
    2076                 : 
    2077 CBC          12 :     result = pnstrdup(buff, nbytes);
    2078                 : 
    2079 GIC          48 :     for (p = result; *p; p++)
    2080                 :     {
    2081 ECB             :         char        c;
    2082                 : 
    2083 CBC          36 :         if (wasalnum)
    2084 GIC          24 :             *p = c = pg_ascii_tolower((unsigned char) *p);
    2085                 :         else
    2086              12 :             *p = c = pg_ascii_toupper((unsigned char) *p);
    2087                 :         /* we don't trust isalnum() here */
    2088              72 :         wasalnum = ((c >= 'A' && c <= 'Z') ||
    2089              72 :                     (c >= 'a' && c <= 'z') ||
    2090 UIC           0 :                     (c >= '0' && c <= '9'));
    2091                 :     }
    2092                 : 
    2093 GIC          12 :     return result;
    2094                 : }
    2095                 : 
    2096                 : /* convenience routines for when the input is null-terminated */
    2097                 : 
    2098                 : static char *
    2099 UIC           0 : str_tolower_z(const char *buff, Oid collid)
    2100                 : {
    2101               0 :     return str_tolower(buff, strlen(buff), collid);
    2102                 : }
    2103                 : 
    2104                 : static char *
    2105 GIC          12 : str_toupper_z(const char *buff, Oid collid)
    2106                 : {
    2107              12 :     return str_toupper(buff, strlen(buff), collid);
    2108                 : }
    2109                 : 
    2110                 : static char *
    2111 UIC           0 : str_initcap_z(const char *buff, Oid collid)
    2112                 : {
    2113               0 :     return str_initcap(buff, strlen(buff), collid);
    2114                 : }
    2115                 : 
    2116                 : static char *
    2117 GIC        2286 : asc_tolower_z(const char *buff)
    2118                 : {
    2119            2286 :     return asc_tolower(buff, strlen(buff));
    2120                 : }
    2121                 : 
    2122                 : static char *
    2123            2286 : asc_toupper_z(const char *buff)
    2124                 : {
    2125            2286 :     return asc_toupper(buff, strlen(buff));
    2126                 : }
    2127                 : 
    2128                 : /* asc_initcap_z is not currently needed */
    2129                 : 
    2130                 : 
    2131                 : /* ----------
    2132                 :  * Skip TM / th in FROM_CHAR
    2133                 :  *
    2134                 :  * If S_THth is on, skip two chars, assuming there are two available
    2135                 :  * ----------
    2136                 :  */
    2137                 : #define SKIP_THth(ptr, _suf) \
    2138                 :     do { \
    2139                 :         if (S_THth(_suf)) \
    2140                 :         { \
    2141                 :             if (*(ptr)) (ptr) += pg_mblen(ptr); \
    2142                 :             if (*(ptr)) (ptr) += pg_mblen(ptr); \
    2143 ECB             :         } \
    2144                 :     } while (0)
    2145                 : 
    2146 EUB             : 
    2147                 : #ifdef DEBUG_TO_FROM_CHAR
    2148 ECB             : /* -----------
    2149 EUB             :  * DEBUG: Call for debug and for index checking; (Show ASCII char
    2150                 :  * and defined keyword for each used position
    2151                 :  * ----------
    2152                 :  */
    2153                 : static void
    2154 ECB             : dump_index(const KeyWord *k, const int *index)
    2155                 : {
    2156                 :     int         i,
    2157                 :                 count = 0,
    2158                 :                 free_i = 0;
    2159                 : 
    2160                 :     elog(DEBUG_elog_output, "TO-FROM_CHAR: Dump KeyWord Index:");
    2161                 : 
    2162                 :     for (i = 0; i < KeyWord_INDEX_SIZE; i++)
    2163                 :     {
    2164                 :         if (index[i] != -1)
    2165                 :         {
    2166                 :             elog(DEBUG_elog_output, "\t%c: %s, ", i + 32, k[index[i]].name);
    2167                 :             count++;
    2168                 :         }
    2169 EUB             :         else
    2170                 :         {
    2171 ECB             :             free_i++;
    2172                 :             elog(DEBUG_elog_output, "\t(%d) %c %d", i, i + 32, index[i]);
    2173                 :         }
    2174                 :     }
    2175                 :     elog(DEBUG_elog_output, "\n\t\tUsed positions: %d,\n\t\tFree positions: %d",
    2176                 :          count, free_i);
    2177                 : }
    2178                 : #endif                          /* DEBUG */
    2179                 : 
    2180                 : /* ----------
    2181                 :  * Return true if next format picture is not digit value
    2182                 :  * ----------
    2183                 :  */
    2184                 : static bool
    2185 GIC       15996 : is_next_separator(FormatNode *n)
    2186 ECB             : {
    2187 CBC       15996 :     if (n->type == NODE_TYPE_END)
    2188 UIC           0 :         return false;
    2189 ECB             : 
    2190 GBC       15996 :     if (n->type == NODE_TYPE_ACTION && S_THth(n->suffix))
    2191 UIC           0 :         return true;
    2192 ECB             : 
    2193                 :     /*
    2194                 :      * Next node
    2195 EUB             :      */
    2196 GIC       15996 :     n++;
    2197                 : 
    2198                 :     /* end of format string is treated like a non-digit separator */
    2199           15996 :     if (n->type == NODE_TYPE_END)
    2200 CBC        2301 :         return true;
    2201                 : 
    2202           13695 :     if (n->type == NODE_TYPE_ACTION)
    2203                 :     {
    2204            1416 :         if (n->key->is_digit)
    2205 GIC         132 :             return false;
    2206 EUB             : 
    2207 GBC        1284 :         return true;
    2208                 :     }
    2209 CBC       12279 :     else if (n->character[1] == '\0' &&
    2210 GIC       12279 :              isdigit((unsigned char) n->character[0]))
    2211 UIC           0 :         return false;
    2212                 : 
    2213 GIC       12279 :     return true;                /* some non-digit input (separator) */
    2214                 : }
    2215                 : 
    2216                 : 
    2217                 : static int
    2218              36 : adjust_partial_year_to_2020(int year)
    2219                 : {
    2220                 :     /*
    2221                 :      * Adjust all dates toward 2020; this is effectively what happens when we
    2222 ECB             :      * assume '70' is 1970 and '69' is 2069.
    2223                 :      */
    2224                 :     /* Force 0-69 into the 2000's */
    2225 CBC          36 :     if (year < 70)
    2226 GIC          15 :         return year + 2000;
    2227 ECB             :     /* Force 70-99 into the 1900's */
    2228 CBC          21 :     else if (year < 100)
    2229              18 :         return year + 1900;
    2230 ECB             :     /* Force 100-519 into the 2000's */
    2231 GIC           3 :     else if (year < 520)
    2232 UIC           0 :         return year + 2000;
    2233                 :     /* Force 520-999 into the 1000's */
    2234 GIC           3 :     else if (year < 1000)
    2235               3 :         return year + 1000;
    2236 ECB             :     else
    2237 UIC           0 :         return year;
    2238                 : }
    2239                 : 
    2240                 : 
    2241                 : static int
    2242 GIC       16017 : strspace_len(const char *str)
    2243                 : {
    2244           16017 :     int         len = 0;
    2245                 : 
    2246           16017 :     while (*str && isspace((unsigned char) *str))
    2247                 :     {
    2248 UIC           0 :         str++;
    2249 LBC           0 :         len++;
    2250                 :     }
    2251 GIC       16017 :     return len;
    2252 ECB             : }
    2253                 : 
    2254                 : /*
    2255                 :  * Set the date mode of a from-char conversion.
    2256                 :  *
    2257                 :  * Puke if the date mode has already been set, and the caller attempts to set
    2258                 :  * it to a conflicting mode.
    2259                 :  *
    2260                 :  * Returns true on success, false on failure (if escontext points to an
    2261                 :  * ErrorSaveContext; otherwise errors are thrown).
    2262                 :  */
    2263                 : static bool
    2264 GNC       16161 : from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode,
    2265                 :                    Node *escontext)
    2266                 : {
    2267 GIC       16161 :     if (mode != FROM_CHAR_DATE_NONE)
    2268                 :     {
    2269            7143 :         if (tmfc->mode == FROM_CHAR_DATE_NONE)
    2270            2634 :             tmfc->mode = mode;
    2271            4509 :         else if (tmfc->mode != mode)
    2272 GNC           3 :             ereturn(escontext, false,
    2273                 :                     (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    2274                 :                      errmsg("invalid combination of date conventions"),
    2275                 :                      errhint("Do not mix Gregorian and ISO week date "
    2276                 :                              "conventions in a formatting template.")));
    2277                 :     }
    2278           16158 :     return true;
    2279                 : }
    2280                 : 
    2281                 : /*
    2282                 :  * Set the integer pointed to by 'dest' to the given value.
    2283                 :  *
    2284                 :  * Puke if the destination integer has previously been set to some other
    2285 ECB             :  * non-zero value.
    2286                 :  *
    2287                 :  * Returns true on success, false on failure (if escontext points to an
    2288                 :  * ErrorSaveContext; otherwise errors are thrown).
    2289                 :  */
    2290                 : static bool
    2291 CBC       16083 : from_char_set_int(int *dest, const int value, const FormatNode *node,
    2292                 :                   Node *escontext)
    2293                 : {
    2294 GIC       16083 :     if (*dest != 0 && *dest != value)
    2295 GNC           3 :         ereturn(escontext, false,
    2296                 :                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    2297                 :                  errmsg("conflicting values for \"%s\" field in formatting string",
    2298                 :                         node->key->name),
    2299                 :                  errdetail("This value contradicts a previous setting "
    2300                 :                            "for the same field type.")));
    2301 CBC       16080 :     *dest = value;
    2302 GNC       16080 :     return true;
    2303                 : }
    2304                 : 
    2305                 : /*
    2306                 :  * Read a single integer from the source string, into the int pointed to by
    2307 ECB             :  * 'dest'. If 'dest' is NULL, the result is discarded.
    2308                 :  *
    2309                 :  * In fixed-width mode (the node does not have the FM suffix), consume at most
    2310                 :  * 'len' characters.  However, any leading whitespace isn't counted in 'len'.
    2311                 :  *
    2312                 :  * We use strtol() to recover the integer value from the source string, in
    2313                 :  * accordance with the given FormatNode.
    2314                 :  *
    2315                 :  * If the conversion completes successfully, src will have been advanced to
    2316                 :  * point at the character immediately following the last character used in the
    2317                 :  * conversion.
    2318                 :  *
    2319                 :  * Returns the number of characters consumed, or -1 on error (if escontext
    2320                 :  * points to an ErrorSaveContext; otherwise errors are thrown).
    2321                 :  *
    2322                 :  * Note that from_char_parse_int() provides a more convenient wrapper where
    2323                 :  * the length of the field is the same as the length of the format keyword (as
    2324                 :  * with DD and MI).
    2325                 :  */
    2326                 : static int
    2327 CBC       16017 : from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *node,
    2328                 :                         Node *escontext)
    2329 ECB             : {
    2330                 :     long        result;
    2331                 :     char        copy[DCH_MAX_ITEM_SIZ + 1];
    2332 CBC       16017 :     const char *init = *src;
    2333                 :     int         used;
    2334                 : 
    2335                 :     /*
    2336                 :      * Skip any whitespace before parsing the integer.
    2337                 :      */
    2338 GIC       16017 :     *src += strspace_len(*src);
    2339                 : 
    2340           16017 :     Assert(len <= DCH_MAX_ITEM_SIZ);
    2341 CBC       16017 :     used = (int) strlcpy(copy, *src, len + 1);
    2342                 : 
    2343 GIC       16017 :     if (S_FM(node->suffix) || is_next_separator(node))
    2344 CBC       15885 :     {
    2345 ECB             :         /*
    2346                 :          * This node is in Fill Mode, or the next node is known to be a
    2347                 :          * non-digit value, so we just slurp as many characters as we can get.
    2348                 :          */
    2349                 :         char       *endptr;
    2350                 : 
    2351 CBC       15885 :         errno = 0;
    2352           15885 :         result = strtol(init, &endptr, 10);
    2353 GIC       15885 :         *src = endptr;
    2354                 :     }
    2355                 :     else
    2356                 :     {
    2357                 :         /*
    2358                 :          * We need to pull exactly the number of characters given in 'len' out
    2359 ECB             :          * of the string, and convert those.
    2360                 :          */
    2361                 :         char       *last;
    2362 EUB             : 
    2363 GIC         132 :         if (used < len)
    2364 GNC           3 :             ereturn(escontext, -1,
    2365                 :                     (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    2366                 :                      errmsg("source string too short for \"%s\" formatting field",
    2367                 :                             node->key->name),
    2368                 :                      errdetail("Field requires %d characters, but only %d remain.",
    2369                 :                                len, used),
    2370                 :                      errhint("If your source string is not fixed-width, "
    2371                 :                              "try using the \"FM\" modifier.")));
    2372                 : 
    2373 GIC         129 :         errno = 0;
    2374             129 :         result = strtol(copy, &last, 10);
    2375             129 :         used = last - copy;
    2376 ECB             : 
    2377 GIC         129 :         if (used > 0 && used < len)
    2378 GNC           3 :             ereturn(escontext, -1,
    2379                 :                     (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    2380                 :                      errmsg("invalid value \"%s\" for \"%s\"",
    2381                 :                             copy, node->key->name),
    2382                 :                      errdetail("Field requires %d characters, but only %d could be parsed.",
    2383                 :                                len, used),
    2384                 :                      errhint("If your source string is not fixed-width, "
    2385                 :                              "try using the \"FM\" modifier.")));
    2386                 : 
    2387 GIC         126 :         *src += used;
    2388                 :     }
    2389                 : 
    2390           16011 :     if (*src == init)
    2391 GNC          45 :         ereturn(escontext, -1,
    2392                 :                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    2393                 :                  errmsg("invalid value \"%s\" for \"%s\"",
    2394                 :                         copy, node->key->name),
    2395                 :                  errdetail("Value must be an integer.")));
    2396                 : 
    2397 GIC       15966 :     if (errno == ERANGE || result < INT_MIN || result > INT_MAX)
    2398 GNC           3 :         ereturn(escontext, -1,
    2399                 :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2400                 :                  errmsg("value for \"%s\" in source string is out of range",
    2401                 :                         node->key->name),
    2402                 :                  errdetail("Value must be in the range %d to %d.",
    2403                 :                            INT_MIN, INT_MAX)));
    2404                 : 
    2405 CBC       15963 :     if (dest != NULL)
    2406                 :     {
    2407 GNC       15960 :         if (!from_char_set_int(dest, (int) result, node, escontext))
    2408 UNC           0 :             return -1;
    2409                 :     }
    2410                 : 
    2411 GIC       15963 :     return *src - init;
    2412                 : }
    2413                 : 
    2414 ECB             : /*
    2415                 :  * Call from_char_parse_int_len(), using the length of the format keyword as
    2416                 :  * the expected length of the field.
    2417                 :  *
    2418                 :  * Don't call this function if the field differs in length from the format
    2419                 :  * keyword (as with HH24; the keyword length is 4, but the field length is 2).
    2420                 :  * In such cases, call from_char_parse_int_len() instead to specify the
    2421                 :  * required length explicitly.
    2422                 :  */
    2423                 : static int
    2424 GNC       11268 : from_char_parse_int(int *dest, const char **src, FormatNode *node,
    2425                 :                     Node *escontext)
    2426                 : {
    2427           11268 :     return from_char_parse_int_len(dest, src, node->key->len, node, escontext);
    2428 ECB             : }
    2429                 : 
    2430                 : /*
    2431                 :  * Sequentially search null-terminated "array" for a case-insensitive match
    2432                 :  * to the initial character(s) of "name".
    2433                 :  *
    2434                 :  * Returns array index of match, or -1 for no match.
    2435                 :  *
    2436                 :  * *len is set to the length of the match, or 0 for no match.
    2437                 :  *
    2438                 :  * Case-insensitivity is defined per pg_ascii_tolower, so this is only
    2439                 :  * suitable for comparisons to ASCII strings.
    2440                 :  */
    2441                 : static int
    2442 GIC         120 : seq_search_ascii(const char *name, const char *const *array, int *len)
    2443                 : {
    2444                 :     unsigned char firstc;
    2445                 :     const char *const *a;
    2446                 : 
    2447             120 :     *len = 0;
    2448 ECB             : 
    2449                 :     /* empty string can't match anything */
    2450 GIC         120 :     if (!*name)
    2451 UIC           0 :         return -1;
    2452                 : 
    2453                 :     /* we handle first char specially to gain some speed */
    2454 CBC         120 :     firstc = pg_ascii_tolower((unsigned char) *name);
    2455                 : 
    2456 GIC         534 :     for (a = array; *a != NULL; a++)
    2457 ECB             :     {
    2458 EUB             :         const char *p;
    2459                 :         const char *n;
    2460                 : 
    2461                 :         /* compare first chars */
    2462 GIC         528 :         if (pg_ascii_tolower((unsigned char) **a) != firstc)
    2463             390 :             continue;
    2464 ECB             : 
    2465                 :         /* compare rest of string */
    2466 CBC         393 :         for (p = *a + 1, n = name + 1;; p++, n++)
    2467                 :         {
    2468 ECB             :             /* return success if we matched whole array entry */
    2469 GIC         393 :             if (*p == '\0')
    2470 ECB             :             {
    2471 CBC         114 :                 *len = n - name;
    2472 GIC         114 :                 return a - array;
    2473                 :             }
    2474                 :             /* else, must have another character in "name" ... */
    2475             279 :             if (*n == '\0')
    2476 UIC           0 :                 break;
    2477                 :             /* ... and it must match */
    2478 GIC         558 :             if (pg_ascii_tolower((unsigned char) *p) !=
    2479 CBC         279 :                 pg_ascii_tolower((unsigned char) *n))
    2480              24 :                 break;
    2481 ECB             :         }
    2482                 :     }
    2483                 : 
    2484 GIC           6 :     return -1;
    2485                 : }
    2486                 : 
    2487                 : /*
    2488                 :  * Sequentially search an array of possibly non-English words for
    2489                 :  * a case-insensitive match to the initial character(s) of "name".
    2490 ECB             :  *
    2491                 :  * This has the same API as seq_search_ascii(), but we use a more general
    2492                 :  * case-folding transformation to achieve case-insensitivity.  Case folding
    2493                 :  * is done per the rules of the collation identified by "collid".
    2494                 :  *
    2495                 :  * The array is treated as const, but we don't declare it that way because
    2496                 :  * the arrays exported by pg_locale.c aren't const.
    2497                 :  */
    2498                 : static int
    2499 CBC           9 : seq_search_localized(const char *name, char **array, int *len, Oid collid)
    2500 ECB             : {
    2501                 :     char      **a;
    2502                 :     char       *upper_name;
    2503                 :     char       *lower_name;
    2504                 : 
    2505 GIC           9 :     *len = 0;
    2506                 : 
    2507 ECB             :     /* empty string can't match anything */
    2508 CBC           9 :     if (!*name)
    2509 UIC           0 :         return -1;
    2510                 : 
    2511                 :     /*
    2512                 :      * The case-folding processing done below is fairly expensive, so before
    2513                 :      * doing that, make a quick pass to see if there is an exact match.
    2514                 :      */
    2515 GIC          84 :     for (a = array; *a != NULL; a++)
    2516                 :     {
    2517              78 :         int         element_len = strlen(*a);
    2518                 : 
    2519              78 :         if (strncmp(name, *a, element_len) == 0)
    2520                 :         {
    2521               3 :             *len = element_len;
    2522               3 :             return a - array;
    2523                 :         }
    2524                 :     }
    2525                 : 
    2526                 :     /*
    2527                 :      * Fold to upper case, then to lower case, so that we can match reliably
    2528                 :      * even in languages in which case conversions are not injective.
    2529                 :      */
    2530               6 :     upper_name = str_toupper(unconstify(char *, name), strlen(name), collid);
    2531               6 :     lower_name = str_tolower(upper_name, strlen(upper_name), collid);
    2532 CBC           6 :     pfree(upper_name);
    2533                 : 
    2534 GIC          45 :     for (a = array; *a != NULL; a++)
    2535                 :     {
    2536                 :         char       *upper_element;
    2537                 :         char       *lower_element;
    2538 ECB             :         int         element_len;
    2539                 : 
    2540                 :         /* Likewise upper/lower-case array element */
    2541 CBC          42 :         upper_element = str_toupper(*a, strlen(*a), collid);
    2542 GIC          42 :         lower_element = str_tolower(upper_element, strlen(upper_element),
    2543 ECB             :                                     collid);
    2544 GIC          42 :         pfree(upper_element);
    2545              42 :         element_len = strlen(lower_element);
    2546                 : 
    2547                 :         /* Match? */
    2548              42 :         if (strncmp(lower_name, lower_element, element_len) == 0)
    2549 ECB             :         {
    2550 GIC           3 :             *len = element_len;
    2551               3 :             pfree(lower_element);
    2552 CBC           3 :             pfree(lower_name);
    2553 GIC           3 :             return a - array;
    2554 ECB             :         }
    2555 GIC          39 :         pfree(lower_element);
    2556 ECB             :     }
    2557                 : 
    2558 GIC           3 :     pfree(lower_name);
    2559               3 :     return -1;
    2560                 : }
    2561 ECB             : 
    2562                 : /*
    2563                 :  * Perform a sequential search in 'array' (or 'localized_array', if that's
    2564                 :  * not NULL) for an entry matching the first character(s) of the 'src'
    2565                 :  * string case-insensitively.
    2566                 :  *
    2567                 :  * The 'array' is presumed to be English words (all-ASCII), but
    2568                 :  * if 'localized_array' is supplied, that might be non-English
    2569                 :  * so we need a more expensive case-folding transformation
    2570                 :  * (which will follow the rules of the collation 'collid').
    2571                 :  *
    2572                 :  * If a match is found, copy the array index of the match into the integer
    2573                 :  * pointed to by 'dest' and advance 'src' to the end of the part of the string
    2574                 :  * which matched.
    2575                 :  *
    2576                 :  * Returns true on match, false on failure (if escontext points to an
    2577                 :  * ErrorSaveContext; otherwise errors are thrown).
    2578                 :  *
    2579                 :  * 'node' is used only for error reports: node->key->name identifies the
    2580                 :  * field type we were searching for.
    2581                 :  */
    2582                 : static bool
    2583 GIC         129 : from_char_seq_search(int *dest, const char **src, const char *const *array,
    2584                 :                      char **localized_array, Oid collid,
    2585                 :                      FormatNode *node, Node *escontext)
    2586 ECB             : {
    2587                 :     int         len;
    2588                 : 
    2589 CBC         129 :     if (localized_array == NULL)
    2590 GIC         120 :         *dest = seq_search_ascii(*src, array, &len);
    2591 ECB             :     else
    2592 GIC           9 :         *dest = seq_search_localized(*src, localized_array, &len, collid);
    2593 ECB             : 
    2594 CBC         129 :     if (len <= 0)
    2595 ECB             :     {
    2596                 :         /*
    2597                 :          * In the error report, truncate the string at the next whitespace (if
    2598                 :          * any) to avoid including irrelevant data.
    2599                 :          */
    2600 CBC           9 :         char       *copy = pstrdup(*src);
    2601                 :         char       *c;
    2602 ECB             : 
    2603 GIC          69 :         for (c = copy; *c; c++)
    2604 ECB             :         {
    2605 CBC          66 :             if (scanner_isspace(*c))
    2606 EUB             :             {
    2607 GIC           6 :                 *c = '\0';
    2608 GBC           6 :                 break;
    2609                 :             }
    2610 EUB             :         }
    2611                 : 
    2612 GNC           9 :         ereturn(escontext, false,
    2613                 :                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    2614                 :                  errmsg("invalid value \"%s\" for \"%s\"",
    2615                 :                         copy, node->key->name),
    2616                 :                  errdetail("The given value did not match any of "
    2617                 :                            "the allowed values for this field.")));
    2618 ECB             :     }
    2619 GIC         120 :     *src += len;
    2620 GNC         120 :     return true;
    2621 ECB             : }
    2622                 : 
    2623                 : /* ----------
    2624                 :  * Process a TmToChar struct as denoted by a list of FormatNodes.
    2625                 :  * The formatted data is written to the string pointed to by 'out'.
    2626                 :  * ----------
    2627                 :  */
    2628                 : static void
    2629 CBC        4552 : DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
    2630                 : {
    2631 ECB             :     FormatNode *n;
    2632                 :     char       *s;
    2633 GBC        4552 :     struct fmt_tm *tm = &in->tm;
    2634 ECB             :     int         i;
    2635                 : 
    2636                 :     /* cache localized days and months */
    2637 CBC        4552 :     cache_locale_time();
    2638 ECB             : 
    2639 CBC        4552 :     s = out;
    2640 GBC       92695 :     for (n = node; n->type != NODE_TYPE_END; n++)
    2641 ECB             :     {
    2642 CBC       88143 :         if (n->type != NODE_TYPE_ACTION)
    2643 ECB             :         {
    2644 CBC       51918 :             strcpy(s, n->character);
    2645 GIC       51918 :             s += strlen(s);
    2646 CBC       51918 :             continue;
    2647 EUB             :         }
    2648 ECB             : 
    2649 CBC       36225 :         switch (n->key->id)
    2650 ECB             :         {
    2651 CBC         381 :             case DCH_A_M:
    2652                 :             case DCH_P_M:
    2653             381 :                 strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
    2654 EUB             :                        ? P_M_STR : A_M_STR);
    2655 CBC         381 :                 s += strlen(s);
    2656             381 :                 break;
    2657 UIC           0 :             case DCH_AM:
    2658                 :             case DCH_PM:
    2659               0 :                 strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
    2660                 :                        ? PM_STR : AM_STR);
    2661               0 :                 s += strlen(s);
    2662               0 :                 break;
    2663 GIC         381 :             case DCH_a_m:
    2664 ECB             :             case DCH_p_m:
    2665 CBC         381 :                 strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
    2666 ECB             :                        ? p_m_STR : a_m_STR);
    2667 CBC         381 :                 s += strlen(s);
    2668             381 :                 break;
    2669             381 :             case DCH_am:
    2670 ECB             :             case DCH_pm:
    2671 GIC         381 :                 strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
    2672 ECB             :                        ? pm_STR : am_STR);
    2673 CBC         381 :                 s += strlen(s);
    2674             381 :                 break;
    2675            2291 :             case DCH_HH:
    2676 ECB             :             case DCH_HH12:
    2677                 : 
    2678                 :                 /*
    2679                 :                  * display time as shown on a 12-hour clock, even for
    2680                 :                  * intervals
    2681                 :                  */
    2682 CBC        2291 :                 sprintf(s, "%0*lld", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
    2683            2291 :                         tm->tm_hour % (HOURS_PER_DAY / 2) == 0 ?
    2684                 :                         (long long) (HOURS_PER_DAY / 2) :
    2685            2216 :                         (long long) (tm->tm_hour % (HOURS_PER_DAY / 2)));
    2686            2291 :                 if (S_THth(n->suffix))
    2687 LBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    2688 CBC        2291 :                 s += strlen(s);
    2689            2291 :                 break;
    2690             763 :             case DCH_HH24:
    2691 GBC         763 :                 sprintf(s, "%0*lld", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
    2692 CBC         763 :                         (long long) tm->tm_hour);
    2693             763 :                 if (S_THth(n->suffix))
    2694 UBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    2695 GBC         763 :                 s += strlen(s);
    2696             763 :                 break;
    2697 GIC        2292 :             case DCH_MI:
    2698            2292 :                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_min >= 0) ? 2 : 3,
    2699 EUB             :                         tm->tm_min);
    2700 GIC        2292 :                 if (S_THth(n->suffix))
    2701 UBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    2702 GBC        2292 :                 s += strlen(s);
    2703            2292 :                 break;
    2704 GIC        2292 :             case DCH_SS:
    2705 GBC        2292 :                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_sec >= 0) ? 2 : 3,
    2706 ECB             :                         tm->tm_sec);
    2707 CBC        2292 :                 if (S_THth(n->suffix))
    2708 LBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    2709 GIC        2292 :                 s += strlen(s);
    2710 CBC        2292 :                 break;
    2711 ECB             : 
    2712                 : #define DCH_to_char_fsec(frac_fmt, frac_val) \
    2713                 :                 sprintf(s, frac_fmt, (int) (frac_val)); \
    2714                 :                 if (S_THth(n->suffix)) \
    2715                 :                     str_numth(s, s, S_TH_TYPE(n->suffix)); \
    2716                 :                 s += strlen(s)
    2717                 : 
    2718 CBC          48 :             case DCH_FF1:       /* tenth of second */
    2719              48 :                 DCH_to_char_fsec("%01d", in->fsec / 100000);
    2720              48 :                 break;
    2721              48 :             case DCH_FF2:       /* hundredth of second */
    2722              48 :                 DCH_to_char_fsec("%02d", in->fsec / 10000);
    2723              48 :                 break;
    2724              72 :             case DCH_FF3:
    2725 ECB             :             case DCH_MS:        /* millisecond */
    2726 CBC          72 :                 DCH_to_char_fsec("%03d", in->fsec / 1000);
    2727              72 :                 break;
    2728              48 :             case DCH_FF4:       /* tenth of a millisecond */
    2729              48 :                 DCH_to_char_fsec("%04d", in->fsec / 100);
    2730              48 :                 break;
    2731              48 :             case DCH_FF5:       /* hundredth of a millisecond */
    2732              48 :                 DCH_to_char_fsec("%05d", in->fsec / 10);
    2733              48 :                 break;
    2734              72 :             case DCH_FF6:
    2735                 :             case DCH_US:        /* microsecond */
    2736              72 :                 DCH_to_char_fsec("%06d", in->fsec);
    2737              72 :                 break;
    2738 ECB             : #undef DCH_to_char_fsec
    2739 GIC         387 :             case DCH_SSSS:
    2740 CBC         387 :                 sprintf(s, "%lld",
    2741             387 :                         (long long) (tm->tm_hour * SECS_PER_HOUR +
    2742 GIC         387 :                                      tm->tm_min * SECS_PER_MINUTE +
    2743 CBC         387 :                                      tm->tm_sec));
    2744             387 :                 if (S_THth(n->suffix))
    2745 LBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    2746 CBC         387 :                 s += strlen(s);
    2747 GBC         387 :                 break;
    2748 UIC           0 :             case DCH_tz:
    2749 UBC           0 :                 INVALID_FOR_INTERVAL;
    2750               0 :                 if (tmtcTzn(in))
    2751 EUB             :                 {
    2752                 :                     /* We assume here that timezone names aren't localized */
    2753 LBC           0 :                     char       *p = asc_tolower_z(tmtcTzn(in));
    2754                 : 
    2755               0 :                     strcpy(s, p);
    2756               0 :                     pfree(p);
    2757               0 :                     s += strlen(s);
    2758 ECB             :                 }
    2759 LBC           0 :                 break;
    2760 GIC           3 :             case DCH_TZ:
    2761 CBC           3 :                 INVALID_FOR_INTERVAL;
    2762               3 :                 if (tmtcTzn(in))
    2763 ECB             :                 {
    2764 CBC           3 :                     strcpy(s, tmtcTzn(in));
    2765               3 :                     s += strlen(s);
    2766 ECB             :                 }
    2767 CBC           3 :                 break;
    2768 GBC          54 :             case DCH_TZH:
    2769 CBC          54 :                 INVALID_FOR_INTERVAL;
    2770 GIC          54 :                 sprintf(s, "%c%02d",
    2771 GBC          54 :                         (tm->tm_gmtoff >= 0) ? '+' : '-',
    2772 GIC          54 :                         abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
    2773 GBC          54 :                 s += strlen(s);
    2774              54 :                 break;
    2775 GIC          54 :             case DCH_TZM:
    2776 GBC          54 :                 INVALID_FOR_INTERVAL;
    2777 GIC          54 :                 sprintf(s, "%02d",
    2778              54 :                         (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
    2779              54 :                 s += strlen(s);
    2780              54 :                 break;
    2781 CBC          54 :             case DCH_OF:
    2782              54 :                 INVALID_FOR_INTERVAL;
    2783             108 :                 sprintf(s, "%c%0*d",
    2784              54 :                         (tm->tm_gmtoff >= 0) ? '+' : '-',
    2785              54 :                         S_FM(n->suffix) ? 0 : 2,
    2786              54 :                         abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
    2787              54 :                 s += strlen(s);
    2788 GBC          54 :                 if (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR != 0)
    2789 ECB             :                 {
    2790 GIC          36 :                     sprintf(s, ":%02d",
    2791 GBC          36 :                             (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
    2792 GIC          36 :                     s += strlen(s);
    2793 EUB             :                 }
    2794 GBC          54 :                 break;
    2795 GIC         381 :             case DCH_A_D:
    2796 EUB             :             case DCH_B_C:
    2797 GIC         381 :                 INVALID_FOR_INTERVAL;
    2798             381 :                 strcpy(s, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
    2799             381 :                 s += strlen(s);
    2800             381 :                 break;
    2801 LBC           0 :             case DCH_AD:
    2802 ECB             :             case DCH_BC:
    2803 LBC           0 :                 INVALID_FOR_INTERVAL;
    2804               0 :                 strcpy(s, (tm->tm_year <= 0 ? BC_STR : AD_STR));
    2805               0 :                 s += strlen(s);
    2806               0 :                 break;
    2807 CBC         381 :             case DCH_a_d:
    2808 EUB             :             case DCH_b_c:
    2809 CBC         381 :                 INVALID_FOR_INTERVAL;
    2810 GIC         381 :                 strcpy(s, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
    2811 GBC         381 :                 s += strlen(s);
    2812 GIC         381 :                 break;
    2813 GBC         381 :             case DCH_ad:
    2814 EUB             :             case DCH_bc:
    2815 GIC         381 :                 INVALID_FOR_INTERVAL;
    2816 GBC         381 :                 strcpy(s, (tm->tm_year <= 0 ? bc_STR : ad_STR));
    2817 GIC         381 :                 s += strlen(s);
    2818             381 :                 break;
    2819             762 :             case DCH_MONTH:
    2820             762 :                 INVALID_FOR_INTERVAL;
    2821 CBC         762 :                 if (!tm->tm_mon)
    2822 LBC           0 :                     break;
    2823 CBC         762 :                 if (S_TM(n->suffix))
    2824 ECB             :                 {
    2825 LBC           0 :                     char       *str = str_toupper_z(localized_full_months[tm->tm_mon - 1], collid);
    2826 ECB             : 
    2827 LBC           0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    2828 UBC           0 :                         strcpy(s, str);
    2829 ECB             :                     else
    2830 UIC           0 :                         ereport(ERROR,
    2831 ECB             :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2832                 :                                  errmsg("localized string format value too long")));
    2833                 :                 }
    2834                 :                 else
    2835 GIC         762 :                     sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
    2836 GBC         762 :                             asc_toupper_z(months_full[tm->tm_mon - 1]));
    2837 GIC         762 :                 s += strlen(s);
    2838             762 :                 break;
    2839             762 :             case DCH_Month:
    2840             762 :                 INVALID_FOR_INTERVAL;
    2841 CBC         762 :                 if (!tm->tm_mon)
    2842 LBC           0 :                     break;
    2843 CBC         762 :                 if (S_TM(n->suffix))
    2844 ECB             :                 {
    2845 LBC           0 :                     char       *str = str_initcap_z(localized_full_months[tm->tm_mon - 1], collid);
    2846 ECB             : 
    2847 UBC           0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    2848 LBC           0 :                         strcpy(s, str);
    2849                 :                     else
    2850 UBC           0 :                         ereport(ERROR,
    2851                 :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2852 EUB             :                                  errmsg("localized string format value too long")));
    2853                 :                 }
    2854                 :                 else
    2855 GBC         762 :                     sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
    2856 GIC         762 :                             months_full[tm->tm_mon - 1]);
    2857             762 :                 s += strlen(s);
    2858             762 :                 break;
    2859             762 :             case DCH_month:
    2860 CBC         762 :                 INVALID_FOR_INTERVAL;
    2861             762 :                 if (!tm->tm_mon)
    2862 LBC           0 :                     break;
    2863 CBC         762 :                 if (S_TM(n->suffix))
    2864 ECB             :                 {
    2865 LBC           0 :                     char       *str = str_tolower_z(localized_full_months[tm->tm_mon - 1], collid);
    2866 EUB             : 
    2867 LBC           0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    2868 UIC           0 :                         strcpy(s, str);
    2869 EUB             :                     else
    2870 UIC           0 :                         ereport(ERROR,
    2871 EUB             :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2872                 :                                  errmsg("localized string format value too long")));
    2873                 :                 }
    2874                 :                 else
    2875 GIC         762 :                     sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
    2876             762 :                             asc_tolower_z(months_full[tm->tm_mon - 1]));
    2877             762 :                 s += strlen(s);
    2878             762 :                 break;
    2879 CBC         393 :             case DCH_MON:
    2880             393 :                 INVALID_FOR_INTERVAL;
    2881             393 :                 if (!tm->tm_mon)
    2882 LBC           0 :                     break;
    2883 CBC         393 :                 if (S_TM(n->suffix))
    2884                 :                 {
    2885              12 :                     char       *str = str_toupper_z(localized_abbrev_months[tm->tm_mon - 1], collid);
    2886 EUB             : 
    2887 CBC          12 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    2888              12 :                         strcpy(s, str);
    2889 ECB             :                     else
    2890 LBC           0 :                         ereport(ERROR,
    2891 ECB             :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2892                 :                                  errmsg("localized string format value too long")));
    2893 EUB             :                 }
    2894                 :                 else
    2895 GBC         381 :                     strcpy(s, asc_toupper_z(months[tm->tm_mon - 1]));
    2896             393 :                 s += strlen(s);
    2897 GIC         393 :                 break;
    2898 GBC         423 :             case DCH_Mon:
    2899 GIC         423 :                 INVALID_FOR_INTERVAL;
    2900             423 :                 if (!tm->tm_mon)
    2901 UIC           0 :                     break;
    2902 GIC         423 :                 if (S_TM(n->suffix))
    2903 ECB             :                 {
    2904 LBC           0 :                     char       *str = str_initcap_z(localized_abbrev_months[tm->tm_mon - 1], collid);
    2905 ECB             : 
    2906 LBC           0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    2907               0 :                         strcpy(s, str);
    2908 ECB             :                     else
    2909 LBC           0 :                         ereport(ERROR,
    2910                 :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2911 EUB             :                                  errmsg("localized string format value too long")));
    2912                 :                 }
    2913                 :                 else
    2914 GBC         423 :                     strcpy(s, months[tm->tm_mon - 1]);
    2915 GIC         423 :                 s += strlen(s);
    2916 GBC         423 :                 break;
    2917 GIC         381 :             case DCH_mon:
    2918             381 :                 INVALID_FOR_INTERVAL;
    2919             381 :                 if (!tm->tm_mon)
    2920 UIC           0 :                     break;
    2921 CBC         381 :                 if (S_TM(n->suffix))
    2922 ECB             :                 {
    2923 LBC           0 :                     char       *str = str_tolower_z(localized_abbrev_months[tm->tm_mon - 1], collid);
    2924 ECB             : 
    2925 LBC           0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    2926               0 :                         strcpy(s, str);
    2927 ECB             :                     else
    2928 UIC           0 :                         ereport(ERROR,
    2929 EUB             :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2930                 :                                  errmsg("localized string format value too long")));
    2931                 :                 }
    2932                 :                 else
    2933 GIC         381 :                     strcpy(s, asc_tolower_z(months[tm->tm_mon - 1]));
    2934 GBC         381 :                 s += strlen(s);
    2935 GIC         381 :                 break;
    2936             771 :             case DCH_MM:
    2937             771 :                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_mon >= 0) ? 2 : 3,
    2938                 :                         tm->tm_mon);
    2939 CBC         771 :                 if (S_THth(n->suffix))
    2940 LBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    2941 CBC         771 :                 s += strlen(s);
    2942             771 :                 break;
    2943             762 :             case DCH_DAY:
    2944             762 :                 INVALID_FOR_INTERVAL;
    2945             762 :                 if (S_TM(n->suffix))
    2946                 :                 {
    2947 UBC           0 :                     char       *str = str_toupper_z(localized_full_days[tm->tm_wday], collid);
    2948                 : 
    2949               0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    2950               0 :                         strcpy(s, str);
    2951                 :                     else
    2952               0 :                         ereport(ERROR,
    2953                 :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2954                 :                                  errmsg("localized string format value too long")));
    2955                 :                 }
    2956                 :                 else
    2957 CBC         762 :                     sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
    2958             762 :                             asc_toupper_z(days[tm->tm_wday]));
    2959             762 :                 s += strlen(s);
    2960             762 :                 break;
    2961             762 :             case DCH_Day:
    2962             762 :                 INVALID_FOR_INTERVAL;
    2963 GIC         762 :                 if (S_TM(n->suffix))
    2964 EUB             :                 {
    2965 UIC           0 :                     char       *str = str_initcap_z(localized_full_days[tm->tm_wday], collid);
    2966 EUB             : 
    2967 UBC           0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    2968 UIC           0 :                         strcpy(s, str);
    2969 EUB             :                     else
    2970 UIC           0 :                         ereport(ERROR,
    2971                 :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2972                 :                                  errmsg("localized string format value too long")));
    2973                 :                 }
    2974 ECB             :                 else
    2975 CBC         762 :                     sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
    2976             762 :                             days[tm->tm_wday]);
    2977             762 :                 s += strlen(s);
    2978             762 :                 break;
    2979             762 :             case DCH_day:
    2980 GIC         762 :                 INVALID_FOR_INTERVAL;
    2981 GBC         762 :                 if (S_TM(n->suffix))
    2982                 :                 {
    2983 UBC           0 :                     char       *str = str_tolower_z(localized_full_days[tm->tm_wday], collid);
    2984 EUB             : 
    2985 UIC           0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    2986 UBC           0 :                         strcpy(s, str);
    2987                 :                     else
    2988 UIC           0 :                         ereport(ERROR,
    2989                 :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    2990                 :                                  errmsg("localized string format value too long")));
    2991 ECB             :                 }
    2992                 :                 else
    2993 CBC         762 :                     sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
    2994             762 :                             asc_tolower_z(days[tm->tm_wday]));
    2995 GIC         762 :                 s += strlen(s);
    2996 CBC         762 :                 break;
    2997             381 :             case DCH_DY:
    2998 GIC         381 :                 INVALID_FOR_INTERVAL;
    2999 CBC         381 :                 if (S_TM(n->suffix))
    3000 ECB             :                 {
    3001 UBC           0 :                     char       *str = str_toupper_z(localized_abbrev_days[tm->tm_wday], collid);
    3002 ECB             : 
    3003 LBC           0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    3004               0 :                         strcpy(s, str);
    3005 ECB             :                     else
    3006 LBC           0 :                         ereport(ERROR,
    3007 EUB             :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    3008 ECB             :                                  errmsg("localized string format value too long")));
    3009                 :                 }
    3010                 :                 else
    3011 CBC         381 :                     strcpy(s, asc_toupper_z(days_short[tm->tm_wday]));
    3012             381 :                 s += strlen(s);
    3013             381 :                 break;
    3014 GBC         381 :             case DCH_Dy:
    3015 CBC         381 :                 INVALID_FOR_INTERVAL;
    3016             381 :                 if (S_TM(n->suffix))
    3017 ECB             :                 {
    3018 LBC           0 :                     char       *str = str_initcap_z(localized_abbrev_days[tm->tm_wday], collid);
    3019 ECB             : 
    3020 LBC           0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    3021 UBC           0 :                         strcpy(s, str);
    3022 ECB             :                     else
    3023 LBC           0 :                         ereport(ERROR,
    3024 ECB             :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    3025                 :                                  errmsg("localized string format value too long")));
    3026                 :                 }
    3027                 :                 else
    3028 GBC         381 :                     strcpy(s, days_short[tm->tm_wday]);
    3029 CBC         381 :                 s += strlen(s);
    3030             381 :                 break;
    3031             381 :             case DCH_dy:
    3032             381 :                 INVALID_FOR_INTERVAL;
    3033 GIC         381 :                 if (S_TM(n->suffix))
    3034 ECB             :                 {
    3035 UBC           0 :                     char       *str = str_tolower_z(localized_abbrev_days[tm->tm_wday], collid);
    3036 ECB             : 
    3037 LBC           0 :                     if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
    3038               0 :                         strcpy(s, str);
    3039 ECB             :                     else
    3040 UBC           0 :                         ereport(ERROR,
    3041 ECB             :                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    3042                 :                                  errmsg("localized string format value too long")));
    3043 EUB             :                 }
    3044 ECB             :                 else
    3045 CBC         381 :                     strcpy(s, asc_tolower_z(days_short[tm->tm_wday]));
    3046             381 :                 s += strlen(s);
    3047             381 :                 break;
    3048 GBC        1524 :             case DCH_DDD:
    3049                 :             case DCH_IDDD:
    3050 GIC        1524 :                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 3,
    3051 CBC        1524 :                         (n->key->id == DCH_DDD) ?
    3052                 :                         tm->tm_yday :
    3053             762 :                         date2isoyearday(tm->tm_year, tm->tm_mon, tm->tm_mday));
    3054 GIC        1524 :                 if (S_THth(n->suffix))
    3055 UIC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3056 CBC        1524 :                 s += strlen(s);
    3057 GIC        1524 :                 break;
    3058 CBC         783 :             case DCH_DD:
    3059             783 :                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mday);
    3060 GIC         783 :                 if (S_THth(n->suffix))
    3061 UBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3062 CBC         783 :                 s += strlen(s);
    3063 GBC         783 :                 break;
    3064 CBC         762 :             case DCH_D:
    3065             762 :                 INVALID_FOR_INTERVAL;
    3066             762 :                 sprintf(s, "%d", tm->tm_wday + 1);
    3067             762 :                 if (S_THth(n->suffix))
    3068 LBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3069 CBC         762 :                 s += strlen(s);
    3070             762 :                 break;
    3071 GBC         762 :             case DCH_ID:
    3072 CBC         762 :                 INVALID_FOR_INTERVAL;
    3073             762 :                 sprintf(s, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
    3074             762 :                 if (S_THth(n->suffix))
    3075 UIC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3076 CBC         762 :                 s += strlen(s);
    3077             762 :                 break;
    3078             762 :             case DCH_WW:
    3079             762 :                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
    3080             762 :                         (tm->tm_yday - 1) / 7 + 1);
    3081             762 :                 if (S_THth(n->suffix))
    3082 UIC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3083 GIC         762 :                 s += strlen(s);
    3084             762 :                 break;
    3085 CBC         762 :             case DCH_IW:
    3086             762 :                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
    3087 ECB             :                         date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
    3088 CBC         762 :                 if (S_THth(n->suffix))
    3089 LBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3090 GIC         762 :                 s += strlen(s);
    3091 CBC         762 :                 break;
    3092             762 :             case DCH_Q:
    3093             762 :                 if (!tm->tm_mon)
    3094 LBC           0 :                     break;
    3095 CBC         762 :                 sprintf(s, "%d", (tm->tm_mon - 1) / 3 + 1);
    3096             762 :                 if (S_THth(n->suffix))
    3097 UIC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3098 GIC         762 :                 s += strlen(s);
    3099 CBC         762 :                 break;
    3100             762 :             case DCH_CC:
    3101 GBC         762 :                 if (is_interval)    /* straight calculation */
    3102 LBC           0 :                     i = tm->tm_year / 100;
    3103 ECB             :                 else
    3104                 :                 {
    3105 GIC         762 :                     if (tm->tm_year > 0)
    3106 ECB             :                         /* Century 20 == 1901 - 2000 */
    3107 CBC         750 :                         i = (tm->tm_year - 1) / 100 + 1;
    3108 ECB             :                     else
    3109                 :                         /* Century 6BC == 600BC - 501BC */
    3110 CBC          12 :                         i = tm->tm_year / 100 - 1;
    3111 ECB             :                 }
    3112 GIC         762 :                 if (i <= 99 && i >= -99)
    3113             762 :                     sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (i >= 0) ? 2 : 3, i);
    3114 ECB             :                 else
    3115 LBC           0 :                     sprintf(s, "%d", i);
    3116 GBC         762 :                 if (S_THth(n->suffix))
    3117 LBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3118 CBC         762 :                 s += strlen(s);
    3119             762 :                 break;
    3120 GIC         762 :             case DCH_Y_YYY:
    3121 CBC         762 :                 i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000;
    3122             762 :                 sprintf(s, "%d,%03d", i,
    3123             762 :                         ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000));
    3124             762 :                 if (S_THth(n->suffix))
    3125 UIC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3126 GIC         762 :                 s += strlen(s);
    3127 CBC         762 :                 break;
    3128            3450 :             case DCH_YYYY:
    3129 EUB             :             case DCH_IYYY:
    3130 CBC        6900 :                 sprintf(s, "%0*d",
    3131            3450 :                         S_FM(n->suffix) ? 0 :
    3132            2688 :                         (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 4 : 5,
    3133 GIC        3450 :                         (n->key->id == DCH_YYYY ?
    3134            2688 :                          ADJUST_YEAR(tm->tm_year, is_interval) :
    3135             762 :                          ADJUST_YEAR(date2isoyear(tm->tm_year,
    3136                 :                                                   tm->tm_mon,
    3137                 :                                                   tm->tm_mday),
    3138                 :                                      is_interval)));
    3139            3450 :                 if (S_THth(n->suffix))
    3140 CBC         762 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3141 GIC        3450 :                 s += strlen(s);
    3142            3450 :                 break;
    3143            1524 :             case DCH_YYY:
    3144 ECB             :             case DCH_IYY:
    3145 GIC        3048 :                 sprintf(s, "%0*d",
    3146            1524 :                         S_FM(n->suffix) ? 0 :
    3147 CBC         762 :                         (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 3 : 4,
    3148            1524 :                         (n->key->id == DCH_YYY ?
    3149 GIC        1524 :                          ADJUST_YEAR(tm->tm_year, is_interval) :
    3150 CBC        1524 :                          ADJUST_YEAR(date2isoyear(tm->tm_year,
    3151                 :                                                   tm->tm_mon,
    3152                 :                                                   tm->tm_mday),
    3153 GIC        3048 :                                      is_interval)) % 1000);
    3154            1524 :                 if (S_THth(n->suffix))
    3155 UIC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3156 GIC        1524 :                 s += strlen(s);
    3157 CBC        1524 :                 break;
    3158 GIC        1524 :             case DCH_YY:
    3159                 :             case DCH_IY:
    3160            3048 :                 sprintf(s, "%0*d",
    3161            1524 :                         S_FM(n->suffix) ? 0 :
    3162             762 :                         (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 2 : 3,
    3163 CBC        1524 :                         (n->key->id == DCH_YY ?
    3164 GIC        1524 :                          ADJUST_YEAR(tm->tm_year, is_interval) :
    3165 CBC        1524 :                          ADJUST_YEAR(date2isoyear(tm->tm_year,
    3166                 :                                                   tm->tm_mon,
    3167                 :                                                   tm->tm_mday),
    3168 GIC        3048 :                                      is_interval)) % 100);
    3169            1524 :                 if (S_THth(n->suffix))
    3170 UIC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3171 GIC        1524 :                 s += strlen(s);
    3172 CBC        1524 :                 break;
    3173 GIC        1524 :             case DCH_Y:
    3174                 :             case DCH_I:
    3175            1524 :                 sprintf(s, "%1d",
    3176            1524 :                         (n->key->id == DCH_Y ?
    3177            1524 :                          ADJUST_YEAR(tm->tm_year, is_interval) :
    3178            1524 :                          ADJUST_YEAR(date2isoyear(tm->tm_year,
    3179                 :                                                   tm->tm_mon,
    3180                 :                                                   tm->tm_mday),
    3181 CBC        3048 :                                      is_interval)) % 10);
    3182 GIC        1524 :                 if (S_THth(n->suffix))
    3183 UIC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3184 CBC        1524 :                 s += strlen(s);
    3185            1524 :                 break;
    3186             924 :             case DCH_RM:
    3187                 :                 /* FALLTHROUGH */
    3188 ECB             :             case DCH_rm:
    3189 EUB             : 
    3190                 :                 /*
    3191                 :                  * For intervals, values like '12 month' will be reduced to 0
    3192                 :                  * month and some years.  These should be processed.
    3193                 :                  */
    3194 GBC         924 :                 if (!tm->tm_mon && !tm->tm_year)
    3195 ECB             :                     break;
    3196                 :                 else
    3197                 :                 {
    3198 CBC         918 :                     int         mon = 0;
    3199 ECB             :                     const char *const *months;
    3200                 : 
    3201 GIC         918 :                     if (n->key->id == DCH_RM)
    3202             840 :                         months = rm_months_upper;
    3203                 :                     else
    3204 CBC          78 :                         months = rm_months_lower;
    3205 ECB             : 
    3206                 :                     /*
    3207                 :                      * Compute the position in the roman-numeral array.  Note
    3208                 :                      * that the contents of the array are reversed, December
    3209                 :                      * being first and January last.
    3210                 :                      */
    3211 GIC         918 :                     if (tm->tm_mon == 0)
    3212                 :                     {
    3213                 :                         /*
    3214                 :                          * This case is special, and tracks the case of full
    3215                 :                          * interval years.
    3216                 :                          */
    3217              12 :                         mon = tm->tm_year >= 0 ? 0 : MONTHS_PER_YEAR - 1;
    3218                 :                     }
    3219             906 :                     else if (tm->tm_mon < 0)
    3220                 :                     {
    3221                 :                         /*
    3222 ECB             :                          * Negative case.  In this case, the calculation is
    3223                 :                          * reversed, where -1 means December, -2 November,
    3224                 :                          * etc.
    3225                 :                          */
    3226 GIC          72 :                         mon = -1 * (tm->tm_mon + 1);
    3227                 :                     }
    3228                 :                     else
    3229 ECB             :                     {
    3230                 :                         /*
    3231                 :                          * Common case, with a strictly positive value.  The
    3232                 :                          * position in the array matches with the value of
    3233                 :                          * tm_mon.
    3234                 :                          */
    3235 CBC         834 :                         mon = MONTHS_PER_YEAR - tm->tm_mon;
    3236                 :                     }
    3237 ECB             : 
    3238 GIC         918 :                     sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
    3239             918 :                             months[mon]);
    3240             918 :                     s += strlen(s);
    3241                 :                 }
    3242             918 :                 break;
    3243 LBC           0 :             case DCH_W:
    3244               0 :                 sprintf(s, "%d", (tm->tm_mday - 1) / 7 + 1);
    3245 UIC           0 :                 if (S_THth(n->suffix))
    3246 LBC           0 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3247 UIC           0 :                 s += strlen(s);
    3248 LBC           0 :                 break;
    3249 CBC        1143 :             case DCH_J:
    3250 GIC        1143 :                 sprintf(s, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
    3251            1143 :                 if (S_THth(n->suffix))
    3252             381 :                     str_numth(s, s, S_TH_TYPE(n->suffix));
    3253 CBC        1143 :                 s += strlen(s);
    3254 GIC        1143 :                 break;
    3255 ECB             :         }
    3256                 :     }
    3257                 : 
    3258 GIC        4552 :     *s = '\0';
    3259            4552 : }
    3260                 : 
    3261 ECB             : /*
    3262                 :  * Process the string 'in' as denoted by the array of FormatNodes 'node[]'.
    3263                 :  * The TmFromChar struct pointed to by 'out' is populated with the results.
    3264                 :  *
    3265                 :  * 'collid' identifies the collation to use, if needed.
    3266                 :  * 'std' specifies standard parsing mode.
    3267                 :  *
    3268                 :  * If escontext points to an ErrorSaveContext, data errors will be reported
    3269                 :  * by filling that struct; the caller must test SOFT_ERROR_OCCURRED() to see
    3270                 :  * whether an error occurred.  Otherwise, errors are thrown.
    3271                 :  *
    3272                 :  * Note: we currently don't have any to_interval() function, so there
    3273                 :  * is no need here for INVALID_FOR_INTERVAL checks.
    3274                 :  */
    3275                 : static void
    3276 GIC        4725 : DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
    3277                 :               Oid collid, bool std, Node *escontext)
    3278                 : {
    3279                 :     FormatNode *n;
    3280                 :     const char *s;
    3281                 :     int         len,
    3282 ECB             :                 value;
    3283 CBC        4725 :     bool        fx_mode = std;
    3284                 : 
    3285 ECB             :     /* number of extra skipped characters (more than given in format string) */
    3286 CBC        4725 :     int         extra_skip = 0;
    3287                 : 
    3288                 :     /* cache localized days and months */
    3289 GIC        4725 :     cache_locale_time();
    3290                 : 
    3291           31686 :     for (n = node, s = in; n->type != NODE_TYPE_END && *s != '\0'; n++)
    3292                 :     {
    3293                 :         /*
    3294                 :          * Ignore spaces at the beginning of the string and before fields when
    3295                 :          * not in FX (fixed width) mode.
    3296                 :          */
    3297 CBC       28398 :         if (!fx_mode && (n->type != NODE_TYPE_ACTION || n->key->id != DCH_FX) &&
    3298 GIC        4116 :             (n->type == NODE_TYPE_ACTION || n == node))
    3299 ECB             :         {
    3300 GIC        2274 :             while (*s != '\0' && isspace((unsigned char) *s))
    3301 ECB             :             {
    3302 GIC          42 :                 s++;
    3303              42 :                 extra_skip++;
    3304                 :             }
    3305                 :         }
    3306                 : 
    3307           28398 :         if (n->type == NODE_TYPE_SPACE || n->type == NODE_TYPE_SEPARATOR)
    3308 ECB             :         {
    3309 GIC       12015 :             if (std)
    3310                 :             {
    3311                 :                 /*
    3312                 :                  * Standard mode requires strict matching between format
    3313                 :                  * string separators/spaces and input string.
    3314                 :                  */
    3315           10317 :                 Assert(n->character[0] && !n->character[1]);
    3316 ECB             : 
    3317 CBC       10317 :                 if (*s == n->character[0])
    3318 GIC        8967 :                     s++;
    3319 ECB             :                 else
    3320 GNC        2646 :                     ereturn(escontext,,
    3321                 :                             (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    3322                 :                              errmsg("unmatched format separator \"%c\"",
    3323                 :                                     n->character[0])));
    3324                 :             }
    3325 GIC        1698 :             else if (!fx_mode)
    3326                 :             {
    3327                 :                 /*
    3328 ECB             :                  * In non FX (fixed format) mode one format string space or
    3329                 :                  * separator match to one space or separator in input string.
    3330                 :                  * Or match nothing if there is no space or separator in the
    3331                 :                  * current position of input string.
    3332                 :                  */
    3333 GIC        1686 :                 extra_skip--;
    3334            1686 :                 if (isspace((unsigned char) *s) || is_separator_char(s))
    3335 ECB             :                 {
    3336 GIC        1197 :                     s++;
    3337 CBC        1197 :                     extra_skip++;
    3338                 :                 }
    3339                 :             }
    3340 ECB             :             else
    3341 EUB             :             {
    3342                 :                 /*
    3343 ECB             :                  * In FX mode, on format string space or separator we consume
    3344                 :                  * exactly one character from input string.  Notice we don't
    3345                 :                  * insist that the consumed character match the format's
    3346                 :                  * character.
    3347                 :                  */
    3348 CBC          12 :                 s += pg_mblen(s);
    3349                 :             }
    3350 GIC       10665 :             continue;
    3351                 :         }
    3352 CBC       16383 :         else if (n->type != NODE_TYPE_ACTION)
    3353                 :         {
    3354                 :             /*
    3355 EUB             :              * Text character, so consume one character from input string.
    3356 ECB             :              * Notice we don't insist that the consumed character match the
    3357 EUB             :              * format's character.
    3358 ECB             :              */
    3359 CBC         222 :             if (!fx_mode)
    3360 ECB             :             {
    3361                 :                 /*
    3362                 :                  * In non FX mode we might have skipped some extra characters
    3363                 :                  * (more than specified in format string) before.  In this
    3364                 :                  * case we don't skip input string character, because it might
    3365                 :                  * be part of field.
    3366                 :                  */
    3367 GBC         201 :                 if (extra_skip > 0)
    3368 CBC          12 :                     extra_skip--;
    3369 EUB             :                 else
    3370 CBC         189 :                     s += pg_mblen(s);
    3371 ECB             :             }
    3372                 :             else
    3373                 :             {
    3374 CBC          21 :                 int         chlen = pg_mblen(s);
    3375 EUB             : 
    3376 ECB             :                 /*
    3377                 :                  * Standard mode requires strict match of format characters.
    3378                 :                  */
    3379 CBC          21 :                 if (std && n->type == NODE_TYPE_CHAR &&
    3380              21 :                     strncmp(s, n->character, chlen) != 0)
    3381 GNC          15 :                     ereturn(escontext,,
    3382                 :                             (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    3383                 :                              errmsg("unmatched format character \"%s\"",
    3384                 :                                     n->character)));
    3385 ECB             : 
    3386 GBC           6 :                 s += chlen;
    3387 ECB             :             }
    3388 CBC         207 :             continue;
    3389 ECB             :         }
    3390                 : 
    3391 GNC       16161 :         if (!from_char_set_mode(out, n->key->date_mode, escontext))
    3392 UNC           0 :             return;
    3393 ECB             : 
    3394 CBC       16158 :         switch (n->key->id)
    3395 ECB             :         {
    3396 CBC           6 :             case DCH_FX:
    3397 GBC           6 :                 fx_mode = true;
    3398 GIC           6 :                 break;
    3399               6 :             case DCH_A_M:
    3400                 :             case DCH_P_M:
    3401                 :             case DCH_a_m:
    3402 ECB             :             case DCH_p_m:
    3403 GNC           6 :                 if (!from_char_seq_search(&value, &s, ampm_strings_long,
    3404                 :                                           NULL, InvalidOid,
    3405                 :                                           n, escontext))
    3406 UNC           0 :                     return;
    3407 GNC           6 :                 if (!from_char_set_int(&out->pm, value % 2, n, escontext))
    3408 UNC           0 :                     return;
    3409 GIC           6 :                 out->clock = CLOCK_12_HOUR;
    3410               6 :                 break;
    3411               6 :             case DCH_AM:
    3412                 :             case DCH_PM:
    3413 ECB             :             case DCH_am:
    3414                 :             case DCH_pm:
    3415 GNC           6 :                 if (!from_char_seq_search(&value, &s, ampm_strings,
    3416                 :                                           NULL, InvalidOid,
    3417                 :                                           n, escontext))
    3418 UNC           0 :                     return;
    3419 GNC           6 :                 if (!from_char_set_int(&out->pm, value % 2, n, escontext))
    3420 UNC           0 :                     return;
    3421 GIC           6 :                 out->clock = CLOCK_12_HOUR;
    3422 CBC           6 :                 break;
    3423              39 :             case DCH_HH:
    3424 ECB             :             case DCH_HH12:
    3425 GNC          39 :                 if (from_char_parse_int_len(&out->hh, &s, 2, n, escontext) < 0)
    3426 UNC           0 :                     return;
    3427 GIC          39 :                 out->clock = CLOCK_12_HOUR;
    3428 CBC          39 :                 SKIP_THth(s, n->suffix);
    3429              39 :                 break;
    3430            3435 :             case DCH_HH24:
    3431 GNC        3435 :                 if (from_char_parse_int_len(&out->hh, &s, 2, n, escontext) < 0)
    3432               9 :                     return;
    3433 CBC        3423 :                 SKIP_THth(s, n->suffix);
    3434            3423 :                 break;
    3435            2436 :             case DCH_MI:
    3436 GNC        2436 :                 if (from_char_parse_int(&out->mi, &s, n, escontext) < 0)
    3437 UNC           0 :                     return;
    3438 CBC        2436 :                 SKIP_THth(s, n->suffix);
    3439 GIC        2436 :                 break;
    3440            1770 :             case DCH_SS:
    3441 GNC        1770 :                 if (from_char_parse_int(&out->ss, &s, n, escontext) < 0)
    3442 UNC           0 :                     return;
    3443 CBC        1770 :                 SKIP_THth(s, n->suffix);
    3444 GIC        1770 :                 break;
    3445               3 :             case DCH_MS:        /* millisecond */
    3446 GNC           3 :                 len = from_char_parse_int_len(&out->ms, &s, 3, n, escontext);
    3447               3 :                 if (len < 0)
    3448 UNC           0 :                     return;
    3449                 : 
    3450                 :                 /*
    3451                 :                  * 25 is 0.25 and 250 is 0.25 too; 025 is 0.025 and not 0.25
    3452                 :                  */
    3453 CBC           6 :                 out->ms *= len == 1 ? 100 :
    3454 GIC           3 :                     len == 2 ? 10 : 1;
    3455 ECB             : 
    3456 CBC           3 :                 SKIP_THth(s, n->suffix);
    3457 GIC           3 :                 break;
    3458             111 :             case DCH_FF1:
    3459                 :             case DCH_FF2:
    3460 ECB             :             case DCH_FF3:
    3461                 :             case DCH_FF4:
    3462                 :             case DCH_FF5:
    3463                 :             case DCH_FF6:
    3464 GIC         111 :                 out->ff = n->key->id - DCH_FF1 + 1;
    3465                 :                 /* fall through */
    3466 CBC         111 :             case DCH_US:        /* microsecond */
    3467 GBC         111 :                 len = from_char_parse_int_len(&out->us, &s,
    3468 CBC         111 :                                               n->key->id == DCH_US ? 6 :
    3469                 :                                               out->ff, n, escontext);
    3470 GNC         111 :                 if (len < 0)
    3471 UNC           0 :                     return;
    3472 ECB             : 
    3473 CBC         204 :                 out->us *= len == 1 ? 100000 :
    3474             168 :                     len == 2 ? 10000 :
    3475 GBC         132 :                     len == 3 ? 1000 :
    3476 CBC          96 :                     len == 4 ? 100 :
    3477              39 :                     len == 5 ? 10 : 1;
    3478                 : 
    3479 GIC         111 :                 SKIP_THth(s, n->suffix);
    3480             111 :                 break;
    3481 CBC          12 :             case DCH_SSSS:
    3482 GNC          12 :                 if (from_char_parse_int(&out->ssss, &s, n, escontext) < 0)
    3483 UNC           0 :                     return;
    3484 GBC          12 :                 SKIP_THth(s, n->suffix);
    3485 CBC          12 :                 break;
    3486 GBC           3 :             case DCH_tz:
    3487 ECB             :             case DCH_TZ:
    3488                 :             case DCH_OF:
    3489 GNC           3 :                 ereturn(escontext,,
    3490                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3491                 :                          errmsg("formatting field \"%s\" is only supported in to_char",
    3492                 :                                 n->key->name)));
    3493                 :                 break;
    3494 GBC        1092 :             case DCH_TZH:
    3495 ECB             : 
    3496 EUB             :                 /*
    3497 ECB             :                  * Value of TZH might be negative.  And the issue is that we
    3498                 :                  * might swallow minus sign as the separator.  So, if we have
    3499                 :                  * skipped more characters than specified in the format
    3500                 :                  * string, then we consider prepending last skipped minus to
    3501                 :                  * TZH.
    3502                 :                  */
    3503 GIC        1092 :                 if (*s == '+' || *s == '-' || *s == ' ')
    3504                 :                 {
    3505 GBC        1074 :                     out->tzsign = *s == '-' ? -1 : +1;
    3506 CBC        1074 :                     s++;
    3507 EUB             :                 }
    3508 ECB             :                 else
    3509                 :                 {
    3510 GIC          18 :                     if (extra_skip > 0 && *(s - 1) == '-')
    3511               9 :                         out->tzsign = -1;
    3512 ECB             :                     else
    3513 CBC           9 :                         out->tzsign = +1;
    3514                 :                 }
    3515                 : 
    3516 GNC        1092 :                 if (from_char_parse_int_len(&out->tzh, &s, 2, n, escontext) < 0)
    3517 UNC           0 :                     return;
    3518 GBC        1092 :                 break;
    3519 CBC          54 :             case DCH_TZM:
    3520 ECB             :                 /* assign positive timezone sign if TZH was not seen before */
    3521 CBC          54 :                 if (!out->tzsign)
    3522 GBC           3 :                     out->tzsign = +1;
    3523 GNC          54 :                 if (from_char_parse_int_len(&out->tzm, &s, 2, n, escontext) < 0)
    3524 UNC           0 :                     return;
    3525 CBC          54 :                 break;
    3526 GIC           6 :             case DCH_A_D:
    3527                 :             case DCH_B_C:
    3528 ECB             :             case DCH_a_d:
    3529                 :             case DCH_b_c:
    3530 GNC           6 :                 if (!from_char_seq_search(&value, &s, adbc_strings_long,
    3531                 :                                           NULL, InvalidOid,
    3532                 :                                           n, escontext))
    3533 UNC           0 :                     return;
    3534 GNC           6 :                 if (!from_char_set_int(&out->bc, value % 2, n, escontext))
    3535 UNC           0 :                     return;
    3536 CBC           6 :                 break;
    3537              18 :             case DCH_AD:
    3538                 :             case DCH_BC:
    3539                 :             case DCH_ad:
    3540 ECB             :             case DCH_bc:
    3541 GNC          18 :                 if (!from_char_seq_search(&value, &s, adbc_strings,
    3542                 :                                           NULL, InvalidOid,
    3543                 :                                           n, escontext))
    3544 UNC           0 :                     return;
    3545 GNC          18 :                 if (!from_char_set_int(&out->bc, value % 2, n, escontext))
    3546 UNC           0 :                     return;
    3547 CBC          18 :                 break;
    3548              12 :             case DCH_MONTH:
    3549 ECB             :             case DCH_Month:
    3550                 :             case DCH_month:
    3551 GNC          12 :                 if (!from_char_seq_search(&value, &s, months_full,
    3552              12 :                                           S_TM(n->suffix) ? localized_full_months : NULL,
    3553                 :                                           collid,
    3554                 :                                           n, escontext))
    3555 UNC           0 :                     return;
    3556 GNC           9 :                 if (!from_char_set_int(&out->mm, value + 1, n, escontext))
    3557 UNC           0 :                     return;
    3558 CBC           9 :                 break;
    3559              66 :             case DCH_MON:
    3560 ECB             :             case DCH_Mon:
    3561 EUB             :             case DCH_mon:
    3562 GNC          66 :                 if (!from_char_seq_search(&value, &s, months,
    3563              66 :                                           S_TM(n->suffix) ? localized_abbrev_months : NULL,
    3564                 :                                           collid,
    3565                 :                                           n, escontext))
    3566 UNC           0 :                     return;
    3567 GNC          60 :                 if (!from_char_set_int(&out->mm, value + 1, n, escontext))
    3568 UNC           0 :                     return;
    3569 CBC          57 :                 break;
    3570            2169 :             case DCH_MM:
    3571 GNC        2169 :                 if (from_char_parse_int(&out->mm, &s, n, escontext) < 0)
    3572 UNC           0 :                     return;
    3573 CBC        2160 :                 SKIP_THth(s, n->suffix);
    3574            2160 :                 break;
    3575               3 :             case DCH_DAY:
    3576 ECB             :             case DCH_Day:
    3577                 :             case DCH_day:
    3578 GNC           3 :                 if (!from_char_seq_search(&value, &s, days,
    3579               3 :                                           S_TM(n->suffix) ? localized_full_days : NULL,
    3580                 :                                           collid,
    3581                 :                                           n, escontext))
    3582 UNC           0 :                     return;
    3583 GNC           3 :                 if (!from_char_set_int(&out->d, value, n, escontext))
    3584 UNC           0 :                     return;
    3585 GIC           3 :                 out->d++;
    3586               3 :                 break;
    3587               9 :             case DCH_DY:
    3588                 :             case DCH_Dy:
    3589                 :             case DCH_dy:
    3590 GNC           9 :                 if (!from_char_seq_search(&value, &s, days_short,
    3591               9 :                                           S_TM(n->suffix) ? localized_abbrev_days : NULL,
    3592                 :                                           collid,
    3593                 :                                           n, escontext))
    3594 UNC           0 :                     return;
    3595 GNC           9 :                 if (!from_char_set_int(&out->d, value, n, escontext))
    3596 UNC           0 :                     return;
    3597 CBC           9 :                 out->d++;
    3598               9 :                 break;
    3599              18 :             case DCH_DDD:
    3600 GNC          18 :                 if (from_char_parse_int(&out->ddd, &s, n, escontext) < 0)
    3601 UNC           0 :                     return;
    3602 CBC          18 :                 SKIP_THth(s, n->suffix);
    3603              18 :                 break;
    3604               3 :             case DCH_IDDD:
    3605 GNC           3 :                 if (from_char_parse_int_len(&out->ddd, &s, 3, n, escontext) < 0)
    3606 UNC           0 :                     return;
    3607 GIC           3 :                 SKIP_THth(s, n->suffix);
    3608               3 :                 break;
    3609            2208 :             case DCH_DD:
    3610 GNC        2208 :                 if (from_char_parse_int(&out->dd, &s, n, escontext) < 0)
    3611 UNC           0 :                     return;
    3612 CBC        2202 :                 SKIP_THth(s, n->suffix);
    3613 GBC        2202 :                 break;
    3614 GIC           3 :             case DCH_D:
    3615 GNC           3 :                 if (from_char_parse_int(&out->d, &s, n, escontext) < 0)
    3616 UNC           0 :                     return;
    3617 CBC           3 :                 SKIP_THth(s, n->suffix);
    3618 GBC           3 :                 break;
    3619 CBC          12 :             case DCH_ID:
    3620 GNC          12 :                 if (from_char_parse_int_len(&out->d, &s, 1, n, escontext) < 0)
    3621 UNC           0 :                     return;
    3622                 :                 /* Shift numbering to match Gregorian where Sunday = 1 */
    3623 CBC          12 :                 if (++out->d > 7)
    3624              12 :                     out->d = 1;
    3625 GIC          12 :                 SKIP_THth(s, n->suffix);
    3626 CBC          12 :                 break;
    3627              15 :             case DCH_WW:
    3628 ECB             :             case DCH_IW:
    3629 GNC          15 :                 if (from_char_parse_int(&out->ww, &s, n, escontext) < 0)
    3630 UNC           0 :                     return;
    3631 CBC          15 :                 SKIP_THth(s, n->suffix);
    3632 GIC          15 :                 break;
    3633 CBC           3 :             case DCH_Q:
    3634 ECB             : 
    3635 EUB             :                 /*
    3636 ECB             :                  * We ignore 'Q' when converting to date because it is unclear
    3637                 :                  * which date in the quarter to use, and some people specify
    3638                 :                  * both quarter and month, so if it was honored it might
    3639                 :                  * conflict with the supplied month. That is also why we don't
    3640                 :                  * throw an error.
    3641                 :                  *
    3642                 :                  * We still parse the source string for an integer, but it
    3643                 :                  * isn't stored anywhere in 'out'.
    3644                 :                  */
    3645 GNC           3 :                 if (from_char_parse_int((int *) NULL, &s, n, escontext) < 0)
    3646 UNC           0 :                     return;
    3647 CBC           3 :                 SKIP_THth(s, n->suffix);
    3648               3 :                 break;
    3649               3 :             case DCH_CC:
    3650 GNC           3 :                 if (from_char_parse_int(&out->cc, &s, n, escontext) < 0)
    3651 UNC           0 :                     return;
    3652 GIC           3 :                 SKIP_THth(s, n->suffix);
    3653 CBC           3 :                 break;
    3654               3 :             case DCH_Y_YYY:
    3655 EUB             :                 {
    3656 ECB             :                     int         matched,
    3657                 :                                 years,
    3658                 :                                 millennia,
    3659                 :                                 nch;
    3660                 : 
    3661 CBC           3 :                     matched = sscanf(s, "%d,%03d%n", &millennia, &years, &nch);
    3662 GIC           3 :                     if (matched < 2)
    3663 UNC           0 :                         ereturn(escontext,,
    3664                 :                                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    3665                 :                                  errmsg("invalid input string for \"Y,YYY\"")));
    3666 GBC           3 :                     years += (millennia * 1000);
    3667 GNC           3 :                     if (!from_char_set_int(&out->year, years, n, escontext))
    3668 UNC           0 :                         return;
    3669 GBC           3 :                     out->yysz = 4;
    3670 CBC           3 :                     s += nch;
    3671               3 :                     SKIP_THth(s, n->suffix);
    3672 ECB             :                 }
    3673 GBC           3 :                 break;
    3674 CBC        2589 :             case DCH_YYYY:
    3675 ECB             :             case DCH_IYYY:
    3676 GNC        2589 :                 if (from_char_parse_int(&out->year, &s, n, escontext) < 0)
    3677              21 :                     return;
    3678 GBC        2562 :                 out->yysz = 4;
    3679 CBC        2562 :                 SKIP_THth(s, n->suffix);
    3680            2562 :                 break;
    3681 GIC           6 :             case DCH_YYY:
    3682                 :             case DCH_IYY:
    3683 GNC           6 :                 len = from_char_parse_int(&out->year, &s, n, escontext);
    3684               6 :                 if (len < 0)
    3685 UNC           0 :                     return;
    3686 GIC           6 :                 if (len < 4)
    3687 CBC           6 :                     out->year = adjust_partial_year_to_2020(out->year);
    3688               6 :                 out->yysz = 3;
    3689 GIC           6 :                 SKIP_THth(s, n->suffix);
    3690 CBC           6 :                 break;
    3691              24 :             case DCH_YY:
    3692                 :             case DCH_IY:
    3693 GNC          24 :                 len = from_char_parse_int(&out->year, &s, n, escontext);
    3694              24 :                 if (len < 0)
    3695 UNC           0 :                     return;
    3696 GIC          24 :                 if (len < 4)
    3697              24 :                     out->year = adjust_partial_year_to_2020(out->year);
    3698              24 :                 out->yysz = 2;
    3699              24 :                 SKIP_THth(s, n->suffix);
    3700              24 :                 break;
    3701 CBC           6 :             case DCH_Y:
    3702                 :             case DCH_I:
    3703 GNC           6 :                 len = from_char_parse_int(&out->year, &s, n, escontext);
    3704               6 :                 if (len < 0)
    3705 UNC           0 :                     return;
    3706 GIC           6 :                 if (len < 4)
    3707               6 :                     out->year = adjust_partial_year_to_2020(out->year);
    3708               6 :                 out->yysz = 1;
    3709 CBC           6 :                 SKIP_THth(s, n->suffix);
    3710               6 :                 break;
    3711 GIC           3 :             case DCH_RM:
    3712 ECB             :             case DCH_rm:
    3713 GNC           3 :                 if (!from_char_seq_search(&value, &s, rm_months_lower,
    3714                 :                                           NULL, InvalidOid,
    3715                 :                                           n, escontext))
    3716 UNC           0 :                     return;
    3717 GNC           3 :                 if (!from_char_set_int(&out->mm, MONTHS_PER_YEAR - value, n,
    3718                 :                                        escontext))
    3719 UNC           0 :                     return;
    3720 GIC           3 :                 break;
    3721               3 :             case DCH_W:
    3722 GNC           3 :                 if (from_char_parse_int(&out->w, &s, n, escontext) < 0)
    3723 UNC           0 :                     return;
    3724 GIC           3 :                 SKIP_THth(s, n->suffix);
    3725               3 :                 break;
    3726               3 :             case DCH_J:
    3727 GNC           3 :                 if (from_char_parse_int(&out->j, &s, n, escontext) < 0)
    3728 UNC           0 :                     return;
    3729 CBC           3 :                 SKIP_THth(s, n->suffix);
    3730 GIC           3 :                 break;
    3731 EUB             :         }
    3732                 : 
    3733                 :         /* Ignore all spaces after fields */
    3734 GIC       16089 :         if (!fx_mode)
    3735 ECB             :         {
    3736 GIC        2190 :             extra_skip = 0;
    3737            2727 :             while (*s != '\0' && isspace((unsigned char) *s))
    3738                 :             {
    3739             537 :                 s++;
    3740             537 :                 extra_skip++;
    3741 ECB             :             }
    3742                 :         }
    3743                 :     }
    3744                 : 
    3745                 :     /*
    3746                 :      * Standard parsing mode doesn't allow unmatched format patterns or
    3747                 :      * trailing characters in the input string.
    3748                 :      */
    3749 CBC        3288 :     if (std)
    3750                 :     {
    3751            2832 :         if (n->type != NODE_TYPE_END)
    3752 GNC         927 :             ereturn(escontext,,
    3753                 :                     (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    3754                 :                      errmsg("input string is too short for datetime format")));
    3755 ECB             : 
    3756 GIC        2247 :         while (*s != '\0' && isspace((unsigned char) *s))
    3757             342 :             s++;
    3758                 : 
    3759            1905 :         if (*s != '\0')
    3760 GNC         348 :             ereturn(escontext,,
    3761                 :                     (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    3762                 :                      errmsg("trailing characters remain in input string after datetime format")));
    3763                 :     }
    3764                 : }
    3765                 : 
    3766                 : /*
    3767                 :  * The invariant for DCH cache entry management is that DCHCounter is equal
    3768                 :  * to the maximum age value among the existing entries, and we increment it
    3769                 :  * whenever an access occurs.  If we approach overflow, deal with that by
    3770                 :  * halving all the age values, so that we retain a fairly accurate idea of
    3771                 :  * which entries are oldest.
    3772                 :  */
    3773 ECB             : static inline void
    3774 CBC        9683 : DCH_prevent_counter_overflow(void)
    3775 ECB             : {
    3776 GIC        9683 :     if (DCHCounter >= (INT_MAX - 1))
    3777                 :     {
    3778 UIC           0 :         for (int i = 0; i < n_DCHCache; i++)
    3779               0 :             DCHCache[i]->age >>= 1;
    3780 LBC           0 :         DCHCounter >>= 1;
    3781 ECB             :     }
    3782 CBC        9683 : }
    3783                 : 
    3784                 : /*
    3785                 :  * Get mask of date/time/zone components present in format nodes.
    3786                 :  */
    3787                 : static int
    3788 GNC        1557 : DCH_datetime_type(FormatNode *node)
    3789                 : {
    3790                 :     FormatNode *n;
    3791 GIC        1557 :     int         flags = 0;
    3792                 : 
    3793           13278 :     for (n = node; n->type != NODE_TYPE_END; n++)
    3794                 :     {
    3795           11721 :         if (n->type != NODE_TYPE_ACTION)
    3796            4902 :             continue;
    3797                 : 
    3798            6819 :         switch (n->key->id)
    3799                 :         {
    3800 UIC           0 :             case DCH_FX:
    3801               0 :                 break;
    3802 GIC        3210 :             case DCH_A_M:
    3803                 :             case DCH_P_M:
    3804                 :             case DCH_a_m:
    3805                 :             case DCH_p_m:
    3806                 :             case DCH_AM:
    3807                 :             case DCH_PM:
    3808                 :             case DCH_am:
    3809                 :             case DCH_pm:
    3810                 :             case DCH_HH:
    3811                 :             case DCH_HH12:
    3812                 :             case DCH_HH24:
    3813                 :             case DCH_MI:
    3814                 :             case DCH_SS:
    3815                 :             case DCH_MS:        /* millisecond */
    3816                 :             case DCH_US:        /* microsecond */
    3817                 :             case DCH_FF1:
    3818                 :             case DCH_FF2:
    3819                 :             case DCH_FF3:
    3820                 :             case DCH_FF4:
    3821                 :             case DCH_FF5:
    3822 ECB             :             case DCH_FF6:
    3823                 :             case DCH_SSSS:
    3824 GIC        3210 :                 flags |= DCH_TIMED;
    3825            3210 :                 break;
    3826             774 :             case DCH_tz:
    3827 ECB             :             case DCH_TZ:
    3828                 :             case DCH_OF:
    3829                 :             case DCH_TZH:
    3830                 :             case DCH_TZM:
    3831 CBC         774 :                 flags |= DCH_ZONED;
    3832 GIC         774 :                 break;
    3833            2835 :             case DCH_A_D:
    3834                 :             case DCH_B_C:
    3835                 :             case DCH_a_d:
    3836 ECB             :             case DCH_b_c:
    3837                 :             case DCH_AD:
    3838                 :             case DCH_BC:
    3839                 :             case DCH_ad:
    3840                 :             case DCH_bc:
    3841                 :             case DCH_MONTH:
    3842                 :             case DCH_Month:
    3843                 :             case DCH_month:
    3844                 :             case DCH_MON:
    3845                 :             case DCH_Mon:
    3846                 :             case DCH_mon:
    3847                 :             case DCH_MM:
    3848                 :             case DCH_DAY:
    3849                 :             case DCH_Day:
    3850                 :             case DCH_day:
    3851                 :             case DCH_DY:
    3852                 :             case DCH_Dy:
    3853                 :             case DCH_dy:
    3854                 :             case DCH_DDD:
    3855                 :             case DCH_IDDD:
    3856                 :             case DCH_DD:
    3857                 :             case DCH_D:
    3858                 :             case DCH_ID:
    3859                 :             case DCH_WW:
    3860                 :             case DCH_Q:
    3861                 :             case DCH_CC:
    3862                 :             case DCH_Y_YYY:
    3863                 :             case DCH_YYYY:
    3864                 :             case DCH_IYYY:
    3865                 :             case DCH_YYY:
    3866                 :             case DCH_IYY:
    3867                 :             case DCH_YY:
    3868                 :             case DCH_IY:
    3869                 :             case DCH_Y:
    3870                 :             case DCH_I:
    3871                 :             case DCH_RM:
    3872                 :             case DCH_rm:
    3873                 :             case DCH_W:
    3874                 :             case DCH_J:
    3875 CBC        2835 :                 flags |= DCH_DATED;
    3876            2835 :                 break;
    3877 ECB             :         }
    3878                 :     }
    3879                 : 
    3880 GIC        1557 :     return flags;
    3881                 : }
    3882                 : 
    3883                 : /* select a DCHCacheEntry to hold the given format picture */
    3884                 : static DCHCacheEntry *
    3885 CBC         403 : DCH_cache_getnew(const char *str, bool std)
    3886                 : {
    3887                 :     DCHCacheEntry *ent;
    3888 ECB             : 
    3889                 :     /* Ensure we can advance DCHCounter below */
    3890 CBC         403 :     DCH_prevent_counter_overflow();
    3891                 : 
    3892 ECB             :     /*
    3893                 :      * If cache is full, remove oldest entry (or recycle first not-valid one)
    3894                 :      */
    3895 GIC         403 :     if (n_DCHCache >= DCH_CACHE_ENTRIES)
    3896 ECB             :     {
    3897 CBC         174 :         DCHCacheEntry *old = DCHCache[0];
    3898                 : 
    3899                 : #ifdef DEBUG_TO_FROM_CHAR
    3900                 :         elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
    3901 ECB             : #endif
    3902 GIC         174 :         if (old->valid)
    3903                 :         {
    3904            3450 :             for (int i = 1; i < DCH_CACHE_ENTRIES; i++)
    3905                 :             {
    3906 CBC        3279 :                 ent = DCHCache[i];
    3907 GIC        3279 :                 if (!ent->valid)
    3908                 :                 {
    3909               3 :                     old = ent;
    3910 CBC           3 :                     break;
    3911                 :                 }
    3912 GIC        3276 :                 if (ent->age < old->age)
    3913             204 :                     old = ent;
    3914                 :             }
    3915                 :         }
    3916                 : #ifdef DEBUG_TO_FROM_CHAR
    3917 ECB             :         elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
    3918                 : #endif
    3919 CBC         174 :         old->valid = false;
    3920 GIC         174 :         strlcpy(old->str, str, DCH_CACHE_SIZE + 1);
    3921             174 :         old->age = (++DCHCounter);
    3922 ECB             :         /* caller is expected to fill format, then set valid */
    3923 GIC         174 :         return old;
    3924 ECB             :     }
    3925                 :     else
    3926                 :     {
    3927                 : #ifdef DEBUG_TO_FROM_CHAR
    3928                 :         elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
    3929                 : #endif
    3930 GIC         229 :         Assert(DCHCache[n_DCHCache] == NULL);
    3931             229 :         DCHCache[n_DCHCache] = ent = (DCHCacheEntry *)
    3932             229 :             MemoryContextAllocZero(TopMemoryContext, sizeof(DCHCacheEntry));
    3933 CBC         229 :         ent->valid = false;
    3934 GIC         229 :         strlcpy(ent->str, str, DCH_CACHE_SIZE + 1);
    3935             229 :         ent->std = std;
    3936             229 :         ent->age = (++DCHCounter);
    3937                 :         /* caller is expected to fill format, then set valid */
    3938             229 :         ++n_DCHCache;
    3939             229 :         return ent;
    3940                 :     }
    3941                 : }
    3942                 : 
    3943                 : /* look for an existing DCHCacheEntry matching the given format picture */
    3944                 : static DCHCacheEntry *
    3945 CBC        9280 : DCH_cache_search(const char *str, bool std)
    3946 ECB             : {
    3947                 :     /* Ensure we can advance DCHCounter below */
    3948 GIC        9280 :     DCH_prevent_counter_overflow();
    3949                 : 
    3950           60509 :     for (int i = 0; i < n_DCHCache; i++)
    3951 ECB             :     {
    3952 CBC       60106 :         DCHCacheEntry *ent = DCHCache[i];
    3953                 : 
    3954           60106 :         if (ent->valid && strcmp(ent->str, str) == 0 && ent->std == std)
    3955                 :         {
    3956 GIC        8877 :             ent->age = (++DCHCounter);
    3957            8877 :             return ent;
    3958                 :         }
    3959                 :     }
    3960 EUB             : 
    3961 GIC         403 :     return NULL;
    3962 EUB             : }
    3963                 : 
    3964                 : /* Find or create a DCHCacheEntry for the given format picture */
    3965                 : static DCHCacheEntry *
    3966 GIC        9280 : DCH_cache_fetch(const char *str, bool std)
    3967                 : {
    3968                 :     DCHCacheEntry *ent;
    3969                 : 
    3970            9280 :     if ((ent = DCH_cache_search(str, std)) == NULL)
    3971                 :     {
    3972 ECB             :         /*
    3973                 :          * Not in the cache, must run parser and save a new format-picture to
    3974                 :          * the cache.  Do not mark the cache entry valid until parsing
    3975                 :          * succeeds.
    3976                 :          */
    3977 GIC         403 :         ent = DCH_cache_getnew(str, std);
    3978                 : 
    3979 CBC         403 :         parse_format(ent->format, str, DCH_keywords, DCH_suff, DCH_index,
    3980                 :                      DCH_FLAG | (std ? STD_FLAG : 0), NULL);
    3981 ECB             : 
    3982 GBC         400 :         ent->valid = true;
    3983                 :     }
    3984 CBC        9277 :     return ent;
    3985                 : }
    3986                 : 
    3987 ECB             : /*
    3988                 :  * Format a date/time or interval into a string according to fmt.
    3989                 :  * We parse fmt into a list of FormatNodes.  This is then passed to DCH_to_char
    3990                 :  * for formatting.
    3991                 :  */
    3992                 : static text *
    3993 GIC        4552 : datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
    3994                 : {
    3995                 :     FormatNode *format;
    3996                 :     char       *fmt_str,
    3997                 :                *result;
    3998                 :     bool        incache;
    3999                 :     int         fmt_len;
    4000                 :     text       *res;
    4001                 : 
    4002 ECB             :     /*
    4003                 :      * Convert fmt to C string
    4004                 :      */
    4005 CBC        4552 :     fmt_str = text_to_cstring(fmt);
    4006 GIC        4552 :     fmt_len = strlen(fmt_str);
    4007                 : 
    4008                 :     /*
    4009                 :      * Allocate workspace for result as C string
    4010                 :      */
    4011            4552 :     result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
    4012 CBC        4552 :     *result = '\0';
    4013 ECB             : 
    4014 GIC        4552 :     if (fmt_len > DCH_CACHE_SIZE)
    4015 ECB             :     {
    4016                 :         /*
    4017                 :          * Allocate new memory if format picture is bigger than static cache
    4018                 :          * and do not use cache (call parser always)
    4019 EUB             :          */
    4020 UIC           0 :         incache = false;
    4021                 : 
    4022               0 :         format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
    4023                 : 
    4024 LBC           0 :         parse_format(format, fmt_str, DCH_keywords,
    4025 ECB             :                      DCH_suff, DCH_index, DCH_FLAG, NULL);
    4026                 :     }
    4027                 :     else
    4028                 :     {
    4029                 :         /*
    4030                 :          * Use cache buffers
    4031 EUB             :          */
    4032 GIC        4552 :         DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, false);
    4033 ECB             : 
    4034 GIC        4552 :         incache = true;
    4035            4552 :         format = ent->format;
    4036                 :     }
    4037 ECB             : 
    4038                 :     /* The real work is here */
    4039 CBC        4552 :     DCH_to_char(format, is_interval, tmtc, result, collid);
    4040 ECB             : 
    4041 GIC        4552 :     if (!incache)
    4042 UIC           0 :         pfree(format);
    4043                 : 
    4044 GIC        4552 :     pfree(fmt_str);
    4045                 : 
    4046                 :     /* convert C-string result to TEXT format */
    4047            4552 :     res = cstring_to_text(result);
    4048 ECB             : 
    4049 CBC        4552 :     pfree(result);
    4050 GIC        4552 :     return res;
    4051 ECB             : }
    4052                 : 
    4053                 : /****************************************************************************
    4054                 :  *              Public routines
    4055 EUB             :  ***************************************************************************/
    4056                 : 
    4057                 : /* -------------------
    4058                 :  * TIMESTAMP to_char()
    4059                 :  * -------------------
    4060 ECB             :  */
    4061                 : Datum
    4062 CBC        2158 : timestamp_to_char(PG_FUNCTION_ARGS)
    4063                 : {
    4064            2158 :     Timestamp   dt = PG_GETARG_TIMESTAMP(0);
    4065 GIC        2158 :     text       *fmt = PG_GETARG_TEXT_PP(1),
    4066 ECB             :                *res;
    4067 EUB             :     TmToChar    tmtc;
    4068                 :     struct pg_tm tt;
    4069 ECB             :     struct fmt_tm *tm;
    4070                 :     int         thisdate;
    4071                 : 
    4072 GIC        2158 :     if (VARSIZE_ANY_EXHDR(fmt) <= 0 || TIMESTAMP_NOT_FINITE(dt))
    4073              66 :         PG_RETURN_NULL();
    4074                 : 
    4075            2092 :     ZERO_tmtc(&tmtc);
    4076            2092 :     tm = tmtcTm(&tmtc);
    4077                 : 
    4078 CBC        2092 :     if (timestamp2tm(dt, NULL, &tt, &tmtcFsec(&tmtc), NULL, NULL) != 0)
    4079 UIC           0 :         ereport(ERROR,
    4080 ECB             :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4081                 :                  errmsg("timestamp out of range")));
    4082                 : 
    4083                 :     /* calculate wday and yday, because timestamp2tm doesn't */
    4084 GIC        2092 :     thisdate = date2j(tt.tm_year, tt.tm_mon, tt.tm_mday);
    4085            2092 :     tt.tm_wday = (thisdate + 1) % 7;
    4086 CBC        2092 :     tt.tm_yday = thisdate - date2j(tt.tm_year, 1, 1) + 1;
    4087                 : 
    4088            2092 :     COPY_tm(tm, &tt);
    4089 EUB             : 
    4090 GIC        2092 :     if (!(res = datetime_to_char_body(&tmtc, fmt, false, PG_GET_COLLATION())))
    4091 LBC           0 :         PG_RETURN_NULL();
    4092 ECB             : 
    4093 GIC        2092 :     PG_RETURN_TEXT_P(res);
    4094 ECB             : }
    4095                 : 
    4096                 : Datum
    4097 CBC        2363 : timestamptz_to_char(PG_FUNCTION_ARGS)
    4098 ECB             : {
    4099 CBC        2363 :     TimestampTz dt = PG_GETARG_TIMESTAMP(0);
    4100            2363 :     text       *fmt = PG_GETARG_TEXT_PP(1),
    4101 ECB             :                *res;
    4102                 :     TmToChar    tmtc;
    4103                 :     int         tz;
    4104                 :     struct pg_tm tt;
    4105                 :     struct fmt_tm *tm;
    4106                 :     int         thisdate;
    4107 EUB             : 
    4108 GIC        2363 :     if (VARSIZE_ANY_EXHDR(fmt) <= 0 || TIMESTAMP_NOT_FINITE(dt))
    4109 CBC          66 :         PG_RETURN_NULL();
    4110                 : 
    4111 GIC        2297 :     ZERO_tmtc(&tmtc);
    4112            2297 :     tm = tmtcTm(&tmtc);
    4113                 : 
    4114            2297 :     if (timestamp2tm(dt, &tz, &tt, &tmtcFsec(&tmtc), &tmtcTzn(&tmtc), NULL) != 0)
    4115 UIC           0 :         ereport(ERROR,
    4116                 :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4117                 :                  errmsg("timestamp out of range")));
    4118                 : 
    4119                 :     /* calculate wday and yday, because timestamp2tm doesn't */
    4120 CBC        2297 :     thisdate = date2j(tt.tm_year, tt.tm_mon, tt.tm_mday);
    4121 GIC        2297 :     tt.tm_wday = (thisdate + 1) % 7;
    4122 CBC        2297 :     tt.tm_yday = thisdate - date2j(tt.tm_year, 1, 1) + 1;
    4123 ECB             : 
    4124 CBC        2297 :     COPY_tm(tm, &tt);
    4125                 : 
    4126 GIC        2297 :     if (!(res = datetime_to_char_body(&tmtc, fmt, false, PG_GET_COLLATION())))
    4127 UIC           0 :         PG_RETURN_NULL();
    4128                 : 
    4129 GIC        2297 :     PG_RETURN_TEXT_P(res);
    4130                 : }
    4131 ECB             : 
    4132                 : 
    4133                 : /* -------------------
    4134                 :  * INTERVAL to_char()
    4135                 :  * -------------------
    4136                 :  */
    4137                 : Datum
    4138 CBC         163 : interval_to_char(PG_FUNCTION_ARGS)
    4139                 : {
    4140             163 :     Interval   *it = PG_GETARG_INTERVAL_P(0);
    4141 GBC         163 :     text       *fmt = PG_GETARG_TEXT_PP(1),
    4142                 :                *res;
    4143                 :     TmToChar    tmtc;
    4144                 :     struct fmt_tm *tm;
    4145 ECB             :     struct pg_itm tt,
    4146 GIC         163 :                *itm = &tt;
    4147 ECB             : 
    4148 GBC         163 :     if (VARSIZE_ANY_EXHDR(fmt) <= 0)
    4149 UIC           0 :         PG_RETURN_NULL();
    4150                 : 
    4151 GIC         163 :     ZERO_tmtc(&tmtc);
    4152             163 :     tm = tmtcTm(&tmtc);
    4153 ECB             : 
    4154 CBC         163 :     interval2itm(*it, itm);
    4155 GIC         163 :     tmtc.fsec = itm->tm_usec;
    4156 CBC         163 :     tm->tm_sec = itm->tm_sec;
    4157 GIC         163 :     tm->tm_min = itm->tm_min;
    4158             163 :     tm->tm_hour = itm->tm_hour;
    4159             163 :     tm->tm_mday = itm->tm_mday;
    4160             163 :     tm->tm_mon = itm->tm_mon;
    4161             163 :     tm->tm_year = itm->tm_year;
    4162                 : 
    4163                 :     /* wday is meaningless, yday approximates the total span in days */
    4164             163 :     tm->tm_yday = (tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon) * DAYS_PER_MONTH + tm->tm_mday;
    4165 ECB             : 
    4166 GIC         163 :     if (!(res = datetime_to_char_body(&tmtc, fmt, true, PG_GET_COLLATION())))
    4167 LBC           0 :         PG_RETURN_NULL();
    4168 ECB             : 
    4169 CBC         163 :     PG_RETURN_TEXT_P(res);
    4170                 : }
    4171                 : 
    4172                 : /* ---------------------
    4173                 :  * TO_TIMESTAMP()
    4174 ECB             :  *
    4175                 :  * Make Timestamp from date_str which is formatted at argument 'fmt'
    4176                 :  * ( to_timestamp is reverse to_char() )
    4177                 :  * ---------------------
    4178                 :  */
    4179 EUB             : Datum
    4180 GIC         396 : to_timestamp(PG_FUNCTION_ARGS)
    4181                 : {
    4182             396 :     text       *date_txt = PG_GETARG_TEXT_PP(0);
    4183             396 :     text       *fmt = PG_GETARG_TEXT_PP(1);
    4184 CBC         396 :     Oid         collid = PG_GET_COLLATION();
    4185                 :     Timestamp   result;
    4186                 :     int         tz;
    4187 ECB             :     struct pg_tm tm;
    4188 EUB             :     fsec_t      fsec;
    4189                 :     int         fprec;
    4190                 : 
    4191 GIC         396 :     do_to_timestamp(date_txt, fmt, collid, false,
    4192                 :                     &tm, &fsec, &fprec, NULL, NULL);
    4193 ECB             : 
    4194                 :     /* Use the specified time zone, if any. */
    4195 GIC         333 :     if (tm.tm_zone)
    4196                 :     {
    4197                 :         DateTimeErrorExtra extra;
    4198 GNC          21 :         int         dterr = DecodeTimezone(tm.tm_zone, &tz);
    4199                 : 
    4200 GIC          21 :         if (dterr)
    4201 UNC           0 :             DateTimeParseError(dterr, &extra, text_to_cstring(date_txt),
    4202                 :                                "timestamptz", NULL);
    4203                 :     }
    4204                 :     else
    4205 GIC         312 :         tz = DetermineTimeZoneOffset(&tm, session_timezone);
    4206                 : 
    4207             333 :     if (tm2timestamp(&tm, fsec, &tz, &result) != 0)
    4208 UIC           0 :         ereport(ERROR,
    4209                 :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4210                 :                  errmsg("timestamp out of range")));
    4211                 : 
    4212                 :     /* Use the specified fractional precision, if any. */
    4213 GIC         333 :     if (fprec)
    4214 GNC         108 :         AdjustTimestampForTypmod(&result, fprec, NULL);
    4215                 : 
    4216 GIC         333 :     PG_RETURN_TIMESTAMP(result);
    4217                 : }
    4218                 : 
    4219                 : /* ----------
    4220                 :  * TO_DATE
    4221                 :  *  Make Date from date_str which is formatted at argument 'fmt'
    4222                 :  * ----------
    4223 ECB             :  */
    4224                 : Datum
    4225 CBC          99 : to_date(PG_FUNCTION_ARGS)
    4226                 : {
    4227              99 :     text       *date_txt = PG_GETARG_TEXT_PP(0);
    4228 GIC          99 :     text       *fmt = PG_GETARG_TEXT_PP(1);
    4229 CBC          99 :     Oid         collid = PG_GET_COLLATION();
    4230                 :     DateADT     result;
    4231 ECB             :     struct pg_tm tm;
    4232                 :     fsec_t      fsec;
    4233                 : 
    4234 GIC          99 :     do_to_timestamp(date_txt, fmt, collid, false,
    4235                 :                     &tm, &fsec, NULL, NULL, NULL);
    4236                 : 
    4237 ECB             :     /* Prevent overflow in Julian-day routines */
    4238 GIC          78 :     if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
    4239 UIC           0 :         ereport(ERROR,
    4240 ECB             :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4241                 :                  errmsg("date out of range: \"%s\"",
    4242                 :                         text_to_cstring(date_txt))));
    4243                 : 
    4244 GBC          78 :     result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - POSTGRES_EPOCH_JDATE;
    4245 EUB             : 
    4246                 :     /* Now check for just-out-of-range dates */
    4247 GBC          78 :     if (!IS_VALID_DATE(result))
    4248 UIC           0 :         ereport(ERROR,
    4249                 :                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4250                 :                  errmsg("date out of range: \"%s\"",
    4251                 :                         text_to_cstring(date_txt))));
    4252                 : 
    4253 GIC          78 :     PG_RETURN_DATEADT(result);
    4254                 : }
    4255                 : 
    4256                 : /*
    4257 EUB             :  * Convert the 'date_txt' input to a datetime type using argument 'fmt'
    4258                 :  * as a format string.  The collation 'collid' may be used for case-folding
    4259                 :  * rules in some cases.  'strict' specifies standard parsing mode.
    4260                 :  *
    4261                 :  * The actual data type (returned in 'typid', 'typmod') is determined by
    4262                 :  * the presence of date/time/zone components in the format string.
    4263                 :  *
    4264                 :  * When a timezone component is present, the corresponding offset is
    4265                 :  * returned in '*tz'.
    4266                 :  *
    4267                 :  * If escontext points to an ErrorSaveContext, data errors will be reported
    4268                 :  * by filling that struct; the caller must test SOFT_ERROR_OCCURRED() to see
    4269                 :  * whether an error occurred.  Otherwise, errors are thrown.
    4270 ECB             :  */
    4271                 : Datum
    4272 CBC        4233 : parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
    4273 ECB             :                Oid *typid, int32 *typmod, int *tz,
    4274                 :                Node *escontext)
    4275                 : {
    4276                 :     struct pg_tm tm;
    4277                 :     fsec_t      fsec;
    4278                 :     int         fprec;
    4279                 :     uint32      flags;
    4280 EUB             : 
    4281 GNC        4233 :     if (!do_to_timestamp(date_txt, fmt, collid, strict,
    4282                 :                          &tm, &fsec, &fprec, &flags, escontext))
    4283            2646 :         return (Datum) 0;
    4284 ECB             : 
    4285 GIC        1557 :     *typmod = fprec ? fprec : -1;   /* fractional part precision */
    4286 ECB             : 
    4287 CBC        1557 :     if (flags & DCH_DATED)
    4288                 :     {
    4289 GIC         945 :         if (flags & DCH_TIMED)
    4290                 :         {
    4291             666 :             if (flags & DCH_ZONED)
    4292 ECB             :             {
    4293                 :                 TimestampTz result;
    4294 EUB             : 
    4295 GIC         375 :                 if (tm.tm_zone)
    4296                 :                 {
    4297                 :                     DateTimeErrorExtra extra;
    4298 GNC         375 :                     int         dterr = DecodeTimezone(tm.tm_zone, tz);
    4299                 : 
    4300 GIC         375 :                     if (dterr)
    4301                 :                     {
    4302 UNC           0 :                         DateTimeParseError(dterr, &extra,
    4303               0 :                                            text_to_cstring(date_txt),
    4304                 :                                            "timestamptz", escontext);
    4305               0 :                         return (Datum) 0;
    4306                 :                     }
    4307                 :                 }
    4308                 :                 else
    4309 ECB             :                 {
    4310 EUB             :                     /*
    4311                 :                      * Time zone is present in format string, but not in input
    4312                 :                      * string.  Assuming do_to_timestamp() triggers no error
    4313                 :                      * this should be possible only in non-strict case.
    4314                 :                      */
    4315 LBC           0 :                     Assert(!strict);
    4316                 : 
    4317 UNC           0 :                     ereturn(escontext, (Datum) 0,
    4318                 :                             (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    4319                 :                              errmsg("missing time zone in input string for type timestamptz")));
    4320 EUB             :                 }
    4321                 : 
    4322 GIC         375 :                 if (tm2timestamp(&tm, fsec, tz, &result) != 0)
    4323 UNC           0 :                     ereturn(escontext, (Datum) 0,
    4324                 :                             (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4325                 :                              errmsg("timestamptz out of range")));
    4326 ECB             : 
    4327 GNC         375 :                 AdjustTimestampForTypmod(&result, *typmod, escontext);
    4328                 : 
    4329 GIC         375 :                 *typid = TIMESTAMPTZOID;
    4330 CBC         375 :                 return TimestampTzGetDatum(result);
    4331                 :             }
    4332 ECB             :             else
    4333                 :             {
    4334                 :                 Timestamp   result;
    4335                 : 
    4336 CBC         291 :                 if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
    4337 UNC           0 :                     ereturn(escontext, (Datum) 0,
    4338                 :                             (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4339                 :                              errmsg("timestamp out of range")));
    4340                 : 
    4341 GNC         291 :                 AdjustTimestampForTypmod(&result, *typmod, escontext);
    4342                 : 
    4343 GBC         291 :                 *typid = TIMESTAMPOID;
    4344             291 :                 return TimestampGetDatum(result);
    4345                 :             }
    4346 EUB             :         }
    4347                 :         else
    4348                 :         {
    4349 GIC         279 :             if (flags & DCH_ZONED)
    4350                 :             {
    4351 UNC           0 :                 ereturn(escontext, (Datum) 0,
    4352                 :                         (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    4353                 :                          errmsg("datetime format is zoned but not timed")));
    4354                 :             }
    4355                 :             else
    4356 EUB             :             {
    4357                 :                 DateADT     result;
    4358                 : 
    4359                 :                 /* Prevent overflow in Julian-day routines */
    4360 GIC         279 :                 if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
    4361 UNC           0 :                     ereturn(escontext, (Datum) 0,
    4362                 :                             (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4363                 :                              errmsg("date out of range: \"%s\"",
    4364                 :                                     text_to_cstring(date_txt))));
    4365                 : 
    4366 GIC         279 :                 result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) -
    4367                 :                     POSTGRES_EPOCH_JDATE;
    4368 ECB             : 
    4369                 :                 /* Now check for just-out-of-range dates */
    4370 CBC         279 :                 if (!IS_VALID_DATE(result))
    4371 UNC           0 :                     ereturn(escontext, (Datum) 0,
    4372                 :                             (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4373                 :                              errmsg("date out of range: \"%s\"",
    4374                 :                                     text_to_cstring(date_txt))));
    4375                 : 
    4376 GIC         279 :                 *typid = DATEOID;
    4377 CBC         279 :                 return DateADTGetDatum(result);
    4378 EUB             :             }
    4379                 :         }
    4380                 :     }
    4381 GIC         612 :     else if (flags & DCH_TIMED)
    4382 ECB             :     {
    4383 GIC         612 :         if (flags & DCH_ZONED)
    4384 ECB             :         {
    4385 CBC         354 :             TimeTzADT  *result = palloc(sizeof(TimeTzADT));
    4386                 : 
    4387 GIC         354 :             if (tm.tm_zone)
    4388                 :             {
    4389                 :                 DateTimeErrorExtra extra;
    4390 GNC         354 :                 int         dterr = DecodeTimezone(tm.tm_zone, tz);
    4391 EUB             : 
    4392 GIC         354 :                 if (dterr)
    4393                 :                 {
    4394 UNC           0 :                     DateTimeParseError(dterr, &extra,
    4395               0 :                                        text_to_cstring(date_txt),
    4396                 :                                        "timetz", escontext);
    4397               0 :                     return (Datum) 0;
    4398                 :                 }
    4399                 :             }
    4400                 :             else
    4401                 :             {
    4402                 :                 /*
    4403                 :                  * Time zone is present in format string, but not in input
    4404                 :                  * string.  Assuming do_to_timestamp() triggers no error this
    4405                 :                  * should be possible only in non-strict case.
    4406                 :                  */
    4407 UIC           0 :                 Assert(!strict);
    4408                 : 
    4409 UNC           0 :                 ereturn(escontext, (Datum) 0,
    4410                 :                         (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    4411                 :                          errmsg("missing time zone in input string for type timetz")));
    4412                 :             }
    4413                 : 
    4414 GIC         354 :             if (tm2timetz(&tm, fsec, *tz, result) != 0)
    4415 UNC           0 :                 ereturn(escontext, (Datum) 0,
    4416                 :                         (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4417                 :                          errmsg("timetz out of range")));
    4418                 : 
    4419 GIC         354 :             AdjustTimeForTypmod(&result->time, *typmod);
    4420                 : 
    4421             354 :             *typid = TIMETZOID;
    4422             354 :             return TimeTzADTPGetDatum(result);
    4423                 :         }
    4424                 :         else
    4425                 :         {
    4426 ECB             :             TimeADT     result;
    4427                 : 
    4428 GIC         258 :             if (tm2time(&tm, fsec, &result) != 0)
    4429 UNC           0 :                 ereturn(escontext, (Datum) 0,
    4430                 :                         (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    4431                 :                          errmsg("time out of range")));
    4432                 : 
    4433 GIC         258 :             AdjustTimeForTypmod(&result, *typmod);
    4434                 : 
    4435 CBC         258 :             *typid = TIMEOID;
    4436 GIC         258 :             return TimeADTGetDatum(result);
    4437 ECB             :         }
    4438                 :     }
    4439                 :     else
    4440                 :     {
    4441 UNC           0 :         ereturn(escontext, (Datum) 0,
    4442                 :                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    4443                 :                  errmsg("datetime format is not dated and not timed")));
    4444 ECB             :     }
    4445                 : }
    4446                 : 
    4447                 : /*
    4448                 :  * do_to_timestamp: shared code for to_timestamp and to_date
    4449                 :  *
    4450                 :  * Parse the 'date_txt' according to 'fmt', return results as a struct pg_tm,
    4451                 :  * fractional seconds, and fractional precision.
    4452                 :  *
    4453                 :  * 'collid' identifies the collation to use, if needed.
    4454                 :  * 'std' specifies standard parsing mode.
    4455                 :  *
    4456                 :  * Bit mask of date/time/zone components found in 'fmt' is returned in 'flags',
    4457                 :  * if that is not NULL.
    4458                 :  *
    4459                 :  * Returns true on success, false on failure (if escontext points to an
    4460                 :  * ErrorSaveContext; otherwise errors are thrown).  Note that currently,
    4461                 :  * soft-error behavior is provided for bad data but not bad format.
    4462                 :  *
    4463                 :  * We parse 'fmt' into a list of FormatNodes, which is then passed to
    4464                 :  * DCH_from_char to populate a TmFromChar with the parsed contents of
    4465                 :  * 'date_txt'.
    4466 EUB             :  *
    4467                 :  * The TmFromChar is then analysed and converted into the final results in
    4468                 :  * struct 'tm', 'fsec', and 'fprec'.
    4469                 :  */
    4470                 : static bool
    4471 GIC        4728 : do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
    4472                 :                 struct pg_tm *tm, fsec_t *fsec, int *fprec,
    4473                 :                 uint32 *flags, Node *escontext)
    4474                 : {
    4475            4728 :     FormatNode *format = NULL;
    4476 ECB             :     TmFromChar  tmfc;
    4477                 :     int         fmt_len;
    4478                 :     char       *date_str;
    4479                 :     int         fmask;
    4480 GIC        4728 :     bool        incache = false;
    4481                 : 
    4482            4728 :     Assert(tm != NULL);
    4483            4728 :     Assert(fsec != NULL);
    4484                 : 
    4485            4728 :     date_str = text_to_cstring(date_txt);
    4486                 : 
    4487 CBC        4728 :     ZERO_tmfc(&tmfc);
    4488            4728 :     ZERO_tm(tm);
    4489            4728 :     *fsec = 0;
    4490            4728 :     if (fprec)
    4491 GIC        4629 :         *fprec = 0;
    4492 CBC        4728 :     if (flags)
    4493            4233 :         *flags = 0;
    4494 GIC        4728 :     fmask = 0;                  /* bit mask for ValidateDate() */
    4495 ECB             : 
    4496 GIC        4728 :     fmt_len = VARSIZE_ANY_EXHDR(fmt);
    4497 EUB             : 
    4498 GBC        4728 :     if (fmt_len)
    4499                 :     {
    4500                 :         char       *fmt_str;
    4501                 : 
    4502 GIC        4728 :         fmt_str = text_to_cstring(fmt);
    4503                 : 
    4504            4728 :         if (fmt_len > DCH_CACHE_SIZE)
    4505                 :         {
    4506                 :             /*
    4507 ECB             :              * Allocate new memory if format picture is bigger than static
    4508                 :              * cache and do not use cache (call parser always)
    4509                 :              */
    4510 UIC           0 :             format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
    4511 ECB             : 
    4512 LBC           0 :             parse_format(format, fmt_str, DCH_keywords, DCH_suff, DCH_index,
    4513 ECB             :                          DCH_FLAG | (std ? STD_FLAG : 0), NULL);
    4514                 :         }
    4515                 :         else
    4516                 :         {
    4517                 :             /*
    4518                 :              * Use cache buffers
    4519                 :              */
    4520 CBC        4728 :             DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, std);
    4521 ECB             : 
    4522 CBC        4725 :             incache = true;
    4523            4725 :             format = ent->format;
    4524                 :         }
    4525 ECB             : 
    4526                 : #ifdef DEBUG_TO_FROM_CHAR
    4527                 :         /* dump_node(format, fmt_len); */
    4528                 :         /* dump_index(DCH_keywords, DCH_index); */
    4529                 : #endif
    4530                 : 
    4531 GNC        4725 :         DCH_from_char(format, date_str, &tmfc, collid, std, escontext);
    4532 GBC        4659 :         pfree(fmt_str);
    4533 GNC        4659 :         if (SOFT_ERROR_OCCURRED(escontext))
    4534            2646 :             goto fail;
    4535                 : 
    4536 GIC        2013 :         if (flags)
    4537 GNC        1557 :             *flags = DCH_datetime_type(format);
    4538 ECB             : 
    4539 CBC        2013 :         if (!incache)
    4540 EUB             :         {
    4541 UIC           0 :             pfree(format);
    4542               0 :             format = NULL;
    4543 ECB             :         }
    4544                 :     }
    4545                 : 
    4546                 :     DEBUG_TMFC(&tmfc);
    4547                 : 
    4548                 :     /*
    4549                 :      * Convert to_date/to_timestamp input fields to standard 'tm'
    4550                 :      */
    4551 CBC        2013 :     if (tmfc.ssss)
    4552 EUB             :     {
    4553 CBC          12 :         int         x = tmfc.ssss;
    4554 ECB             : 
    4555 GIC          12 :         tm->tm_hour = x / SECS_PER_HOUR;
    4556 CBC          12 :         x %= SECS_PER_HOUR;
    4557              12 :         tm->tm_min = x / SECS_PER_MINUTE;
    4558 GIC          12 :         x %= SECS_PER_MINUTE;
    4559 GBC          12 :         tm->tm_sec = x;
    4560                 :     }
    4561                 : 
    4562 GIC        2013 :     if (tmfc.ss)
    4563             351 :         tm->tm_sec = tmfc.ss;
    4564 GBC        2013 :     if (tmfc.mi)
    4565 GIC        1473 :         tm->tm_min = tmfc.mi;
    4566            2013 :     if (tmfc.hh)
    4567            1488 :         tm->tm_hour = tmfc.hh;
    4568                 : 
    4569            2013 :     if (tmfc.clock == CLOCK_12_HOUR)
    4570 ECB             :     {
    4571 CBC          36 :         if (tm->tm_hour < 1 || tm->tm_hour > HOURS_PER_DAY / 2)
    4572 ECB             :         {
    4573 GNC           3 :             errsave(escontext,
    4574                 :                     (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    4575                 :                      errmsg("hour \"%d\" is invalid for the 12-hour clock",
    4576                 :                             tm->tm_hour),
    4577                 :                      errhint("Use the 24-hour clock, or give an hour between 1 and 12.")));
    4578 UNC           0 :             goto fail;
    4579                 :         }
    4580 ECB             : 
    4581 GIC          33 :         if (tmfc.pm && tm->tm_hour < HOURS_PER_DAY / 2)
    4582               6 :             tm->tm_hour += HOURS_PER_DAY / 2;
    4583 GBC          27 :         else if (!tmfc.pm && tm->tm_hour == HOURS_PER_DAY / 2)
    4584 UBC           0 :             tm->tm_hour = 0;
    4585 EUB             :     }
    4586                 : 
    4587 GBC        2010 :     if (tmfc.year)
    4588                 :     {
    4589                 :         /*
    4590 EUB             :          * If CC and YY (or Y) are provided, use YY as 2 low-order digits for
    4591                 :          * the year in the given century.  Keep in mind that the 21st century
    4592                 :          * AD runs from 2001-2100, not 2000-2099; 6th century BC runs from
    4593                 :          * 600BC to 501BC.
    4594 ECB             :          */
    4595 GIC        1392 :         if (tmfc.cc && tmfc.yysz <= 2)
    4596 ECB             :         {
    4597 CBC           3 :             if (tmfc.bc)
    4598 UIC           0 :                 tmfc.cc = -tmfc.cc;
    4599 GIC           3 :             tm->tm_year = tmfc.year % 100;
    4600 CBC           3 :             if (tm->tm_year)
    4601                 :             {
    4602               3 :                 if (tmfc.cc >= 0)
    4603 GIC           3 :                     tm->tm_year += (tmfc.cc - 1) * 100;
    4604                 :                 else
    4605 UIC           0 :                     tm->tm_year = (tmfc.cc + 1) * 100 - tm->tm_year + 1;
    4606                 :             }
    4607                 :             else
    4608 ECB             :             {
    4609                 :                 /* find century year for dates ending in "00" */
    4610 UIC           0 :                 tm->tm_year = tmfc.cc * 100 + ((tmfc.cc >= 0) ? 0 : 1);
    4611 EUB             :             }
    4612 ECB             :         }
    4613                 :         else
    4614                 :         {
    4615                 :             /* If a 4-digit year is provided, we use that and ignore CC. */
    4616 GIC        1389 :             tm->tm_year = tmfc.year;
    4617            1389 :             if (tmfc.bc)
    4618 CBC          18 :                 tm->tm_year = -tm->tm_year;
    4619 ECB             :             /* correct for our representation of BC years */
    4620 CBC        1389 :             if (tm->tm_year < 0)
    4621 GIC          18 :                 tm->tm_year++;
    4622 ECB             :         }
    4623 CBC        1392 :         fmask |= DTK_M(YEAR);
    4624                 :     }
    4625             618 :     else if (tmfc.cc)
    4626                 :     {
    4627 ECB             :         /* use first year of century */
    4628 LBC           0 :         if (tmfc.bc)
    4629 UIC           0 :             tmfc.cc = -tmfc.cc;
    4630               0 :         if (tmfc.cc >= 0)
    4631 ECB             :             /* +1 because 21st century started in 2001 */
    4632 UIC           0 :             tm->tm_year = (tmfc.cc - 1) * 100 + 1;
    4633                 :         else
    4634                 :             /* +1 because year == 599 is 600 BC */
    4635               0 :             tm->tm_year = tmfc.cc * 100 + 1;
    4636               0 :         fmask |= DTK_M(YEAR);
    4637                 :     }
    4638                 : 
    4639 GIC        2010 :     if (tmfc.j)
    4640 ECB             :     {
    4641 GIC           3 :         j2date(tmfc.j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
    4642 GBC           3 :         fmask |= DTK_DATE_M;
    4643                 :     }
    4644                 : 
    4645            2010 :     if (tmfc.ww)
    4646                 :     {
    4647 GIC          15 :         if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
    4648 ECB             :         {
    4649                 :             /*
    4650                 :              * If tmfc.d is not set, then the date is left at the beginning of
    4651                 :              * the ISO week (Monday).
    4652                 :              */
    4653 GIC          12 :             if (tmfc.d)
    4654 CBC          12 :                 isoweekdate2date(tmfc.ww, tmfc.d, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
    4655 ECB             :             else
    4656 UIC           0 :                 isoweek2date(tmfc.ww, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
    4657 GIC          12 :             fmask |= DTK_DATE_M;
    4658                 :         }
    4659                 :         else
    4660               3 :             tmfc.ddd = (tmfc.ww - 1) * 7 + 1;
    4661                 :     }
    4662                 : 
    4663            2010 :     if (tmfc.w)
    4664               3 :         tmfc.dd = (tmfc.w - 1) * 7 + 1;
    4665            2010 :     if (tmfc.dd)
    4666 ECB             :     {
    4667 GIC        1326 :         tm->tm_mday = tmfc.dd;
    4668 CBC        1326 :         fmask |= DTK_M(DAY);
    4669                 :     }
    4670            2010 :     if (tmfc.mm)
    4671 ECB             :     {
    4672 GIC        1344 :         tm->tm_mon = tmfc.mm;
    4673 CBC        1344 :         fmask |= DTK_M(MONTH);
    4674 ECB             :     }
    4675                 : 
    4676 CBC        2010 :     if (tmfc.ddd && (tm->tm_mon <= 1 || tm->tm_mday <= 1))
    4677 ECB             :     {
    4678                 :         /*
    4679                 :          * The month and day field have not been set, so we use the
    4680                 :          * day-of-year field to populate them.  Depending on the date mode,
    4681                 :          * this field may be interpreted as a Gregorian day-of-year, or an ISO
    4682                 :          * week date day-of-year.
    4683                 :          */
    4684                 : 
    4685 CBC          24 :         if (!tm->tm_year && !tmfc.bc)
    4686 ECB             :         {
    4687 UNC           0 :             errsave(escontext,
    4688                 :                     (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
    4689                 :                      errmsg("cannot calculate day of year without year information")));
    4690               0 :             goto fail;
    4691                 :         }
    4692 ECB             : 
    4693 GIC          24 :         if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
    4694                 :         {
    4695 ECB             :             int         j0;     /* zeroth day of the ISO year, in Julian */
    4696                 : 
    4697 CBC           3 :             j0 = isoweek2j(tm->tm_year, 1) - 1;
    4698                 : 
    4699 GIC           3 :             j2date(j0 + tmfc.ddd, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
    4700               3 :             fmask |= DTK_DATE_M;
    4701                 :         }
    4702                 :         else
    4703                 :         {
    4704 ECB             :             const int  *y;
    4705                 :             int         i;
    4706 EUB             : 
    4707                 :             static const int ysum[2][13] = {
    4708                 :                 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
    4709                 :             {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
    4710                 : 
    4711 CBC          21 :             y = ysum[isleap(tm->tm_year)];
    4712 ECB             : 
    4713 CBC         246 :             for (i = 1; i <= MONTHS_PER_YEAR; i++)
    4714 ECB             :             {
    4715 GIC         240 :                 if (tmfc.ddd <= y[i])
    4716 CBC          15 :                     break;
    4717                 :             }
    4718 GBC          21 :             if (tm->tm_mon <= 1)
    4719 GIC          21 :                 tm->tm_mon = i;
    4720                 : 
    4721              21 :             if (tm->tm_mday <= 1)
    4722 CBC          21 :                 tm->tm_mday = tmfc.ddd - y[i - 1];
    4723                 : 
    4724 GIC          21 :             fmask |= DTK_M(MONTH) | DTK_M(DAY);
    4725                 :         }
    4726 ECB             :     }
    4727                 : 
    4728 GIC        2010 :     if (tmfc.ms)
    4729 GBC           3 :         *fsec += tmfc.ms * 1000;
    4730 GIC        2010 :     if (tmfc.us)
    4731 GBC         111 :         *fsec += tmfc.us;
    4732 GIC        2010 :     if (fprec)
    4733            1917 :         *fprec = tmfc.ff;       /* fractional precision, if specified */
    4734 ECB             : 
    4735                 :     /* Range-check date fields according to bit mask computed above */
    4736 GIC        2010 :     if (fmask != 0)
    4737 ECB             :     {
    4738                 :         /* We already dealt with AD/BC, so pass isjulian = true */
    4739 GIC        1398 :         int         dterr = ValidateDate(fmask, true, false, false, tm);
    4740                 : 
    4741            1398 :         if (dterr != 0)
    4742 ECB             :         {
    4743 EUB             :             /*
    4744 ECB             :              * Force the error to be DTERR_FIELD_OVERFLOW even if ValidateDate
    4745                 :              * said DTERR_MD_FIELD_OVERFLOW, because we don't want to print an
    4746                 :              * irrelevant hint about datestyle.
    4747                 :              */
    4748 GNC          24 :             DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL,
    4749                 :                                date_str, "timestamp", escontext);
    4750 UNC           0 :             goto fail;
    4751 ECB             :         }
    4752 EUB             :     }
    4753 ECB             : 
    4754                 :     /* Range-check time fields too */
    4755 CBC        1986 :     if (tm->tm_hour < 0 || tm->tm_hour >= HOURS_PER_DAY ||
    4756 GIC        1977 :         tm->tm_min < 0 || tm->tm_min >= MINS_PER_HOUR ||
    4757            1974 :         tm->tm_sec < 0 || tm->tm_sec >= SECS_PER_MINUTE ||
    4758            1971 :         *fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
    4759                 :     {
    4760 GNC          18 :         DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL,
    4761                 :                            date_str, "timestamp", escontext);
    4762 UNC           0 :         goto fail;
    4763                 :     }
    4764                 : 
    4765                 :     /* Save parsed time-zone into tm->tm_zone if it was specified */
    4766 GIC        1968 :     if (tmfc.tzsign)
    4767 ECB             :     {
    4768                 :         char       *tz;
    4769                 : 
    4770 CBC         750 :         if (tmfc.tzh < 0 || tmfc.tzh > MAX_TZDISP_HOUR ||
    4771             750 :             tmfc.tzm < 0 || tmfc.tzm >= MINS_PER_HOUR)
    4772                 :         {
    4773 UNC           0 :             DateTimeParseError(DTERR_TZDISP_OVERFLOW, NULL,
    4774                 :                                date_str, "timestamp", escontext);
    4775               0 :             goto fail;
    4776                 :         }
    4777                 : 
    4778 GIC         750 :         tz = psprintf("%c%02d:%02d",
    4779             750 :                       tmfc.tzsign > 0 ? '+' : '-', tmfc.tzh, tmfc.tzm);
    4780                 : 
    4781             750 :         tm->tm_zone = tz;
    4782                 :     }
    4783                 : 
    4784                 :     DEBUG_TM(tm);
    4785                 : 
    4786            1968 :     if (format && !incache)
    4787 UIC           0 :         pfree(format);
    4788 CBC        1968 :     pfree(date_str);
    4789                 : 
    4790 GNC        1968 :     return true;
    4791                 : 
    4792            2646 : fail:
    4793            2646 :     if (format && !incache)
    4794 UNC           0 :         pfree(format);
    4795 GNC        2646 :     pfree(date_str);
    4796                 : 
    4797            2646 :     return false;
    4798                 : }
    4799 ECB             : 
    4800                 : 
    4801 EUB             : /**********************************************************************
    4802                 :  *  the NUMBER version part
    4803                 :  *********************************************************************/
    4804                 : 
    4805 ECB             : 
    4806                 : static char *
    4807 GIC          69 : fill_str(char *str, int c, int max)
    4808                 : {
    4809 CBC          69 :     memset(str, c, max);
    4810 GIC          69 :     *(str + max) = '\0';
    4811              69 :     return str;
    4812                 : }
    4813                 : 
    4814 ECB             : #define zeroize_NUM(_n) \
    4815                 : do { \
    4816                 :     (_n)->flag       = 0;    \
    4817                 :     (_n)->lsign      = 0;    \
    4818                 :     (_n)->pre        = 0;    \
    4819                 :     (_n)->post       = 0;    \
    4820                 :     (_n)->pre_lsign_num = 0; \
    4821                 :     (_n)->need_locale    = 0;    \
    4822                 :     (_n)->multi      = 0;    \
    4823                 :     (_n)->zero_start = 0;    \
    4824                 :     (_n)->zero_end       = 0;    \
    4825                 : } while(0)
    4826                 : 
    4827                 : /* This works the same as DCH_prevent_counter_overflow */
    4828                 : static inline void
    4829 GIC      498131 : NUM_prevent_counter_overflow(void)
    4830 ECB             : {
    4831 CBC      498131 :     if (NUMCounter >= (INT_MAX - 1))
    4832                 :     {
    4833 UBC           0 :         for (int i = 0; i < n_NUMCache; i++)
    4834               0 :             NUMCache[i]->age >>= 1;
    4835 UIC           0 :         NUMCounter >>= 1;
    4836 ECB             :     }
    4837 CBC      498131 : }
    4838                 : 
    4839                 : /* select a NUMCacheEntry to hold the given format picture */
    4840                 : static NUMCacheEntry *
    4841 GIC         266 : NUM_cache_getnew(const char *str)
    4842                 : {
    4843 ECB             :     NUMCacheEntry *ent;
    4844                 : 
    4845                 :     /* Ensure we can advance NUMCounter below */
    4846 GIC         266 :     NUM_prevent_counter_overflow();
    4847 ECB             : 
    4848                 :     /*
    4849                 :      * If cache is full, remove oldest entry (or recycle first not-valid one)
    4850                 :      */
    4851 GIC         266 :     if (n_NUMCache >= NUM_CACHE_ENTRIES)
    4852                 :     {
    4853             105 :         NUMCacheEntry *old = NUMCache[0];
    4854 ECB             : 
    4855                 : #ifdef DEBUG_TO_FROM_CHAR
    4856                 :         elog(DEBUG_elog_output, "Cache is full (%d)", n_NUMCache);
    4857                 : #endif
    4858 CBC         105 :         if (old->valid)
    4859 ECB             :         {
    4860 GIC        2100 :             for (int i = 1; i < NUM_CACHE_ENTRIES; i++)
    4861 ECB             :             {
    4862 CBC        1995 :                 ent = NUMCache[i];
    4863 GIC        1995 :                 if (!ent->valid)
    4864                 :                 {
    4865 UIC           0 :                     old = ent;
    4866               0 :                     break;
    4867                 :                 }
    4868 CBC        1995 :                 if (ent->age < old->age)
    4869 GIC          99 :                     old = ent;
    4870                 :             }
    4871 ECB             :         }
    4872                 : #ifdef DEBUG_TO_FROM_CHAR
    4873                 :         elog(DEBUG_elog_output, "OLD: \"%s\" AGE: %d", old->str, old->age);
    4874                 : #endif
    4875 CBC         105 :         old->valid = false;
    4876 GIC         105 :         strlcpy(old->str, str, NUM_CACHE_SIZE + 1);
    4877 CBC         105 :         old->age = (++NUMCounter);
    4878                 :         /* caller is expected to fill format and Num, then set valid */
    4879             105 :         return old;
    4880 ECB             :     }
    4881                 :     else
    4882                 :     {
    4883                 : #ifdef DEBUG_TO_FROM_CHAR
    4884                 :         elog(DEBUG_elog_output, "NEW (%d)", n_NUMCache);
    4885                 : #endif
    4886 GIC         161 :         Assert(NUMCache[n_NUMCache] == NULL);
    4887             161 :         NUMCache[n_NUMCache] = ent = (NUMCacheEntry *)
    4888             161 :             MemoryContextAllocZero(TopMemoryContext, sizeof(NUMCacheEntry));
    4889 CBC         161 :         ent->valid = false;
    4890 GIC         161 :         strlcpy(ent->str, str, NUM_CACHE_SIZE + 1);
    4891             161 :         ent->age = (++NUMCounter);
    4892                 :         /* caller is expected to fill format and Num, then set valid */
    4893 CBC         161 :         ++n_NUMCache;
    4894 GIC         161 :         return ent;
    4895                 :     }
    4896                 : }
    4897                 : 
    4898                 : /* look for an existing NUMCacheEntry matching the given format picture */
    4899                 : static NUMCacheEntry *
    4900 CBC      497865 : NUM_cache_search(const char *str)
    4901                 : {
    4902 ECB             :     /* Ensure we can advance NUMCounter below */
    4903 GIC      497865 :     NUM_prevent_counter_overflow();
    4904 ECB             : 
    4905 GIC      631671 :     for (int i = 0; i < n_NUMCache; i++)
    4906                 :     {
    4907 CBC      631405 :         NUMCacheEntry *ent = NUMCache[i];
    4908                 : 
    4909          631405 :         if (ent->valid && strcmp(ent->str, str) == 0)
    4910                 :         {
    4911 GIC      497599 :             ent->age = (++NUMCounter);
    4912          497599 :             return ent;
    4913                 :         }
    4914                 :     }
    4915                 : 
    4916             266 :     return NULL;
    4917 ECB             : }
    4918                 : 
    4919                 : /* Find or create a NUMCacheEntry for the given format picture */
    4920                 : static NUMCacheEntry *
    4921 GIC      497865 : NUM_cache_fetch(const char *str)
    4922 ECB             : {
    4923                 :     NUMCacheEntry *ent;
    4924                 : 
    4925 GIC      497865 :     if ((ent = NUM_cache_search(str)) == NULL)
    4926                 :     {
    4927                 :         /*
    4928                 :          * Not in the cache, must run parser and save a new format-picture to
    4929                 :          * the cache.  Do not mark the cache entry valid until parsing
    4930 ECB             :          * succeeds.
    4931                 :          */
    4932 CBC         266 :         ent = NUM_cache_getnew(str);
    4933                 : 
    4934             266 :         zeroize_NUM(&ent->Num);
    4935                 : 
    4936             266 :         parse_format(ent->format, str, NUM_keywords,
    4937                 :                      NULL, NUM_index, NUM_FLAG, &ent->Num);
    4938                 : 
    4939 GIC         266 :         ent->valid = true;
    4940                 :     }
    4941          497865 :     return ent;
    4942                 : }
    4943                 : 
    4944 ECB             : /* ----------
    4945                 :  * Cache routine for NUM to_char version
    4946                 :  * ----------
    4947                 :  */
    4948                 : static FormatNode *
    4949 GIC      497970 : NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
    4950                 : {
    4951          497970 :     FormatNode *format = NULL;
    4952                 :     char       *str;
    4953 ECB             : 
    4954 CBC      497970 :     str = text_to_cstring(pars_str);
    4955 ECB             : 
    4956 CBC      497970 :     if (len > NUM_CACHE_SIZE)
    4957 ECB             :     {
    4958                 :         /*
    4959                 :          * Allocate new memory if format picture is bigger than static cache
    4960                 :          * and do not use cache (call parser always)
    4961                 :          */
    4962 GIC         105 :         format = (FormatNode *) palloc((len + 1) * sizeof(FormatNode));
    4963                 : 
    4964             105 :         *shouldFree = true;
    4965                 : 
    4966             105 :         zeroize_NUM(Num);
    4967                 : 
    4968             105 :         parse_format(format, str, NUM_keywords,
    4969 ECB             :                      NULL, NUM_index, NUM_FLAG, Num);
    4970                 :     }
    4971                 :     else
    4972                 :     {
    4973                 :         /*
    4974                 :          * Use cache buffers
    4975 EUB             :          */
    4976 GIC      497865 :         NUMCacheEntry *ent = NUM_cache_fetch(str);
    4977                 : 
    4978          497865 :         *shouldFree = false;
    4979                 : 
    4980          497865 :         format = ent->format;
    4981                 : 
    4982                 :         /*
    4983 EUB             :          * Copy cache to used struct
    4984                 :          */
    4985 GIC      497865 :         Num->flag = ent->Num.flag;
    4986 GBC      497865 :         Num->lsign = ent->Num.lsign;
    4987 GIC      497865 :         Num->pre = ent->Num.pre;
    4988 GBC      497865 :         Num->post = ent->Num.post;
    4989          497865 :         Num->pre_lsign_num = ent->Num.pre_lsign_num;
    4990 GIC      497865 :         Num->need_locale = ent->Num.need_locale;
    4991 GBC      497865 :         Num->multi = ent->Num.multi;
    4992 GIC      497865 :         Num->zero_start = ent->Num.zero_start;
    4993 GBC      497865 :         Num->zero_end = ent->Num.zero_end;
    4994                 :     }
    4995 EUB             : 
    4996                 : #ifdef DEBUG_TO_FROM_CHAR
    4997                 :     /* dump_node(format, len); */
    4998                 :     dump_index(NUM_keywords, NUM_index);
    4999                 : #endif
    5000                 : 
    5001 GBC      497970 :     pfree(str);
    5002          497970 :     return format;
    5003                 : }
    5004                 : 
    5005                 : 
    5006 EUB             : static char *
    5007 UBC           0 : int_to_roman(int number)
    5008 EUB             : {
    5009                 :     int         len,
    5010                 :                 num;
    5011                 :     char       *p,
    5012                 :                *result,
    5013                 :                 numstr[12];
    5014                 : 
    5015 UIC           0 :     result = (char *) palloc(16);
    5016               0 :     *result = '\0';
    5017                 : 
    5018               0 :     if (number > 3999 || number < 1)
    5019                 :     {
    5020               0 :         fill_str(result, '#', 15);
    5021               0 :         return result;
    5022                 :     }
    5023               0 :     len = snprintf(numstr, sizeof(numstr), "%d", number);
    5024 ECB             : 
    5025 UIC           0 :     for (p = numstr; *p != '\0'; p++, --len)
    5026 ECB             :     {
    5027 UIC           0 :         num = *p - ('0' + 1);
    5028               0 :         if (num < 0)
    5029               0 :             continue;
    5030                 : 
    5031               0 :         if (len > 3)
    5032                 :         {
    5033 LBC           0 :             while (num-- != -1)
    5034 UIC           0 :                 strcat(result, "M");
    5035                 :         }
    5036                 :         else
    5037                 :         {
    5038 LBC           0 :             if (len == 3)
    5039 UBC           0 :                 strcat(result, rm100[num]);
    5040 UIC           0 :             else if (len == 2)
    5041 LBC           0 :                 strcat(result, rm10[num]);
    5042 UIC           0 :             else if (len == 1)
    5043 LBC           0 :                 strcat(result, rm1[num]);
    5044 EUB             :         }
    5045                 :     }
    5046 LBC           0 :     return result;
    5047                 : }
    5048                 : 
    5049                 : 
    5050                 : 
    5051 ECB             : /* ----------
    5052                 :  * Locale
    5053                 :  * ----------
    5054                 :  */
    5055 EUB             : static void
    5056 GIC      497811 : NUM_prepare_locale(NUMProc *Np)
    5057 ECB             : {
    5058 CBC      497811 :     if (Np->Num->need_locale)
    5059                 :     {
    5060                 :         struct lconv *lconv;
    5061                 : 
    5062                 :         /*
    5063                 :          * Get locales
    5064                 :          */
    5065 GIC         421 :         lconv = PGLC_localeconv();
    5066                 : 
    5067 ECB             :         /*
    5068 EUB             :          * Positive / Negative number sign
    5069                 :          */
    5070 CBC         421 :         if (lconv->negative_sign && *lconv->negative_sign)
    5071 LBC           0 :             Np->L_negative_sign = lconv->negative_sign;
    5072                 :         else
    5073 GBC         421 :             Np->L_negative_sign = "-";
    5074                 : 
    5075 GIC         421 :         if (lconv->positive_sign && *lconv->positive_sign)
    5076 UIC           0 :             Np->L_positive_sign = lconv->positive_sign;
    5077                 :         else
    5078 CBC         421 :             Np->L_positive_sign = "+";
    5079 EUB             : 
    5080                 :         /*
    5081 ECB             :          * Number decimal point
    5082                 :          */
    5083 GIC         421 :         if (lconv->decimal_point && *lconv->decimal_point)
    5084             421 :             Np->decimal = lconv->decimal_point;
    5085                 : 
    5086                 :         else
    5087 UIC           0 :             Np->decimal = ".";
    5088 ECB             : 
    5089 CBC         421 :         if (!IS_LDECIMAL(Np->Num))
    5090             354 :             Np->decimal = ".";
    5091                 : 
    5092 ECB             :         /*
    5093                 :          * Number thousands separator
    5094                 :          *
    5095                 :          * Some locales (e.g. broken glibc pt_BR), have a comma for decimal,
    5096                 :          * but "" for thousands_sep, so we set the thousands_sep too.
    5097                 :          * http://archives.postgresql.org/pgsql-hackers/2007-11/msg00772.php
    5098                 :          */
    5099 GIC         421 :         if (lconv->thousands_sep && *lconv->thousands_sep)
    5100 UIC           0 :             Np->L_thousands_sep = lconv->thousands_sep;
    5101                 :         /* Make sure thousands separator doesn't match decimal point symbol. */
    5102 GIC         421 :         else if (strcmp(Np->decimal, ",") != 0)
    5103             421 :             Np->L_thousands_sep = ",";
    5104                 :         else
    5105 UIC           0 :             Np->L_thousands_sep = ".";
    5106 ECB             : 
    5107                 :         /*
    5108                 :          * Currency symbol
    5109                 :          */
    5110 GIC         421 :         if (lconv->currency_symbol && *lconv->currency_symbol)
    5111 UIC           0 :             Np->L_currency_symbol = lconv->currency_symbol;
    5112                 :         else
    5113 GIC         421 :             Np->L_currency_symbol = " ";
    5114                 :     }
    5115 ECB             :     else
    5116                 :     {
    5117                 :         /*
    5118                 :          * Default values
    5119                 :          */
    5120 CBC      497390 :         Np->L_negative_sign = "-";
    5121 GIC      497390 :         Np->L_positive_sign = "+";
    5122 CBC      497390 :         Np->decimal = ".";
    5123 ECB             : 
    5124 GIC      497390 :         Np->L_thousands_sep = ",";
    5125          497390 :         Np->L_currency_symbol = " ";
    5126 ECB             :     }
    5127 GIC      497811 : }
    5128                 : 
    5129                 : /* ----------
    5130                 :  * Return pointer of last relevant number after decimal point
    5131                 :  *  12.0500 --> last relevant is '5'
    5132                 :  *  12.0000 --> last relevant is '.'
    5133                 :  * If there is no decimal point, return NULL (which will result in same
    5134                 :  * behavior as if FM hadn't been specified).
    5135                 :  * ----------
    5136                 :  */
    5137                 : static char *
    5138             339 : get_last_relevant_decnum(char *num)
    5139                 : {
    5140                 :     char       *result,
    5141             339 :                *p = strchr(num, '.');
    5142 ECB             : 
    5143                 : #ifdef DEBUG_TO_FROM_CHAR
    5144                 :     elog(DEBUG_elog_output, "get_last_relevant_decnum()");
    5145                 : #endif
    5146                 : 
    5147 GIC         339 :     if (!p)
    5148               3 :         return NULL;
    5149                 : 
    5150             336 :     result = p;
    5151 ECB             : 
    5152 GBC        4971 :     while (*(++p))
    5153                 :     {
    5154 CBC        4635 :         if (*p != '0')
    5155 GBC         972 :             result = p;
    5156                 :     }
    5157 ECB             : 
    5158 GBC         336 :     return result;
    5159                 : }
    5160                 : 
    5161                 : /*
    5162                 :  * These macros are used in NUM_processor() and its subsidiary routines.
    5163 ECB             :  * OVERLOAD_TEST: true if we've reached end of input string
    5164                 :  * AMOUNT_TEST(s): true if at least s bytes remain in string
    5165                 :  */
    5166                 : #define OVERLOAD_TEST   (Np->inout_p >= Np->inout + input_len)
    5167                 : #define AMOUNT_TEST(s)  (Np->inout_p <= Np->inout + (input_len - (s)))
    5168                 : 
    5169                 : /* ----------
    5170                 :  * Number extraction for TO_NUMBER()
    5171                 :  * ----------
    5172                 :  */
    5173                 : static void
    5174 CBC         429 : NUM_numpart_from_char(NUMProc *Np, int id, int input_len)
    5175 ECB             : {
    5176 CBC         429 :     bool        isread = false;
    5177                 : 
    5178                 : #ifdef DEBUG_TO_FROM_CHAR
    5179                 :     elog(DEBUG_elog_output, " --- scan start --- id=%s",
    5180                 :          (id == NUM_0 || id == NUM_9) ? "NUM_0/9" : id == NUM_DEC ? "NUM_DEC" : "???");
    5181 ECB             : #endif
    5182                 : 
    5183 CBC         429 :     if (OVERLOAD_TEST)
    5184 UIC           0 :         return;
    5185 ECB             : 
    5186 CBC         429 :     if (*Np->inout_p == ' ')
    5187 UIC           0 :         Np->inout_p++;
    5188 ECB             : 
    5189 CBC         429 :     if (OVERLOAD_TEST)
    5190 LBC           0 :         return;
    5191                 : 
    5192 EUB             :     /*
    5193                 :      * read sign before number
    5194                 :      */
    5195 GIC         429 :     if (*Np->number == ' ' && (id == NUM_0 || id == NUM_9) &&
    5196             285 :         (Np->read_pre + Np->read_post) == 0)
    5197                 :     {
    5198                 : #ifdef DEBUG_TO_FROM_CHAR
    5199                 :         elog(DEBUG_elog_output, "Try read sign (%c), locale positive: %s, negative: %s",
    5200                 :              *Np->inout_p, Np->L_positive_sign, Np->L_negative_sign);
    5201                 : #endif
    5202                 : 
    5203                 :         /*
    5204                 :          * locale sign
    5205 ECB             :          */
    5206 CBC          84 :         if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_PRE)
    5207 GIC           6 :         {
    5208 CBC           6 :             int         x = 0;
    5209 ECB             : 
    5210                 : #ifdef DEBUG_TO_FROM_CHAR
    5211                 :             elog(DEBUG_elog_output, "Try read locale pre-sign (%c)", *Np->inout_p);
    5212                 : #endif
    5213 GBC           6 :             if ((x = strlen(Np->L_negative_sign)) &&
    5214               6 :                 AMOUNT_TEST(x) &&
    5215 GIC           6 :                 strncmp(Np->inout_p, Np->L_negative_sign, x) == 0)
    5216                 :             {
    5217               3 :                 Np->inout_p += x;
    5218               3 :                 *Np->number = '-';
    5219 ECB             :             }
    5220 GBC           3 :             else if ((x = strlen(Np->L_positive_sign)) &&
    5221 GIC           3 :                      AMOUNT_TEST(x) &&
    5222               3 :                      strncmp(Np->inout_p, Np->L_positive_sign, x) == 0)
    5223                 :             {
    5224 UIC           0 :                 Np->inout_p += x;
    5225               0 :                 *Np->number = '+';
    5226                 :             }
    5227                 :         }
    5228                 :         else
    5229 ECB             :         {
    5230                 : #ifdef DEBUG_TO_FROM_CHAR
    5231                 :             elog(DEBUG_elog_output, "Try read simple sign (%c)", *Np->inout_p);
    5232 EUB             : #endif
    5233                 : 
    5234 ECB             :             /*
    5235                 :              * simple + - < >
    5236                 :              */
    5237 CBC          78 :             if (*Np->inout_p == '-' || (IS_BRACKET(Np->Num) &&
    5238               3 :                                         *Np->inout_p == '<'))
    5239                 :             {
    5240               9 :                 *Np->number = '-';   /* set - */
    5241 GIC           9 :                 Np->inout_p++;
    5242 ECB             :             }
    5243 GIC          69 :             else if (*Np->inout_p == '+')
    5244                 :             {
    5245 UIC           0 :                 *Np->number = '+';   /* set + */
    5246               0 :                 Np->inout_p++;
    5247                 :             }
    5248 ECB             :         }
    5249                 :     }
    5250                 : 
    5251 GIC         429 :     if (OVERLOAD_TEST)
    5252 UIC           0 :         return;
    5253                 : 
    5254                 : #ifdef DEBUG_TO_FROM_CHAR
    5255 ECB             :     elog(DEBUG_elog_output, "Scan for numbers (%c), current number: '%s'", *Np->inout_p, Np->number);
    5256                 : #endif
    5257                 : 
    5258                 :     /*
    5259                 :      * read digit or decimal point
    5260                 :      */
    5261 CBC         429 :     if (isdigit((unsigned char) *Np->inout_p))
    5262                 :     {
    5263             363 :         if (Np->read_dec && Np->read_post == Np->Num->post)
    5264 LBC           0 :             return;
    5265 ECB             : 
    5266 CBC         363 :         *Np->number_p = *Np->inout_p;
    5267             363 :         Np->number_p++;
    5268                 : 
    5269 GIC         363 :         if (Np->read_dec)
    5270             132 :             Np->read_post++;
    5271 ECB             :         else
    5272 GBC         231 :             Np->read_pre++;
    5273                 : 
    5274 GIC         363 :         isread = true;
    5275                 : 
    5276                 : #ifdef DEBUG_TO_FROM_CHAR
    5277                 :         elog(DEBUG_elog_output, "Read digit (%c)", *Np->inout_p);
    5278                 : #endif
    5279                 :     }
    5280              66 :     else if (IS_DECIMAL(Np->Num) && Np->read_dec == false)
    5281                 :     {
    5282                 :         /*
    5283 ECB             :          * We need not test IS_LDECIMAL(Np->Num) explicitly here, because
    5284                 :          * Np->decimal is always just "." if we don't have a D format token.
    5285                 :          * So we just unconditionally match to Np->decimal.
    5286                 :          */
    5287 GIC          60 :         int         x = strlen(Np->decimal);
    5288                 : 
    5289                 : #ifdef DEBUG_TO_FROM_CHAR
    5290 ECB             :         elog(DEBUG_elog_output, "Try read decimal point (%c)",
    5291                 :              *Np->inout_p);
    5292                 : #endif
    5293 CBC          60 :         if (x && AMOUNT_TEST(x) && strncmp(Np->inout_p, Np->decimal, x) == 0)
    5294                 :         {
    5295              54 :             Np->inout_p += x - 1;
    5296 GIC          54 :             *Np->number_p = '.';
    5297              54 :             Np->number_p++;
    5298              54 :             Np->read_dec = true;
    5299              54 :             isread = true;
    5300 ECB             :         }
    5301                 :     }
    5302                 : 
    5303 GIC         429 :     if (OVERLOAD_TEST)
    5304 LBC           0 :         return;
    5305 ECB             : 
    5306                 :     /*
    5307                 :      * Read sign behind "last" number
    5308                 :      *
    5309                 :      * We need sign detection because determine exact position of post-sign is
    5310                 :      * difficult:
    5311 EUB             :      *
    5312                 :      * FM9999.9999999S     -> 123.001- 9.9S             -> .5- FM9.999999MI ->
    5313                 :      * 5.01-
    5314 ECB             :      */
    5315 GIC         429 :     if (*Np->number == ' ' && Np->read_pre + Np->read_post > 0)
    5316 ECB             :     {
    5317                 :         /*
    5318                 :          * locale sign (NUM_S) is always anchored behind a last number, if: -
    5319                 :          * locale sign expected - last read char was NUM_0/9 or NUM_DEC - and
    5320                 :          * next char is not digit
    5321                 :          */
    5322 GIC         300 :         if (IS_LSIGN(Np->Num) && isread &&
    5323              87 :             (Np->inout_p + 1) < Np->inout + input_len &&
    5324              87 :             !isdigit((unsigned char) *(Np->inout_p + 1)))
    5325              39 :         {
    5326                 :             int         x;
    5327              39 :             char       *tmp = Np->inout_p++;
    5328                 : 
    5329 ECB             : #ifdef DEBUG_TO_FROM_CHAR
    5330                 :             elog(DEBUG_elog_output, "Try read locale post-sign (%c)", *Np->inout_p);
    5331                 : #endif
    5332 GIC          39 :             if ((x = strlen(Np->L_negative_sign)) &&
    5333              39 :                 AMOUNT_TEST(x) &&
    5334              39 :                 strncmp(Np->inout_p, Np->L_negative_sign, x) == 0)
    5335                 :             {
    5336              18 :                 Np->inout_p += x - 1;    /* -1 .. NUM_processor() do inout_p++ */
    5337              18 :                 *Np->number = '-';
    5338                 :             }
    5339 CBC          21 :             else if ((x = strlen(Np->L_positive_sign)) &&
    5340 GIC          21 :                      AMOUNT_TEST(x) &&
    5341 CBC          21 :                      strncmp(Np->inout_p, Np->L_positive_sign, x) == 0)
    5342                 :             {
    5343 UIC           0 :                 Np->inout_p += x - 1;    /* -1 .. NUM_processor() do inout_p++ */
    5344               0 :                 *Np->number = '+';
    5345                 :             }
    5346 GIC          39 :             if (*Np->number == ' ')
    5347                 :                 /* no sign read */
    5348              21 :                 Np->inout_p = tmp;
    5349                 :         }
    5350                 : 
    5351                 :         /*
    5352                 :          * try read non-locale sign, it's happen only if format is not exact
    5353                 :          * and we cannot determine sign position of MI/PL/SG, an example:
    5354                 :          *
    5355                 :          * FM9.999999MI            -> 5.01-
    5356                 :          *
    5357 ECB             :          * if (.... && IS_LSIGN(Np->Num)==false) prevents read wrong formats
    5358                 :          * like to_number('1 -', '9S') where sign is not anchored to last
    5359                 :          * number.
    5360                 :          */
    5361 CBC         261 :         else if (isread == false && IS_LSIGN(Np->Num) == false &&
    5362 GBC          12 :                  (IS_PLUS(Np->Num) || IS_MINUS(Np->Num)))
    5363                 :         {
    5364                 : #ifdef DEBUG_TO_FROM_CHAR
    5365                 :             elog(DEBUG_elog_output, "Try read simple post-sign (%c)", *Np->inout_p);
    5366                 : #endif
    5367                 : 
    5368                 :             /*
    5369                 :              * simple + -
    5370                 :              */
    5371 GIC           3 :             if (*Np->inout_p == '-' || *Np->inout_p == '+')
    5372                 :                 /* NUM_processor() do inout_p++ */
    5373               3 :                 *Np->number = *Np->inout_p;
    5374                 :         }
    5375                 :     }
    5376                 : }
    5377                 : 
    5378                 : #define IS_PREDEC_SPACE(_n) \
    5379 ECB             :         (IS_ZERO((_n)->Num)==false && \
    5380                 :          (_n)->number == (_n)->number_p && \
    5381                 :          *(_n)->number == '0' && \
    5382                 :                  (_n)->Num->post != 0)
    5383                 : 
    5384                 : /* ----------
    5385                 :  * Add digit or sign to number-string
    5386                 :  * ----------
    5387                 :  */
    5388                 : static void
    5389 CBC     4413985 : NUM_numpart_to_char(NUMProc *Np, int id)
    5390                 : {
    5391 ECB             :     int         end;
    5392                 : 
    5393 CBC     4413985 :     if (IS_ROMAN(Np->Num))
    5394 LBC           0 :         return;
    5395                 : 
    5396 ECB             :     /* Note: in this elog() output not set '\0' in 'inout' */
    5397                 : 
    5398                 : #ifdef DEBUG_TO_FROM_CHAR
    5399                 : 
    5400                 :     /*
    5401                 :      * Np->num_curr is number of current item in format-picture, it is not
    5402                 :      * current position in inout!
    5403                 :      */
    5404                 :     elog(DEBUG_elog_output,
    5405                 :          "SIGN_WROTE: %d, CURRENT: %d, NUMBER_P: \"%s\", INOUT: \"%s\"",
    5406                 :          Np->sign_wrote,
    5407                 :          Np->num_curr,
    5408                 :          Np->number_p,
    5409                 :          Np->inout);
    5410                 : #endif
    5411 CBC     4413985 :     Np->num_in = false;
    5412 ECB             : 
    5413                 :     /*
    5414                 :      * Write sign if real number will write to output Note: IS_PREDEC_SPACE()
    5415                 :      * handle "9.9" --> " .1"
    5416                 :      */
    5417 GIC     4413985 :     if (Np->sign_wrote == false &&
    5418 CBC        7323 :         (Np->num_curr >= Np->out_pre_spaces || (IS_ZERO(Np->Num) && Np->Num->zero_start == Np->num_curr)) &&
    5419            1491 :         (IS_PREDEC_SPACE(Np) == false || (Np->last_relevant && *Np->last_relevant == '.')))
    5420 ECB             :     {
    5421 GIC        1419 :         if (IS_LSIGN(Np->Num))
    5422                 :         {
    5423             969 :             if (Np->Num->lsign == NUM_LSIGN_PRE)
    5424                 :             {
    5425             180 :                 if (Np->sign == '-')
    5426              57 :                     strcpy(Np->inout_p, Np->L_negative_sign);
    5427                 :                 else
    5428 CBC         123 :                     strcpy(Np->inout_p, Np->L_positive_sign);
    5429 GIC         180 :                 Np->inout_p += strlen(Np->inout_p);
    5430 CBC         180 :                 Np->sign_wrote = true;
    5431 ECB             :             }
    5432                 :         }
    5433 GIC         450 :         else if (IS_BRACKET(Np->Num))
    5434                 :         {
    5435              72 :             *Np->inout_p = Np->sign == '+' ? ' ' : '<';
    5436 CBC          72 :             ++Np->inout_p;
    5437 GIC          72 :             Np->sign_wrote = true;
    5438 ECB             :         }
    5439 CBC         378 :         else if (Np->sign == '+')
    5440                 :         {
    5441 GIC         246 :             if (!IS_FILLMODE(Np->Num))
    5442 ECB             :             {
    5443 CBC         246 :                 *Np->inout_p = ' '; /* Write + */
    5444             246 :                 ++Np->inout_p;
    5445                 :             }
    5446 GIC         246 :             Np->sign_wrote = true;
    5447                 :         }
    5448             132 :         else if (Np->sign == '-')
    5449 ECB             :         {                       /* Write - */
    5450 CBC         132 :             *Np->inout_p = '-';
    5451             132 :             ++Np->inout_p;
    5452 GIC         132 :             Np->sign_wrote = true;
    5453                 :         }
    5454                 :     }
    5455                 : 
    5456                 : 
    5457                 :     /*
    5458 ECB             :      * digits / FM / Zero / Dec. point
    5459                 :      */
    5460 CBC     4413985 :     if (id == NUM_9 || id == NUM_0 || id == NUM_D || id == NUM_DEC)
    5461                 :     {
    5462         4413985 :         if (Np->num_curr < Np->out_pre_spaces &&
    5463         2674147 :             (Np->Num->zero_start > Np->num_curr || !IS_ZERO(Np->Num)))
    5464                 :         {
    5465                 :             /*
    5466                 :              * Write blank space
    5467                 :              */
    5468 GIC        7728 :             if (!IS_FILLMODE(Np->Num))
    5469 ECB             :             {
    5470 CBC        4851 :                 *Np->inout_p = ' '; /* Write ' ' */
    5471 GIC        4851 :                 ++Np->inout_p;
    5472 ECB             :             }
    5473                 :         }
    5474 GIC     4406257 :         else if (IS_ZERO(Np->Num) &&
    5475         4393027 :                  Np->num_curr < Np->out_pre_spaces &&
    5476         2666419 :                  Np->Num->zero_start <= Np->num_curr)
    5477                 :         {
    5478                 :             /*
    5479                 :              * Write ZERO
    5480                 :              */
    5481 CBC     2666419 :             *Np->inout_p = '0'; /* Write '0' */
    5482 GIC     2666419 :             ++Np->inout_p;
    5483         2666419 :             Np->num_in = true;
    5484                 :         }
    5485                 :         else
    5486                 :         {
    5487                 :             /*
    5488 ECB             :              * Write Decimal point
    5489                 :              */
    5490 CBC     1739838 :             if (*Np->number_p == '.')
    5491                 :             {
    5492             784 :                 if (!Np->last_relevant || *Np->last_relevant != '.')
    5493 ECB             :                 {
    5494 GIC         694 :                     strcpy(Np->inout_p, Np->decimal); /* Write DEC/D */
    5495             694 :                     Np->inout_p += strlen(Np->inout_p);
    5496                 :                 }
    5497                 : 
    5498                 :                 /*
    5499 ECB             :                  * Ora 'n' -- FM9.9 --> 'n.'
    5500                 :                  */
    5501 CBC          90 :                 else if (IS_FILLMODE(Np->Num) &&
    5502              90 :                          Np->last_relevant && *Np->last_relevant == '.')
    5503                 :                 {
    5504 GIC          90 :                     strcpy(Np->inout_p, Np->decimal); /* Write DEC/D */
    5505              90 :                     Np->inout_p += strlen(Np->inout_p);
    5506                 :                 }
    5507 ECB             :             }
    5508                 :             else
    5509                 :             {
    5510                 :                 /*
    5511                 :                  * Write Digits
    5512                 :                  */
    5513 CBC     1739054 :                 if (Np->last_relevant && Np->number_p > Np->last_relevant &&
    5514 ECB             :                     id != NUM_0)
    5515                 :                     ;
    5516                 : 
    5517                 :                 /*
    5518                 :                  * '0.1' -- 9.9 --> '  .1'
    5519                 :                  */
    5520 CBC     1735718 :                 else if (IS_PREDEC_SPACE(Np))
    5521                 :                 {
    5522             114 :                     if (!IS_FILLMODE(Np->Num))
    5523                 :                     {
    5524              78 :                         *Np->inout_p = ' ';
    5525 GIC          78 :                         ++Np->inout_p;
    5526 ECB             :                     }
    5527                 : 
    5528                 :                     /*
    5529                 :                      * '0' -- FM9.9 --> '0.'
    5530                 :                      */
    5531 CBC          36 :                     else if (Np->last_relevant && *Np->last_relevant == '.')
    5532 ECB             :                     {
    5533 GIC          30 :                         *Np->inout_p = '0';
    5534 CBC          30 :                         ++Np->inout_p;
    5535 ECB             :                     }
    5536                 :                 }
    5537                 :                 else
    5538                 :                 {
    5539 GIC     1735604 :                     *Np->inout_p = *Np->number_p; /* Write DIGIT */
    5540 CBC     1735604 :                     ++Np->inout_p;
    5541 GIC     1735604 :                     Np->num_in = true;
    5542                 :                 }
    5543                 :             }
    5544                 :             /* do no exceed string length */
    5545         1739838 :             if (*Np->number_p)
    5546         1739667 :                 ++Np->number_p;
    5547 ECB             :         }
    5548                 : 
    5549 CBC     4413985 :         end = Np->num_count + (Np->out_pre_spaces ? 1 : 0) + (IS_DECIMAL(Np->Num) ? 1 : 0);
    5550                 : 
    5551         4413985 :         if (Np->last_relevant && Np->last_relevant == Np->number_p)
    5552 GBC         336 :             end = Np->num_curr;
    5553 ECB             : 
    5554 CBC     4413985 :         if (Np->num_curr + 1 == end)
    5555 ECB             :         {
    5556 GIC      497727 :             if (Np->sign_wrote == true && IS_BRACKET(Np->Num))
    5557 ECB             :             {
    5558 GIC          72 :                 *Np->inout_p = Np->sign == '+' ? ' ' : '>';
    5559              72 :                 ++Np->inout_p;
    5560 ECB             :             }
    5561 GIC      497655 :             else if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_POST)
    5562                 :             {
    5563              46 :                 if (Np->sign == '-')
    5564              25 :                     strcpy(Np->inout_p, Np->L_negative_sign);
    5565                 :                 else
    5566 CBC          21 :                     strcpy(Np->inout_p, Np->L_positive_sign);
    5567 GIC          46 :                 Np->inout_p += strlen(Np->inout_p);
    5568                 :             }
    5569                 :         }
    5570 ECB             :     }
    5571                 : 
    5572 CBC     4413985 :     ++Np->num_curr;
    5573 ECB             : }
    5574                 : 
    5575                 : /*
    5576                 :  * Skip over "n" input characters, but only if they aren't numeric data
    5577                 :  */
    5578                 : static void
    5579 CBC          18 : NUM_eat_non_data_chars(NUMProc *Np, int n, int input_len)
    5580                 : {
    5581              33 :     while (n-- > 0)
    5582 ECB             :     {
    5583 GIC          21 :         if (OVERLOAD_TEST)
    5584 LBC           0 :             break;              /* end of input */
    5585 GIC          21 :         if (strchr("0123456789.,+-", *Np->inout_p) != NULL)
    5586 CBC           6 :             break;              /* it's a data character */
    5587 GBC          15 :         Np->inout_p += pg_mblen(Np->inout_p);
    5588                 :     }
    5589 GIC          18 : }
    5590 ECB             : 
    5591                 : static char *
    5592 GIC      497970 : NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
    5593                 :               char *number, int input_len, int to_char_out_pre_spaces,
    5594                 :               int sign, bool is_to_char, Oid collid)
    5595                 : {
    5596 ECB             :     FormatNode *n;
    5597                 :     NUMProc     _Np,
    5598 GBC      497970 :                *Np = &_Np;
    5599 EUB             :     const char *pattern;
    5600                 :     int         pattern_len;
    5601                 : 
    5602 GIC     8963460 :     MemSet(Np, 0, sizeof(NUMProc));
    5603 EUB             : 
    5604 GBC      497970 :     Np->Num = Num;
    5605 GIC      497970 :     Np->is_to_char = is_to_char;
    5606 GBC      497970 :     Np->number = number;
    5607 GIC      497970 :     Np->inout = inout;
    5608 GBC      497970 :     Np->last_relevant = NULL;
    5609          497970 :     Np->read_post = 0;
    5610 GIC      497970 :     Np->read_pre = 0;
    5611          497970 :     Np->read_dec = false;
    5612 EUB             : 
    5613 GBC      497970 :     if (Np->Num->zero_start)
    5614 GIC      496796 :         --Np->Num->zero_start;
    5615                 : 
    5616          497970 :     if (IS_EEEE(Np->Num))
    5617                 :     {
    5618             159 :         if (!Np->is_to_char)
    5619 LBC           0 :             ereport(ERROR,
    5620                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    5621 ECB             :                      errmsg("\"EEEE\" not supported for input")));
    5622 GIC         159 :         return strcpy(inout, number);
    5623                 :     }
    5624 ECB             : 
    5625                 :     /*
    5626                 :      * Roman correction
    5627 EUB             :      */
    5628 GIC      497811 :     if (IS_ROMAN(Np->Num))
    5629 ECB             :     {
    5630 UIC           0 :         if (!Np->is_to_char)
    5631               0 :             ereport(ERROR,
    5632                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    5633 ECB             :                      errmsg("\"RN\" not supported for input")));
    5634                 : 
    5635 LBC           0 :         Np->Num->lsign = Np->Num->pre_lsign_num = Np->Num->post =
    5636               0 :             Np->Num->pre = Np->out_pre_spaces = Np->sign = 0;
    5637                 : 
    5638 UIC           0 :         if (IS_FILLMODE(Np->Num))
    5639 ECB             :         {
    5640 LBC           0 :             Np->Num->flag = 0;
    5641 UIC           0 :             Np->Num->flag |= NUM_F_FILLMODE;
    5642 ECB             :         }
    5643                 :         else
    5644 LBC           0 :             Np->Num->flag = 0;
    5645               0 :         Np->Num->flag |= NUM_F_ROMAN;
    5646                 :     }
    5647                 : 
    5648                 :     /*
    5649 ECB             :      * Sign
    5650                 :      */
    5651 GIC      497811 :     if (is_to_char)
    5652                 :     {
    5653          497739 :         Np->sign = sign;
    5654 ECB             : 
    5655                 :         /* MI/PL/SG - write sign itself and not in number */
    5656 CBC      497739 :         if (IS_PLUS(Np->Num) || IS_MINUS(Np->Num))
    5657                 :         {
    5658             261 :             if (IS_PLUS(Np->Num) && IS_MINUS(Np->Num) == false)
    5659 UIC           0 :                 Np->sign_wrote = false; /* need sign */
    5660 ECB             :             else
    5661 GIC         261 :                 Np->sign_wrote = true;   /* needn't sign */
    5662 ECB             :         }
    5663                 :         else
    5664                 :         {
    5665 GIC      497478 :             if (Np->sign != '-')
    5666                 :             {
    5667 GNC      497216 :                 if (IS_FILLMODE(Np->Num))
    5668 GIC      496853 :                     Np->Num->flag &= ~NUM_F_BRACKET;
    5669                 :             }
    5670                 : 
    5671          497478 :             if (Np->sign == '+' && IS_FILLMODE(Np->Num) && IS_LSIGN(Np->Num) == false)
    5672 CBC      496799 :                 Np->sign_wrote = true;   /* needn't sign */
    5673 ECB             :             else
    5674 GIC         679 :                 Np->sign_wrote = false; /* need sign */
    5675 ECB             : 
    5676 CBC      497478 :             if (Np->Num->lsign == NUM_LSIGN_PRE && Np->Num->pre == Np->Num->pre_lsign_num)
    5677              15 :                 Np->Num->lsign = NUM_LSIGN_POST;
    5678                 :         }
    5679                 :     }
    5680                 :     else
    5681              72 :         Np->sign = false;
    5682 ECB             : 
    5683                 :     /*
    5684                 :      * Count
    5685                 :      */
    5686 CBC      497811 :     Np->num_count = Np->Num->post + Np->Num->pre - 1;
    5687 ECB             : 
    5688 CBC      497811 :     if (is_to_char)
    5689                 :     {
    5690 GIC      497739 :         Np->out_pre_spaces = to_char_out_pre_spaces;
    5691 ECB             : 
    5692 CBC      497739 :         if (IS_FILLMODE(Np->Num) && IS_DECIMAL(Np->Num))
    5693                 :         {
    5694 GIC         339 :             Np->last_relevant = get_last_relevant_decnum(Np->number);
    5695                 : 
    5696                 :             /*
    5697                 :              * If any '0' specifiers are present, make sure we don't strip
    5698                 :              * those digits.  But don't advance last_relevant beyond the last
    5699                 :              * character of the Np->number string, which is a hazard if the
    5700                 :              * number got shortened due to precision limitations.
    5701                 :              */
    5702             339 :             if (Np->last_relevant && Np->Num->zero_end > Np->out_pre_spaces)
    5703                 :             {
    5704                 :                 int         last_zero_pos;
    5705                 :                 char       *last_zero;
    5706                 : 
    5707                 :                 /* note that Np->number cannot be zero-length here */
    5708             138 :                 last_zero_pos = strlen(Np->number) - 1;
    5709             138 :                 last_zero_pos = Min(last_zero_pos,
    5710                 :                                     Np->Num->zero_end - Np->out_pre_spaces);
    5711             138 :                 last_zero = Np->number + last_zero_pos;
    5712             138 :                 if (Np->last_relevant < last_zero)
    5713              72 :                     Np->last_relevant = last_zero;
    5714                 :             }
    5715                 :         }
    5716                 : 
    5717          497739 :         if (Np->sign_wrote == false && Np->out_pre_spaces == 0)
    5718             190 :             ++Np->num_count;
    5719                 :     }
    5720 ECB             :     else
    5721                 :     {
    5722 GIC          72 :         Np->out_pre_spaces = 0;
    5723              72 :         *Np->number = ' ';       /* sign space */
    5724              72 :         *(Np->number + 1) = '\0';
    5725 ECB             :     }
    5726                 : 
    5727 GIC      497811 :     Np->num_in = 0;
    5728 CBC      497811 :     Np->num_curr = 0;
    5729                 : 
    5730 ECB             : #ifdef DEBUG_TO_FROM_CHAR
    5731                 :     elog(DEBUG_elog_output,
    5732                 :          "\n\tSIGN: '%c'\n\tNUM: '%s'\n\tPRE: %d\n\tPOST: %d\n\tNUM_COUNT: %d\n\tNUM_PRE: %d\n\tSIGN_WROTE: %s\n\tZERO: %s\n\tZERO_START: %d\n\tZERO_END: %d\n\tLAST_RELEVANT: %s\n\tBRACKET: %s\n\tPLUS: %s\n\tMINUS: %s\n\tFILLMODE: %s\n\tROMAN: %s\n\tEEEE: %s",
    5733                 :          Np->sign,
    5734                 :          Np->number,
    5735                 :          Np->Num->pre,
    5736                 :          Np->Num->post,
    5737                 :          Np->num_count,
    5738                 :          Np->out_pre_spaces,
    5739                 :          Np->sign_wrote ? "Yes" : "No",
    5740                 :          IS_ZERO(Np->Num) ? "Yes" : "No",
    5741                 :          Np->Num->zero_start,
    5742                 :          Np->Num->zero_end,
    5743                 :          Np->last_relevant ? Np->last_relevant : "<not set>",
    5744                 :          IS_BRACKET(Np->Num) ? "Yes" : "No",
    5745                 :          IS_PLUS(Np->Num) ? "Yes" : "No",
    5746                 :          IS_MINUS(Np->Num) ? "Yes" : "No",
    5747                 :          IS_FILLMODE(Np->Num) ? "Yes" : "No",
    5748                 :          IS_ROMAN(Np->Num) ? "Yes" : "No",
    5749                 :          IS_EEEE(Np->Num) ? "Yes" : "No"
    5750                 :         );
    5751                 : #endif
    5752                 : 
    5753                 :     /*
    5754                 :      * Locale
    5755                 :      */
    5756 GIC      497811 :     NUM_prepare_locale(Np);
    5757                 : 
    5758                 :     /*
    5759                 :      * Processor direct cycle
    5760 ECB             :      */
    5761 GIC      497811 :     if (Np->is_to_char)
    5762 CBC      497739 :         Np->number_p = Np->number;
    5763                 :     else
    5764 GIC          72 :         Np->number_p = Np->number + 1;    /* first char is space for sign */
    5765                 : 
    5766 CBC     5415052 :     for (n = node, Np->inout_p = Np->inout; n->type != NODE_TYPE_END; n++)
    5767                 :     {
    5768         4917280 :         if (!Np->is_to_char)
    5769 ECB             :         {
    5770                 :             /*
    5771                 :              * Check at least one byte remains to be scanned.  (In actions
    5772                 :              * below, must use AMOUNT_TEST if we want to read more bytes than
    5773                 :              * that.)
    5774                 :              */
    5775 GIC         579 :             if (OVERLOAD_TEST)
    5776              39 :                 break;
    5777 ECB             :         }
    5778                 : 
    5779                 :         /*
    5780                 :          * Format pictures actions
    5781                 :          */
    5782 CBC     4917241 :         if (n->type == NODE_TYPE_ACTION)
    5783 EUB             :         {
    5784                 :             /*
    5785 ECB             :              * Create/read digit/zero/blank/sign/special-case
    5786                 :              *
    5787                 :              * 'NUM_S' note: The locale sign is anchored to number and we
    5788                 :              * read/write it when we work with first or last number
    5789                 :              * (NUM_0/NUM_9).  This is why NUM_S is missing in switch().
    5790                 :              *
    5791                 :              * Notice the "Np->inout_p++" at the bottom of the loop.  This is
    5792                 :              * why most of the actions advance inout_p one less than you might
    5793                 :              * expect.  In cases where we don't want that increment to happen,
    5794                 :              * a switch case ends with "continue" not "break".
    5795 EUB             :              */
    5796 GIC     4912927 :             switch (n->key->id)
    5797 ECB             :             {
    5798 CBC     4414414 :                 case NUM_9:
    5799                 :                 case NUM_0:
    5800 ECB             :                 case NUM_DEC:
    5801                 :                 case NUM_D:
    5802 CBC     4414414 :                     if (Np->is_to_char)
    5803 ECB             :                     {
    5804 CBC     4413985 :                         NUM_numpart_to_char(Np, n->key->id);
    5805         4413985 :                         continue;   /* for() */
    5806                 :                     }
    5807 ECB             :                     else
    5808                 :                     {
    5809 CBC         429 :                         NUM_numpart_from_char(Np, n->key->id, input_len);
    5810 GBC         429 :                         break;  /* switch() case: */
    5811                 :                     }
    5812                 : 
    5813 GIC         183 :                 case NUM_COMMA:
    5814 CBC         183 :                     if (Np->is_to_char)
    5815 ECB             :                     {
    5816 CBC         165 :                         if (!Np->num_in)
    5817                 :                         {
    5818 GIC          60 :                             if (IS_FILLMODE(Np->Num))
    5819 UIC           0 :                                 continue;
    5820                 :                             else
    5821 CBC          60 :                                 *Np->inout_p = ' ';
    5822 ECB             :                         }
    5823                 :                         else
    5824 GIC         105 :                             *Np->inout_p = ',';
    5825                 :                     }
    5826                 :                     else
    5827 ECB             :                     {
    5828 GIC          18 :                         if (!Np->num_in)
    5829 ECB             :                         {
    5830 GBC          18 :                             if (IS_FILLMODE(Np->Num))
    5831 UIC           0 :                                 continue;
    5832                 :                         }
    5833 GIC          18 :                         if (*Np->inout_p != ',')
    5834              18 :                             continue;
    5835                 :                     }
    5836             165 :                     break;
    5837                 : 
    5838             612 :                 case NUM_G:
    5839 CBC         612 :                     pattern = Np->L_thousands_sep;
    5840             612 :                     pattern_len = strlen(pattern);
    5841             612 :                     if (Np->is_to_char)
    5842                 :                     {
    5843             585 :                         if (!Np->num_in)
    5844                 :                         {
    5845             294 :                             if (IS_FILLMODE(Np->Num))
    5846 UIC           0 :                                 continue;
    5847 ECB             :                             else
    5848                 :                             {
    5849                 :                                 /* just in case there are MB chars */
    5850 GIC         294 :                                 pattern_len = pg_mbstrlen(pattern);
    5851 CBC         294 :                                 memset(Np->inout_p, ' ', pattern_len);
    5852             294 :                                 Np->inout_p += pattern_len - 1;
    5853                 :                             }
    5854                 :                         }
    5855                 :                         else
    5856 ECB             :                         {
    5857 CBC         291 :                             strcpy(Np->inout_p, pattern);
    5858 GIC         291 :                             Np->inout_p += pattern_len - 1;
    5859 ECB             :                         }
    5860                 :                     }
    5861 EUB             :                     else
    5862                 :                     {
    5863 GIC          27 :                         if (!Np->num_in)
    5864 EUB             :                         {
    5865 GBC          27 :                             if (IS_FILLMODE(Np->Num))
    5866 UIC           0 :                                 continue;
    5867                 :                         }
    5868                 : 
    5869 EUB             :                         /*
    5870                 :                          * Because L_thousands_sep typically contains data
    5871                 :                          * characters (either '.' or ','), we can't use
    5872                 :                          * NUM_eat_non_data_chars here.  Instead skip only if
    5873                 :                          * the input matches L_thousands_sep.
    5874                 :                          */
    5875 GBC          27 :                         if (AMOUNT_TEST(pattern_len) &&
    5876 GIC          27 :                             strncmp(Np->inout_p, pattern, pattern_len) == 0)
    5877 GBC          24 :                             Np->inout_p += pattern_len - 1;
    5878 EUB             :                         else
    5879 GIC           3 :                             continue;
    5880                 :                     }
    5881             609 :                     break;
    5882 EUB             : 
    5883 GBC          60 :                 case NUM_L:
    5884 GIC          60 :                     pattern = Np->L_currency_symbol;
    5885 GBC          60 :                     if (Np->is_to_char)
    5886                 :                     {
    5887 CBC          45 :                         strcpy(Np->inout_p, pattern);
    5888              45 :                         Np->inout_p += strlen(pattern) - 1;
    5889 ECB             :                     }
    5890                 :                     else
    5891                 :                     {
    5892 CBC          15 :                         NUM_eat_non_data_chars(Np, pg_mbstrlen(pattern), input_len);
    5893 GIC          15 :                         continue;
    5894 ECB             :                     }
    5895 CBC          45 :                     break;
    5896                 : 
    5897 UIC           0 :                 case NUM_RN:
    5898               0 :                     if (IS_FILLMODE(Np->Num))
    5899                 :                     {
    5900 LBC           0 :                         strcpy(Np->inout_p, Np->number_p);
    5901               0 :                         Np->inout_p += strlen(Np->inout_p) - 1;
    5902                 :                     }
    5903 ECB             :                     else
    5904                 :                     {
    5905 LBC           0 :                         sprintf(Np->inout_p, "%15s", Np->number_p);
    5906               0 :                         Np->inout_p += strlen(Np->inout_p) - 1;
    5907 ECB             :                     }
    5908 LBC           0 :                     break;
    5909                 : 
    5910               0 :                 case NUM_rn:
    5911 UIC           0 :                     if (IS_FILLMODE(Np->Num))
    5912 ECB             :                     {
    5913 LBC           0 :                         strcpy(Np->inout_p, asc_tolower_z(Np->number_p));
    5914 UIC           0 :                         Np->inout_p += strlen(Np->inout_p) - 1;
    5915                 :                     }
    5916                 :                     else
    5917                 :                     {
    5918 UBC           0 :                         sprintf(Np->inout_p, "%15s", asc_tolower_z(Np->number_p));
    5919               0 :                         Np->inout_p += strlen(Np->inout_p) - 1;
    5920                 :                     }
    5921 LBC           0 :                     break;
    5922                 : 
    5923 CBC          48 :                 case NUM_th:
    5924              48 :                     if (IS_ROMAN(Np->Num) || *Np->number == '#' ||
    5925 GIC          48 :                         Np->sign == '-' || IS_DECIMAL(Np->Num))
    5926 CBC          33 :                         continue;
    5927 ECB             : 
    5928 CBC          15 :                     if (Np->is_to_char)
    5929 EUB             :                     {
    5930 GIC          12 :                         strcpy(Np->inout_p, get_th(Np->number, TH_LOWER));
    5931 CBC          12 :                         Np->inout_p += 1;
    5932                 :                     }
    5933                 :                     else
    5934                 :                     {
    5935 EUB             :                         /* All variants of 'th' occupy 2 characters */
    5936 GBC           3 :                         NUM_eat_non_data_chars(Np, 2, input_len);
    5937 GIC           3 :                         continue;
    5938                 :                     }
    5939 GBC          12 :                     break;
    5940 EUB             : 
    5941 GIC          45 :                 case NUM_TH:
    5942              45 :                     if (IS_ROMAN(Np->Num) || *Np->number == '#' ||
    5943 CBC          45 :                         Np->sign == '-' || IS_DECIMAL(Np->Num))
    5944 GIC          33 :                         continue;
    5945 EUB             : 
    5946 GBC          12 :                     if (Np->is_to_char)
    5947                 :                     {
    5948              12 :                         strcpy(Np->inout_p, get_th(Np->number, TH_UPPER));
    5949              12 :                         Np->inout_p += 1;
    5950 EUB             :                     }
    5951                 :                     else
    5952                 :                     {
    5953                 :                         /* All variants of 'TH' occupy 2 characters */
    5954 UIC           0 :                         NUM_eat_non_data_chars(Np, 2, input_len);
    5955               0 :                         continue;
    5956                 :                     }
    5957 GBC          12 :                     break;
    5958 EUB             : 
    5959 GIC         171 :                 case NUM_MI:
    5960             171 :                     if (Np->is_to_char)
    5961 EUB             :                     {
    5962 GBC         171 :                         if (Np->sign == '-')
    5963 GIC          48 :                             *Np->inout_p = '-';
    5964             123 :                         else if (IS_FILLMODE(Np->Num))
    5965 UBC           0 :                             continue;
    5966                 :                         else
    5967 CBC         123 :                             *Np->inout_p = ' ';
    5968 ECB             :                     }
    5969                 :                     else
    5970                 :                     {
    5971 UIC           0 :                         if (*Np->inout_p == '-')
    5972 UBC           0 :                             *Np->number = '-';
    5973 EUB             :                         else
    5974                 :                         {
    5975 UBC           0 :                             NUM_eat_non_data_chars(Np, 1, input_len);
    5976 UIC           0 :                             continue;
    5977                 :                         }
    5978 EUB             :                     }
    5979 GBC         171 :                     break;
    5980                 : 
    5981 UIC           0 :                 case NUM_PL:
    5982 LBC           0 :                     if (Np->is_to_char)
    5983                 :                     {
    5984               0 :                         if (Np->sign == '+')
    5985               0 :                             *Np->inout_p = '+';
    5986 UIC           0 :                         else if (IS_FILLMODE(Np->Num))
    5987               0 :                             continue;
    5988                 :                         else
    5989               0 :                             *Np->inout_p = ' ';
    5990                 :                     }
    5991                 :                     else
    5992                 :                     {
    5993               0 :                         if (*Np->inout_p == '+')
    5994               0 :                             *Np->number = '+';
    5995                 :                         else
    5996                 :                         {
    5997 LBC           0 :                             NUM_eat_non_data_chars(Np, 1, input_len);
    5998 UIC           0 :                             continue;
    5999 ECB             :                         }
    6000                 :                     }
    6001 UIC           0 :                     break;
    6002                 : 
    6003 GIC          90 :                 case NUM_SG:
    6004 CBC          90 :                     if (Np->is_to_char)
    6005 GIC          90 :                         *Np->inout_p = Np->sign;
    6006 ECB             :                     else
    6007                 :                     {
    6008 LBC           0 :                         if (*Np->inout_p == '-')
    6009 UIC           0 :                             *Np->number = '-';
    6010               0 :                         else if (*Np->inout_p == '+')
    6011 LBC           0 :                             *Np->number = '+';
    6012                 :                         else
    6013 ECB             :                         {
    6014 LBC           0 :                             NUM_eat_non_data_chars(Np, 1, input_len);
    6015 UIC           0 :                             continue;
    6016                 :                         }
    6017                 :                     }
    6018 CBC          90 :                     break;
    6019 EUB             : 
    6020 GIC      497304 :                 default:
    6021 CBC      497304 :                     continue;
    6022                 :                     break;
    6023                 :             }
    6024                 :         }
    6025                 :         else
    6026 ECB             :         {
    6027                 :             /*
    6028                 :              * In TO_CHAR, non-pattern characters in the format are copied to
    6029                 :              * the output.  In TO_NUMBER, we skip one input character for each
    6030                 :              * non-pattern format character, whether or not it matches the
    6031                 :              * format character.
    6032                 :              */
    6033 GIC        4314 :             if (Np->is_to_char)
    6034                 :             {
    6035            4281 :                 strcpy(Np->inout_p, n->character);
    6036            4281 :                 Np->inout_p += strlen(Np->inout_p);
    6037                 :             }
    6038                 :             else
    6039                 :             {
    6040              33 :                 Np->inout_p += pg_mblen(Np->inout_p);
    6041                 :             }
    6042            4314 :             continue;
    6043                 :         }
    6044            1533 :         Np->inout_p++;
    6045                 :     }
    6046                 : 
    6047          497811 :     if (Np->is_to_char)
    6048                 :     {
    6049          497739 :         *Np->inout_p = '\0';
    6050          497739 :         return Np->inout;
    6051                 :     }
    6052                 :     else
    6053                 :     {
    6054              72 :         if (*(Np->number_p - 1) == '.')
    6055 UIC           0 :             *(Np->number_p - 1) = '\0';
    6056                 :         else
    6057 GIC          72 :             *Np->number_p = '\0';
    6058                 : 
    6059                 :         /*
    6060                 :          * Correction - precision of dec. number
    6061                 :          */
    6062              72 :         Np->Num->post = Np->read_post;
    6063                 : 
    6064                 : #ifdef DEBUG_TO_FROM_CHAR
    6065                 :         elog(DEBUG_elog_output, "TO_NUMBER (number): '%s'", Np->number);
    6066                 : #endif
    6067              72 :         return Np->number;
    6068                 :     }
    6069                 : }
    6070                 : 
    6071                 : /* ----------
    6072                 :  * MACRO: Start part of NUM - for all NUM's to_char variants
    6073                 :  *  (sorry, but I hate copy same code - macro is better..)
    6074                 :  * ----------
    6075                 :  */
    6076 ECB             : #define NUM_TOCHAR_prepare \
    6077                 : do { \
    6078                 :     int len = VARSIZE_ANY_EXHDR(fmt); \
    6079                 :     if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ)       \
    6080                 :         PG_RETURN_TEXT_P(cstring_to_text("")); \
    6081                 :     result  = (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ);    \
    6082                 :     format  = NUM_cache(len, &Num, fmt, &shouldFree);       \
    6083                 : } while (0)
    6084                 : 
    6085                 : /* ----------
    6086                 :  * MACRO: Finish part of NUM
    6087                 :  * ----------
    6088                 :  */
    6089                 : #define NUM_TOCHAR_finish \
    6090                 : do { \
    6091                 :     int     len; \
    6092 EUB             :                                     \
    6093                 :     NUM_processor(format, &Num, VARDATA(result), numstr, 0, out_pre_spaces, sign, true, PG_GET_COLLATION()); \
    6094 ECB             :                                     \
    6095                 :     if (shouldFree)                 \
    6096                 :         pfree(format);              \
    6097                 :                                     \
    6098                 :     /*                              \
    6099                 :      * Convert null-terminated representation of result to standard text. \
    6100                 :      * The result is usually much bigger than it needs to be, but there \
    6101                 :      * seems little point in realloc'ing it smaller. \
    6102                 :      */                             \
    6103                 :     len = strlen(VARDATA(result));  \
    6104                 :     SET_VARSIZE(result, len + VARHDRSZ); \
    6105 EUB             : } while (0)
    6106                 : 
    6107 ECB             : /* -------------------
    6108                 :  * NUMERIC to_number() (convert string to numeric)
    6109                 :  * -------------------
    6110                 :  */
    6111                 : Datum
    6112 CBC          72 : numeric_to_number(PG_FUNCTION_ARGS)
    6113                 : {
    6114 GIC          72 :     text       *value = PG_GETARG_TEXT_PP(0);
    6115 GBC          72 :     text       *fmt = PG_GETARG_TEXT_PP(1);
    6116 EUB             :     NUMDesc     Num;
    6117                 :     Datum       result;
    6118                 :     FormatNode *format;
    6119                 :     char       *numstr;
    6120                 :     bool        shouldFree;
    6121 GBC          72 :     int         len = 0;
    6122                 :     int         scale,
    6123                 :                 precision;
    6124                 : 
    6125 GIC          72 :     len = VARSIZE_ANY_EXHDR(fmt);
    6126 ECB             : 
    6127 CBC          72 :     if (len <= 0 || len >= INT_MAX / NUM_MAX_ITEM_SIZ)
    6128 UIC           0 :         PG_RETURN_NULL();
    6129                 : 
    6130 GIC          72 :     format = NUM_cache(len, &Num, fmt, &shouldFree);
    6131                 : 
    6132              72 :     numstr = (char *) palloc((len * NUM_MAX_ITEM_SIZ) + 1);
    6133                 : 
    6134              72 :     NUM_processor(format, &Num, VARDATA_ANY(value), numstr,
    6135 CBC          72 :                   VARSIZE_ANY_EXHDR(value), 0, 0, false, PG_GET_COLLATION());
    6136                 : 
    6137              72 :     scale = Num.post;
    6138              72 :     precision = Num.pre + Num.multi + scale;
    6139                 : 
    6140 GIC          72 :     if (shouldFree)
    6141 UIC           0 :         pfree(format);
    6142                 : 
    6143 CBC          72 :     result = DirectFunctionCall3(numeric_in,
    6144 ECB             :                                  CStringGetDatum(numstr),
    6145                 :                                  ObjectIdGetDatum(InvalidOid),
    6146                 :                                  Int32GetDatum(((precision << 16) | scale) + VARHDRSZ));
    6147                 : 
    6148 GIC          72 :     if (IS_MULTI(&Num))
    6149                 :     {
    6150 ECB             :         Numeric     x;
    6151 UIC           0 :         Numeric     a = int64_to_numeric(10);
    6152               0 :         Numeric     b = int64_to_numeric(-Num.multi);
    6153                 : 
    6154               0 :         x = DatumGetNumeric(DirectFunctionCall2(numeric_power,
    6155 ECB             :                                                 NumericGetDatum(a),
    6156                 :                                                 NumericGetDatum(b)));
    6157 UBC           0 :         result = DirectFunctionCall2(numeric_mul,
    6158                 :                                      result,
    6159                 :                                      NumericGetDatum(x));
    6160                 :     }
    6161 EUB             : 
    6162 GIC          72 :     pfree(numstr);
    6163              72 :     return result;
    6164 ECB             : }
    6165                 : 
    6166                 : /* ------------------
    6167                 :  * NUMERIC to_char()
    6168                 :  * ------------------
    6169                 :  */
    6170                 : Datum
    6171 GIC         859 : numeric_to_char(PG_FUNCTION_ARGS)
    6172                 : {
    6173             859 :     Numeric     value = PG_GETARG_NUMERIC(0);
    6174 CBC         859 :     text       *fmt = PG_GETARG_TEXT_PP(1);
    6175 ECB             :     NUMDesc     Num;
    6176                 :     FormatNode *format;
    6177                 :     text       *result;
    6178                 :     bool        shouldFree;
    6179 GIC         859 :     int         out_pre_spaces = 0,
    6180             859 :                 sign = 0;
    6181                 :     char       *numstr,
    6182 ECB             :                *orgnum,
    6183                 :                *p;
    6184                 :     Numeric     x;
    6185                 : 
    6186 GIC         859 :     NUM_TOCHAR_prepare;
    6187 ECB             : 
    6188                 :     /*
    6189                 :      * On DateType depend part (numeric)
    6190                 :      */
    6191 CBC         859 :     if (IS_ROMAN(&Num))
    6192                 :     {
    6193 UIC           0 :         x = DatumGetNumeric(DirectFunctionCall2(numeric_round,
    6194                 :                                                 NumericGetDatum(value),
    6195 ECB             :                                                 Int32GetDatum(0)));
    6196                 :         numstr =
    6197 UIC           0 :             int_to_roman(DatumGetInt32(DirectFunctionCall1(numeric_int4,
    6198                 :                                                            NumericGetDatum(x))));
    6199                 :     }
    6200 GIC         859 :     else if (IS_EEEE(&Num))
    6201 ECB             :     {
    6202 GIC         117 :         orgnum = numeric_out_sci(value, Num.post);
    6203 ECB             : 
    6204                 :         /*
    6205 EUB             :          * numeric_out_sci() does not emit a sign for positive numbers.  We
    6206                 :          * need to add a space in this case so that positive and negative
    6207                 :          * numbers are aligned.  Also must check for NaN/infinity cases, which
    6208                 :          * we handle the same way as in float8_to_char.
    6209                 :          */
    6210 GIC         117 :         if (strcmp(orgnum, "NaN") == 0 ||
    6211 GBC         114 :             strcmp(orgnum, "Infinity") == 0 ||
    6212 GIC         111 :             strcmp(orgnum, "-Infinity") == 0)
    6213                 :         {
    6214 EUB             :             /*
    6215                 :              * Allow 6 characters for the leading sign, the decimal point,
    6216                 :              * "e", the exponent's sign and two exponent digits.
    6217 ECB             :              */
    6218 GIC           9 :             numstr = (char *) palloc(Num.pre + Num.post + 7);
    6219               9 :             fill_str(numstr, '#', Num.pre + Num.post + 6);
    6220 CBC           9 :             *numstr = ' ';
    6221 GIC           9 :             *(numstr + Num.pre + 1) = '.';
    6222                 :         }
    6223 CBC         108 :         else if (*orgnum != '-')
    6224                 :         {
    6225              96 :             numstr = (char *) palloc(strlen(orgnum) + 2);
    6226              96 :             *numstr = ' ';
    6227 GIC          96 :             strcpy(numstr + 1, orgnum);
    6228                 :         }
    6229                 :         else
    6230 ECB             :         {
    6231 CBC          12 :             numstr = orgnum;
    6232                 :         }
    6233                 :     }
    6234 ECB             :     else
    6235                 :     {
    6236                 :         int         numstr_pre_len;
    6237 CBC         742 :         Numeric     val = value;
    6238                 : 
    6239 GIC         742 :         if (IS_MULTI(&Num))
    6240 ECB             :         {
    6241 LBC           0 :             Numeric     a = int64_to_numeric(10);
    6242 UIC           0 :             Numeric     b = int64_to_numeric(Num.multi);
    6243 ECB             : 
    6244 UIC           0 :             x = DatumGetNumeric(DirectFunctionCall2(numeric_power,
    6245 ECB             :                                                     NumericGetDatum(a),
    6246                 :                                                     NumericGetDatum(b)));
    6247 LBC           0 :             val = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
    6248                 :                                                       NumericGetDatum(value),
    6249                 :                                                       NumericGetDatum(x)));
    6250 UIC           0 :             Num.pre += Num.multi;
    6251 ECB             :         }
    6252                 : 
    6253 GIC         742 :         x = DatumGetNumeric(DirectFunctionCall2(numeric_round,
    6254                 :                                                 NumericGetDatum(val),
    6255                 :                                                 Int32GetDatum(Num.post)));
    6256             742 :         orgnum = DatumGetCString(DirectFunctionCall1(numeric_out,
    6257                 :                                                      NumericGetDatum(x)));
    6258                 : 
    6259             742 :         if (*orgnum == '-')
    6260 ECB             :         {
    6261 GIC         211 :             sign = '-';
    6262 CBC         211 :             numstr = orgnum + 1;
    6263 ECB             :         }
    6264                 :         else
    6265                 :         {
    6266 GIC         531 :             sign = '+';
    6267             531 :             numstr = orgnum;
    6268 ECB             :         }
    6269                 : 
    6270 GIC         742 :         if ((p = strchr(numstr, '.')))
    6271             598 :             numstr_pre_len = p - numstr;
    6272                 :         else
    6273 CBC         144 :             numstr_pre_len = strlen(numstr);
    6274                 : 
    6275                 :         /* needs padding? */
    6276 GIC         742 :         if (numstr_pre_len < Num.pre)
    6277             687 :             out_pre_spaces = Num.pre - numstr_pre_len;
    6278 ECB             :         /* overflowed prefix digit format? */
    6279 GBC          55 :         else if (numstr_pre_len > Num.pre)
    6280 ECB             :         {
    6281 GIC          15 :             numstr = (char *) palloc(Num.pre + Num.post + 2);
    6282              15 :             fill_str(numstr, '#', Num.pre + Num.post + 1);
    6283 GBC          15 :             *(numstr + Num.pre) = '.';
    6284                 :         }
    6285 EUB             :     }
    6286                 : 
    6287 GIC         859 :     NUM_TOCHAR_finish;
    6288             859 :     PG_RETURN_TEXT_P(result);
    6289                 : }
    6290 EUB             : 
    6291                 : /* ---------------
    6292                 :  * INT4 to_char()
    6293                 :  * ---------------
    6294                 :  */
    6295                 : Datum
    6296 GIC      496585 : int4_to_char(PG_FUNCTION_ARGS)
    6297                 : {
    6298          496585 :     int32       value = PG_GETARG_INT32(0);
    6299 CBC      496585 :     text       *fmt = PG_GETARG_TEXT_PP(1);
    6300                 :     NUMDesc     Num;
    6301 EUB             :     FormatNode *format;
    6302                 :     text       *result;
    6303                 :     bool        shouldFree;
    6304 GIC      496585 :     int         out_pre_spaces = 0,
    6305          496585 :                 sign = 0;
    6306                 :     char       *numstr,
    6307 ECB             :                *orgnum;
    6308                 : 
    6309 GIC      496585 :     NUM_TOCHAR_prepare;
    6310                 : 
    6311 ECB             :     /*
    6312                 :      * On DateType depend part (int32)
    6313 EUB             :      */
    6314 GBC      496585 :     if (IS_ROMAN(&Num))
    6315 UIC           0 :         numstr = int_to_roman(value);
    6316 GIC      496585 :     else if (IS_EEEE(&Num))
    6317 ECB             :     {
    6318                 :         /* we can do it easily because float8 won't lose any precision */
    6319 LBC           0 :         float8      val = (float8) value;
    6320                 : 
    6321 UIC           0 :         orgnum = (char *) psprintf("%+.*e", Num.post, val);
    6322 ECB             : 
    6323                 :         /*
    6324 EUB             :          * Swap a leading positive sign for a space.
    6325                 :          */
    6326 UBC           0 :         if (*orgnum == '+')
    6327               0 :             *orgnum = ' ';
    6328 EUB             : 
    6329 UIC           0 :         numstr = orgnum;
    6330                 :     }
    6331 ECB             :     else
    6332                 :     {
    6333                 :         int         numstr_pre_len;
    6334                 : 
    6335 CBC      496585 :         if (IS_MULTI(&Num))
    6336                 :         {
    6337 LBC           0 :             orgnum = DatumGetCString(DirectFunctionCall1(int4out,
    6338                 :                                                          Int32GetDatum(value * ((int32) pow((double) 10, (double) Num.multi)))));
    6339 UBC           0 :             Num.pre += Num.multi;
    6340 EUB             :         }
    6341                 :         else
    6342                 :         {
    6343 GIC      496585 :             orgnum = DatumGetCString(DirectFunctionCall1(int4out,
    6344                 :                                                          Int32GetDatum(value)));
    6345 ECB             :         }
    6346                 : 
    6347 GIC      496585 :         if (*orgnum == '-')
    6348                 :         {
    6349 UIC           0 :             sign = '-';
    6350               0 :             orgnum++;
    6351                 :         }
    6352                 :         else
    6353 GIC      496585 :             sign = '+';
    6354 ECB             : 
    6355 GIC      496585 :         numstr_pre_len = strlen(orgnum);
    6356 ECB             : 
    6357                 :         /* post-decimal digits?  Pad out with zeros. */
    6358 GIC      496585 :         if (Num.post)
    6359                 :         {
    6360 UIC           0 :             numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
    6361               0 :             strcpy(numstr, orgnum);
    6362 LBC           0 :             *(numstr + numstr_pre_len) = '.';
    6363               0 :             memset(numstr + numstr_pre_len + 1, '0', Num.post);
    6364 UIC           0 :             *(numstr + numstr_pre_len + Num.post + 1) = '\0';
    6365                 :         }
    6366                 :         else
    6367 CBC      496585 :             numstr = orgnum;
    6368                 : 
    6369                 :         /* needs padding? */
    6370 GIC      496585 :         if (numstr_pre_len < Num.pre)
    6371          489438 :             out_pre_spaces = Num.pre - numstr_pre_len;
    6372 ECB             :         /* overflowed prefix digit format? */
    6373 GIC        7147 :         else if (numstr_pre_len > Num.pre)
    6374                 :         {
    6375 UBC           0 :             numstr = (char *) palloc(Num.pre + Num.post + 2);
    6376 UIC           0 :             fill_str(numstr, '#', Num.pre + Num.post + 1);
    6377 LBC           0 :             *(numstr + Num.pre) = '.';
    6378                 :         }
    6379                 :     }
    6380 EUB             : 
    6381 GIC      496585 :     NUM_TOCHAR_finish;
    6382          496585 :     PG_RETURN_TEXT_P(result);
    6383                 : }
    6384                 : 
    6385                 : /* ---------------
    6386                 :  * INT8 to_char()
    6387                 :  * ---------------
    6388 EUB             :  */
    6389                 : Datum
    6390 GBC         316 : int8_to_char(PG_FUNCTION_ARGS)
    6391 EUB             : {
    6392 GBC         316 :     int64       value = PG_GETARG_INT64(0);
    6393 GIC         316 :     text       *fmt = PG_GETARG_TEXT_PP(1);
    6394                 :     NUMDesc     Num;
    6395                 :     FormatNode *format;
    6396 EUB             :     text       *result;
    6397                 :     bool        shouldFree;
    6398 GIC         316 :     int         out_pre_spaces = 0,
    6399             316 :                 sign = 0;
    6400                 :     char       *numstr,
    6401                 :                *orgnum;
    6402                 : 
    6403 CBC         316 :     NUM_TOCHAR_prepare;
    6404                 : 
    6405 EUB             :     /*
    6406                 :      * On DateType depend part (int32)
    6407                 :      */
    6408 GIC         316 :     if (IS_ROMAN(&Num))
    6409                 :     {
    6410                 :         /* Currently don't support int8 conversion to roman... */
    6411 UBC           0 :         numstr = int_to_roman(DatumGetInt32(DirectFunctionCall1(int84, Int64GetDatum(value))));
    6412                 :     }
    6413 GIC         316 :     else if (IS_EEEE(&Num))
    6414 ECB             :     {
    6415                 :         /* to avoid loss of precision, must go via numeric not float8 */
    6416 UIC           0 :         orgnum = numeric_out_sci(int64_to_numeric(value),
    6417 ECB             :                                  Num.post);
    6418                 : 
    6419                 :         /*
    6420                 :          * numeric_out_sci() does not emit a sign for positive numbers.  We
    6421                 :          * need to add a space in this case so that positive and negative
    6422                 :          * numbers are aligned.  We don't have to worry about NaN/inf here.
    6423                 :          */
    6424 UIC           0 :         if (*orgnum != '-')
    6425 ECB             :         {
    6426 UIC           0 :             numstr = (char *) palloc(strlen(orgnum) + 2);
    6427               0 :             *numstr = ' ';
    6428 LBC           0 :             strcpy(numstr + 1, orgnum);
    6429                 :         }
    6430 ECB             :         else
    6431                 :         {
    6432 LBC           0 :             numstr = orgnum;
    6433 ECB             :         }
    6434                 :     }
    6435                 :     else
    6436                 :     {
    6437                 :         int         numstr_pre_len;
    6438                 : 
    6439 GIC         316 :         if (IS_MULTI(&Num))
    6440 ECB             :         {
    6441 LBC           0 :             double      multi = pow((double) 10, (double) Num.multi);
    6442                 : 
    6443               0 :             value = DatumGetInt64(DirectFunctionCall2(int8mul,
    6444                 :                                                       Int64GetDatum(value),
    6445 EUB             :                                                       DirectFunctionCall1(dtoi8,
    6446                 :                                                                           Float8GetDatum(multi))));
    6447 UBC           0 :             Num.pre += Num.multi;
    6448                 :         }
    6449                 : 
    6450 GIC         316 :         orgnum = DatumGetCString(DirectFunctionCall1(int8out,
    6451 ECB             :                                                      Int64GetDatum(value)));
    6452                 : 
    6453 GIC         316 :         if (*orgnum == '-')
    6454                 :         {
    6455              99 :             sign = '-';
    6456              99 :             orgnum++;
    6457                 :         }
    6458                 :         else
    6459             217 :             sign = '+';
    6460 ECB             : 
    6461 GIC         316 :         numstr_pre_len = strlen(orgnum);
    6462 ECB             : 
    6463                 :         /* post-decimal digits?  Pad out with zeros. */
    6464 GIC         316 :         if (Num.post)
    6465                 :         {
    6466             105 :             numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
    6467             105 :             strcpy(numstr, orgnum);
    6468 CBC         105 :             *(numstr + numstr_pre_len) = '.';
    6469             105 :             memset(numstr + numstr_pre_len + 1, '0', Num.post);
    6470 GIC         105 :             *(numstr + numstr_pre_len + Num.post + 1) = '\0';
    6471                 :         }
    6472                 :         else
    6473 CBC         211 :             numstr = orgnum;
    6474                 : 
    6475 ECB             :         /* needs padding? */
    6476 GBC         316 :         if (numstr_pre_len < Num.pre)
    6477 CBC         126 :             out_pre_spaces = Num.pre - numstr_pre_len;
    6478                 :         /* overflowed prefix digit format? */
    6479             190 :         else if (numstr_pre_len > Num.pre)
    6480                 :         {
    6481 UIC           0 :             numstr = (char *) palloc(Num.pre + Num.post + 2);
    6482               0 :             fill_str(numstr, '#', Num.pre + Num.post + 1);
    6483               0 :             *(numstr + Num.pre) = '.';
    6484                 :         }
    6485 ECB             :     }
    6486                 : 
    6487 CBC         316 :     NUM_TOCHAR_finish;
    6488             316 :     PG_RETURN_TEXT_P(result);
    6489                 : }
    6490                 : 
    6491                 : /* -----------------
    6492 ECB             :  * FLOAT4 to_char()
    6493                 :  * -----------------
    6494                 :  */
    6495                 : Datum
    6496 GIC          65 : float4_to_char(PG_FUNCTION_ARGS)
    6497 ECB             : {
    6498 CBC          65 :     float4      value = PG_GETARG_FLOAT4(0);
    6499 GIC          65 :     text       *fmt = PG_GETARG_TEXT_PP(1);
    6500                 :     NUMDesc     Num;
    6501                 :     FormatNode *format;
    6502                 :     text       *result;
    6503 ECB             :     bool        shouldFree;
    6504 GIC          65 :     int         out_pre_spaces = 0,
    6505              65 :                 sign = 0;
    6506                 :     char       *numstr,
    6507 ECB             :                *p;
    6508                 : 
    6509 GBC          65 :     NUM_TOCHAR_prepare;
    6510                 : 
    6511              65 :     if (IS_ROMAN(&Num))
    6512 UBC           0 :         numstr = int_to_roman((int) rint(value));
    6513 GIC          65 :     else if (IS_EEEE(&Num))
    6514                 :     {
    6515 CBC          21 :         if (isnan(value) || isinf(value))
    6516 ECB             :         {
    6517                 :             /*
    6518                 :              * Allow 6 characters for the leading sign, the decimal point,
    6519                 :              * "e", the exponent's sign and two exponent digits.
    6520                 :              */
    6521 CBC           9 :             numstr = (char *) palloc(Num.pre + Num.post + 7);
    6522 GBC           9 :             fill_str(numstr, '#', Num.pre + Num.post + 6);
    6523 CBC           9 :             *numstr = ' ';
    6524 GIC           9 :             *(numstr + Num.pre + 1) = '.';
    6525 ECB             :         }
    6526                 :         else
    6527                 :         {
    6528 CBC          12 :             numstr = psprintf("%+.*e", Num.post, value);
    6529                 : 
    6530                 :             /*
    6531                 :              * Swap a leading positive sign for a space.
    6532 ECB             :              */
    6533 CBC          12 :             if (*numstr == '+')
    6534 GIC           9 :                 *numstr = ' ';
    6535                 :         }
    6536 ECB             :     }
    6537                 :     else
    6538                 :     {
    6539 CBC          44 :         float4      val = value;
    6540                 :         char       *orgnum;
    6541                 :         int         numstr_pre_len;
    6542 ECB             : 
    6543 CBC          44 :         if (IS_MULTI(&Num))
    6544                 :         {
    6545 LBC           0 :             float       multi = pow((double) 10, (double) Num.multi);
    6546                 : 
    6547               0 :             val = value * multi;
    6548               0 :             Num.pre += Num.multi;
    6549 ECB             :         }
    6550                 : 
    6551 GIC          44 :         orgnum = psprintf("%.0f", fabs(val));
    6552              44 :         numstr_pre_len = strlen(orgnum);
    6553 ECB             : 
    6554                 :         /* adjust post digits to fit max float digits */
    6555 GIC          44 :         if (numstr_pre_len >= FLT_DIG)
    6556              18 :             Num.post = 0;
    6557              26 :         else if (numstr_pre_len + Num.post > FLT_DIG)
    6558 UIC           0 :             Num.post = FLT_DIG - numstr_pre_len;
    6559 GIC          44 :         orgnum = psprintf("%.*f", Num.post, val);
    6560                 : 
    6561              44 :         if (*orgnum == '-')
    6562 ECB             :         {                       /* < 0 */
    6563 GIC          12 :             sign = '-';
    6564 CBC          12 :             numstr = orgnum + 1;
    6565 ECB             :         }
    6566                 :         else
    6567                 :         {
    6568 GIC          32 :             sign = '+';
    6569              32 :             numstr = orgnum;
    6570 ECB             :         }
    6571                 : 
    6572 GIC          44 :         if ((p = strchr(numstr, '.')))
    6573              20 :             numstr_pre_len = p - numstr;
    6574                 :         else
    6575 CBC          24 :             numstr_pre_len = strlen(numstr);
    6576                 : 
    6577 ECB             :         /* needs padding? */
    6578 GBC          44 :         if (numstr_pre_len < Num.pre)
    6579 CBC          27 :             out_pre_spaces = Num.pre - numstr_pre_len;
    6580                 :         /* overflowed prefix digit format? */
    6581              17 :         else if (numstr_pre_len > Num.pre)
    6582                 :         {
    6583 GIC          12 :             numstr = (char *) palloc(Num.pre + Num.post + 2);
    6584              12 :             fill_str(numstr, '#', Num.pre + Num.post + 1);
    6585              12 :             *(numstr + Num.pre) = '.';
    6586                 :         }
    6587 ECB             :     }
    6588                 : 
    6589 CBC          65 :     NUM_TOCHAR_finish;
    6590              65 :     PG_RETURN_TEXT_P(result);
    6591                 : }
    6592                 : 
    6593                 : /* -----------------
    6594 ECB             :  * FLOAT8 to_char()
    6595                 :  * -----------------
    6596                 :  */
    6597                 : Datum
    6598 GIC          73 : float8_to_char(PG_FUNCTION_ARGS)
    6599 ECB             : {
    6600 CBC          73 :     float8      value = PG_GETARG_FLOAT8(0);
    6601 GIC          73 :     text       *fmt = PG_GETARG_TEXT_PP(1);
    6602                 :     NUMDesc     Num;
    6603                 :     FormatNode *format;
    6604                 :     text       *result;
    6605 ECB             :     bool        shouldFree;
    6606 GIC          73 :     int         out_pre_spaces = 0,
    6607              73 :                 sign = 0;
    6608                 :     char       *numstr,
    6609 ECB             :                *p;
    6610                 : 
    6611 GBC          73 :     NUM_TOCHAR_prepare;
    6612                 : 
    6613              73 :     if (IS_ROMAN(&Num))
    6614 UBC           0 :         numstr = int_to_roman((int) rint(value));
    6615 GIC          73 :     else if (IS_EEEE(&Num))
    6616                 :     {
    6617 CBC          21 :         if (isnan(value) || isinf(value))
    6618 ECB             :         {
    6619                 :             /*
    6620                 :              * Allow 6 characters for the leading sign, the decimal point,
    6621                 :              * "e", the exponent's sign and two exponent digits.
    6622                 :              */
    6623 CBC           9 :             numstr = (char *) palloc(Num.pre + Num.post + 7);
    6624               9 :             fill_str(numstr, '#', Num.pre + Num.post + 6);
    6625               9 :             *numstr = ' ';
    6626 GIC           9 :             *(numstr + Num.pre + 1) = '.';
    6627 ECB             :         }
    6628                 :         else
    6629                 :         {
    6630 CBC          12 :             numstr = psprintf("%+.*e", Num.post, value);
    6631                 : 
    6632                 :             /*
    6633                 :              * Swap a leading positive sign for a space.
    6634 ECB             :              */
    6635 CBC          12 :             if (*numstr == '+')
    6636 GIC           9 :                 *numstr = ' ';
    6637                 :         }
    6638 ECB             :     }
    6639                 :     else
    6640                 :     {
    6641 CBC          52 :         float8      val = value;
    6642                 :         char       *orgnum;
    6643                 :         int         numstr_pre_len;
    6644 ECB             : 
    6645 CBC          52 :         if (IS_MULTI(&Num))
    6646                 :         {
    6647 LBC           0 :             double      multi = pow((double) 10, (double) Num.multi);
    6648                 : 
    6649               0 :             val = value * multi;
    6650               0 :             Num.pre += Num.multi;
    6651 ECB             :         }
    6652                 : 
    6653 GIC          52 :         orgnum = psprintf("%.0f", fabs(val));
    6654              52 :         numstr_pre_len = strlen(orgnum);
    6655 ECB             : 
    6656                 :         /* adjust post digits to fit max double digits */
    6657 GIC          52 :         if (numstr_pre_len >= DBL_DIG)
    6658               3 :             Num.post = 0;
    6659              49 :         else if (numstr_pre_len + Num.post > DBL_DIG)
    6660               3 :             Num.post = DBL_DIG - numstr_pre_len;
    6661              52 :         orgnum = psprintf("%.*f", Num.post, val);
    6662                 : 
    6663              52 :         if (*orgnum == '-')
    6664                 :         {                       /* < 0 */
    6665              12 :             sign = '-';
    6666              12 :             numstr = orgnum + 1;
    6667                 :         }
    6668                 :         else
    6669                 :         {
    6670              40 :             sign = '+';
    6671              40 :             numstr = orgnum;
    6672                 :         }
    6673                 : 
    6674              52 :         if ((p = strchr(numstr, '.')))
    6675              31 :             numstr_pre_len = p - numstr;
    6676                 :         else
    6677              21 :             numstr_pre_len = strlen(numstr);
    6678                 : 
    6679                 :         /* needs padding? */
    6680              52 :         if (numstr_pre_len < Num.pre)
    6681              30 :             out_pre_spaces = Num.pre - numstr_pre_len;
    6682                 :         /* overflowed prefix digit format? */
    6683              22 :         else if (numstr_pre_len > Num.pre)
    6684                 :         {
    6685              15 :             numstr = (char *) palloc(Num.pre + Num.post + 2);
    6686              15 :             fill_str(numstr, '#', Num.pre + Num.post + 1);
    6687              15 :             *(numstr + Num.pre) = '.';
    6688                 :         }
    6689                 :     }
    6690                 : 
    6691              73 :     NUM_TOCHAR_finish;
    6692              73 :     PG_RETURN_TEXT_P(result);
    6693                 : }
        

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