OSDN Git Service

Per-column collation support
[pg-rex/syncrep.git] / src / backend / utils / adt / formatting.c
1 /* -----------------------------------------------------------------------
2  * formatting.c
3  *
4  * src/backend/utils/adt/formatting.c
5  *
6  *
7  *       Portions Copyright (c) 1999-2011, 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 abstime
53  *      - add support for roman number to standard number conversion
54  *      - add support for number spelling
55  *      - add support for string to string formatting (we must be better
56  *        than Oracle :-),
57  *              to_char('Hello', 'X X X X X') -> 'H e l l o'
58  *
59  * -----------------------------------------------------------------------
60  */
61
62 #ifdef DEBUG_TO_FROM_CHAR
63 #define DEBUG_elog_output       DEBUG3
64 #endif
65
66 #include "postgres.h"
67
68 #include <ctype.h>
69 #include <unistd.h>
70 #include <math.h>
71 #include <float.h>
72 #include <limits.h>
73
74 /*
75  * towlower() and friends should be in <wctype.h>, but some pre-C99 systems
76  * declare them in <wchar.h>.
77  */
78 #ifdef HAVE_WCHAR_H
79 #include <wchar.h>
80 #endif
81 #ifdef HAVE_WCTYPE_H
82 #include <wctype.h>
83 #endif
84
85 #include "catalog/pg_collation.h"
86 #include "mb/pg_wchar.h"
87 #include "utils/builtins.h"
88 #include "utils/date.h"
89 #include "utils/datetime.h"
90 #include "utils/formatting.h"
91 #include "utils/int8.h"
92 #include "utils/numeric.h"
93 #include "utils/pg_locale.h"
94
95 /* ----------
96  * Routines type
97  * ----------
98  */
99 #define DCH_TYPE                1               /* DATE-TIME version    */
100 #define NUM_TYPE                2               /* NUMBER version       */
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                9               /* max julian day               */
114 #define NUM_MAX_ITEM_SIZ                8               /* roman number (RN has 15 chars)       */
115
116 /* ----------
117  * More is in float.c
118  * ----------
119  */
120 #define MAXFLOATWIDTH   60
121 #define MAXDOUBLEWIDTH  500
122
123
124 /* ----------
125  * External (defined in PgSQL datetime.c (timestamp utils))
126  * ----------
127  */
128 extern char *months[],                  /* month abbreviation   */
129                    *days[];                             /* full days            */
130
131 /* ----------
132  * Format parser structs
133  * ----------
134  */
135 typedef struct
136 {
137         char       *name;                       /* suffix string                */
138         int                     len,                    /* suffix length                */
139                                 id,                             /* used in node->suffix */
140                                 type;                   /* prefix / postfix                     */
141 } KeySuffix;
142
143 /* ----------
144  * FromCharDateMode
145  * ----------
146  *
147  * This value is used to nominate one of several distinct (and mutually
148  * exclusive) date conventions that a keyword can belong to.
149  */
150 typedef enum
151 {
152         FROM_CHAR_DATE_NONE = 0,        /* Value does not affect date mode. */
153         FROM_CHAR_DATE_GREGORIAN,       /* Gregorian (day, month, year) style date */
154         FROM_CHAR_DATE_ISOWEEK          /* ISO 8601 week date */
155 } FromCharDateMode;
156
157 typedef struct FormatNode FormatNode;
158
159 typedef struct
160 {
161         const char *name;
162         int                     len;
163         int                     id;
164         bool            is_digit;
165         FromCharDateMode date_mode;
166 } KeyWord;
167
168 struct FormatNode
169 {
170         int                     type;                   /* node type                    */
171         const KeyWord *key;                     /* if node type is KEYWORD      */
172         char            character;              /* if node type is CHAR         */
173         int                     suffix;                 /* keyword suffix               */
174 };
175
176 #define NODE_TYPE_END           1
177 #define NODE_TYPE_ACTION        2
178 #define NODE_TYPE_CHAR          3
179
180 #define SUFFTYPE_PREFIX         1
181 #define SUFFTYPE_POSTFIX        2
182
183 #define CLOCK_24_HOUR           0
184 #define CLOCK_12_HOUR           1
185
186
187 /* ----------
188  * Full months
189  * ----------
190  */
191 static char *months_full[] = {
192         "January", "February", "March", "April", "May", "June", "July",
193         "August", "September", "October", "November", "December", NULL
194 };
195
196 static char *days_short[] = {
197         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
198 };
199
200 /* ----------
201  * AD / BC
202  * ----------
203  *      There is no 0 AD.  Years go from 1 BC to 1 AD, so we make it
204  *      positive and map year == -1 to year zero, and shift all negative
205  *      years up one.  For interval years, we just return the year.
206  */
207 #define ADJUST_YEAR(year, is_interval)  ((is_interval) ? (year) : ((year) <= 0 ? -((year) - 1) : (year)))
208
209 #define A_D_STR         "A.D."
210 #define a_d_STR         "a.d."
211 #define AD_STR          "AD"
212 #define ad_STR          "ad"
213
214 #define B_C_STR         "B.C."
215 #define b_c_STR         "b.c."
216 #define BC_STR          "BC"
217 #define bc_STR          "bc"
218
219 /*
220  * AD / BC strings for seq_search.
221  *
222  * These are given in two variants, a long form with periods and a standard
223  * form without.
224  *
225  * The array is laid out such that matches for AD have an even index, and
226  * matches for BC have an odd index.  So the boolean value for BC is given by
227  * taking the array index of the match, modulo 2.
228  */
229 static char *adbc_strings[] = {ad_STR, bc_STR, AD_STR, BC_STR, NULL};
230 static char *adbc_strings_long[] = {a_d_STR, b_c_STR, A_D_STR, B_C_STR, NULL};
231
232 /* ----------
233  * AM / PM
234  * ----------
235  */
236 #define A_M_STR         "A.M."
237 #define a_m_STR         "a.m."
238 #define AM_STR          "AM"
239 #define am_STR          "am"
240
241 #define P_M_STR         "P.M."
242 #define p_m_STR         "p.m."
243 #define PM_STR          "PM"
244 #define pm_STR          "pm"
245
246 /*
247  * AM / PM strings for seq_search.
248  *
249  * These are given in two variants, a long form with periods and a standard
250  * form without.
251  *
252  * The array is laid out such that matches for AM have an even index, and
253  * matches for PM have an odd index.  So the boolean value for PM is given by
254  * taking the array index of the match, modulo 2.
255  */
256 static char *ampm_strings[] = {am_STR, pm_STR, AM_STR, PM_STR, NULL};
257 static char *ampm_strings_long[] = {a_m_STR, p_m_STR, A_M_STR, P_M_STR, NULL};
258
259 /* ----------
260  * Months in roman-numeral
261  * (Must be in reverse order for seq_search (in FROM_CHAR), because
262  *      'VIII' must have higher precedence than 'V')
263  * ----------
264  */
265 static char *rm_months_upper[] =
266 {"XII", "XI", "X", "IX", "VIII", "VII", "VI", "V", "IV", "III", "II", "I", NULL};
267
268 static char *rm_months_lower[] =
269 {"xii", "xi", "x", "ix", "viii", "vii", "vi", "v", "iv", "iii", "ii", "i", NULL};
270
271 /* ----------
272  * Roman numbers
273  * ----------
274  */
275 static char *rm1[] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", NULL};
276 static char *rm10[] = {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", NULL};
277 static char *rm100[] = {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", NULL};
278
279 /* ----------
280  * Ordinal postfixes
281  * ----------
282  */
283 static char *numTH[] = {"ST", "ND", "RD", "TH", NULL};
284 static char *numth[] = {"st", "nd", "rd", "th", NULL};
285
286 /* ----------
287  * Flags & Options:
288  * ----------
289  */
290 #define ONE_UPPER               1               /* Name */
291 #define ALL_UPPER               2               /* NAME */
292 #define ALL_LOWER               3               /* name */
293
294 #define FULL_SIZ                0
295
296 #define MAX_MONTH_LEN   9
297 #define MAX_MON_LEN             3
298 #define MAX_DAY_LEN             9
299 #define MAX_DY_LEN              3
300 #define MAX_RM_LEN              4
301
302 #define TH_UPPER                1
303 #define TH_LOWER                2
304
305 /* ----------
306  * Number description struct
307  * ----------
308  */
309 typedef struct
310 {
311         int                     pre,                    /* (count) numbers before decimal */
312                                 post,                   /* (count) numbers after decimal  */
313                                 lsign,                  /* want locales sign              */
314                                 flag,                   /* number parameters              */
315                                 pre_lsign_num,  /* tmp value for lsign            */
316                                 multi,                  /* multiplier for 'V'             */
317                                 zero_start,             /* position of first zero         */
318                                 zero_end,               /* position of last zero          */
319                                 need_locale;    /* needs it locale                */
320 } NUMDesc;
321
322 /* ----------
323  * Flags for NUMBER version
324  * ----------
325  */
326 #define NUM_F_DECIMAL           (1 << 1)
327 #define NUM_F_LDECIMAL          (1 << 2)
328 #define NUM_F_ZERO                      (1 << 3)
329 #define NUM_F_BLANK                     (1 << 4)
330 #define NUM_F_FILLMODE          (1 << 5)
331 #define NUM_F_LSIGN                     (1 << 6)
332 #define NUM_F_BRACKET           (1 << 7)
333 #define NUM_F_MINUS                     (1 << 8)
334 #define NUM_F_PLUS                      (1 << 9)
335 #define NUM_F_ROMAN                     (1 << 10)
336 #define NUM_F_MULTI                     (1 << 11)
337 #define NUM_F_PLUS_POST         (1 << 12)
338 #define NUM_F_MINUS_POST        (1 << 13)
339 #define NUM_F_EEEE                      (1 << 14)
340
341 #define NUM_LSIGN_PRE   (-1)
342 #define NUM_LSIGN_POST  1
343 #define NUM_LSIGN_NONE  0
344
345 /* ----------
346  * Tests
347  * ----------
348  */
349 #define IS_DECIMAL(_f)  ((_f)->flag & NUM_F_DECIMAL)
350 #define IS_LDECIMAL(_f) ((_f)->flag & NUM_F_LDECIMAL)
351 #define IS_ZERO(_f) ((_f)->flag & NUM_F_ZERO)
352 #define IS_BLANK(_f)    ((_f)->flag & NUM_F_BLANK)
353 #define IS_FILLMODE(_f) ((_f)->flag & NUM_F_FILLMODE)
354 #define IS_BRACKET(_f)  ((_f)->flag & NUM_F_BRACKET)
355 #define IS_MINUS(_f)    ((_f)->flag & NUM_F_MINUS)
356 #define IS_LSIGN(_f)    ((_f)->flag & NUM_F_LSIGN)
357 #define IS_PLUS(_f) ((_f)->flag & NUM_F_PLUS)
358 #define IS_ROMAN(_f)    ((_f)->flag & NUM_F_ROMAN)
359 #define IS_MULTI(_f)    ((_f)->flag & NUM_F_MULTI)
360 #define IS_EEEE(_f)             ((_f)->flag & NUM_F_EEEE)
361
362 /* ----------
363  * Format picture cache
364  *      (cache size:
365  *              Number part = NUM_CACHE_SIZE * NUM_CACHE_FIELDS
366  *              Date-time part  = DCH_CACHE_SIZE * DCH_CACHE_FIELDS
367  *      )
368  * ----------
369  */
370 #define NUM_CACHE_SIZE          64
371 #define NUM_CACHE_FIELDS        16
372 #define DCH_CACHE_SIZE          128
373 #define DCH_CACHE_FIELDS        16
374
375 typedef struct
376 {
377         FormatNode      format[DCH_CACHE_SIZE + 1];
378         char            str[DCH_CACHE_SIZE + 1];
379         int                     age;
380 } DCHCacheEntry;
381
382 typedef struct
383 {
384         FormatNode      format[NUM_CACHE_SIZE + 1];
385         char            str[NUM_CACHE_SIZE + 1];
386         int                     age;
387         NUMDesc         Num;
388 } NUMCacheEntry;
389
390 /* global cache for --- date/time part */
391 static DCHCacheEntry DCHCache[DCH_CACHE_FIELDS + 1];
392
393 static int      n_DCHCache = 0;         /* number of entries */
394 static int      DCHCounter = 0;
395
396 /* global cache for --- number part */
397 static NUMCacheEntry NUMCache[NUM_CACHE_FIELDS + 1];
398
399 static int      n_NUMCache = 0;         /* number of entries */
400 static int      NUMCounter = 0;
401 static NUMCacheEntry *last_NUMCacheEntry = NUMCache + 0;
402
403 /* ----------
404  * For char->date/time conversion
405  * ----------
406  */
407 typedef struct
408 {
409         FromCharDateMode mode;
410         int                     hh,
411                                 pm,
412                                 mi,
413                                 ss,
414                                 ssss,
415                                 d,
416                                 dd,
417                                 ddd,
418                                 mm,
419                                 ms,
420                                 year,
421                                 bc,
422                                 ww,
423                                 w,
424                                 cc,
425                                 j,
426                                 us,
427                                 yysz,                   /* is it YY or YYYY ? */
428                                 clock;                  /* 12 or 24 hour clock? */
429 } TmFromChar;
430
431 #define ZERO_tmfc(_X) memset(_X, 0, sizeof(TmFromChar))
432
433 /* ----------
434  * Debug
435  * ----------
436  */
437 #ifdef DEBUG_TO_FROM_CHAR
438 #define DEBUG_TMFC(_X) \
439                 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", \
440                         (_X)->mode, (_X)->hh, (_X)->pm, (_X)->mi, (_X)->ss, (_X)->ssss, \
441                         (_X)->d, (_X)->dd, (_X)->ddd, (_X)->mm, (_X)->ms, (_X)->year, \
442                         (_X)->bc, (_X)->ww, (_X)->w, (_X)->cc, (_X)->j, (_X)->us, \
443                         (_X)->yysz, (_X)->clock);
444 #define DEBUG_TM(_X) \
445                 elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\
446                         (_X)->tm_sec, (_X)->tm_year,\
447                         (_X)->tm_min, (_X)->tm_wday, (_X)->tm_hour, (_X)->tm_yday,\
448                         (_X)->tm_mday, (_X)->tm_isdst, (_X)->tm_mon)
449 #else
450 #define DEBUG_TMFC(_X)
451 #define DEBUG_TM(_X)
452 #endif
453
454 /* ----------
455  * Datetime to char conversion
456  * ----------
457  */
458 typedef struct TmToChar
459 {
460         struct pg_tm tm;                        /* classic 'tm' struct */
461         fsec_t          fsec;                   /* fractional seconds */
462         char       *tzn;                        /* timezone */
463 } TmToChar;
464
465 #define tmtcTm(_X)      (&(_X)->tm)
466 #define tmtcTzn(_X) ((_X)->tzn)
467 #define tmtcFsec(_X)    ((_X)->fsec)
468
469 #define ZERO_tm(_X) \
470 do {    \
471         (_X)->tm_sec  = (_X)->tm_year = (_X)->tm_min = (_X)->tm_wday = \
472         (_X)->tm_hour = (_X)->tm_yday = (_X)->tm_isdst = 0; \
473         (_X)->tm_mday = (_X)->tm_mon  = 1; \
474 } while(0)
475
476 #define ZERO_tmtc(_X) \
477 do { \
478         ZERO_tm( tmtcTm(_X) ); \
479         tmtcFsec(_X) = 0; \
480         tmtcTzn(_X) = NULL; \
481 } while(0)
482
483 /*
484  *      to_char(time) appears to to_char() as an interval, so this check
485  *      is really for interval and time data types.
486  */
487 #define INVALID_FOR_INTERVAL  \
488 do { \
489         if (is_interval) \
490                 ereport(ERROR, \
491                                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT), \
492                                  errmsg("invalid format specification for an interval value"), \
493                                  errhint("Intervals are not tied to specific calendar dates."))); \
494 } while(0)
495
496 /*****************************************************************************
497  *                      KeyWord definitions
498  *****************************************************************************/
499
500 /* ----------
501  * Suffixes:
502  * ----------
503  */
504 #define DCH_S_FM        0x01
505 #define DCH_S_TH        0x02
506 #define DCH_S_th        0x04
507 #define DCH_S_SP        0x08
508 #define DCH_S_TM        0x10
509
510 /* ----------
511  * Suffix tests
512  * ----------
513  */
514 #define S_THth(_s)      ((((_s) & DCH_S_TH) || ((_s) & DCH_S_th)) ? 1 : 0)
515 #define S_TH(_s)        (((_s) & DCH_S_TH) ? 1 : 0)
516 #define S_th(_s)        (((_s) & DCH_S_th) ? 1 : 0)
517 #define S_TH_TYPE(_s)   (((_s) & DCH_S_TH) ? TH_UPPER : TH_LOWER)
518
519 /* Oracle toggles FM behavior, we don't; see docs. */
520 #define S_FM(_s)        (((_s) & DCH_S_FM) ? 1 : 0)
521 #define S_SP(_s)        (((_s) & DCH_S_SP) ? 1 : 0)
522 #define S_TM(_s)        (((_s) & DCH_S_TM) ? 1 : 0)
523
524 /* ----------
525  * Suffixes definition for DATE-TIME TO/FROM CHAR
526  * ----------
527  */
528 static KeySuffix DCH_suff[] = {
529         {"FM", 2, DCH_S_FM, SUFFTYPE_PREFIX},
530         {"fm", 2, DCH_S_FM, SUFFTYPE_PREFIX},
531         {"TM", 2, DCH_S_TM, SUFFTYPE_PREFIX},
532         {"tm", 2, DCH_S_TM, SUFFTYPE_PREFIX},
533         {"TH", 2, DCH_S_TH, SUFFTYPE_POSTFIX},
534         {"th", 2, DCH_S_th, SUFFTYPE_POSTFIX},
535         {"SP", 2, DCH_S_SP, SUFFTYPE_POSTFIX},
536         /* last */
537         {NULL, 0, 0, 0}
538 };
539
540 /* ----------
541  * Format-pictures (KeyWord).
542  *
543  * The KeyWord field; alphabetic sorted, *BUT* strings alike is sorted
544  *                complicated -to-> easy:
545  *
546  *      (example: "DDD","DD","Day","D" )
547  *
548  * (this specific sort needs the algorithm for sequential search for strings,
549  * which not has exact end; -> How keyword is in "HH12blabla" ? - "HH"
550  * or "HH12"? You must first try "HH12", because "HH" is in string, but
551  * it is not good.
552  *
553  * (!)
554  *       - Position for the keyword is similar as position in the enum DCH/NUM_poz.
555  * (!)
556  *
557  * For fast search is used the 'int index[]', index is ascii table from position
558  * 32 (' ') to 126 (~), in this index is DCH_ / NUM_ enums for each ASCII
559  * position or -1 if char is not used in the KeyWord. Search example for
560  * string "MM":
561  *      1)      see in index to index['M' - 32],
562  *      2)      take keywords position (enum DCH_MI) from index
563  *      3)      run sequential search in keywords[] from this position
564  *
565  * ----------
566  */
567
568 typedef enum
569 {
570         DCH_A_D,
571         DCH_A_M,
572         DCH_AD,
573         DCH_AM,
574         DCH_B_C,
575         DCH_BC,
576         DCH_CC,
577         DCH_DAY,
578         DCH_DDD,
579         DCH_DD,
580         DCH_DY,
581         DCH_Day,
582         DCH_Dy,
583         DCH_D,
584         DCH_FX,                                         /* global suffix */
585         DCH_HH24,
586         DCH_HH12,
587         DCH_HH,
588         DCH_IDDD,
589         DCH_ID,
590         DCH_IW,
591         DCH_IYYY,
592         DCH_IYY,
593         DCH_IY,
594         DCH_I,
595         DCH_J,
596         DCH_MI,
597         DCH_MM,
598         DCH_MONTH,
599         DCH_MON,
600         DCH_MS,
601         DCH_Month,
602         DCH_Mon,
603         DCH_P_M,
604         DCH_PM,
605         DCH_Q,
606         DCH_RM,
607         DCH_SSSS,
608         DCH_SS,
609         DCH_TZ,
610         DCH_US,
611         DCH_WW,
612         DCH_W,
613         DCH_Y_YYY,
614         DCH_YYYY,
615         DCH_YYY,
616         DCH_YY,
617         DCH_Y,
618         DCH_a_d,
619         DCH_a_m,
620         DCH_ad,
621         DCH_am,
622         DCH_b_c,
623         DCH_bc,
624         DCH_cc,
625         DCH_day,
626         DCH_ddd,
627         DCH_dd,
628         DCH_dy,
629         DCH_d,
630         DCH_fx,
631         DCH_hh24,
632         DCH_hh12,
633         DCH_hh,
634         DCH_iddd,
635         DCH_id,
636         DCH_iw,
637         DCH_iyyy,
638         DCH_iyy,
639         DCH_iy,
640         DCH_i,
641         DCH_j,
642         DCH_mi,
643         DCH_mm,
644         DCH_month,
645         DCH_mon,
646         DCH_ms,
647         DCH_p_m,
648         DCH_pm,
649         DCH_q,
650         DCH_rm,
651         DCH_ssss,
652         DCH_ss,
653         DCH_tz,
654         DCH_us,
655         DCH_ww,
656         DCH_w,
657         DCH_y_yyy,
658         DCH_yyyy,
659         DCH_yyy,
660         DCH_yy,
661         DCH_y,
662
663         /* last */
664         _DCH_last_
665 } DCH_poz;
666
667 typedef enum
668 {
669         NUM_COMMA,
670         NUM_DEC,
671         NUM_0,
672         NUM_9,
673         NUM_B,
674         NUM_C,
675         NUM_D,
676         NUM_E,
677         NUM_FM,
678         NUM_G,
679         NUM_L,
680         NUM_MI,
681         NUM_PL,
682         NUM_PR,
683         NUM_RN,
684         NUM_SG,
685         NUM_SP,
686         NUM_S,
687         NUM_TH,
688         NUM_V,
689         NUM_b,
690         NUM_c,
691         NUM_d,
692         NUM_e,
693         NUM_fm,
694         NUM_g,
695         NUM_l,
696         NUM_mi,
697         NUM_pl,
698         NUM_pr,
699         NUM_rn,
700         NUM_sg,
701         NUM_sp,
702         NUM_s,
703         NUM_th,
704         NUM_v,
705
706         /* last */
707         _NUM_last_
708 } NUM_poz;
709
710 /* ----------
711  * KeyWords for DATE-TIME version
712  * ----------
713  */
714 static const KeyWord DCH_keywords[] = {
715 /*      name, len, id, is_digit, date_mode */
716         {"A.D.", 4, DCH_A_D, FALSE, FROM_CHAR_DATE_NONE},       /* A */
717         {"A.M.", 4, DCH_A_M, FALSE, FROM_CHAR_DATE_NONE},
718         {"AD", 2, DCH_AD, FALSE, FROM_CHAR_DATE_NONE},
719         {"AM", 2, DCH_AM, FALSE, FROM_CHAR_DATE_NONE},
720         {"B.C.", 4, DCH_B_C, FALSE, FROM_CHAR_DATE_NONE},       /* B */
721         {"BC", 2, DCH_BC, FALSE, FROM_CHAR_DATE_NONE},
722         {"CC", 2, DCH_CC, TRUE, FROM_CHAR_DATE_NONE},           /* C */
723         {"DAY", 3, DCH_DAY, FALSE, FROM_CHAR_DATE_NONE},        /* D */
724         {"DDD", 3, DCH_DDD, TRUE, FROM_CHAR_DATE_GREGORIAN},
725         {"DD", 2, DCH_DD, TRUE, FROM_CHAR_DATE_GREGORIAN},
726         {"DY", 2, DCH_DY, FALSE, FROM_CHAR_DATE_NONE},
727         {"Day", 3, DCH_Day, FALSE, FROM_CHAR_DATE_NONE},
728         {"Dy", 2, DCH_Dy, FALSE, FROM_CHAR_DATE_NONE},
729         {"D", 1, DCH_D, TRUE, FROM_CHAR_DATE_GREGORIAN},
730         {"FX", 2, DCH_FX, FALSE, FROM_CHAR_DATE_NONE},          /* F */
731         {"HH24", 4, DCH_HH24, TRUE, FROM_CHAR_DATE_NONE},       /* H */
732         {"HH12", 4, DCH_HH12, TRUE, FROM_CHAR_DATE_NONE},
733         {"HH", 2, DCH_HH, TRUE, FROM_CHAR_DATE_NONE},
734         {"IDDD", 4, DCH_IDDD, TRUE, FROM_CHAR_DATE_ISOWEEK},            /* I */
735         {"ID", 2, DCH_ID, TRUE, FROM_CHAR_DATE_ISOWEEK},
736         {"IW", 2, DCH_IW, TRUE, FROM_CHAR_DATE_ISOWEEK},
737         {"IYYY", 4, DCH_IYYY, TRUE, FROM_CHAR_DATE_ISOWEEK},
738         {"IYY", 3, DCH_IYY, TRUE, FROM_CHAR_DATE_ISOWEEK},
739         {"IY", 2, DCH_IY, TRUE, FROM_CHAR_DATE_ISOWEEK},
740         {"I", 1, DCH_I, TRUE, FROM_CHAR_DATE_ISOWEEK},
741         {"J", 1, DCH_J, TRUE, FROM_CHAR_DATE_NONE}, /* J */
742         {"MI", 2, DCH_MI, TRUE, FROM_CHAR_DATE_NONE},           /* M */
743         {"MM", 2, DCH_MM, TRUE, FROM_CHAR_DATE_GREGORIAN},
744         {"MONTH", 5, DCH_MONTH, FALSE, FROM_CHAR_DATE_GREGORIAN},
745         {"MON", 3, DCH_MON, FALSE, FROM_CHAR_DATE_GREGORIAN},
746         {"MS", 2, DCH_MS, TRUE, FROM_CHAR_DATE_NONE},
747         {"Month", 5, DCH_Month, FALSE, FROM_CHAR_DATE_GREGORIAN},
748         {"Mon", 3, DCH_Mon, FALSE, FROM_CHAR_DATE_GREGORIAN},
749         {"P.M.", 4, DCH_P_M, FALSE, FROM_CHAR_DATE_NONE},       /* P */
750         {"PM", 2, DCH_PM, FALSE, FROM_CHAR_DATE_NONE},
751         {"Q", 1, DCH_Q, TRUE, FROM_CHAR_DATE_NONE}, /* Q */
752         {"RM", 2, DCH_RM, FALSE, FROM_CHAR_DATE_GREGORIAN}, /* R */
753         {"SSSS", 4, DCH_SSSS, TRUE, FROM_CHAR_DATE_NONE},       /* S */
754         {"SS", 2, DCH_SS, TRUE, FROM_CHAR_DATE_NONE},
755         {"TZ", 2, DCH_TZ, FALSE, FROM_CHAR_DATE_NONE},          /* T */
756         {"US", 2, DCH_US, TRUE, FROM_CHAR_DATE_NONE},           /* U */
757         {"WW", 2, DCH_WW, TRUE, FROM_CHAR_DATE_GREGORIAN},      /* W */
758         {"W", 1, DCH_W, TRUE, FROM_CHAR_DATE_GREGORIAN},
759         {"Y,YYY", 5, DCH_Y_YYY, TRUE, FROM_CHAR_DATE_GREGORIAN},        /* Y */
760         {"YYYY", 4, DCH_YYYY, TRUE, FROM_CHAR_DATE_GREGORIAN},
761         {"YYY", 3, DCH_YYY, TRUE, FROM_CHAR_DATE_GREGORIAN},
762         {"YY", 2, DCH_YY, TRUE, FROM_CHAR_DATE_GREGORIAN},
763         {"Y", 1, DCH_Y, TRUE, FROM_CHAR_DATE_GREGORIAN},
764         {"a.d.", 4, DCH_a_d, FALSE, FROM_CHAR_DATE_NONE},       /* a */
765         {"a.m.", 4, DCH_a_m, FALSE, FROM_CHAR_DATE_NONE},
766         {"ad", 2, DCH_ad, FALSE, FROM_CHAR_DATE_NONE},
767         {"am", 2, DCH_am, FALSE, FROM_CHAR_DATE_NONE},
768         {"b.c.", 4, DCH_b_c, FALSE, FROM_CHAR_DATE_NONE},       /* b */
769         {"bc", 2, DCH_bc, FALSE, FROM_CHAR_DATE_NONE},
770         {"cc", 2, DCH_CC, TRUE, FROM_CHAR_DATE_NONE},           /* c */
771         {"day", 3, DCH_day, FALSE, FROM_CHAR_DATE_NONE},        /* d */
772         {"ddd", 3, DCH_DDD, TRUE, FROM_CHAR_DATE_GREGORIAN},
773         {"dd", 2, DCH_DD, TRUE, FROM_CHAR_DATE_GREGORIAN},
774         {"dy", 2, DCH_dy, FALSE, FROM_CHAR_DATE_NONE},
775         {"d", 1, DCH_D, TRUE, FROM_CHAR_DATE_GREGORIAN},
776         {"fx", 2, DCH_FX, FALSE, FROM_CHAR_DATE_NONE},          /* f */
777         {"hh24", 4, DCH_HH24, TRUE, FROM_CHAR_DATE_NONE},       /* h */
778         {"hh12", 4, DCH_HH12, TRUE, FROM_CHAR_DATE_NONE},
779         {"hh", 2, DCH_HH, TRUE, FROM_CHAR_DATE_NONE},
780         {"iddd", 4, DCH_IDDD, TRUE, FROM_CHAR_DATE_ISOWEEK},            /* i */
781         {"id", 2, DCH_ID, TRUE, FROM_CHAR_DATE_ISOWEEK},
782         {"iw", 2, DCH_IW, TRUE, FROM_CHAR_DATE_ISOWEEK},
783         {"iyyy", 4, DCH_IYYY, TRUE, FROM_CHAR_DATE_ISOWEEK},
784         {"iyy", 3, DCH_IYY, TRUE, FROM_CHAR_DATE_ISOWEEK},
785         {"iy", 2, DCH_IY, TRUE, FROM_CHAR_DATE_ISOWEEK},
786         {"i", 1, DCH_I, TRUE, FROM_CHAR_DATE_ISOWEEK},
787         {"j", 1, DCH_J, TRUE, FROM_CHAR_DATE_NONE}, /* j */
788         {"mi", 2, DCH_MI, TRUE, FROM_CHAR_DATE_NONE},           /* m */
789         {"mm", 2, DCH_MM, TRUE, FROM_CHAR_DATE_GREGORIAN},
790         {"month", 5, DCH_month, FALSE, FROM_CHAR_DATE_GREGORIAN},
791         {"mon", 3, DCH_mon, FALSE, FROM_CHAR_DATE_GREGORIAN},
792         {"ms", 2, DCH_MS, TRUE, FROM_CHAR_DATE_NONE},
793         {"p.m.", 4, DCH_p_m, FALSE, FROM_CHAR_DATE_NONE},       /* p */
794         {"pm", 2, DCH_pm, FALSE, FROM_CHAR_DATE_NONE},
795         {"q", 1, DCH_Q, TRUE, FROM_CHAR_DATE_NONE}, /* q */
796         {"rm", 2, DCH_rm, FALSE, FROM_CHAR_DATE_GREGORIAN}, /* r */
797         {"ssss", 4, DCH_SSSS, TRUE, FROM_CHAR_DATE_NONE},       /* s */
798         {"ss", 2, DCH_SS, TRUE, FROM_CHAR_DATE_NONE},
799         {"tz", 2, DCH_tz, FALSE, FROM_CHAR_DATE_NONE},          /* t */
800         {"us", 2, DCH_US, TRUE, FROM_CHAR_DATE_NONE},           /* u */
801         {"ww", 2, DCH_WW, TRUE, FROM_CHAR_DATE_GREGORIAN},      /* w */
802         {"w", 1, DCH_W, TRUE, FROM_CHAR_DATE_GREGORIAN},
803         {"y,yyy", 5, DCH_Y_YYY, TRUE, FROM_CHAR_DATE_GREGORIAN},        /* y */
804         {"yyyy", 4, DCH_YYYY, TRUE, FROM_CHAR_DATE_GREGORIAN},
805         {"yyy", 3, DCH_YYY, TRUE, FROM_CHAR_DATE_GREGORIAN},
806         {"yy", 2, DCH_YY, TRUE, FROM_CHAR_DATE_GREGORIAN},
807         {"y", 1, DCH_Y, TRUE, FROM_CHAR_DATE_GREGORIAN},
808
809         /* last */
810         {NULL, 0, 0, 0, 0}
811 };
812
813 /* ----------
814  * KeyWords for NUMBER version
815  *
816  * The is_digit and date_mode fields are not relevant here.
817  * ----------
818  */
819 static const KeyWord NUM_keywords[] = {
820 /*      name, len, id                   is in Index */
821         {",", 1, NUM_COMMA},            /* , */
822         {".", 1, NUM_DEC},                      /* . */
823         {"0", 1, NUM_0},                        /* 0 */
824         {"9", 1, NUM_9},                        /* 9 */
825         {"B", 1, NUM_B},                        /* B */
826         {"C", 1, NUM_C},                        /* C */
827         {"D", 1, NUM_D},                        /* D */
828         {"EEEE", 4, NUM_E},                     /* E */
829         {"FM", 2, NUM_FM},                      /* F */
830         {"G", 1, NUM_G},                        /* G */
831         {"L", 1, NUM_L},                        /* L */
832         {"MI", 2, NUM_MI},                      /* M */
833         {"PL", 2, NUM_PL},                      /* P */
834         {"PR", 2, NUM_PR},
835         {"RN", 2, NUM_RN},                      /* R */
836         {"SG", 2, NUM_SG},                      /* S */
837         {"SP", 2, NUM_SP},
838         {"S", 1, NUM_S},
839         {"TH", 2, NUM_TH},                      /* T */
840         {"V", 1, NUM_V},                        /* V */
841         {"b", 1, NUM_B},                        /* b */
842         {"c", 1, NUM_C},                        /* c */
843         {"d", 1, NUM_D},                        /* d */
844         {"eeee", 4, NUM_E},                     /* e */
845         {"fm", 2, NUM_FM},                      /* f */
846         {"g", 1, NUM_G},                        /* g */
847         {"l", 1, NUM_L},                        /* l */
848         {"mi", 2, NUM_MI},                      /* m */
849         {"pl", 2, NUM_PL},                      /* p */
850         {"pr", 2, NUM_PR},
851         {"rn", 2, NUM_rn},                      /* r */
852         {"sg", 2, NUM_SG},                      /* s */
853         {"sp", 2, NUM_SP},
854         {"s", 1, NUM_S},
855         {"th", 2, NUM_th},                      /* t */
856         {"v", 1, NUM_V},                        /* v */
857
858         /* last */
859         {NULL, 0, 0}
860 };
861
862
863 /* ----------
864  * KeyWords index for DATE-TIME version
865  * ----------
866  */
867 static const int DCH_index[KeyWord_INDEX_SIZE] = {
868 /*
869 0       1       2       3       4       5       6       7       8       9
870 */
871         /*---- first 0..31 chars are skipped ----*/
872
873         -1, -1, -1, -1, -1, -1, -1, -1,
874         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
875         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
876         -1, -1, -1, -1, -1, DCH_A_D, DCH_B_C, DCH_CC, DCH_DAY, -1,
877         DCH_FX, -1, DCH_HH24, DCH_IDDD, DCH_J, -1, -1, DCH_MI, -1, -1,
878         DCH_P_M, DCH_Q, DCH_RM, DCH_SSSS, DCH_TZ, DCH_US, -1, DCH_WW, -1, DCH_Y_YYY,
879         -1, -1, -1, -1, -1, -1, -1, DCH_a_d, DCH_b_c, DCH_cc,
880         DCH_day, -1, DCH_fx, -1, DCH_hh24, DCH_iddd, DCH_j, -1, -1, DCH_mi,
881         -1, -1, DCH_p_m, DCH_q, DCH_rm, DCH_ssss, DCH_tz, DCH_us, -1, DCH_ww,
882         -1, DCH_y_yyy, -1, -1, -1, -1
883
884         /*---- chars over 126 are skipped ----*/
885 };
886
887 /* ----------
888  * KeyWords index for NUMBER version
889  * ----------
890  */
891 static const int NUM_index[KeyWord_INDEX_SIZE] = {
892 /*
893 0       1       2       3       4       5       6       7       8       9
894 */
895         /*---- first 0..31 chars are skipped ----*/
896
897         -1, -1, -1, -1, -1, -1, -1, -1,
898         -1, -1, -1, -1, NUM_COMMA, -1, NUM_DEC, -1, NUM_0, -1,
899         -1, -1, -1, -1, -1, -1, -1, NUM_9, -1, -1,
900         -1, -1, -1, -1, -1, -1, NUM_B, NUM_C, NUM_D, NUM_E,
901         NUM_FM, NUM_G, -1, -1, -1, -1, NUM_L, NUM_MI, -1, -1,
902         NUM_PL, -1, NUM_RN, NUM_SG, NUM_TH, -1, NUM_V, -1, -1, -1,
903         -1, -1, -1, -1, -1, -1, -1, -1, NUM_b, NUM_c,
904         NUM_d, NUM_e, NUM_fm, NUM_g, -1, -1, -1, -1, NUM_l, NUM_mi,
905         -1, -1, NUM_pl, -1, NUM_rn, NUM_sg, NUM_th, -1, NUM_v, -1,
906         -1, -1, -1, -1, -1, -1
907
908         /*---- chars over 126 are skipped ----*/
909 };
910
911 /* ----------
912  * Number processor struct
913  * ----------
914  */
915 typedef struct NUMProc
916 {
917         bool            is_to_char;
918         NUMDesc    *Num;                        /* number description           */
919
920         int                     sign,                   /* '-' or '+'                   */
921                                 sign_wrote,             /* was sign write               */
922                                 num_count,              /* number of write digits       */
923                                 num_in,                 /* is inside number             */
924                                 num_curr,               /* current position in number   */
925                                 num_pre,                /* space before first number    */
926
927                                 read_dec,               /* to_number - was read dec. point      */
928                                 read_post,              /* to_number - number of dec. digit */
929                                 read_pre;               /* to_number - number non-dec. digit */
930
931         char       *number,                     /* string with number   */
932                            *number_p,           /* pointer to current number position */
933                            *inout,                      /* in / out buffer      */
934                            *inout_p,            /* pointer to current inout position */
935                            *last_relevant,      /* last relevant number after decimal point */
936
937                            *L_negative_sign,    /* Locale */
938                            *L_positive_sign,
939                            *decimal,
940                            *L_thousands_sep,
941                            *L_currency_symbol;
942 } NUMProc;
943
944
945 /* ----------
946  * Functions
947  * ----------
948  */
949 static const KeyWord *index_seq_search(char *str, const KeyWord *kw,
950                                  const int *index);
951 static KeySuffix *suff_search(char *str, KeySuffix *suf, int type);
952 static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);
953 static void parse_format(FormatNode *node, char *str, const KeyWord *kw,
954                          KeySuffix *suf, const int *index, int ver, NUMDesc *Num);
955
956 static void DCH_to_char(FormatNode *node, bool is_interval,
957                         TmToChar *in, char *out, Oid collid);
958 static void DCH_from_char(FormatNode *node, char *in, TmFromChar *out);
959
960 #ifdef DEBUG_TO_FROM_CHAR
961 static void dump_index(const KeyWord *k, const int *index);
962 static void dump_node(FormatNode *node, int max);
963 #endif
964
965 static char *get_th(char *num, int type);
966 static char *str_numth(char *dest, char *num, int type);
967 static int      strspace_len(char *str);
968 static int      strdigits_len(char *str);
969 static void from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode);
970 static void from_char_set_int(int *dest, const int value, const FormatNode *node);
971 static int      from_char_parse_int_len(int *dest, char **src, const int len, FormatNode *node);
972 static int      from_char_parse_int(int *dest, char **src, FormatNode *node);
973 static int      seq_search(char *name, char **array, int type, int max, int *len);
974 static int      from_char_seq_search(int *dest, char **src, char **array, int type, int max, FormatNode *node);
975 static void do_to_timestamp(text *date_txt, text *fmt,
976                                 struct pg_tm * tm, fsec_t *fsec);
977 static char *fill_str(char *str, int c, int max);
978 static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree);
979 static char *int_to_roman(int number);
980 static void NUM_prepare_locale(NUMProc *Np);
981 static char *get_last_relevant_decnum(char *num);
982 static void NUM_numpart_from_char(NUMProc *Np, int id, int plen);
983 static void NUM_numpart_to_char(NUMProc *Np, int id);
984 static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
985                           int plen, int sign, bool is_to_char, Oid collid);
986 static DCHCacheEntry *DCH_cache_search(char *str);
987 static DCHCacheEntry *DCH_cache_getnew(char *str);
988
989 static NUMCacheEntry *NUM_cache_search(char *str);
990 static NUMCacheEntry *NUM_cache_getnew(char *str);
991 static void NUM_cache_remove(NUMCacheEntry *ent);
992
993
994 /* ----------
995  * Fast sequential search, use index for data selection which
996  * go to seq. cycle (it is very fast for unwanted strings)
997  * (can't be used binary search in format parsing)
998  * ----------
999  */
1000 static const KeyWord *
1001 index_seq_search(char *str, const KeyWord *kw, const int *index)
1002 {
1003         int                     poz;
1004
1005         if (!KeyWord_INDEX_FILTER(*str))
1006                 return NULL;
1007
1008         if ((poz = *(index + (*str - ' '))) > -1)
1009         {
1010                 const KeyWord *k = kw + poz;
1011
1012                 do
1013                 {
1014                         if (!strncmp(str, k->name, k->len))
1015                                 return k;
1016                         k++;
1017                         if (!k->name)
1018                                 return NULL;
1019                 } while (*str == *k->name);
1020         }
1021         return NULL;
1022 }
1023
1024 static KeySuffix *
1025 suff_search(char *str, KeySuffix *suf, int type)
1026 {
1027         KeySuffix  *s;
1028
1029         for (s = suf; s->name != NULL; s++)
1030         {
1031                 if (s->type != type)
1032                         continue;
1033
1034                 if (!strncmp(str, s->name, s->len))
1035                         return s;
1036         }
1037         return NULL;
1038 }
1039
1040 /* ----------
1041  * Prepare NUMDesc (number description struct) via FormatNode struct
1042  * ----------
1043  */
1044 static void
1045 NUMDesc_prepare(NUMDesc *num, FormatNode *n)
1046 {
1047
1048         if (n->type != NODE_TYPE_ACTION)
1049                 return;
1050
1051         /*
1052          * In case of an error, we need to remove the numeric from the cache.  Use
1053          * a PG_TRY block to ensure that this happens.
1054          */
1055         PG_TRY();
1056         {
1057                 if (IS_EEEE(num) && n->key->id != NUM_E)
1058                         ereport(ERROR,
1059                                         (errcode(ERRCODE_SYNTAX_ERROR),
1060                                          errmsg("\"EEEE\" must be the last pattern used")));
1061
1062                 switch (n->key->id)
1063                 {
1064                         case NUM_9:
1065                                 if (IS_BRACKET(num))
1066                                         ereport(ERROR,
1067                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1068                                                          errmsg("\"9\" must be ahead of \"PR\"")));
1069                                 if (IS_MULTI(num))
1070                                 {
1071                                         ++num->multi;
1072                                         break;
1073                                 }
1074                                 if (IS_DECIMAL(num))
1075                                         ++num->post;
1076                                 else
1077                                         ++num->pre;
1078                                 break;
1079
1080                         case NUM_0:
1081                                 if (IS_BRACKET(num))
1082                                         ereport(ERROR,
1083                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1084                                                          errmsg("\"0\" must be ahead of \"PR\"")));
1085                                 if (!IS_ZERO(num) && !IS_DECIMAL(num))
1086                                 {
1087                                         num->flag |= NUM_F_ZERO;
1088                                         num->zero_start = num->pre + 1;
1089                                 }
1090                                 if (!IS_DECIMAL(num))
1091                                         ++num->pre;
1092                                 else
1093                                         ++num->post;
1094
1095                                 num->zero_end = num->pre + num->post;
1096                                 break;
1097
1098                         case NUM_B:
1099                                 if (num->pre == 0 && num->post == 0 && (!IS_ZERO(num)))
1100                                         num->flag |= NUM_F_BLANK;
1101                                 break;
1102
1103                         case NUM_D:
1104                                 num->flag |= NUM_F_LDECIMAL;
1105                                 num->need_locale = TRUE;
1106                         case NUM_DEC:
1107                                 if (IS_DECIMAL(num))
1108                                         ereport(ERROR,
1109                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1110                                                          errmsg("multiple decimal points")));
1111                                 if (IS_MULTI(num))
1112                                         ereport(ERROR,
1113                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1114                                          errmsg("cannot use \"V\" and decimal point together")));
1115                                 num->flag |= NUM_F_DECIMAL;
1116                                 break;
1117
1118                         case NUM_FM:
1119                                 num->flag |= NUM_F_FILLMODE;
1120                                 break;
1121
1122                         case NUM_S:
1123                                 if (IS_LSIGN(num))
1124                                         ereport(ERROR,
1125                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1126                                                          errmsg("cannot use \"S\" twice")));
1127                                 if (IS_PLUS(num) || IS_MINUS(num) || IS_BRACKET(num))
1128                                         ereport(ERROR,
1129                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1130                                                          errmsg("cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together")));
1131                                 if (!IS_DECIMAL(num))
1132                                 {
1133                                         num->lsign = NUM_LSIGN_PRE;
1134                                         num->pre_lsign_num = num->pre;
1135                                         num->need_locale = TRUE;
1136                                         num->flag |= NUM_F_LSIGN;
1137                                 }
1138                                 else if (num->lsign == NUM_LSIGN_NONE)
1139                                 {
1140                                         num->lsign = NUM_LSIGN_POST;
1141                                         num->need_locale = TRUE;
1142                                         num->flag |= NUM_F_LSIGN;
1143                                 }
1144                                 break;
1145
1146                         case NUM_MI:
1147                                 if (IS_LSIGN(num))
1148                                         ereport(ERROR,
1149                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1150                                                          errmsg("cannot use \"S\" and \"MI\" together")));
1151                                 num->flag |= NUM_F_MINUS;
1152                                 if (IS_DECIMAL(num))
1153                                         num->flag |= NUM_F_MINUS_POST;
1154                                 break;
1155
1156                         case NUM_PL:
1157                                 if (IS_LSIGN(num))
1158                                         ereport(ERROR,
1159                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1160                                                          errmsg("cannot use \"S\" and \"PL\" together")));
1161                                 num->flag |= NUM_F_PLUS;
1162                                 if (IS_DECIMAL(num))
1163                                         num->flag |= NUM_F_PLUS_POST;
1164                                 break;
1165
1166                         case NUM_SG:
1167                                 if (IS_LSIGN(num))
1168                                         ereport(ERROR,
1169                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1170                                                          errmsg("cannot use \"S\" and \"SG\" together")));
1171                                 num->flag |= NUM_F_MINUS;
1172                                 num->flag |= NUM_F_PLUS;
1173                                 break;
1174
1175                         case NUM_PR:
1176                                 if (IS_LSIGN(num) || IS_PLUS(num) || IS_MINUS(num))
1177                                         ereport(ERROR,
1178                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1179                                                          errmsg("cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together")));
1180                                 num->flag |= NUM_F_BRACKET;
1181                                 break;
1182
1183                         case NUM_rn:
1184                         case NUM_RN:
1185                                 num->flag |= NUM_F_ROMAN;
1186                                 break;
1187
1188                         case NUM_L:
1189                         case NUM_G:
1190                                 num->need_locale = TRUE;
1191                                 break;
1192
1193                         case NUM_V:
1194                                 if (IS_DECIMAL(num))
1195                                         ereport(ERROR,
1196                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1197                                          errmsg("cannot use \"V\" and decimal point together")));
1198                                 num->flag |= NUM_F_MULTI;
1199                                 break;
1200
1201                         case NUM_E:
1202                                 if (IS_EEEE(num))
1203                                         ereport(ERROR,
1204                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1205                                                          errmsg("cannot use \"EEEE\" twice")));
1206                                 if (IS_BLANK(num) || IS_FILLMODE(num) || IS_LSIGN(num) ||
1207                                         IS_BRACKET(num) || IS_MINUS(num) || IS_PLUS(num) ||
1208                                         IS_ROMAN(num) || IS_MULTI(num))
1209                                         ereport(ERROR,
1210                                                         (errcode(ERRCODE_SYNTAX_ERROR),
1211                                            errmsg("\"EEEE\" is incompatible with other formats"),
1212                                                          errdetail("\"EEEE\" may only be used together with digit and decimal point patterns.")));
1213                                 num->flag |= NUM_F_EEEE;
1214                                 break;
1215                 }
1216         }
1217         PG_CATCH();
1218         {
1219                 NUM_cache_remove(last_NUMCacheEntry);
1220                 PG_RE_THROW();
1221         }
1222         PG_END_TRY();
1223
1224
1225         return;
1226 }
1227
1228 /* ----------
1229  * Format parser, search small keywords and keyword's suffixes, and make
1230  * format-node tree.
1231  *
1232  * for DATE-TIME & NUMBER version
1233  * ----------
1234  */
1235 static void
1236 parse_format(FormatNode *node, char *str, const KeyWord *kw,
1237                          KeySuffix *suf, const int *index, int ver, NUMDesc *Num)
1238 {
1239         KeySuffix  *s;
1240         FormatNode *n;
1241         int                     node_set = 0,
1242                                 suffix,
1243                                 last = 0;
1244
1245 #ifdef DEBUG_TO_FROM_CHAR
1246         elog(DEBUG_elog_output, "to_char/number(): run parser");
1247 #endif
1248
1249         n = node;
1250
1251         while (*str)
1252         {
1253                 suffix = 0;
1254
1255                 /*
1256                  * Prefix
1257                  */
1258                 if (ver == DCH_TYPE && (s = suff_search(str, suf, SUFFTYPE_PREFIX)) != NULL)
1259                 {
1260                         suffix |= s->id;
1261                         if (s->len)
1262                                 str += s->len;
1263                 }
1264
1265                 /*
1266                  * Keyword
1267                  */
1268                 if (*str && (n->key = index_seq_search(str, kw, index)) != NULL)
1269                 {
1270                         n->type = NODE_TYPE_ACTION;
1271                         n->suffix = 0;
1272                         node_set = 1;
1273                         if (n->key->len)
1274                                 str += n->key->len;
1275
1276                         /*
1277                          * NUM version: Prepare global NUMDesc struct
1278                          */
1279                         if (ver == NUM_TYPE)
1280                                 NUMDesc_prepare(Num, n);
1281
1282                         /*
1283                          * Postfix
1284                          */
1285                         if (ver == DCH_TYPE && *str && (s = suff_search(str, suf, SUFFTYPE_POSTFIX)) != NULL)
1286                         {
1287                                 suffix |= s->id;
1288                                 if (s->len)
1289                                         str += s->len;
1290                         }
1291                 }
1292                 else if (*str)
1293                 {
1294                         /*
1295                          * Special characters '\' and '"'
1296                          */
1297                         if (*str == '"' && last != '\\')
1298                         {
1299                                 int                     x = 0;
1300
1301                                 while (*(++str))
1302                                 {
1303                                         if (*str == '"' && x != '\\')
1304                                         {
1305                                                 str++;
1306                                                 break;
1307                                         }
1308                                         else if (*str == '\\' && x != '\\')
1309                                         {
1310                                                 x = '\\';
1311                                                 continue;
1312                                         }
1313                                         n->type = NODE_TYPE_CHAR;
1314                                         n->character = *str;
1315                                         n->key = NULL;
1316                                         n->suffix = 0;
1317                                         ++n;
1318                                         x = *str;
1319                                 }
1320                                 node_set = 0;
1321                                 suffix = 0;
1322                                 last = 0;
1323                         }
1324                         else if (*str && *str == '\\' && last != '\\' && *(str + 1) == '"')
1325                         {
1326                                 last = *str;
1327                                 str++;
1328                         }
1329                         else if (*str)
1330                         {
1331                                 n->type = NODE_TYPE_CHAR;
1332                                 n->character = *str;
1333                                 n->key = NULL;
1334                                 node_set = 1;
1335                                 last = 0;
1336                                 str++;
1337                         }
1338                 }
1339
1340                 /* end */
1341                 if (node_set)
1342                 {
1343                         if (n->type == NODE_TYPE_ACTION)
1344                                 n->suffix = suffix;
1345                         ++n;
1346
1347                         n->suffix = 0;
1348                         node_set = 0;
1349                 }
1350         }
1351
1352         n->type = NODE_TYPE_END;
1353         n->suffix = 0;
1354         return;
1355 }
1356
1357 /* ----------
1358  * DEBUG: Dump the FormatNode Tree (debug)
1359  * ----------
1360  */
1361 #ifdef DEBUG_TO_FROM_CHAR
1362
1363 #define DUMP_THth(_suf) (S_TH(_suf) ? "TH" : (S_th(_suf) ? "th" : " "))
1364 #define DUMP_FM(_suf)   (S_FM(_suf) ? "FM" : " ")
1365
1366 static void
1367 dump_node(FormatNode *node, int max)
1368 {
1369         FormatNode *n;
1370         int                     a;
1371
1372         elog(DEBUG_elog_output, "to_from-char(): DUMP FORMAT");
1373
1374         for (a = 0, n = node; a <= max; n++, a++)
1375         {
1376                 if (n->type == NODE_TYPE_ACTION)
1377                         elog(DEBUG_elog_output, "%d:\t NODE_TYPE_ACTION '%s'\t(%s,%s)",
1378                                  a, n->key->name, DUMP_THth(n->suffix), DUMP_FM(n->suffix));
1379                 else if (n->type == NODE_TYPE_CHAR)
1380                         elog(DEBUG_elog_output, "%d:\t NODE_TYPE_CHAR '%c'", a, n->character);
1381                 else if (n->type == NODE_TYPE_END)
1382                 {
1383                         elog(DEBUG_elog_output, "%d:\t NODE_TYPE_END", a);
1384                         return;
1385                 }
1386                 else
1387                         elog(DEBUG_elog_output, "%d:\t unknown NODE!", a);
1388         }
1389 }
1390 #endif   /* DEBUG */
1391
1392 /*****************************************************************************
1393  *                      Private utils
1394  *****************************************************************************/
1395
1396 /* ----------
1397  * Return ST/ND/RD/TH for simple (1..9) numbers
1398  * type --> 0 upper, 1 lower
1399  * ----------
1400  */
1401 static char *
1402 get_th(char *num, int type)
1403 {
1404         int                     len = strlen(num),
1405                                 last,
1406                                 seclast;
1407
1408         last = *(num + (len - 1));
1409         if (!isdigit((unsigned char) last))
1410                 ereport(ERROR,
1411                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1412                                  errmsg("\"%s\" is not a number", num)));
1413
1414         /*
1415          * All "teens" (<x>1[0-9]) get 'TH/th', while <x>[02-9][123] still get
1416          * 'ST/st', 'ND/nd', 'RD/rd', respectively
1417          */
1418         if ((len > 1) && ((seclast = num[len - 2]) == '1'))
1419                 last = 0;
1420
1421         switch (last)
1422         {
1423                 case '1':
1424                         if (type == TH_UPPER)
1425                                 return numTH[0];
1426                         return numth[0];
1427                 case '2':
1428                         if (type == TH_UPPER)
1429                                 return numTH[1];
1430                         return numth[1];
1431                 case '3':
1432                         if (type == TH_UPPER)
1433                                 return numTH[2];
1434                         return numth[2];
1435                 default:
1436                         if (type == TH_UPPER)
1437                                 return numTH[3];
1438                         return numth[3];
1439         }
1440         return NULL;
1441 }
1442
1443 /* ----------
1444  * Convert string-number to ordinal string-number
1445  * type --> 0 upper, 1 lower
1446  * ----------
1447  */
1448 static char *
1449 str_numth(char *dest, char *num, int type)
1450 {
1451         if (dest != num)
1452                 strcpy(dest, num);
1453         strcat(dest, get_th(num, type));
1454         return dest;
1455 }
1456
1457 /*
1458  * If the system provides the needed functions for wide-character manipulation
1459  * (which are all standardized by C99), then we implement upper/lower/initcap
1460  * using wide-character functions, if necessary.  Otherwise we use the
1461  * traditional <ctype.h> functions, which of course will not work as desired
1462  * in multibyte character sets.  Note that in either case we are effectively
1463  * assuming that the database character encoding matches the encoding implied
1464  * by LC_CTYPE.
1465  */
1466
1467 /*
1468  * wide-character-aware lower function
1469  *
1470  * We pass the number of bytes so we can pass varlena and char*
1471  * to this function.  The result is a palloc'd, null-terminated string.
1472  */
1473 char *
1474 str_tolower(const char *buff, size_t nbytes, Oid collid)
1475 {
1476         char       *result;
1477         pg_locale_t     mylocale = 0;
1478
1479         if (!buff)
1480                 return NULL;
1481
1482         if (collid != DEFAULT_COLLATION_OID)
1483                 mylocale = pg_newlocale_from_collation(collid);
1484
1485 #ifdef USE_WIDE_UPPER_LOWER
1486         if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c(collid))
1487         {
1488                 wchar_t    *workspace;
1489                 size_t          curr_char;
1490                 size_t          result_size;
1491
1492                 /* Overflow paranoia */
1493                 if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1494                         ereport(ERROR,
1495                                         (errcode(ERRCODE_OUT_OF_MEMORY),
1496                                          errmsg("out of memory")));
1497
1498                 /* Output workspace cannot have more codes than input bytes */
1499                 workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1500
1501                 char2wchar(workspace, nbytes + 1, buff, nbytes, collid);
1502
1503                 for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1504 #ifdef HAVE_LOCALE_T
1505                         if (mylocale)
1506                                 workspace[curr_char] = towlower_l(workspace[curr_char], mylocale);
1507                         else
1508 #endif
1509                         workspace[curr_char] = towlower(workspace[curr_char]);
1510
1511                 /* Make result large enough; case change might change number of bytes */
1512                 result_size = curr_char * pg_database_encoding_max_length() + 1;
1513                 result = palloc(result_size);
1514
1515                 wchar2char(result, workspace, result_size, collid);
1516                 pfree(workspace);
1517         }
1518         else
1519 #endif   /* USE_WIDE_UPPER_LOWER */
1520         {
1521                 char       *p;
1522
1523                 result = pnstrdup(buff, nbytes);
1524
1525                 for (p = result; *p; p++)
1526                         *p = pg_tolower((unsigned char) *p);
1527         }
1528
1529         return result;
1530 }
1531
1532 /*
1533  * wide-character-aware upper function
1534  *
1535  * We pass the number of bytes so we can pass varlena and char*
1536  * to this function.  The result is a palloc'd, null-terminated string.
1537  */
1538 char *
1539 str_toupper(const char *buff, size_t nbytes, Oid collid)
1540 {
1541         char       *result;
1542         pg_locale_t     mylocale = 0;
1543
1544         if (!buff)
1545                 return NULL;
1546
1547         if (collid != DEFAULT_COLLATION_OID)
1548                 mylocale = pg_newlocale_from_collation(collid);
1549
1550 #ifdef USE_WIDE_UPPER_LOWER
1551         if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c(collid))
1552         {
1553                 wchar_t    *workspace;
1554                 size_t          curr_char;
1555                 size_t          result_size;
1556
1557                 /* Overflow paranoia */
1558                 if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1559                         ereport(ERROR,
1560                                         (errcode(ERRCODE_OUT_OF_MEMORY),
1561                                          errmsg("out of memory")));
1562
1563                 /* Output workspace cannot have more codes than input bytes */
1564                 workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1565
1566                 char2wchar(workspace, nbytes + 1, buff, nbytes, collid);
1567
1568                 for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1569 #ifdef HAVE_LOCALE_T
1570                         if (mylocale)
1571                                 workspace[curr_char] = towupper_l(workspace[curr_char], mylocale);
1572                         else
1573 #endif
1574                         workspace[curr_char] = towupper(workspace[curr_char]);
1575
1576                 /* Make result large enough; case change might change number of bytes */
1577                 result_size = curr_char * pg_database_encoding_max_length() + 1;
1578                 result = palloc(result_size);
1579
1580                 wchar2char(result, workspace, result_size, collid);
1581                 pfree(workspace);
1582         }
1583         else
1584 #endif   /* USE_WIDE_UPPER_LOWER */
1585         {
1586                 char       *p;
1587
1588                 result = pnstrdup(buff, nbytes);
1589
1590                 for (p = result; *p; p++)
1591                         *p = pg_toupper((unsigned char) *p);
1592         }
1593
1594         return result;
1595 }
1596
1597 /*
1598  * wide-character-aware initcap function
1599  *
1600  * We pass the number of bytes so we can pass varlena and char*
1601  * to this function.  The result is a palloc'd, null-terminated string.
1602  */
1603 char *
1604 str_initcap(const char *buff, size_t nbytes, Oid collid)
1605 {
1606         char       *result;
1607         int                     wasalnum = false;
1608         pg_locale_t     mylocale = 0;
1609
1610         if (!buff)
1611                 return NULL;
1612
1613         if (collid != DEFAULT_COLLATION_OID)
1614                 mylocale = pg_newlocale_from_collation(collid);
1615
1616 #ifdef USE_WIDE_UPPER_LOWER
1617         if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c(collid))
1618         {
1619                 wchar_t    *workspace;
1620                 size_t          curr_char;
1621                 size_t          result_size;
1622
1623                 /* Overflow paranoia */
1624                 if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1625                         ereport(ERROR,
1626                                         (errcode(ERRCODE_OUT_OF_MEMORY),
1627                                          errmsg("out of memory")));
1628
1629                 /* Output workspace cannot have more codes than input bytes */
1630                 workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1631
1632                 char2wchar(workspace, nbytes + 1, buff, nbytes, collid);
1633
1634                 for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1635                 {
1636 #ifdef HAVE_LOCALE_T
1637                         if (mylocale)
1638                         {
1639                                 if (wasalnum)
1640                                         workspace[curr_char] = towlower_l(workspace[curr_char], mylocale);
1641                                 else
1642                                         workspace[curr_char] = towupper_l(workspace[curr_char], mylocale);
1643                                 wasalnum = iswalnum_l(workspace[curr_char], mylocale);
1644                         }
1645                         else
1646 #endif
1647                         {
1648                                 if (wasalnum)
1649                                         workspace[curr_char] = towlower(workspace[curr_char]);
1650                                 else
1651                                         workspace[curr_char] = towupper(workspace[curr_char]);
1652                                 wasalnum = iswalnum(workspace[curr_char]);
1653                         }
1654                 }
1655
1656                 /* Make result large enough; case change might change number of bytes */
1657                 result_size = curr_char * pg_database_encoding_max_length() + 1;
1658                 result = palloc(result_size);
1659
1660                 wchar2char(result, workspace, result_size, collid);
1661                 pfree(workspace);
1662         }
1663         else
1664 #endif   /* USE_WIDE_UPPER_LOWER */
1665         {
1666                 char       *p;
1667
1668                 result = pnstrdup(buff, nbytes);
1669
1670                 for (p = result; *p; p++)
1671                 {
1672                         if (wasalnum)
1673                                 *p = pg_tolower((unsigned char) *p);
1674                         else
1675                                 *p = pg_toupper((unsigned char) *p);
1676                         wasalnum = isalnum((unsigned char) *p);
1677                 }
1678         }
1679
1680         return result;
1681 }
1682
1683 /* convenience routines for when the input is null-terminated */
1684
1685 static char *
1686 str_tolower_z(const char *buff, Oid collid)
1687 {
1688         return str_tolower(buff, strlen(buff), collid);
1689 }
1690
1691 static char *
1692 str_toupper_z(const char *buff, Oid collid)
1693 {
1694         return str_toupper(buff, strlen(buff), collid);
1695 }
1696
1697 static char *
1698 str_initcap_z(const char *buff, Oid collid)
1699 {
1700         return str_initcap(buff, strlen(buff), collid);
1701 }
1702
1703
1704 /* ----------
1705  * Skip TM / th in FROM_CHAR
1706  * ----------
1707  */
1708 #define SKIP_THth(_suf)         (S_THth(_suf) ? 2 : 0)
1709
1710 #ifdef DEBUG_TO_FROM_CHAR
1711 /* -----------
1712  * DEBUG: Call for debug and for index checking; (Show ASCII char
1713  * and defined keyword for each used position
1714  * ----------
1715  */
1716 static void
1717 dump_index(const KeyWord *k, const int *index)
1718 {
1719         int                     i,
1720                                 count = 0,
1721                                 free_i = 0;
1722
1723         elog(DEBUG_elog_output, "TO-FROM_CHAR: Dump KeyWord Index:");
1724
1725         for (i = 0; i < KeyWord_INDEX_SIZE; i++)
1726         {
1727                 if (index[i] != -1)
1728                 {
1729                         elog(DEBUG_elog_output, "\t%c: %s, ", i + 32, k[index[i]].name);
1730                         count++;
1731                 }
1732                 else
1733                 {
1734                         free_i++;
1735                         elog(DEBUG_elog_output, "\t(%d) %c %d", i, i + 32, index[i]);
1736                 }
1737         }
1738         elog(DEBUG_elog_output, "\n\t\tUsed positions: %d,\n\t\tFree positions: %d",
1739                  count, free_i);
1740 }
1741 #endif   /* DEBUG */
1742
1743 /* ----------
1744  * Return TRUE if next format picture is not digit value
1745  * ----------
1746  */
1747 static bool
1748 is_next_separator(FormatNode *n)
1749 {
1750         if (n->type == NODE_TYPE_END)
1751                 return FALSE;
1752
1753         if (n->type == NODE_TYPE_ACTION && S_THth(n->suffix))
1754                 return TRUE;
1755
1756         /*
1757          * Next node
1758          */
1759         n++;
1760
1761         /* end of format string is treated like a non-digit separator */
1762         if (n->type == NODE_TYPE_END)
1763                 return TRUE;
1764
1765         if (n->type == NODE_TYPE_ACTION)
1766         {
1767                 if (n->key->is_digit)
1768                         return FALSE;
1769
1770                 return TRUE;
1771         }
1772         else if (isdigit((unsigned char) n->character))
1773                 return FALSE;
1774
1775         return TRUE;                            /* some non-digit input (separator) */
1776 }
1777
1778 static int
1779 strspace_len(char *str)
1780 {
1781         int                     len = 0;
1782
1783         while (*str && isspace((unsigned char) *str))
1784         {
1785                 str++;
1786                 len++;
1787         }
1788         return len;
1789 }
1790
1791 static int
1792 strdigits_len(char *str)
1793 {
1794         char       *p = str;
1795         int                     len;
1796
1797         len = strspace_len(str);
1798         p += len;
1799
1800         while (*p && isdigit((unsigned char) *p) && len <= DCH_MAX_ITEM_SIZ)
1801         {
1802                 len++;
1803                 p++;
1804         }
1805         return len;
1806 }
1807
1808 /*
1809  * Set the date mode of a from-char conversion.
1810  *
1811  * Puke if the date mode has already been set, and the caller attempts to set
1812  * it to a conflicting mode.
1813  */
1814 static void
1815 from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode)
1816 {
1817         if (mode != FROM_CHAR_DATE_NONE)
1818         {
1819                 if (tmfc->mode == FROM_CHAR_DATE_NONE)
1820                         tmfc->mode = mode;
1821                 else if (tmfc->mode != mode)
1822                         ereport(ERROR,
1823                                         (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
1824                                          errmsg("invalid combination of date conventions"),
1825                                          errhint("Do not mix Gregorian and ISO week date "
1826                                                          "conventions in a formatting template.")));
1827         }
1828 }
1829
1830 /*
1831  * Set the integer pointed to by 'dest' to the given value.
1832  *
1833  * Puke if the destination integer has previously been set to some other
1834  * non-zero value.
1835  */
1836 static void
1837 from_char_set_int(int *dest, const int value, const FormatNode *node)
1838 {
1839         if (*dest != 0 && *dest != value)
1840                 ereport(ERROR,
1841                                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
1842                    errmsg("conflicting values for \"%s\" field in formatting string",
1843                                   node->key->name),
1844                                  errdetail("This value contradicts a previous setting for "
1845                                                    "the same field type.")));
1846         *dest = value;
1847 }
1848
1849 /*
1850  * Read a single integer from the source string, into the int pointed to by
1851  * 'dest'. If 'dest' is NULL, the result is discarded.
1852  *
1853  * In fixed-width mode (the node does not have the FM suffix), consume at most
1854  * 'len' characters.  However, any leading whitespace isn't counted in 'len'.
1855  *
1856  * We use strtol() to recover the integer value from the source string, in
1857  * accordance with the given FormatNode.
1858  *
1859  * If the conversion completes successfully, src will have been advanced to
1860  * point at the character immediately following the last character used in the
1861  * conversion.
1862  *
1863  * Return the number of characters consumed.
1864  *
1865  * Note that from_char_parse_int() provides a more convenient wrapper where
1866  * the length of the field is the same as the length of the format keyword (as
1867  * with DD and MI).
1868  */
1869 static int
1870 from_char_parse_int_len(int *dest, char **src, const int len, FormatNode *node)
1871 {
1872         long            result;
1873         char            copy[DCH_MAX_ITEM_SIZ + 1];
1874         char       *init = *src;
1875         int                     used;
1876
1877         /*
1878          * Skip any whitespace before parsing the integer.
1879          */
1880         *src += strspace_len(*src);
1881
1882         Assert(len <= DCH_MAX_ITEM_SIZ);
1883         used = (int) strlcpy(copy, *src, len + 1);
1884
1885         if (S_FM(node->suffix) || is_next_separator(node))
1886         {
1887                 /*
1888                  * This node is in Fill Mode, or the next node is known to be a
1889                  * non-digit value, so we just slurp as many characters as we can get.
1890                  */
1891                 errno = 0;
1892                 result = strtol(init, src, 10);
1893         }
1894         else
1895         {
1896                 /*
1897                  * We need to pull exactly the number of characters given in 'len' out
1898                  * of the string, and convert those.
1899                  */
1900                 char       *last;
1901
1902                 if (used < len)
1903                         ereport(ERROR,
1904                                         (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
1905                                 errmsg("source string too short for \"%s\" formatting field",
1906                                            node->key->name),
1907                                          errdetail("Field requires %d characters, but only %d "
1908                                                            "remain.",
1909                                                            len, used),
1910                                          errhint("If your source string is not fixed-width, try "
1911                                                          "using the \"FM\" modifier.")));
1912
1913                 errno = 0;
1914                 result = strtol(copy, &last, 10);
1915                 used = last - copy;
1916
1917                 if (used > 0 && used < len)
1918                         ereport(ERROR,
1919                                         (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
1920                                          errmsg("invalid value \"%s\" for \"%s\"",
1921                                                         copy, node->key->name),
1922                                          errdetail("Field requires %d characters, but only %d "
1923                                                            "could be parsed.", len, used),
1924                                          errhint("If your source string is not fixed-width, try "
1925                                                          "using the \"FM\" modifier.")));
1926
1927                 *src += used;
1928         }
1929
1930         if (*src == init)
1931                 ereport(ERROR,
1932                                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
1933                                  errmsg("invalid value \"%s\" for \"%s\"",
1934                                                 copy, node->key->name),
1935                                  errdetail("Value must be an integer.")));
1936
1937         if (errno == ERANGE || result < INT_MIN || result > INT_MAX)
1938                 ereport(ERROR,
1939                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1940                                  errmsg("value for \"%s\" in source string is out of range",
1941                                                 node->key->name),
1942                                  errdetail("Value must be in the range %d to %d.",
1943                                                    INT_MIN, INT_MAX)));
1944
1945         if (dest != NULL)
1946                 from_char_set_int(dest, (int) result, node);
1947         return *src - init;
1948 }
1949
1950 /*
1951  * Call from_char_parse_int_len(), using the length of the format keyword as
1952  * the expected length of the field.
1953  *
1954  * Don't call this function if the field differs in length from the format
1955  * keyword (as with HH24; the keyword length is 4, but the field length is 2).
1956  * In such cases, call from_char_parse_int_len() instead to specify the
1957  * required length explictly.
1958  */
1959 static int
1960 from_char_parse_int(int *dest, char **src, FormatNode *node)
1961 {
1962         return from_char_parse_int_len(dest, src, node->key->len, node);
1963 }
1964
1965 /* ----------
1966  * Sequential search with to upper/lower conversion
1967  * ----------
1968  */
1969 static int
1970 seq_search(char *name, char **array, int type, int max, int *len)
1971 {
1972         char       *p,
1973                            *n,
1974                           **a;
1975         int                     last,
1976                                 i;
1977
1978         *len = 0;
1979
1980         if (!*name)
1981                 return -1;
1982
1983         /* set first char */
1984         if (type == ONE_UPPER || type == ALL_UPPER)
1985                 *name = pg_toupper((unsigned char) *name);
1986         else if (type == ALL_LOWER)
1987                 *name = pg_tolower((unsigned char) *name);
1988
1989         for (last = 0, a = array; *a != NULL; a++)
1990         {
1991                 /* comperate first chars */
1992                 if (*name != **a)
1993                         continue;
1994
1995                 for (i = 1, p = *a + 1, n = name + 1;; n++, p++, i++)
1996                 {
1997                         /* search fragment (max) only */
1998                         if (max && i == max)
1999                         {
2000                                 *len = i;
2001                                 return a - array;
2002                         }
2003                         /* full size */
2004                         if (*p == '\0')
2005                         {
2006                                 *len = i;
2007                                 return a - array;
2008                         }
2009                         /* Not found in array 'a' */
2010                         if (*n == '\0')
2011                                 break;
2012
2013                         /*
2014                          * Convert (but convert new chars only)
2015                          */
2016                         if (i > last)
2017                         {
2018                                 if (type == ONE_UPPER || type == ALL_LOWER)
2019                                         *n = pg_tolower((unsigned char) *n);
2020                                 else if (type == ALL_UPPER)
2021                                         *n = pg_toupper((unsigned char) *n);
2022                                 last = i;
2023                         }
2024
2025 #ifdef DEBUG_TO_FROM_CHAR
2026                         elog(DEBUG_elog_output, "N: %c, P: %c, A: %s (%s)",
2027                                  *n, *p, *a, name);
2028 #endif
2029                         if (*n != *p)
2030                                 break;
2031                 }
2032         }
2033
2034         return -1;
2035 }
2036
2037 /*
2038  * Perform a sequential search in 'array' for text matching the first 'max'
2039  * characters of the source string.
2040  *
2041  * If a match is found, copy the array index of the match into the integer
2042  * pointed to by 'dest', advance 'src' to the end of the part of the string
2043  * which matched, and return the number of characters consumed.
2044  *
2045  * If the string doesn't match, throw an error.
2046  */
2047 static int
2048 from_char_seq_search(int *dest, char **src, char **array, int type, int max,
2049                                          FormatNode *node)
2050 {
2051         int                     len;
2052
2053         *dest = seq_search(*src, array, type, max, &len);
2054         if (len <= 0)
2055         {
2056                 char            copy[DCH_MAX_ITEM_SIZ + 1];
2057
2058                 Assert(max <= DCH_MAX_ITEM_SIZ);
2059                 strlcpy(copy, *src, max + 1);
2060
2061                 ereport(ERROR,
2062                                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2063                                  errmsg("invalid value \"%s\" for \"%s\"",
2064                                                 copy, node->key->name),
2065                                  errdetail("The given value did not match any of the allowed "
2066                                                    "values for this field.")));
2067         }
2068         *src += len;
2069         return len;
2070 }
2071
2072 /* ----------
2073  * Process a TmToChar struct as denoted by a list of FormatNodes.
2074  * The formatted data is written to the string pointed to by 'out'.
2075  * ----------
2076  */
2077 static void
2078 DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
2079 {
2080         FormatNode *n;
2081         char       *s;
2082         struct pg_tm *tm = &in->tm;
2083         int                     i;
2084
2085         /* cache localized days and months */
2086         cache_locale_time();
2087
2088         s = out;
2089         for (n = node; n->type != NODE_TYPE_END; n++)
2090         {
2091                 if (n->type != NODE_TYPE_ACTION)
2092                 {
2093                         *s = n->character;
2094                         s++;
2095                         continue;
2096                 }
2097
2098                 switch (n->key->id)
2099                 {
2100                         case DCH_A_M:
2101                         case DCH_P_M:
2102                                 strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2103                                            ? P_M_STR : A_M_STR);
2104                                 s += strlen(s);
2105                                 break;
2106                         case DCH_AM:
2107                         case DCH_PM:
2108                                 strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2109                                            ? PM_STR : AM_STR);
2110                                 s += strlen(s);
2111                                 break;
2112                         case DCH_a_m:
2113                         case DCH_p_m:
2114                                 strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2115                                            ? p_m_STR : a_m_STR);
2116                                 s += strlen(s);
2117                                 break;
2118                         case DCH_am:
2119                         case DCH_pm:
2120                                 strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2121                                            ? pm_STR : am_STR);
2122                                 s += strlen(s);
2123                                 break;
2124                         case DCH_HH:
2125                         case DCH_HH12:
2126
2127                                 /*
2128                                  * display time as shown on a 12-hour clock, even for
2129                                  * intervals
2130                                  */
2131                                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
2132                                                 tm->tm_hour % (HOURS_PER_DAY / 2) == 0 ? 12 :
2133                                                 tm->tm_hour % (HOURS_PER_DAY / 2));
2134                                 if (S_THth(n->suffix))
2135                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2136                                 s += strlen(s);
2137                                 break;
2138                         case DCH_HH24:
2139                                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_hour);
2140                                 if (S_THth(n->suffix))
2141                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2142                                 s += strlen(s);
2143                                 break;
2144                         case DCH_MI:
2145                                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_min);
2146                                 if (S_THth(n->suffix))
2147                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2148                                 s += strlen(s);
2149                                 break;
2150                         case DCH_SS:
2151                                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_sec);
2152                                 if (S_THth(n->suffix))
2153                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2154                                 s += strlen(s);
2155                                 break;
2156                         case DCH_MS:            /* millisecond */
2157 #ifdef HAVE_INT64_TIMESTAMP
2158                                 sprintf(s, "%03d", (int) (in->fsec / INT64CONST(1000)));
2159 #else
2160                                 /* No rint() because we can't overflow and we might print US */
2161                                 sprintf(s, "%03d", (int) (in->fsec * 1000));
2162 #endif
2163                                 if (S_THth(n->suffix))
2164                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2165                                 s += strlen(s);
2166                                 break;
2167                         case DCH_US:            /* microsecond */
2168 #ifdef HAVE_INT64_TIMESTAMP
2169                                 sprintf(s, "%06d", (int) in->fsec);
2170 #else
2171                                 /* don't use rint() because we can't overflow 1000 */
2172                                 sprintf(s, "%06d", (int) (in->fsec * 1000000));
2173 #endif
2174                                 if (S_THth(n->suffix))
2175                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2176                                 s += strlen(s);
2177                                 break;
2178                         case DCH_SSSS:
2179                                 sprintf(s, "%d", tm->tm_hour * SECS_PER_HOUR +
2180                                                 tm->tm_min * SECS_PER_MINUTE +
2181                                                 tm->tm_sec);
2182                                 if (S_THth(n->suffix))
2183                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2184                                 s += strlen(s);
2185                                 break;
2186                         case DCH_tz:
2187                                 INVALID_FOR_INTERVAL;
2188                                 if (tmtcTzn(in))
2189                                 {
2190                                         char       *p = str_tolower_z(tmtcTzn(in), collid);
2191
2192                                         strcpy(s, p);
2193                                         pfree(p);
2194                                         s += strlen(s);
2195                                 }
2196                                 break;
2197                         case DCH_TZ:
2198                                 INVALID_FOR_INTERVAL;
2199                                 if (tmtcTzn(in))
2200                                 {
2201                                         strcpy(s, tmtcTzn(in));
2202                                         s += strlen(s);
2203                                 }
2204                                 break;
2205                         case DCH_A_D:
2206                         case DCH_B_C:
2207                                 INVALID_FOR_INTERVAL;
2208                                 strcpy(s, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
2209                                 s += strlen(s);
2210                                 break;
2211                         case DCH_AD:
2212                         case DCH_BC:
2213                                 INVALID_FOR_INTERVAL;
2214                                 strcpy(s, (tm->tm_year <= 0 ? BC_STR : AD_STR));
2215                                 s += strlen(s);
2216                                 break;
2217                         case DCH_a_d:
2218                         case DCH_b_c:
2219                                 INVALID_FOR_INTERVAL;
2220                                 strcpy(s, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
2221                                 s += strlen(s);
2222                                 break;
2223                         case DCH_ad:
2224                         case DCH_bc:
2225                                 INVALID_FOR_INTERVAL;
2226                                 strcpy(s, (tm->tm_year <= 0 ? bc_STR : ad_STR));
2227                                 s += strlen(s);
2228                                 break;
2229                         case DCH_MONTH:
2230                                 INVALID_FOR_INTERVAL;
2231                                 if (!tm->tm_mon)
2232                                         break;
2233                                 if (S_TM(n->suffix))
2234                                         strcpy(s, str_toupper_z(localized_full_months[tm->tm_mon - 1], collid));
2235                                 else
2236                                         sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2237                                                         str_toupper_z(months_full[tm->tm_mon - 1], collid));
2238                                 s += strlen(s);
2239                                 break;
2240                         case DCH_Month:
2241                                 INVALID_FOR_INTERVAL;
2242                                 if (!tm->tm_mon)
2243                                         break;
2244                                 if (S_TM(n->suffix))
2245                                         strcpy(s, str_initcap_z(localized_full_months[tm->tm_mon - 1], collid));
2246                                 else
2247                                         sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9, months_full[tm->tm_mon - 1]);
2248                                 s += strlen(s);
2249                                 break;
2250                         case DCH_month:
2251                                 INVALID_FOR_INTERVAL;
2252                                 if (!tm->tm_mon)
2253                                         break;
2254                                 if (S_TM(n->suffix))
2255                                         strcpy(s, str_tolower_z(localized_full_months[tm->tm_mon - 1], collid));
2256                                 else
2257                                 {
2258                                         sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9, months_full[tm->tm_mon - 1]);
2259                                         *s = pg_tolower((unsigned char) *s);
2260                                 }
2261                                 s += strlen(s);
2262                                 break;
2263                         case DCH_MON:
2264                                 INVALID_FOR_INTERVAL;
2265                                 if (!tm->tm_mon)
2266                                         break;
2267                                 if (S_TM(n->suffix))
2268                                         strcpy(s, str_toupper_z(localized_abbrev_months[tm->tm_mon - 1], collid));
2269                                 else
2270                                         strcpy(s, str_toupper_z(months[tm->tm_mon - 1], collid));
2271                                 s += strlen(s);
2272                                 break;
2273                         case DCH_Mon:
2274                                 INVALID_FOR_INTERVAL;
2275                                 if (!tm->tm_mon)
2276                                         break;
2277                                 if (S_TM(n->suffix))
2278                                         strcpy(s, str_initcap_z(localized_abbrev_months[tm->tm_mon - 1], collid));
2279                                 else
2280                                         strcpy(s, months[tm->tm_mon - 1]);
2281                                 s += strlen(s);
2282                                 break;
2283                         case DCH_mon:
2284                                 INVALID_FOR_INTERVAL;
2285                                 if (!tm->tm_mon)
2286                                         break;
2287                                 if (S_TM(n->suffix))
2288                                         strcpy(s, str_tolower_z(localized_abbrev_months[tm->tm_mon - 1], collid));
2289                                 else
2290                                 {
2291                                         strcpy(s, months[tm->tm_mon - 1]);
2292                                         *s = pg_tolower((unsigned char) *s);
2293                                 }
2294                                 s += strlen(s);
2295                                 break;
2296                         case DCH_MM:
2297                                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mon);
2298                                 if (S_THth(n->suffix))
2299                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2300                                 s += strlen(s);
2301                                 break;
2302                         case DCH_DAY:
2303                                 INVALID_FOR_INTERVAL;
2304                                 if (S_TM(n->suffix))
2305                                         strcpy(s, str_toupper_z(localized_full_days[tm->tm_wday], collid));
2306                                 else
2307                                         sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2308                                                         str_toupper_z(days[tm->tm_wday], collid));
2309                                 s += strlen(s);
2310                                 break;
2311                         case DCH_Day:
2312                                 INVALID_FOR_INTERVAL;
2313                                 if (S_TM(n->suffix))
2314                                         strcpy(s, str_initcap_z(localized_full_days[tm->tm_wday], collid));
2315                                 else
2316                                         sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9, days[tm->tm_wday]);
2317                                 s += strlen(s);
2318                                 break;
2319                         case DCH_day:
2320                                 INVALID_FOR_INTERVAL;
2321                                 if (S_TM(n->suffix))
2322                                         strcpy(s, str_tolower_z(localized_full_days[tm->tm_wday], collid));
2323                                 else
2324                                 {
2325                                         sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9, days[tm->tm_wday]);
2326                                         *s = pg_tolower((unsigned char) *s);
2327                                 }
2328                                 s += strlen(s);
2329                                 break;
2330                         case DCH_DY:
2331                                 INVALID_FOR_INTERVAL;
2332                                 if (S_TM(n->suffix))
2333                                         strcpy(s, str_toupper_z(localized_abbrev_days[tm->tm_wday], collid));
2334                                 else
2335                                         strcpy(s, str_toupper_z(days_short[tm->tm_wday], collid));
2336                                 s += strlen(s);
2337                                 break;
2338                         case DCH_Dy:
2339                                 INVALID_FOR_INTERVAL;
2340                                 if (S_TM(n->suffix))
2341                                         strcpy(s, str_initcap_z(localized_abbrev_days[tm->tm_wday], collid));
2342                                 else
2343                                         strcpy(s, days_short[tm->tm_wday]);
2344                                 s += strlen(s);
2345                                 break;
2346                         case DCH_dy:
2347                                 INVALID_FOR_INTERVAL;
2348                                 if (S_TM(n->suffix))
2349                                         strcpy(s, str_tolower_z(localized_abbrev_days[tm->tm_wday], collid));
2350                                 else
2351                                 {
2352                                         strcpy(s, days_short[tm->tm_wday]);
2353                                         *s = pg_tolower((unsigned char) *s);
2354                                 }
2355                                 s += strlen(s);
2356                                 break;
2357                         case DCH_DDD:
2358                         case DCH_IDDD:
2359                                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 3,
2360                                                 (n->key->id == DCH_DDD) ?
2361                                                 tm->tm_yday :
2362                                           date2isoyearday(tm->tm_year, tm->tm_mon, tm->tm_mday));
2363                                 if (S_THth(n->suffix))
2364                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2365                                 s += strlen(s);
2366                                 break;
2367                         case DCH_DD:
2368                                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mday);
2369                                 if (S_THth(n->suffix))
2370                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2371                                 s += strlen(s);
2372                                 break;
2373                         case DCH_D:
2374                                 INVALID_FOR_INTERVAL;
2375                                 sprintf(s, "%d", tm->tm_wday + 1);
2376                                 if (S_THth(n->suffix))
2377                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2378                                 s += strlen(s);
2379                                 break;
2380                         case DCH_ID:
2381                                 INVALID_FOR_INTERVAL;
2382                                 sprintf(s, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
2383                                 if (S_THth(n->suffix))
2384                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2385                                 s += strlen(s);
2386                                 break;
2387                         case DCH_WW:
2388                                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
2389                                                 (tm->tm_yday - 1) / 7 + 1);
2390                                 if (S_THth(n->suffix))
2391                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2392                                 s += strlen(s);
2393                                 break;
2394                         case DCH_IW:
2395                                 sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
2396                                                 date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
2397                                 if (S_THth(n->suffix))
2398                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2399                                 s += strlen(s);
2400                                 break;
2401                         case DCH_Q:
2402                                 if (!tm->tm_mon)
2403                                         break;
2404                                 sprintf(s, "%d", (tm->tm_mon - 1) / 3 + 1);
2405                                 if (S_THth(n->suffix))
2406                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2407                                 s += strlen(s);
2408                                 break;
2409                         case DCH_CC:
2410                                 if (is_interval)        /* straight calculation */
2411                                         i = tm->tm_year / 100;
2412                                 else    /* century 21 starts in 2001 */
2413                                         i = (tm->tm_year - 1) / 100 + 1;
2414                                 if (i <= 99 && i >= -99)
2415                                         sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, i);
2416                                 else
2417                                         sprintf(s, "%d", i);
2418                                 if (S_THth(n->suffix))
2419                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2420                                 s += strlen(s);
2421                                 break;
2422                         case DCH_Y_YYY:
2423                                 i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000;
2424                                 sprintf(s, "%d,%03d", i,
2425                                                 ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000));
2426                                 if (S_THth(n->suffix))
2427                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2428                                 s += strlen(s);
2429                                 break;
2430                         case DCH_YYYY:
2431                         case DCH_IYYY:
2432                                 sprintf(s, "%0*d",
2433                                                 S_FM(n->suffix) ? 0 : 4,
2434                                                 (n->key->id == DCH_YYYY ?
2435                                                  ADJUST_YEAR(tm->tm_year, is_interval) :
2436                                                  ADJUST_YEAR(date2isoyear(tm->tm_year,
2437                                                                                                   tm->tm_mon,
2438                                                                                                   tm->tm_mday),
2439                                                                          is_interval)));
2440                                 if (S_THth(n->suffix))
2441                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2442                                 s += strlen(s);
2443                                 break;
2444                         case DCH_YYY:
2445                         case DCH_IYY:
2446                                 sprintf(s, "%0*d",
2447                                                 S_FM(n->suffix) ? 0 : 3,
2448                                                 (n->key->id == DCH_YYY ?
2449                                                  ADJUST_YEAR(tm->tm_year, is_interval) :
2450                                                  ADJUST_YEAR(date2isoyear(tm->tm_year,
2451                                                                                                   tm->tm_mon,
2452                                                                                                   tm->tm_mday),
2453                                                                          is_interval)) % 1000);
2454                                 if (S_THth(n->suffix))
2455                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2456                                 s += strlen(s);
2457                                 break;
2458                         case DCH_YY:
2459                         case DCH_IY:
2460                                 sprintf(s, "%0*d",
2461                                                 S_FM(n->suffix) ? 0 : 2,
2462                                                 (n->key->id == DCH_YY ?
2463                                                  ADJUST_YEAR(tm->tm_year, is_interval) :
2464                                                  ADJUST_YEAR(date2isoyear(tm->tm_year,
2465                                                                                                   tm->tm_mon,
2466                                                                                                   tm->tm_mday),
2467                                                                          is_interval)) % 100);
2468                                 if (S_THth(n->suffix))
2469                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2470                                 s += strlen(s);
2471                                 break;
2472                         case DCH_Y:
2473                         case DCH_I:
2474                                 sprintf(s, "%1d",
2475                                                 (n->key->id == DCH_Y ?
2476                                                  ADJUST_YEAR(tm->tm_year, is_interval) :
2477                                                  ADJUST_YEAR(date2isoyear(tm->tm_year,
2478                                                                                                   tm->tm_mon,
2479                                                                                                   tm->tm_mday),
2480                                                                          is_interval)) % 10);
2481                                 if (S_THth(n->suffix))
2482                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2483                                 s += strlen(s);
2484                                 break;
2485                         case DCH_RM:
2486                                 if (!tm->tm_mon)
2487                                         break;
2488                                 sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
2489                                                 rm_months_upper[12 - tm->tm_mon]);
2490                                 s += strlen(s);
2491                                 break;
2492                         case DCH_rm:
2493                                 if (!tm->tm_mon)
2494                                         break;
2495                                 sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
2496                                                 rm_months_lower[12 - tm->tm_mon]);
2497                                 s += strlen(s);
2498                                 break;
2499                         case DCH_W:
2500                                 sprintf(s, "%d", (tm->tm_mday - 1) / 7 + 1);
2501                                 if (S_THth(n->suffix))
2502                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2503                                 s += strlen(s);
2504                                 break;
2505                         case DCH_J:
2506                                 sprintf(s, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
2507                                 if (S_THth(n->suffix))
2508                                         str_numth(s, s, S_TH_TYPE(n->suffix));
2509                                 s += strlen(s);
2510                                 break;
2511                 }
2512         }
2513
2514         *s = '\0';
2515 }
2516
2517 /* ----------
2518  * Process a string as denoted by a list of FormatNodes.
2519  * The TmFromChar struct pointed to by 'out' is populated with the results.
2520  *
2521  * Note: we currently don't have any to_interval() function, so there
2522  * is no need here for INVALID_FOR_INTERVAL checks.
2523  * ----------
2524  */
2525 static void
2526 DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
2527 {
2528         FormatNode *n;
2529         char       *s;
2530         int                     len,
2531                                 value;
2532         bool            fx_mode = false;
2533
2534         for (n = node, s = in; n->type != NODE_TYPE_END && *s != '\0'; n++)
2535         {
2536                 if (n->type != NODE_TYPE_ACTION)
2537                 {
2538                         s++;
2539                         /* Ignore spaces when not in FX (fixed width) mode */
2540                         if (isspace((unsigned char) n->character) && !fx_mode)
2541                         {
2542                                 while (*s != '\0' && isspace((unsigned char) *s))
2543                                         s++;
2544                         }
2545                         continue;
2546                 }
2547
2548                 from_char_set_mode(out, n->key->date_mode);
2549
2550                 switch (n->key->id)
2551                 {
2552                         case DCH_FX:
2553                                 fx_mode = true;
2554                                 break;
2555                         case DCH_A_M:
2556                         case DCH_P_M:
2557                         case DCH_a_m:
2558                         case DCH_p_m:
2559                                 from_char_seq_search(&value, &s, ampm_strings_long,
2560                                                                          ALL_UPPER, n->key->len, n);
2561                                 from_char_set_int(&out->pm, value % 2, n);
2562                                 out->clock = CLOCK_12_HOUR;
2563                                 break;
2564                         case DCH_AM:
2565                         case DCH_PM:
2566                         case DCH_am:
2567                         case DCH_pm:
2568                                 from_char_seq_search(&value, &s, ampm_strings,
2569                                                                          ALL_UPPER, n->key->len, n);
2570                                 from_char_set_int(&out->pm, value % 2, n);
2571                                 out->clock = CLOCK_12_HOUR;
2572                                 break;
2573                         case DCH_HH:
2574                         case DCH_HH12:
2575                                 from_char_parse_int_len(&out->hh, &s, 2, n);
2576                                 out->clock = CLOCK_12_HOUR;
2577                                 s += SKIP_THth(n->suffix);
2578                                 break;
2579                         case DCH_HH24:
2580                                 from_char_parse_int_len(&out->hh, &s, 2, n);
2581                                 s += SKIP_THth(n->suffix);
2582                                 break;
2583                         case DCH_MI:
2584                                 from_char_parse_int(&out->mi, &s, n);
2585                                 s += SKIP_THth(n->suffix);
2586                                 break;
2587                         case DCH_SS:
2588                                 from_char_parse_int(&out->ss, &s, n);
2589                                 s += SKIP_THth(n->suffix);
2590                                 break;
2591                         case DCH_MS:            /* millisecond */
2592                                 len = from_char_parse_int_len(&out->ms, &s, 3, n);
2593
2594                                 /*
2595                                  * 25 is 0.25 and 250 is 0.25 too; 025 is 0.025 and not 0.25
2596                                  */
2597                                 out->ms *= len == 1 ? 100 :
2598                                         len == 2 ? 10 : 1;
2599
2600                                 s += SKIP_THth(n->suffix);
2601                                 break;
2602                         case DCH_US:            /* microsecond */
2603                                 len = from_char_parse_int_len(&out->us, &s, 6, n);
2604
2605                                 out->us *= len == 1 ? 100000 :
2606                                         len == 2 ? 10000 :
2607                                         len == 3 ? 1000 :
2608                                         len == 4 ? 100 :
2609                                         len == 5 ? 10 : 1;
2610
2611                                 s += SKIP_THth(n->suffix);
2612                                 break;
2613                         case DCH_SSSS:
2614                                 from_char_parse_int(&out->ssss, &s, n);
2615                                 s += SKIP_THth(n->suffix);
2616                                 break;
2617                         case DCH_tz:
2618                         case DCH_TZ:
2619                                 ereport(ERROR,
2620                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2621                                                  errmsg("\"TZ\"/\"tz\" format patterns are not supported in to_date")));
2622                         case DCH_A_D:
2623                         case DCH_B_C:
2624                         case DCH_a_d:
2625                         case DCH_b_c:
2626                                 from_char_seq_search(&value, &s, adbc_strings_long,
2627                                                                          ALL_UPPER, n->key->len, n);
2628                                 from_char_set_int(&out->bc, value % 2, n);
2629                                 break;
2630                         case DCH_AD:
2631                         case DCH_BC:
2632                         case DCH_ad:
2633                         case DCH_bc:
2634                                 from_char_seq_search(&value, &s, adbc_strings,
2635                                                                          ALL_UPPER, n->key->len, n);
2636                                 from_char_set_int(&out->bc, value % 2, n);
2637                                 break;
2638                         case DCH_MONTH:
2639                         case DCH_Month:
2640                         case DCH_month:
2641                                 from_char_seq_search(&value, &s, months_full, ONE_UPPER,
2642                                                                          MAX_MONTH_LEN, n);
2643                                 from_char_set_int(&out->mm, value + 1, n);
2644                                 break;
2645                         case DCH_MON:
2646                         case DCH_Mon:
2647                         case DCH_mon:
2648                                 from_char_seq_search(&value, &s, months, ONE_UPPER,
2649                                                                          MAX_MON_LEN, n);
2650                                 from_char_set_int(&out->mm, value + 1, n);
2651                                 break;
2652                         case DCH_MM:
2653                                 from_char_parse_int(&out->mm, &s, n);
2654                                 s += SKIP_THth(n->suffix);
2655                                 break;
2656                         case DCH_DAY:
2657                         case DCH_Day:
2658                         case DCH_day:
2659                                 from_char_seq_search(&value, &s, days, ONE_UPPER,
2660                                                                          MAX_DAY_LEN, n);
2661                                 from_char_set_int(&out->d, value, n);
2662                                 break;
2663                         case DCH_DY:
2664                         case DCH_Dy:
2665                         case DCH_dy:
2666                                 from_char_seq_search(&value, &s, days, ONE_UPPER,
2667                                                                          MAX_DY_LEN, n);
2668                                 from_char_set_int(&out->d, value, n);
2669                                 break;
2670                         case DCH_DDD:
2671                                 from_char_parse_int(&out->ddd, &s, n);
2672                                 s += SKIP_THth(n->suffix);
2673                                 break;
2674                         case DCH_IDDD:
2675                                 from_char_parse_int_len(&out->ddd, &s, 3, n);
2676                                 s += SKIP_THth(n->suffix);
2677                                 break;
2678                         case DCH_DD:
2679                                 from_char_parse_int(&out->dd, &s, n);
2680                                 s += SKIP_THth(n->suffix);
2681                                 break;
2682                         case DCH_D:
2683                                 from_char_parse_int(&out->d, &s, n);
2684                                 out->d--;
2685                                 s += SKIP_THth(n->suffix);
2686                                 break;
2687                         case DCH_ID:
2688                                 from_char_parse_int_len(&out->d, &s, 1, n);
2689                                 s += SKIP_THth(n->suffix);
2690                                 break;
2691                         case DCH_WW:
2692                         case DCH_IW:
2693                                 from_char_parse_int(&out->ww, &s, n);
2694                                 s += SKIP_THth(n->suffix);
2695                                 break;
2696                         case DCH_Q:
2697
2698                                 /*
2699                                  * We ignore 'Q' when converting to date because it is unclear
2700                                  * which date in the quarter to use, and some people specify
2701                                  * both quarter and month, so if it was honored it might
2702                                  * conflict with the supplied month. That is also why we don't
2703                                  * throw an error.
2704                                  *
2705                                  * We still parse the source string for an integer, but it
2706                                  * isn't stored anywhere in 'out'.
2707                                  */
2708                                 from_char_parse_int((int *) NULL, &s, n);
2709                                 s += SKIP_THth(n->suffix);
2710                                 break;
2711                         case DCH_CC:
2712                                 from_char_parse_int(&out->cc, &s, n);
2713                                 s += SKIP_THth(n->suffix);
2714                                 break;
2715                         case DCH_Y_YYY:
2716                                 {
2717                                         int                     matched,
2718                                                                 years,
2719                                                                 millenia;
2720
2721                                         matched = sscanf(s, "%d,%03d", &millenia, &years);
2722                                         if (matched != 2)
2723                                                 ereport(ERROR,
2724                                                                 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2725                                                           errmsg("invalid input string for \"Y,YYY\"")));
2726                                         years += (millenia * 1000);
2727                                         from_char_set_int(&out->year, years, n);
2728                                         out->yysz = 4;
2729                                         s += strdigits_len(s) + 4 + SKIP_THth(n->suffix);
2730                                 }
2731                                 break;
2732                         case DCH_YYYY:
2733                         case DCH_IYYY:
2734                                 from_char_parse_int(&out->year, &s, n);
2735                                 out->yysz = 4;
2736                                 s += SKIP_THth(n->suffix);
2737                                 break;
2738                         case DCH_YYY:
2739                         case DCH_IYY:
2740                                 from_char_parse_int(&out->year, &s, n);
2741                                 out->yysz = 3;
2742
2743                                 /*
2744                                  * 3-digit year: '100' ... '999' = 1100 ... 1999 '000' ...
2745                                  * '099' = 2000 ... 2099
2746                                  */
2747                                 if (out->year >= 100)
2748                                         out->year += 1000;
2749                                 else
2750                                         out->year += 2000;
2751                                 s += SKIP_THth(n->suffix);
2752                                 break;
2753                         case DCH_YY:
2754                         case DCH_IY:
2755                                 from_char_parse_int(&out->year, &s, n);
2756                                 out->yysz = 2;
2757
2758                                 /*
2759                                  * 2-digit year: '00' ... '69'  = 2000 ... 2069 '70' ... '99'
2760                                  * = 1970 ... 1999
2761                                  */
2762                                 if (out->year < 70)
2763                                         out->year += 2000;
2764                                 else
2765                                         out->year += 1900;
2766                                 s += SKIP_THth(n->suffix);
2767                                 break;
2768                         case DCH_Y:
2769                         case DCH_I:
2770                                 from_char_parse_int(&out->year, &s, n);
2771                                 out->yysz = 1;
2772
2773                                 /*
2774                                  * 1-digit year: always +2000
2775                                  */
2776                                 out->year += 2000;
2777                                 s += SKIP_THth(n->suffix);
2778                                 break;
2779                         case DCH_RM:
2780                                 from_char_seq_search(&value, &s, rm_months_upper,
2781                                                                          ALL_UPPER, MAX_RM_LEN, n);
2782                                 from_char_set_int(&out->mm, 12 - value, n);
2783                                 break;
2784                         case DCH_rm:
2785                                 from_char_seq_search(&value, &s, rm_months_lower,
2786                                                                          ALL_LOWER, MAX_RM_LEN, n);
2787                                 from_char_set_int(&out->mm, 12 - value, n);
2788                                 break;
2789                         case DCH_W:
2790                                 from_char_parse_int(&out->w, &s, n);
2791                                 s += SKIP_THth(n->suffix);
2792                                 break;
2793                         case DCH_J:
2794                                 from_char_parse_int(&out->j, &s, n);
2795                                 s += SKIP_THth(n->suffix);
2796                                 break;
2797                 }
2798         }
2799 }
2800
2801 static DCHCacheEntry *
2802 DCH_cache_getnew(char *str)
2803 {
2804         DCHCacheEntry *ent;
2805
2806         /* counter overflow check - paranoia? */
2807         if (DCHCounter >= (INT_MAX - DCH_CACHE_FIELDS - 1))
2808         {
2809                 DCHCounter = 0;
2810
2811                 for (ent = DCHCache; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++)
2812                         ent->age = (++DCHCounter);
2813         }
2814
2815         /*
2816          * If cache is full, remove oldest entry
2817          */
2818         if (n_DCHCache > DCH_CACHE_FIELDS)
2819         {
2820                 DCHCacheEntry *old = DCHCache + 0;
2821
2822 #ifdef DEBUG_TO_FROM_CHAR
2823                 elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
2824 #endif
2825                 for (ent = DCHCache + 1; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++)
2826                 {
2827                         if (ent->age < old->age)
2828                                 old = ent;
2829                 }
2830 #ifdef DEBUG_TO_FROM_CHAR
2831                 elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
2832 #endif
2833                 StrNCpy(old->str, str, DCH_CACHE_SIZE + 1);
2834                 /* old->format fill parser */
2835                 old->age = (++DCHCounter);
2836                 return old;
2837         }
2838         else
2839         {
2840 #ifdef DEBUG_TO_FROM_CHAR
2841                 elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
2842 #endif
2843                 ent = DCHCache + n_DCHCache;
2844                 StrNCpy(ent->str, str, DCH_CACHE_SIZE + 1);
2845                 /* ent->format fill parser */
2846                 ent->age = (++DCHCounter);
2847                 ++n_DCHCache;
2848                 return ent;
2849         }
2850 }
2851
2852 static DCHCacheEntry *
2853 DCH_cache_search(char *str)
2854 {
2855         int                     i;
2856         DCHCacheEntry *ent;
2857
2858         /* counter overflow check - paranoia? */
2859         if (DCHCounter >= (INT_MAX - DCH_CACHE_FIELDS - 1))
2860         {
2861                 DCHCounter = 0;
2862
2863                 for (ent = DCHCache; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++)
2864                         ent->age = (++DCHCounter);
2865         }
2866
2867         for (i = 0, ent = DCHCache; i < n_DCHCache; i++, ent++)
2868         {
2869                 if (strcmp(ent->str, str) == 0)
2870                 {
2871                         ent->age = (++DCHCounter);
2872                         return ent;
2873                 }
2874         }
2875
2876         return NULL;
2877 }
2878
2879 /*
2880  * Format a date/time or interval into a string according to fmt.
2881  * We parse fmt into a list of FormatNodes.  This is then passed to DCH_to_char
2882  * for formatting.
2883  */
2884 static text *
2885 datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
2886 {
2887         FormatNode *format;
2888         char       *fmt_str,
2889                            *result;
2890         bool            incache;
2891         int                     fmt_len;
2892         text       *res;
2893
2894         /*
2895          * Convert fmt to C string
2896          */
2897         fmt_str = text_to_cstring(fmt);
2898         fmt_len = strlen(fmt_str);
2899
2900         /*
2901          * Allocate workspace for result as C string
2902          */
2903         result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
2904         *result = '\0';
2905
2906         /*
2907          * Allocate new memory if format picture is bigger than static cache and
2908          * not use cache (call parser always)
2909          */
2910         if (fmt_len > DCH_CACHE_SIZE)
2911         {
2912                 format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
2913                 incache = FALSE;
2914
2915                 parse_format(format, fmt_str, DCH_keywords,
2916                                          DCH_suff, DCH_index, DCH_TYPE, NULL);
2917
2918                 (format + fmt_len)->type = NODE_TYPE_END;               /* Paranoia? */
2919         }
2920         else
2921         {
2922                 /*
2923                  * Use cache buffers
2924                  */
2925                 DCHCacheEntry *ent;
2926
2927                 incache = TRUE;
2928
2929                 if ((ent = DCH_cache_search(fmt_str)) == NULL)
2930                 {
2931                         ent = DCH_cache_getnew(fmt_str);
2932
2933                         /*
2934                          * Not in the cache, must run parser and save a new format-picture
2935                          * to the cache.
2936                          */
2937                         parse_format(ent->format, fmt_str, DCH_keywords,
2938                                                  DCH_suff, DCH_index, DCH_TYPE, NULL);
2939
2940                         (ent->format + fmt_len)->type = NODE_TYPE_END;          /* Paranoia? */
2941
2942 #ifdef DEBUG_TO_FROM_CHAR
2943                         /* dump_node(ent->format, fmt_len); */
2944                         /* dump_index(DCH_keywords, DCH_index);  */
2945 #endif
2946                 }
2947                 format = ent->format;
2948         }
2949
2950         /* The real work is here */
2951         DCH_to_char(format, is_interval, tmtc, result, collid);
2952
2953         if (!incache)
2954                 pfree(format);
2955
2956         pfree(fmt_str);
2957
2958         /* convert C-string result to TEXT format */
2959         res = cstring_to_text(result);
2960
2961         pfree(result);
2962         return res;
2963 }
2964
2965 /****************************************************************************
2966  *                              Public routines
2967  ***************************************************************************/
2968
2969 /* -------------------
2970  * TIMESTAMP to_char()
2971  * -------------------
2972  */
2973 Datum
2974 timestamp_to_char(PG_FUNCTION_ARGS)
2975 {
2976         Timestamp       dt = PG_GETARG_TIMESTAMP(0);
2977         text       *fmt = PG_GETARG_TEXT_P(1),
2978                            *res;
2979         TmToChar        tmtc;
2980         struct pg_tm *tm;
2981         int                     thisdate;
2982
2983         if ((VARSIZE(fmt) - VARHDRSZ) <= 0 || TIMESTAMP_NOT_FINITE(dt))
2984                 PG_RETURN_NULL();
2985
2986         ZERO_tmtc(&tmtc);
2987         tm = tmtcTm(&tmtc);
2988
2989         if (timestamp2tm(dt, NULL, tm, &tmtcFsec(&tmtc), NULL, NULL) != 0)
2990                 ereport(ERROR,
2991                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2992                                  errmsg("timestamp out of range")));
2993
2994         thisdate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
2995         tm->tm_wday = (thisdate + 1) % 7;
2996         tm->tm_yday = thisdate - date2j(tm->tm_year, 1, 1) + 1;
2997
2998         if (!(res = datetime_to_char_body(&tmtc, fmt, false, PG_GET_COLLATION())))
2999                 PG_RETURN_NULL();
3000
3001         PG_RETURN_TEXT_P(res);
3002 }
3003
3004 Datum
3005 timestamptz_to_char(PG_FUNCTION_ARGS)
3006 {
3007         TimestampTz dt = PG_GETARG_TIMESTAMP(0);
3008         text       *fmt = PG_GETARG_TEXT_P(1),
3009                            *res;
3010         TmToChar        tmtc;
3011         int                     tz;
3012         struct pg_tm *tm;
3013         int                     thisdate;
3014
3015         if ((VARSIZE(fmt) - VARHDRSZ) <= 0 || TIMESTAMP_NOT_FINITE(dt))
3016                 PG_RETURN_NULL();
3017
3018         ZERO_tmtc(&tmtc);
3019         tm = tmtcTm(&tmtc);
3020
3021         if (timestamp2tm(dt, &tz, tm, &tmtcFsec(&tmtc), &tmtcTzn(&tmtc), NULL) != 0)
3022                 ereport(ERROR,
3023                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3024                                  errmsg("timestamp out of range")));
3025
3026         thisdate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3027         tm->tm_wday = (thisdate + 1) % 7;
3028         tm->tm_yday = thisdate - date2j(tm->tm_year, 1, 1) + 1;
3029
3030         if (!(res = datetime_to_char_body(&tmtc, fmt, false, PG_GET_COLLATION())))
3031                 PG_RETURN_NULL();
3032
3033         PG_RETURN_TEXT_P(res);
3034 }
3035
3036
3037 /* -------------------
3038  * INTERVAL to_char()
3039  * -------------------
3040  */
3041 Datum
3042 interval_to_char(PG_FUNCTION_ARGS)
3043 {
3044         Interval   *it = PG_GETARG_INTERVAL_P(0);
3045         text       *fmt = PG_GETARG_TEXT_P(1),
3046                            *res;
3047         TmToChar        tmtc;
3048         struct pg_tm *tm;
3049
3050         if ((VARSIZE(fmt) - VARHDRSZ) <= 0)
3051                 PG_RETURN_NULL();
3052
3053         ZERO_tmtc(&tmtc);
3054         tm = tmtcTm(&tmtc);
3055
3056         if (interval2tm(*it, tm, &tmtcFsec(&tmtc)) != 0)
3057                 PG_RETURN_NULL();
3058
3059         /* wday is meaningless, yday approximates the total span in days */
3060         tm->tm_yday = (tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon) * DAYS_PER_MONTH + tm->tm_mday;
3061
3062         if (!(res = datetime_to_char_body(&tmtc, fmt, true, PG_GET_COLLATION())))
3063                 PG_RETURN_NULL();
3064
3065         PG_RETURN_TEXT_P(res);
3066 }
3067
3068 /* ---------------------
3069  * TO_TIMESTAMP()
3070  *
3071  * Make Timestamp from date_str which is formatted at argument 'fmt'
3072  * ( to_timestamp is reverse to_char() )
3073  * ---------------------
3074  */
3075 Datum
3076 to_timestamp(PG_FUNCTION_ARGS)
3077 {
3078         text       *date_txt = PG_GETARG_TEXT_P(0);
3079         text       *fmt = PG_GETARG_TEXT_P(1);
3080         Timestamp       result;
3081         int                     tz;
3082         struct pg_tm tm;
3083         fsec_t          fsec;
3084
3085         do_to_timestamp(date_txt, fmt, &tm, &fsec);
3086
3087         tz = DetermineTimeZoneOffset(&tm, session_timezone);
3088
3089         if (tm2timestamp(&tm, fsec, &tz, &result) != 0)
3090                 ereport(ERROR,
3091                                 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3092                                  errmsg("timestamp out of range")));
3093
3094         PG_RETURN_TIMESTAMP(result);
3095 }
3096
3097 /* ----------
3098  * TO_DATE
3099  *      Make Date from date_str which is formated at argument 'fmt'
3100  * ----------
3101  */
3102 Datum
3103 to_date(PG_FUNCTION_ARGS)
3104 {
3105         text       *date_txt = PG_GETARG_TEXT_P(0);
3106         text       *fmt = PG_GETARG_TEXT_P(1);
3107         DateADT         result;
3108         struct pg_tm tm;
3109         fsec_t          fsec;
3110
3111         do_to_timestamp(date_txt, fmt, &tm, &fsec);
3112
3113         result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - POSTGRES_EPOCH_JDATE;
3114
3115         PG_RETURN_DATEADT(result);
3116 }
3117
3118 /*
3119  * do_to_timestamp: shared code for to_timestamp and to_date
3120  *
3121  * Parse the 'date_txt' according to 'fmt', return results as a struct pg_tm
3122  * and fractional seconds.
3123  *
3124  * We parse 'fmt' into a list of FormatNodes, which is then passed to
3125  * DCH_from_char to populate a TmFromChar with the parsed contents of
3126  * 'date_txt'.
3127  *
3128  * The TmFromChar is then analysed and converted into the final results in
3129  * struct 'tm' and 'fsec'.
3130  *
3131  * This function does very little error checking, e.g.
3132  * to_timestamp('20096040','YYYYMMDD') works
3133  */
3134 static void
3135 do_to_timestamp(text *date_txt, text *fmt,
3136                                 struct pg_tm * tm, fsec_t *fsec)
3137 {
3138         FormatNode *format;
3139         TmFromChar      tmfc;
3140         int                     fmt_len;
3141
3142         ZERO_tmfc(&tmfc);
3143         ZERO_tm(tm);
3144         *fsec = 0;
3145
3146         fmt_len = VARSIZE_ANY_EXHDR(fmt);
3147
3148         if (fmt_len)
3149         {
3150                 char       *fmt_str;
3151                 char       *date_str;
3152                 bool            incache;
3153
3154                 fmt_str = text_to_cstring(fmt);
3155
3156                 /*
3157                  * Allocate new memory if format picture is bigger than static cache
3158                  * and not use cache (call parser always)
3159                  */
3160                 if (fmt_len > DCH_CACHE_SIZE)
3161                 {
3162                         format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
3163                         incache = FALSE;
3164
3165                         parse_format(format, fmt_str, DCH_keywords,
3166                                                  DCH_suff, DCH_index, DCH_TYPE, NULL);
3167
3168                         (format + fmt_len)->type = NODE_TYPE_END;       /* Paranoia? */
3169                 }
3170                 else
3171                 {
3172                         /*
3173                          * Use cache buffers
3174                          */
3175                         DCHCacheEntry *ent;
3176
3177                         incache = TRUE;
3178
3179                         if ((ent = DCH_cache_search(fmt_str)) == NULL)
3180                         {
3181                                 ent = DCH_cache_getnew(fmt_str);
3182
3183                                 /*
3184                                  * Not in the cache, must run parser and save a new
3185                                  * format-picture to the cache.
3186                                  */
3187                                 parse_format(ent->format, fmt_str, DCH_keywords,
3188                                                          DCH_suff, DCH_index, DCH_TYPE, NULL);
3189
3190                                 (ent->format + fmt_len)->type = NODE_TYPE_END;  /* Paranoia? */
3191 #ifdef DEBUG_TO_FROM_CHAR
3192                                 /* dump_node(ent->format, fmt_len); */
3193                                 /* dump_index(DCH_keywords, DCH_index); */
3194 #endif
3195                         }
3196                         format = ent->format;
3197                 }
3198
3199 #ifdef DEBUG_TO_FROM_CHAR
3200                 /* dump_node(format, fmt_len); */
3201 #endif
3202
3203                 date_str = text_to_cstring(date_txt);
3204
3205                 DCH_from_char(format, date_str, &tmfc);
3206
3207                 pfree(date_str);
3208                 pfree(fmt_str);
3209                 if (!incache)
3210                         pfree(format);
3211         }
3212
3213         DEBUG_TMFC(&tmfc);
3214
3215         /*
3216          * Convert values that user define for FROM_CHAR (to_date/to_timestamp) to
3217          * standard 'tm'
3218          */
3219         if (tmfc.ssss)
3220         {
3221                 int                     x = tmfc.ssss;
3222
3223                 tm->tm_hour = x / SECS_PER_HOUR;
3224                 x %= SECS_PER_HOUR;
3225                 tm->tm_min = x / SECS_PER_MINUTE;
3226                 x %= SECS_PER_MINUTE;
3227                 tm->tm_sec = x;
3228         }
3229
3230         if (tmfc.ss)
3231                 tm->tm_sec = tmfc.ss;
3232         if (tmfc.mi)
3233                 tm->tm_min = tmfc.mi;
3234         if (tmfc.hh)
3235                 tm->tm_hour = tmfc.hh;
3236
3237         if (tmfc.clock == CLOCK_12_HOUR)
3238         {
3239                 if (tm->tm_hour < 1 || tm->tm_hour > 12)
3240                         ereport(ERROR,
3241                                         (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3242                                          errmsg("hour \"%d\" is invalid for the 12-hour clock",
3243                                                         tm->tm_hour),
3244                                          errhint("Use the 24-hour clock, or give an hour between 1 and 12.")));
3245
3246                 if (tmfc.pm && tm->tm_hour < 12)
3247                         tm->tm_hour += 12;
3248                 else if (!tmfc.pm && tm->tm_hour == 12)
3249                         tm->tm_hour = 0;
3250         }
3251
3252         if (tmfc.year)
3253         {
3254                 /*
3255                  * If CC and YY (or Y) are provided, use YY as 2 low-order digits for
3256                  * the year in the given century.  Keep in mind that the 21st century
3257                  * runs from 2001-2100, not 2000-2099.
3258                  *
3259                  * If a 4-digit year is provided, we use that and ignore CC.
3260                  */
3261                 if (tmfc.cc && tmfc.yysz <= 2)
3262                 {
3263                         tm->tm_year = tmfc.year % 100;
3264                         if (tm->tm_year)
3265                                 tm->tm_year += (tmfc.cc - 1) * 100;
3266                         else
3267                                 tm->tm_year = tmfc.cc * 100;
3268                 }
3269                 else
3270                         tm->tm_year = tmfc.year;
3271         }
3272         else if (tmfc.cc)                       /* use first year of century */
3273                 tm->tm_year = (tmfc.cc - 1) * 100 + 1;
3274
3275         if (tmfc.bc)
3276         {
3277                 if (tm->tm_year > 0)
3278                         tm->tm_year = -(tm->tm_year - 1);
3279                 else
3280                         ereport(ERROR,
3281                                         (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3282                                          errmsg("inconsistent use of year %04d and \"BC\"",
3283                                                         tm->tm_year)));
3284         }
3285
3286         if (tmfc.j)
3287                 j2date(tmfc.j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3288
3289         if (tmfc.ww)
3290         {
3291                 if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
3292                 {
3293                         /*
3294                          * If tmfc.d is not set, then the date is left at the beginning of
3295                          * the ISO week (Monday).
3296                          */
3297                         if (tmfc.d)
3298                                 isoweekdate2date(tmfc.ww, tmfc.d, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3299                         else
3300                                 isoweek2date(tmfc.ww, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3301                 }
3302                 else
3303                         tmfc.ddd = (tmfc.ww - 1) * 7 + 1;
3304         }
3305
3306         if (tmfc.w)
3307                 tmfc.dd = (tmfc.w - 1) * 7 + 1;
3308         if (tmfc.d)
3309                 tm->tm_wday = tmfc.d;
3310         if (tmfc.dd)
3311                 tm->tm_mday = tmfc.dd;
3312         if (tmfc.ddd)
3313                 tm->tm_yday = tmfc.ddd;
3314         if (tmfc.mm)
3315                 tm->tm_mon = tmfc.mm;
3316
3317         if (tmfc.ddd && (tm->tm_mon <= 1 || tm->tm_mday <= 1))
3318         {
3319                 /*
3320                  * The month and day field have not been set, so we use the
3321                  * day-of-year field to populate them.  Depending on the date mode,
3322                  * this field may be interpreted as a Gregorian day-of-year, or an ISO
3323                  * week date day-of-year.
3324                  */
3325
3326                 if (!tm->tm_year && !tmfc.bc)
3327                         ereport(ERROR,
3328                                         (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3329                         errmsg("cannot calculate day of year without year information")));
3330
3331                 if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
3332                 {
3333                         int                     j0;             /* zeroth day of the ISO year, in Julian */
3334
3335                         j0 = isoweek2j(tm->tm_year, 1) - 1;
3336
3337                         j2date(j0 + tmfc.ddd, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3338                 }
3339                 else
3340                 {
3341                         const int  *y;
3342                         int                     i;
3343
3344                         static const int ysum[2][13] = {
3345                                 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
3346                         {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
3347
3348                         y = ysum[isleap(tm->tm_year)];
3349
3350                         for (i = 1; i <= 12; i++)
3351                         {
3352                                 if (tmfc.ddd < y[i])
3353                                         break;
3354                         }
3355                         if (tm->tm_mon <= 1)
3356                                 tm->tm_mon = i;
3357
3358                         if (tm->tm_mday <= 1)
3359                                 tm->tm_mday = tmfc.ddd - y[i - 1];
3360                 }
3361         }
3362
3363 #ifdef HAVE_INT64_TIMESTAMP
3364         if (tmfc.ms)
3365                 *fsec += tmfc.ms * 1000;
3366         if (tmfc.us)
3367                 *fsec += tmfc.us;
3368 #else
3369         if (tmfc.ms)
3370                 *fsec += (double) tmfc.ms / 1000;
3371         if (tmfc.us)
3372                 *fsec += (double) tmfc.us / 1000000;
3373 #endif
3374
3375         DEBUG_TM(tm);
3376 }
3377
3378
3379 /**********************************************************************
3380  *      the NUMBER version part
3381  *********************************************************************/
3382
3383
3384 static char *
3385 fill_str(char *str, int c, int max)
3386 {
3387         memset(str, c, max);
3388         *(str + max) = '\0';
3389         return str;
3390 }
3391
3392 #define zeroize_NUM(_n) \
3393 do { \
3394         (_n)->flag              = 0;    \
3395         (_n)->lsign             = 0;    \
3396         (_n)->pre               = 0;    \
3397         (_n)->post              = 0;    \
3398         (_n)->pre_lsign_num = 0;        \
3399         (_n)->need_locale       = 0;    \
3400         (_n)->multi             = 0;    \
3401         (_n)->zero_start        = 0;    \
3402         (_n)->zero_end          = 0;    \
3403 } while(0)
3404
3405 static NUMCacheEntry *
3406 NUM_cache_getnew(char *str)
3407 {
3408         NUMCacheEntry *ent;
3409
3410         /* counter overflow check - paranoia? */
3411         if (NUMCounter >= (INT_MAX - NUM_CACHE_FIELDS - 1))
3412         {
3413                 NUMCounter = 0;
3414
3415                 for (ent = NUMCache; ent <= (NUMCache + NUM_CACHE_FIELDS); ent++)
3416                         ent->age = (++NUMCounter);
3417         }
3418
3419         /*
3420          * If cache is full, remove oldest entry
3421          */
3422         if (n_NUMCache > NUM_CACHE_FIELDS)
3423         {
3424                 NUMCacheEntry *old = NUMCache + 0;
3425
3426 #ifdef DEBUG_TO_FROM_CHAR
3427                 elog(DEBUG_elog_output, "Cache is full (%d)", n_NUMCache);
3428 #endif
3429                 for (ent = NUMCache; ent <= (NUMCache + NUM_CACHE_FIELDS); ent++)
3430                 {
3431                         /*
3432                          * entry removed via NUM_cache_remove() can be used here, which is
3433                          * why it's worth scanning first entry again
3434                          */
3435                         if (ent->str[0] == '\0')
3436                         {
3437                                 old = ent;
3438                                 break;
3439                         }
3440                         if (ent->age < old->age)
3441                                 old = ent;
3442                 }
3443 #ifdef DEBUG_TO_FROM_CHAR
3444                 elog(DEBUG_elog_output, "OLD: \"%s\" AGE: %d", old->str, old->age);
3445 #endif
3446                 StrNCpy(old->str, str, NUM_CACHE_SIZE + 1);
3447                 /* old->format fill parser */
3448                 old->age = (++NUMCounter);
3449                 ent = old;
3450         }
3451         else
3452         {
3453 #ifdef DEBUG_TO_FROM_CHAR
3454                 elog(DEBUG_elog_output, "NEW (%d)", n_NUMCache);
3455 #endif
3456                 ent = NUMCache + n_NUMCache;
3457                 StrNCpy(ent->str, str, NUM_CACHE_SIZE + 1);
3458                 /* ent->format fill parser */
3459                 ent->age = (++NUMCounter);
3460                 ++n_NUMCache;
3461         }
3462
3463         zeroize_NUM(&ent->Num);
3464
3465         last_NUMCacheEntry = ent;
3466         return ent;
3467 }
3468
3469 static NUMCacheEntry *
3470 NUM_cache_search(char *str)
3471 {
3472         int                     i;
3473         NUMCacheEntry *ent;
3474
3475         /* counter overflow check - paranoia? */
3476         if (NUMCounter >= (INT_MAX - NUM_CACHE_FIELDS - 1))
3477         {
3478                 NUMCounter = 0;
3479
3480                 for (ent = NUMCache; ent <= (NUMCache + NUM_CACHE_FIELDS); ent++)
3481                         ent->age = (++NUMCounter);
3482         }
3483
3484         for (i = 0, ent = NUMCache; i < n_NUMCache; i++, ent++)
3485         {
3486                 if (strcmp(ent->str, str) == 0)
3487                 {
3488                         ent->age = (++NUMCounter);
3489                         last_NUMCacheEntry = ent;
3490                         return ent;
3491                 }
3492         }
3493
3494         return NULL;
3495 }
3496
3497 static void
3498 NUM_cache_remove(NUMCacheEntry *ent)
3499 {
3500 #ifdef DEBUG_TO_FROM_CHAR
3501         elog(DEBUG_elog_output, "REMOVING ENTRY (%s)", ent->str);
3502 #endif
3503         ent->str[0] = '\0';
3504         ent->age = 0;
3505 }
3506
3507 /* ----------
3508  * Cache routine for NUM to_char version
3509  * ----------
3510  */
3511 static FormatNode *
3512 NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
3513 {
3514         FormatNode *format = NULL;
3515         char       *str;
3516
3517         str = text_to_cstring(pars_str);
3518
3519         /*
3520          * Allocate new memory if format picture is bigger than static cache and
3521          * not use cache (call parser always). This branches sets shouldFree to
3522          * true, accordingly.
3523          */
3524         if (len > NUM_CACHE_SIZE)
3525         {
3526                 format = (FormatNode *) palloc((len + 1) * sizeof(FormatNode));
3527
3528                 *shouldFree = true;
3529
3530                 zeroize_NUM(Num);
3531
3532                 parse_format(format, str, NUM_keywords,
3533                                          NULL, NUM_index, NUM_TYPE, Num);
3534
3535                 (format + len)->type = NODE_TYPE_END;   /* Paranoia? */
3536         }
3537         else
3538         {
3539                 /*
3540                  * Use cache buffers
3541                  */
3542                 NUMCacheEntry *ent;
3543
3544                 *shouldFree = false;
3545
3546                 if ((ent = NUM_cache_search(str)) == NULL)
3547                 {
3548                         ent = NUM_cache_getnew(str);
3549
3550                         /*
3551                          * Not in the cache, must run parser and save a new format-picture
3552                          * to the cache.
3553                          */
3554                         parse_format(ent->format, str, NUM_keywords,
3555                                                  NULL, NUM_index, NUM_TYPE, &ent->Num);
3556
3557                         (ent->format + len)->type = NODE_TYPE_END;      /* Paranoia? */
3558                 }
3559
3560                 format = ent->format;
3561
3562                 /*
3563                  * Copy cache to used struct
3564                  */
3565                 Num->flag = ent->Num.flag;
3566                 Num->lsign = ent->Num.lsign;
3567                 Num->pre = ent->Num.pre;
3568                 Num->post = ent->Num.post;
3569                 Num->pre_lsign_num = ent->Num.pre_lsign_num;
3570                 Num->need_locale = ent->Num.need_locale;
3571                 Num->multi = ent->Num.multi;
3572                 Num->zero_start = ent->Num.zero_start;
3573                 Num->zero_end = ent->Num.zero_end;
3574         }
3575
3576 #ifdef DEBUG_TO_FROM_CHAR
3577         /* dump_node(format, len); */
3578         dump_index(NUM_keywords, NUM_index);
3579 #endif
3580
3581         pfree(str);
3582         return format;
3583 }
3584
3585
3586 static char *
3587 int_to_roman(int number)
3588 {
3589         int                     len = 0,
3590                                 num = 0;
3591         char       *p = NULL,
3592                            *result,
3593                                 numstr[5];
3594
3595         result = (char *) palloc(16);
3596         *result = '\0';
3597
3598         if (number > 3999 || number < 1)
3599         {
3600                 fill_str(result, '#', 15);
3601                 return result;
3602         }
3603         len = snprintf(numstr, sizeof(numstr), "%d", number);
3604
3605         for (p = numstr; *p != '\0'; p++, --len)
3606         {
3607                 num = *p - 49;                  /* 48 ascii + 1 */
3608                 if (num < 0)
3609                         continue;
3610
3611                 if (len > 3)
3612                 {
3613                         while (num-- != -1)
3614                                 strcat(result, "M");
3615                 }
3616                 else
3617                 {
3618                         if (len == 3)
3619                                 strcat(result, rm100[num]);
3620                         else if (len == 2)
3621                                 strcat(result, rm10[num]);
3622                         else if (len == 1)
3623                                 strcat(result, rm1[num]);
3624                 }
3625         }
3626         return result;
3627 }
3628
3629
3630
3631 /* ----------
3632  * Locale
3633  * ----------
3634  */
3635 static void
3636 NUM_prepare_locale(NUMProc *Np)
3637 {
3638         if (Np->Num->need_locale)
3639         {
3640                 struct lconv *lconv;
3641
3642                 /*
3643                  * Get locales
3644                  */
3645                 lconv = PGLC_localeconv();
3646
3647                 /*
3648                  * Positive / Negative number sign
3649                  */
3650                 if (lconv->negative_sign && *lconv->negative_sign)
3651                         Np->L_negative_sign = lconv->negative_sign;
3652                 else
3653                         Np->L_negative_sign = "-";
3654
3655                 if (lconv->positive_sign && *lconv->positive_sign)
3656                         Np->L_positive_sign = lconv->positive_sign;
3657                 else
3658                         Np->L_positive_sign = "+";
3659
3660                 /*
3661                  * Number decimal point
3662                  */
3663                 if (lconv->decimal_point && *lconv->decimal_point)
3664                         Np->decimal = lconv->decimal_point;
3665
3666                 else
3667                         Np->decimal = ".";
3668
3669                 if (!IS_LDECIMAL(Np->Num))
3670                         Np->decimal = ".";
3671
3672                 /*
3673                  * Number thousands separator
3674                  *
3675                  * Some locales (e.g. broken glibc pt_BR), have a comma for decimal,
3676                  * but "" for thousands_sep, so we set the thousands_sep too.
3677                  * http://archives.postgresql.org/pgsql-hackers/2007-11/msg00772.php
3678                  */
3679                 if (lconv->thousands_sep && *lconv->thousands_sep)
3680                         Np->L_thousands_sep = lconv->thousands_sep;
3681                 /* Make sure thousands separator doesn't match decimal point symbol. */
3682                 else if (strcmp(Np->decimal, ",") !=0)
3683                         Np->L_thousands_sep = ",";
3684                 else
3685                         Np->L_thousands_sep = ".";
3686
3687                 /*
3688                  * Currency symbol
3689                  */
3690                 if (lconv->currency_symbol && *lconv->currency_symbol)
3691                         Np->L_currency_symbol = lconv->currency_symbol;
3692                 else
3693                         Np->L_currency_symbol = " ";
3694         }
3695         else
3696         {
3697                 /*
3698                  * Default values
3699                  */
3700                 Np->L_negative_sign = "-";
3701                 Np->L_positive_sign = "+";
3702                 Np->decimal = ".";
3703
3704                 Np->L_thousands_sep = ",";
3705                 Np->L_currency_symbol = " ";
3706         }
3707 }
3708
3709 /* ----------
3710  * Return pointer of last relevant number after decimal point
3711  *      12.0500 --> last relevant is '5'
3712  * ----------
3713  */
3714 static char *
3715 get_last_relevant_decnum(char *num)
3716 {
3717         char       *result,
3718                            *p = strchr(num, '.');
3719
3720 #ifdef DEBUG_TO_FROM_CHAR
3721         elog(DEBUG_elog_output, "get_last_relevant_decnum()");
3722 #endif
3723
3724         if (!p)
3725                 p = num;
3726         result = p;
3727
3728         while (*(++p))
3729         {
3730                 if (*p != '0')
3731                         result = p;
3732         }
3733
3734         return result;
3735 }
3736
3737 /* ----------
3738  * Number extraction for TO_NUMBER()
3739  * ----------
3740  */
3741 static void
3742 NUM_numpart_from_char(NUMProc *Np, int id, int plen)
3743 {
3744         bool            isread = FALSE;
3745
3746 #ifdef DEBUG_TO_FROM_CHAR
3747         elog(DEBUG_elog_output, " --- scan start --- id=%s",
3748                  (id == NUM_0 || id == NUM_9) ? "NUM_0/9" : id == NUM_DEC ? "NUM_DEC" : "???");
3749 #endif
3750
3751         if (*Np->inout_p == ' ')
3752                 Np->inout_p++;
3753
3754 #define OVERLOAD_TEST   (Np->inout_p >= Np->inout + plen)
3755 #define AMOUNT_TEST(_s) (plen-(Np->inout_p-Np->inout) >= _s)
3756
3757         if (*Np->inout_p == ' ')
3758                 Np->inout_p++;
3759
3760         if (OVERLOAD_TEST)
3761                 return;
3762
3763         /*
3764          * read sign before number
3765          */
3766         if (*Np->number == ' ' && (id == NUM_0 || id == NUM_9) &&
3767                 (Np->read_pre + Np->read_post) == 0)
3768         {
3769 #ifdef DEBUG_TO_FROM_CHAR
3770                 elog(DEBUG_elog_output, "Try read sign (%c), locale positive: %s, negative: %s",
3771                          *Np->inout_p, Np->L_positive_sign, Np->L_negative_sign);
3772 #endif
3773
3774                 /*
3775                  * locale sign
3776                  */
3777                 if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_PRE)
3778                 {
3779                         int                     x = 0;
3780
3781 #ifdef DEBUG_TO_FROM_CHAR
3782                         elog(DEBUG_elog_output, "Try read locale pre-sign (%c)", *Np->inout_p);
3783 #endif
3784                         if ((x = strlen(Np->L_negative_sign)) &&
3785                                 AMOUNT_TEST(x) &&
3786                                 strncmp(Np->inout_p, Np->L_negative_sign, x) == 0)
3787                         {
3788                                 Np->inout_p += x;
3789                                 *Np->number = '-';
3790                         }
3791                         else if ((x = strlen(Np->L_positive_sign)) &&
3792                                          AMOUNT_TEST(x) &&
3793                                          strncmp(Np->inout_p, Np->L_positive_sign, x) == 0)
3794                         {
3795                                 Np->inout_p += x;
3796                                 *Np->number = '+';
3797                         }
3798                 }
3799                 else
3800                 {
3801 #ifdef DEBUG_TO_FROM_CHAR
3802                         elog(DEBUG_elog_output, "Try read simple sign (%c)", *Np->inout_p);
3803 #endif
3804
3805                         /*
3806                          * simple + - < >
3807                          */
3808                         if (*Np->inout_p == '-' || (IS_BRACKET(Np->Num) &&
3809                                                                                 *Np->inout_p == '<'))
3810                         {
3811                                 *Np->number = '-';              /* set - */
3812                                 Np->inout_p++;
3813                         }
3814                         else if (*Np->inout_p == '+')
3815                         {
3816                                 *Np->number = '+';              /* set + */
3817                                 Np->inout_p++;
3818                         }
3819                 }
3820         }
3821
3822         if (OVERLOAD_TEST)
3823                 return;
3824
3825 #ifdef DEBUG_TO_FROM_CHAR
3826         elog(DEBUG_elog_output, "Scan for numbers (%c), current number: '%s'", *Np->inout_p, Np->number);
3827 #endif
3828
3829         /*
3830          * read digit
3831          */
3832         if (isdigit((unsigned char) *Np->inout_p))
3833         {
3834                 if (Np->read_dec && Np->read_post == Np->Num->post)
3835                         return;
3836
3837                 *Np->number_p = *Np->inout_p;
3838                 Np->number_p++;
3839
3840                 if (Np->read_dec)
3841                         Np->read_post++;
3842                 else
3843                         Np->read_pre++;
3844
3845                 isread = TRUE;
3846
3847 #ifdef DEBUG_TO_FROM_CHAR
3848                 elog(DEBUG_elog_output, "Read digit (%c)", *Np->inout_p);
3849 #endif
3850
3851                 /*
3852                  * read decimal point
3853                  */
3854         }
3855         else if (IS_DECIMAL(Np->Num) && Np->read_dec == FALSE)
3856         {
3857 #ifdef DEBUG_TO_FROM_CHAR
3858                 elog(DEBUG_elog_output, "Try read decimal point (%c)", *Np->inout_p);
3859 #endif
3860                 if (*Np->inout_p == '.')
3861                 {
3862                         *Np->number_p = '.';
3863                         Np->number_p++;
3864                         Np->read_dec = TRUE;
3865                         isread = TRUE;
3866                 }
3867                 else
3868                 {
3869                         int                     x = strlen(Np->decimal);
3870
3871 #ifdef DEBUG_TO_FROM_CHAR
3872                         elog(DEBUG_elog_output, "Try read locale point (%c)",
3873                                  *Np->inout_p);
3874 #endif
3875                         if (x && AMOUNT_TEST(x) && strncmp(Np->inout_p, Np->decimal, x) == 0)
3876                         {
3877                                 Np->inout_p += x - 1;
3878                                 *Np->number_p = '.';
3879                                 Np->number_p++;
3880                                 Np->read_dec = TRUE;
3881                                 isread = TRUE;
3882                         }
3883                 }
3884         }
3885
3886         if (OVERLOAD_TEST)
3887                 return;
3888
3889         /*
3890          * Read sign behind "last" number
3891          *
3892          * We need sign detection because determine exact position of post-sign is
3893          * difficult:
3894          *
3895          * FM9999.9999999S         -> 123.001- 9.9S                        -> .5- FM9.999999MI ->
3896          * 5.01-
3897          */
3898         if (*Np->number == ' ' && Np->read_pre + Np->read_post > 0)
3899         {
3900                 /*
3901                  * locale sign (NUM_S) is always anchored behind a last number, if: -
3902                  * locale sign expected - last read char was NUM_0/9 or NUM_DEC - and
3903                  * next char is not digit
3904                  */
3905                 if (IS_LSIGN(Np->Num) && isread &&
3906                         (Np->inout_p + 1) <= Np->inout + plen &&
3907                         !isdigit((unsigned char) *(Np->inout_p + 1)))
3908                 {
3909                         int                     x;
3910                         char       *tmp = Np->inout_p++;
3911
3912 #ifdef DEBUG_TO_FROM_CHAR
3913                         elog(DEBUG_elog_output, "Try read locale post-sign (%c)", *Np->inout_p);
3914 #endif
3915                         if ((x = strlen(Np->L_negative_sign)) &&
3916                                 AMOUNT_TEST(x) &&
3917                                 strncmp(Np->inout_p, Np->L_negative_sign, x) == 0)
3918                         {
3919                                 Np->inout_p += x - 1;   /* -1 .. NUM_processor() do inout_p++ */
3920                                 *Np->number = '-';
3921                         }
3922                         else if ((x = strlen(Np->L_positive_sign)) &&
3923                                          AMOUNT_TEST(x) &&
3924                                          strncmp(Np->inout_p, Np->L_positive_sign, x) == 0)
3925                         {
3926                                 Np->inout_p += x - 1;   /* -1 .. NUM_processor() do inout_p++ */
3927                                 *Np->number = '+';
3928                         }
3929                         if (*Np->number == ' ')
3930                                 /* no sign read */
3931                                 Np->inout_p = tmp;
3932                 }
3933
3934                 /*
3935                  * try read non-locale sign, it's happen only if format is not exact
3936                  * and we cannot determine sign position of MI/PL/SG, an example:
3937                  *
3938                  * FM9.999999MI                    -> 5.01-
3939                  *
3940                  * if (.... && IS_LSIGN(Np->Num)==FALSE) prevents read wrong formats
3941                  * like to_number('1 -', '9S') where sign is not anchored to last
3942                  * number.
3943                  */
3944                 else if (isread == FALSE && IS_LSIGN(Np->Num) == FALSE &&
3945                                  (IS_PLUS(Np->Num) || IS_MINUS(Np->Num)))
3946                 {
3947 #ifdef DEBUG_TO_FROM_CHAR
3948                         elog(DEBUG_elog_output, "Try read simple post-sign (%c)", *Np->inout_p);
3949 #endif
3950
3951                         /*
3952                          * simple + -
3953                          */
3954                         if (*Np->inout_p == '-' || *Np->inout_p == '+')
3955                                 /* NUM_processor() do inout_p++ */
3956                                 *Np->number = *Np->inout_p;
3957                 }
3958         }
3959 }
3960
3961 #define IS_PREDEC_SPACE(_n) \
3962                 (IS_ZERO((_n)->Num)==FALSE && \
3963                  (_n)->number == (_n)->number_p && \
3964                  *(_n)->number == '0' && \
3965                                  (_n)->Num->post != 0)
3966
3967 /* ----------
3968  * Add digit or sign to number-string
3969  * ----------
3970  */
3971 static void
3972 NUM_numpart_to_char(NUMProc *Np, int id)
3973 {
3974         int                     end;
3975
3976         if (IS_ROMAN(Np->Num))
3977                 return;
3978
3979         /* Note: in this elog() output not set '\0' in 'inout' */
3980
3981 #ifdef DEBUG_TO_FROM_CHAR
3982
3983         /*
3984          * Np->num_curr is number of current item in format-picture, it is not
3985          * current position in inout!
3986          */
3987         elog(DEBUG_elog_output,
3988                  "SIGN_WROTE: %d, CURRENT: %d, NUMBER_P: \"%s\", INOUT: \"%s\"",
3989                  Np->sign_wrote,
3990                  Np->num_curr,
3991                  Np->number_p,
3992                  Np->inout);
3993 #endif
3994         Np->num_in = FALSE;
3995
3996         /*
3997          * Write sign if real number will write to output Note: IS_PREDEC_SPACE()
3998          * handle "9.9" --> " .1"
3999          */
4000         if (Np->sign_wrote == FALSE &&
4001                 (Np->num_curr >= Np->num_pre || (IS_ZERO(Np->Num) && Np->Num->zero_start == Np->num_curr)) &&
4002                 (IS_PREDEC_SPACE(Np) == FALSE || (Np->last_relevant && *Np->last_relevant == '.')))
4003         {
4004                 if (IS_LSIGN(Np->Num))
4005                 {
4006                         if (Np->Num->lsign == NUM_LSIGN_PRE)
4007                         {
4008                                 if (Np->sign == '-')
4009                                         strcpy(Np->inout_p, Np->L_negative_sign);
4010                                 else
4011                                         strcpy(Np->inout_p, Np->L_positive_sign);
4012                                 Np->inout_p += strlen(Np->inout_p);
4013                                 Np->sign_wrote = TRUE;
4014                         }
4015                 }
4016                 else if (IS_BRACKET(Np->Num))
4017                 {
4018                         *Np->inout_p = Np->sign == '+' ? ' ' : '<';
4019                         ++Np->inout_p;
4020                         Np->sign_wrote = TRUE;
4021                 }
4022                 else if (Np->sign == '+')
4023                 {
4024                         if (!IS_FILLMODE(Np->Num))
4025                         {
4026                                 *Np->inout_p = ' ';             /* Write + */
4027                                 ++Np->inout_p;
4028                         }
4029                         Np->sign_wrote = TRUE;
4030                 }
4031                 else if (Np->sign == '-')
4032                 {                                               /* Write - */
4033                         *Np->inout_p = '-';
4034                         ++Np->inout_p;
4035                         Np->sign_wrote = TRUE;
4036                 }
4037         }
4038
4039
4040         /*
4041          * digits / FM / Zero / Dec. point
4042          */
4043         if (id == NUM_9 || id == NUM_0 || id == NUM_D || id == NUM_DEC)
4044         {
4045                 if (Np->num_curr < Np->num_pre &&
4046                         (Np->Num->zero_start > Np->num_curr || !IS_ZERO(Np->Num)))
4047                 {
4048                         /*
4049                          * Write blank space
4050                          */
4051                         if (!IS_FILLMODE(Np->Num))
4052                         {
4053                                 *Np->inout_p = ' ';             /* Write ' ' */
4054                                 ++Np->inout_p;
4055                         }
4056                 }
4057                 else if (IS_ZERO(Np->Num) &&
4058                                  Np->num_curr < Np->num_pre &&
4059                                  Np->Num->zero_start <= Np->num_curr)
4060                 {
4061                         /*
4062                          * Write ZERO
4063                          */
4064                         *Np->inout_p = '0'; /* Write '0' */
4065                         ++Np->inout_p;
4066                         Np->num_in = TRUE;
4067                 }
4068                 else
4069                 {
4070                         /*
4071                          * Write Decimal point
4072                          */
4073                         if (*Np->number_p == '.')
4074                         {
4075                                 if (!Np->last_relevant || *Np->last_relevant != '.')
4076                                 {
4077                                         strcpy(Np->inout_p, Np->decimal);       /* Write DEC/D */
4078                                         Np->inout_p += strlen(Np->inout_p);
4079                                 }
4080
4081                                 /*
4082                                  * Ora 'n' -- FM9.9 --> 'n.'
4083                                  */
4084                                 else if (IS_FILLMODE(Np->Num) &&
4085                                                  Np->last_relevant && *Np->last_relevant == '.')
4086                                 {
4087                                         strcpy(Np->inout_p, Np->decimal);       /* Write DEC/D */
4088                                         Np->inout_p += strlen(Np->inout_p);
4089                                 }
4090                         }
4091                         else
4092                         {
4093                                 /*
4094                                  * Write Digits
4095                                  */
4096                                 if (Np->last_relevant && Np->number_p > Np->last_relevant &&
4097                                         id != NUM_0)
4098                                         ;
4099
4100                                 /*
4101                                  * '0.1' -- 9.9 --> '  .1'
4102                                  */
4103                                 else if (IS_PREDEC_SPACE(Np))
4104                                 {
4105                                         if (!IS_FILLMODE(Np->Num))
4106                                         {
4107                                                 *Np->inout_p = ' ';
4108                                                 ++Np->inout_p;
4109                                         }
4110
4111                                         /*
4112                                          * '0' -- FM9.9 --> '0.'
4113                                          */
4114                                         else if (Np->last_relevant && *Np->last_relevant == '.')
4115                                         {
4116                                                 *Np->inout_p = '0';
4117                                                 ++Np->inout_p;
4118                                         }
4119                                 }
4120                                 else
4121                                 {
4122                                         *Np->inout_p = *Np->number_p;           /* Write DIGIT */
4123                                         ++Np->inout_p;
4124                                         Np->num_in = TRUE;
4125                                 }
4126                         }
4127                         ++Np->number_p;
4128                 }
4129
4130                 end = Np->num_count + (Np->num_pre ? 1 : 0) + (IS_DECIMAL(Np->Num) ? 1 : 0);
4131
4132                 if (Np->last_relevant && Np->last_relevant == Np->number_p)
4133                         end = Np->num_curr;
4134
4135                 if (Np->num_curr + 1 == end)
4136                 {
4137                         if (Np->sign_wrote == TRUE && IS_BRACKET(Np->Num))
4138                         {
4139                                 *Np->inout_p = Np->sign == '+' ? ' ' : '>';
4140                                 ++Np->inout_p;
4141                         }
4142                         else if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_POST)
4143                         {
4144                                 if (Np->sign == '-')
4145                                         strcpy(Np->inout_p, Np->L_negative_sign);
4146                                 else
4147                                         strcpy(Np->inout_p, Np->L_positive_sign);
4148                                 Np->inout_p += strlen(Np->inout_p);
4149                         }
4150                 }
4151         }
4152
4153         ++Np->num_curr;
4154 }
4155
4156 /*
4157  * Note: 'plen' is used in FROM_CHAR conversion and it's length of
4158  * input (inout). In TO_CHAR conversion it's space before first number.
4159  */
4160 static char *
4161 NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
4162                           int plen, int sign, bool is_to_char, Oid collid)
4163 {
4164         FormatNode *n;
4165         NUMProc         _Np,
4166                            *Np = &_Np;
4167
4168         MemSet(Np, 0, sizeof(NUMProc));
4169
4170         Np->Num = Num;
4171         Np->is_to_char = is_to_char;
4172         Np->number = number;
4173         Np->inout = inout;
4174         Np->last_relevant = NULL;
4175         Np->read_post = 0;
4176         Np->read_pre = 0;
4177         Np->read_dec = FALSE;
4178
4179         if (Np->Num->zero_start)
4180                 --Np->Num->zero_start;
4181
4182         if (IS_EEEE(Np->Num))
4183         {
4184                 if (!Np->is_to_char)
4185                         ereport(ERROR,
4186                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4187                                          errmsg("\"EEEE\" not supported for input")));
4188                 return strcpy(inout, number);
4189         }
4190
4191         /*
4192          * Roman correction
4193          */
4194         if (IS_ROMAN(Np->Num))
4195         {
4196                 if (!Np->is_to_char)
4197                         ereport(ERROR,
4198                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4199                                          errmsg("\"RN\" not supported for input")));
4200
4201                 Np->Num->lsign = Np->Num->pre_lsign_num = Np->Num->post =
4202                         Np->Num->pre = Np->num_pre = Np->sign = 0;
4203
4204                 if (IS_FILLMODE(Np->Num))
4205                 {
4206                         Np->Num->flag = 0;
4207                         Np->Num->flag |= NUM_F_FILLMODE;
4208                 }
4209                 else
4210                         Np->Num->flag = 0;
4211                 Np->Num->flag |= NUM_F_ROMAN;
4212         }
4213
4214         /*
4215          * Sign
4216          */
4217         if (is_to_char)
4218         {
4219                 Np->sign = sign;
4220
4221                 /* MI/PL/SG - write sign itself and not in number */
4222                 if (IS_PLUS(Np->Num) || IS_MINUS(Np->Num))
4223                 {
4224                         if (IS_PLUS(Np->Num) && IS_MINUS(Np->Num) == FALSE)
4225                                 Np->sign_wrote = FALSE; /* need sign */
4226                         else
4227                                 Np->sign_wrote = TRUE;  /* needn't sign */
4228                 }
4229                 else
4230                 {
4231                         if (Np->sign != '-')
4232                         {
4233                                 if (IS_BRACKET(Np->Num) && IS_FILLMODE(Np->Num))
4234                                         Np->Num->flag &= ~NUM_F_BRACKET;
4235                                 if (IS_MINUS(Np->Num))
4236                                         Np->Num->flag &= ~NUM_F_MINUS;
4237                         }
4238                         else if (Np->sign != '+' && IS_PLUS(Np->Num))
4239                                 Np->Num->flag &= ~NUM_F_PLUS;
4240
4241                         if (Np->sign == '+' && IS_FILLMODE(Np->Num) && IS_LSIGN(Np->Num) == FALSE)
4242                                 Np->sign_wrote = TRUE;  /* needn't sign */
4243                         else
4244                                 Np->sign_wrote = FALSE; /* need sign */
4245
4246                         if (Np->Num->lsign == NUM_LSIGN_PRE && Np->Num->pre == Np->Num->pre_lsign_num)
4247                                 Np->Num->lsign = NUM_LSIGN_POST;
4248                 }
4249         }
4250         else
4251                 Np->sign = FALSE;
4252
4253         /*
4254          * Count
4255          */
4256         Np->num_count = Np->Num->post + Np->Num->pre - 1;
4257
4258         if (is_to_char)
4259         {
4260                 Np->num_pre = plen;
4261
4262                 if (IS_FILLMODE(Np->Num))
4263                 {
4264                         if (IS_DECIMAL(Np->Num))
4265                                 Np->last_relevant = get_last_relevant_decnum(
4266                                                                                                                          Np->number +
4267                                                                          ((Np->Num->zero_end - Np->num_pre > 0) ?
4268                                                                           Np->Num->zero_end - Np->num_pre : 0));
4269                 }
4270
4271                 if (Np->sign_wrote == FALSE && Np->num_pre == 0)
4272                         ++Np->num_count;
4273         }
4274         else
4275         {
4276                 Np->num_pre = 0;
4277                 *Np->number = ' ';              /* sign space */
4278                 *(Np->number + 1) = '\0';
4279         }
4280
4281         Np->num_in = 0;
4282         Np->num_curr = 0;
4283
4284 #ifdef DEBUG_TO_FROM_CHAR
4285         elog(DEBUG_elog_output,
4286                  "\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",
4287                  Np->sign,
4288                  Np->number,
4289                  Np->Num->pre,
4290                  Np->Num->post,
4291                  Np->num_count,
4292                  Np->num_pre,
4293                  Np->sign_wrote ? "Yes" : "No",
4294                  IS_ZERO(Np->Num) ? "Yes" : "No",
4295                  Np->Num->zero_start,
4296                  Np->Num->zero_end,
4297                  Np->last_relevant ? Np->last_relevant : "<not set>",
4298                  IS_BRACKET(Np->Num) ? "Yes" : "No",
4299                  IS_PLUS(Np->Num) ? "Yes" : "No",
4300                  IS_MINUS(Np->Num) ? "Yes" : "No",
4301                  IS_FILLMODE(Np->Num) ? "Yes" : "No",
4302                  IS_ROMAN(Np->Num) ? "Yes" : "No",
4303                  IS_EEEE(Np->Num) ? "Yes" : "No"
4304                 );
4305 #endif
4306
4307         /*
4308          * Locale
4309          */
4310         NUM_prepare_locale(Np);
4311
4312         /*
4313          * Processor direct cycle
4314          */
4315         if (Np->is_to_char)
4316                 Np->number_p = Np->number;
4317         else
4318                 Np->number_p = Np->number + 1;  /* first char is space for sign */
4319
4320         for (n = node, Np->inout_p = Np->inout; n->type != NODE_TYPE_END; n++)
4321         {
4322                 if (!Np->is_to_char)
4323                 {
4324                         /*
4325                          * Check non-string inout end
4326                          */
4327                         if (Np->inout_p >= Np->inout + plen)
4328                                 break;
4329                 }
4330
4331                 /*
4332                  * Format pictures actions
4333                  */
4334                 if (n->type == NODE_TYPE_ACTION)
4335                 {
4336                         /*
4337                          * Create/reading digit/zero/blank/sing
4338                          *
4339                          * 'NUM_S' note: The locale sign is anchored to number and we
4340                          * read/write it when we work with first or last number
4341                          * (NUM_0/NUM_9). This is reason why NUM_S missing in follow
4342                          * switch().
4343                          */
4344                         switch (n->key->id)
4345                         {
4346                                 case NUM_9:
4347                                 case NUM_0:
4348                                 case NUM_DEC:
4349                                 case NUM_D:
4350                                         if (Np->is_to_char)
4351                                         {
4352                                                 NUM_numpart_to_char(Np, n->key->id);
4353                                                 continue;               /* for() */
4354                                         }
4355                                         else
4356                                         {
4357                                                 NUM_numpart_from_char(Np, n->key->id, plen);
4358                                                 break;  /* switch() case: */
4359                                         }
4360
4361                                 case NUM_COMMA:
4362                                         if (Np->is_to_char)
4363                                         {
4364                                                 if (!Np->num_in)
4365                                                 {
4366                                                         if (IS_FILLMODE(Np->Num))
4367                                                                 continue;
4368                                                         else
4369                                                                 *Np->inout_p = ' ';
4370                                                 }
4371                                                 else
4372                                                         *Np->inout_p = ',';
4373                                         }
4374                                         else
4375                                         {
4376                                                 if (!Np->num_in)
4377                                                 {
4378                                                         if (IS_FILLMODE(Np->Num))
4379                                                                 continue;
4380                                                 }
4381                                         }
4382                                         break;
4383
4384                                 case NUM_G:
4385                                         if (Np->is_to_char)
4386                                         {
4387                                                 if (!Np->num_in)
4388                                                 {
4389                                                         if (IS_FILLMODE(Np->Num))
4390                                                                 continue;
4391                                                         else
4392                                                         {
4393                                                                 int                     x = strlen(Np->L_thousands_sep);
4394
4395                                                                 memset(Np->inout_p, ' ', x);
4396                                                                 Np->inout_p += x - 1;
4397                                                         }
4398                                                 }
4399                                                 else
4400                                                 {
4401                                                         strcpy(Np->inout_p, Np->L_thousands_sep);
4402                                                         Np->inout_p += strlen(Np->inout_p) - 1;
4403                                                 }
4404                                         }
4405                                         else
4406                                         {
4407                                                 if (!Np->num_in)
4408                                                 {
4409                                                         if (IS_FILLMODE(Np->Num))
4410                                                                 continue;
4411                                                 }
4412                                                 Np->inout_p += strlen(Np->L_thousands_sep) - 1;
4413                                         }
4414                                         break;
4415
4416                                 case NUM_L:
4417                                         if (Np->is_to_char)
4418                                         {
4419                                                 strcpy(Np->inout_p, Np->L_currency_symbol);
4420                                                 Np->inout_p += strlen(Np->inout_p) - 1;
4421                                         }
4422                                         else
4423                                                 Np->inout_p += strlen(Np->L_currency_symbol) - 1;
4424                                         break;
4425
4426                                 case NUM_RN:
4427                                         if (IS_FILLMODE(Np->Num))
4428                                         {
4429                                                 strcpy(Np->inout_p, Np->number_p);
4430                                                 Np->inout_p += strlen(Np->inout_p) - 1;
4431                                         }
4432                                         else
4433                                         {
4434                                                 sprintf(Np->inout_p, "%15s", Np->number_p);
4435                                                 Np->inout_p += strlen(Np->inout_p) - 1;
4436                                         }
4437                                         break;
4438
4439                                 case NUM_rn:
4440                                         if (IS_FILLMODE(Np->Num))
4441                                         {
4442                                                 strcpy(Np->inout_p, str_tolower_z(Np->number_p, collid));
4443                                                 Np->inout_p += strlen(Np->inout_p) - 1;
4444                                         }
4445                                         else
4446                                         {
4447                                                 sprintf(Np->inout_p, "%15s", str_tolower_z(Np->number_p, collid));
4448                                                 Np->inout_p += strlen(Np->inout_p) - 1;
4449                                         }
4450                                         break;
4451
4452                                 case NUM_th:
4453                                         if (IS_ROMAN(Np->Num) || *Np->number == '#' ||
4454                                                 Np->sign == '-' || IS_DECIMAL(Np->Num))
4455                                                 continue;
4456
4457                                         if (Np->is_to_char)
4458                                                 strcpy(Np->inout_p, get_th(Np->number, TH_LOWER));
4459                                         Np->inout_p += 1;
4460                                         break;
4461
4462                                 case NUM_TH:
4463                                         if (IS_ROMAN(Np->Num) || *Np->number == '#' ||
4464                                                 Np->sign == '-' || IS_DECIMAL(Np->Num))
4465                                                 continue;
4466
4467                                         if (Np->is_to_char)
4468                                                 strcpy(Np->inout_p, get_th(Np->number, TH_UPPER));
4469                                         Np->inout_p += 1;
4470                                         break;
4471
4472                                 case NUM_MI:
4473                                         if (Np->is_to_char)
4474                                         {
4475                                                 if (Np->sign == '-')
4476                                                         *Np->inout_p = '-';
4477                                                 else if (IS_FILLMODE(Np->Num))
4478                                                         continue;
4479                                                 else
4480                                                         *Np->inout_p = ' ';
4481                                         }
4482                                         else
4483                                         {
4484                                                 if (*Np->inout_p == '-')
4485                                                         *Np->number = '-';
4486                                         }
4487                                         break;
4488
4489                                 case NUM_PL:
4490                                         if (Np->is_to_char)
4491                                         {
4492                                                 if (Np->sign == '+')
4493                                                         *Np->inout_p = '+';
4494                                                 else if (IS_FILLMODE(Np->Num))
4495                                                         continue;
4496                                                 else
4497                                                         *Np->inout_p = ' ';
4498                                         }
4499                                         else
4500                                         {
4501                                                 if (*Np->inout_p == '+')
4502                                                         *Np->number = '+';
4503                                         }
4504                                         break;
4505
4506                                 case NUM_SG:
4507                                         if (Np->is_to_char)
4508                                                 *Np->inout_p = Np->sign;
4509
4510                                         else
4511                                         {
4512                                                 if (*Np->inout_p == '-')
4513                                                         *Np->number = '-';
4514                                                 else if (*Np->inout_p == '+')
4515                                                         *Np->number = '+';
4516                                         }
4517                                         break;
4518
4519
4520                                 default:
4521                                         continue;
4522                                         break;
4523                         }
4524                 }
4525                 else
4526                 {
4527                         /*
4528                          * Remove to output char from input in TO_CHAR
4529                          */
4530                         if (Np->is_to_char)
4531                                 *Np->inout_p = n->character;
4532                 }
4533                 Np->inout_p++;
4534         }
4535
4536         if (Np->is_to_char)
4537         {
4538                 *Np->inout_p = '\0';
4539                 return Np->inout;
4540         }
4541         else
4542         {
4543                 if (*(Np->number_p - 1) == '.')
4544                         *(Np->number_p - 1) = '\0';
4545                 else
4546                         *Np->number_p = '\0';
4547
4548                 /*
4549                  * Correction - precision of dec. number
4550                  */
4551                 Np->Num->post = Np->read_post;
4552
4553 #ifdef DEBUG_TO_FROM_CHAR
4554                 elog(DEBUG_elog_output, "TO_NUMBER (number): '%s'", Np->number);
4555 #endif
4556                 return Np->number;
4557         }
4558 }
4559
4560 /* ----------
4561  * MACRO: Start part of NUM - for all NUM's to_char variants
4562  *      (sorry, but I hate copy same code - macro is better..)
4563  * ----------
4564  */
4565 #define NUM_TOCHAR_prepare \
4566 do { \
4567         len = VARSIZE_ANY_EXHDR(fmt); \
4568         if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ)             \
4569                 PG_RETURN_TEXT_P(cstring_to_text("")); \
4570         result  = (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ);    \
4571         format  = NUM_cache(len, &Num, fmt, &shouldFree);               \
4572 } while (0)
4573
4574 /* ----------
4575  * MACRO: Finish part of NUM
4576  * ----------
4577  */
4578 #define NUM_TOCHAR_finish \
4579 do { \
4580         NUM_processor(format, &Num, VARDATA(result), numstr, plen, sign, true, PG_GET_COLLATION()); \
4581                                                                         \
4582         if (shouldFree)                                 \
4583                 pfree(format);                          \
4584                                                                         \
4585         /*                                                              \
4586          * Convert null-terminated representation of result to standard text. \
4587          * The result is usually much bigger than it needs to be, but there \
4588          * seems little point in realloc'ing it smaller. \
4589          */                                                             \
4590         len = strlen(VARDATA(result));  \
4591         SET_VARSIZE(result, len + VARHDRSZ); \
4592 } while (0)
4593
4594 /* -------------------
4595  * NUMERIC to_number() (convert string to numeric)
4596  * -------------------
4597  */
4598 Datum
4599 numeric_to_number(PG_FUNCTION_ARGS)
4600 {
4601         text       *value = PG_GETARG_TEXT_P(0);
4602         text       *fmt = PG_GETARG_TEXT_P(1);
4603         NUMDesc         Num;
4604         Datum           result;
4605         FormatNode *format;
4606         char       *numstr;
4607         bool            shouldFree;
4608         int                     len = 0;
4609         int                     scale,
4610                                 precision;
4611
4612         len = VARSIZE(fmt) - VARHDRSZ;
4613
4614         if (len <= 0 || len >= INT_MAX / NUM_MAX_ITEM_SIZ)
4615                 PG_RETURN_NULL();
4616
4617         format = NUM_cache(len, &Num, fmt, &shouldFree);
4618
4619         numstr = (char *) palloc((len * NUM_MAX_ITEM_SIZ) + 1);
4620
4621         NUM_processor(format, &Num, VARDATA(value), numstr,
4622                                   VARSIZE(value) - VARHDRSZ, 0, false, PG_GET_COLLATION());
4623
4624         scale = Num.post;
4625         precision = Max(0, Num.pre) + scale;
4626
4627         if (shouldFree)
4628                 pfree(format);
4629
4630         result = DirectFunctionCall3(numeric_in,
4631                                                                  CStringGetDatum(numstr),
4632                                                                  ObjectIdGetDatum(InvalidOid),
4633                                           Int32GetDatum(((precision << 16) | scale) + VARHDRSZ));
4634         pfree(numstr);
4635         return result;
4636 }
4637
4638 /* ------------------
4639  * NUMERIC to_char()
4640  * ------------------
4641  */
4642 Datum
4643 numeric_to_char(PG_FUNCTION_ARGS)
4644 {
4645         Numeric         value = PG_GETARG_NUMERIC(0);
4646         text       *fmt = PG_GETARG_TEXT_P(1);
4647         NUMDesc         Num;
4648         FormatNode *format;
4649         text       *result;
4650         bool            shouldFree;
4651         int                     len = 0,
4652                                 plen = 0,
4653                                 sign = 0;
4654         char       *numstr,
4655                            *orgnum,
4656                            *p;
4657         Numeric         x;
4658
4659         NUM_TOCHAR_prepare;
4660
4661         /*
4662          * On DateType depend part (numeric)
4663          */
4664         if (IS_ROMAN(&Num))
4665         {
4666                 x = DatumGetNumeric(DirectFunctionCall2(numeric_round,
4667                                                                                                 NumericGetDatum(value),
4668                                                                                                 Int32GetDatum(0)));
4669                 numstr = orgnum =
4670                         int_to_roman(DatumGetInt32(DirectFunctionCall1(numeric_int4,
4671                                                                                                            NumericGetDatum(x))));
4672         }
4673         else if (IS_EEEE(&Num))
4674         {
4675                 orgnum = numeric_out_sci(value, Num.post);
4676
4677                 /*
4678                  * numeric_out_sci() does not emit a sign for positive numbers.  We
4679                  * need to add a space in this case so that positive and negative
4680                  * numbers are aligned.  We also have to do the right thing for NaN.
4681                  */
4682                 if (strcmp(orgnum, "NaN") == 0)
4683                 {
4684                         /*
4685                          * Allow 6 characters for the leading sign, the decimal point,
4686                          * "e", the exponent's sign and two exponent digits.
4687                          */
4688                         numstr = (char *) palloc(Num.pre + Num.post + 7);
4689                         fill_str(numstr, '#', Num.pre + Num.post + 6);
4690                         *numstr = ' ';
4691                         *(numstr + Num.pre + 1) = '.';
4692                 }
4693                 else if (*orgnum != '-')
4694                 {
4695                         numstr = (char *) palloc(strlen(orgnum) + 2);
4696                         *numstr = ' ';
4697                         strcpy(numstr + 1, orgnum);
4698                         len = strlen(numstr);
4699                 }
4700                 else
4701                 {
4702                         numstr = orgnum;
4703                         len = strlen(orgnum);
4704                 }
4705         }
4706         else
4707         {
4708                 Numeric         val = value;
4709
4710                 if (IS_MULTI(&Num))
4711                 {
4712                         Numeric         a = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
4713                                                                                                                  Int32GetDatum(10)));
4714                         Numeric         b = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
4715                                                                                                   Int32GetDatum(Num.multi)));
4716
4717                         x = DatumGetNumeric(DirectFunctionCall2(numeric_power,
4718                                                                                                         NumericGetDatum(a),
4719                                                                                                         NumericGetDatum(b)));
4720                         val = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
4721                                                                                                           NumericGetDatum(value),
4722                                                                                                           NumericGetDatum(x)));
4723                         Num.pre += Num.multi;
4724                 }
4725
4726                 x = DatumGetNumeric(DirectFunctionCall2(numeric_round,
4727                                                                                                 NumericGetDatum(val),
4728                                                                                                 Int32GetDatum(Num.post)));
4729                 orgnum = DatumGetCString(DirectFunctionCall1(numeric_out,
4730                                                                                                          NumericGetDatum(x)));
4731
4732                 if (*orgnum == '-')
4733                 {
4734                         sign = '-';
4735                         numstr = orgnum + 1;
4736                 }
4737                 else
4738                 {
4739                         sign = '+';
4740                         numstr = orgnum;
4741                 }
4742                 if ((p = strchr(numstr, '.')))
4743                         len = p - numstr;
4744                 else
4745                         len = strlen(numstr);
4746
4747                 if (Num.pre > len)
4748                         plen = Num.pre - len;
4749                 else if (len > Num.pre)
4750                 {
4751                         numstr = (char *) palloc(Num.pre + Num.post + 2);
4752                         fill_str(numstr, '#', Num.pre + Num.post + 1);
4753                         *(numstr + Num.pre) = '.';
4754                 }
4755         }
4756
4757         NUM_TOCHAR_finish;
4758         PG_RETURN_TEXT_P(result);
4759 }
4760
4761 /* ---------------
4762  * INT4 to_char()
4763  * ---------------
4764  */
4765 Datum
4766 int4_to_char(PG_FUNCTION_ARGS)
4767 {
4768         int32           value = PG_GETARG_INT32(0);
4769         text       *fmt = PG_GETARG_TEXT_P(1);
4770         NUMDesc         Num;
4771         FormatNode *format;
4772         text       *result;
4773         bool            shouldFree;
4774         int                     len = 0,
4775                                 plen = 0,
4776                                 sign = 0;
4777         char       *numstr,
4778                            *orgnum;
4779
4780         NUM_TOCHAR_prepare;
4781
4782         /*
4783          * On DateType depend part (int32)
4784          */
4785         if (IS_ROMAN(&Num))
4786                 numstr = orgnum = int_to_roman(value);
4787         else if (IS_EEEE(&Num))
4788         {
4789                 /* we can do it easily because float8 won't lose any precision */
4790                 float8          val = (float8) value;
4791
4792                 orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
4793                 snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, val);
4794
4795                 /*
4796                  * Swap a leading positive sign for a space.
4797                  */
4798                 if (*orgnum == '+')
4799                         *orgnum = ' ';
4800
4801                 len = strlen(orgnum);
4802                 numstr = orgnum;
4803         }
4804         else
4805         {
4806                 if (IS_MULTI(&Num))
4807                 {
4808                         orgnum = DatumGetCString(DirectFunctionCall1(int4out,
4809                                                                                                                  Int32GetDatum(value * ((int32) pow((double) 10, (double) Num.multi)))));
4810                         Num.pre += Num.multi;
4811                 }
4812                 else
4813                 {
4814                         orgnum = DatumGetCString(DirectFunctionCall1(int4out,
4815                                                                                                           Int32GetDatum(value)));
4816                 }
4817
4818                 if (*orgnum == '-')
4819                 {
4820                         sign = '-';
4821                         orgnum++;
4822                 }
4823                 else
4824                         sign = '+';
4825                 len = strlen(orgnum);
4826
4827                 if (Num.post)
4828                 {
4829                         numstr = (char *) palloc(len + Num.post + 2);
4830                         strcpy(numstr, orgnum);
4831                         *(numstr + len) = '.';
4832                         memset(numstr + len + 1, '0', Num.post);
4833                         *(numstr + len + Num.post + 1) = '\0';
4834                 }
4835                 else
4836                         numstr = orgnum;
4837
4838                 if (Num.pre > len)
4839                         plen = Num.pre - len;
4840                 else if (len > Num.pre)
4841                 {
4842                         numstr = (char *) palloc(Num.pre + Num.post + 2);
4843                         fill_str(numstr, '#', Num.pre + Num.post + 1);
4844                         *(numstr + Num.pre) = '.';
4845                 }
4846         }
4847
4848         NUM_TOCHAR_finish;
4849         PG_RETURN_TEXT_P(result);
4850 }
4851
4852 /* ---------------
4853  * INT8 to_char()
4854  * ---------------
4855  */
4856 Datum
4857 int8_to_char(PG_FUNCTION_ARGS)
4858 {
4859         int64           value = PG_GETARG_INT64(0);
4860         text       *fmt = PG_GETARG_TEXT_P(1);
4861         NUMDesc         Num;
4862         FormatNode *format;
4863         text       *result;
4864         bool            shouldFree;
4865         int                     len = 0,
4866                                 plen = 0,
4867                                 sign = 0;
4868         char       *numstr,
4869                            *orgnum;
4870
4871         NUM_TOCHAR_prepare;
4872
4873         /*
4874          * On DateType depend part (int32)
4875          */
4876         if (IS_ROMAN(&Num))
4877         {
4878                 /* Currently don't support int8 conversion to roman... */
4879                 numstr = orgnum = int_to_roman(DatumGetInt32(
4880                                                   DirectFunctionCall1(int84, Int64GetDatum(value))));
4881         }
4882         else if (IS_EEEE(&Num))
4883         {
4884                 /* to avoid loss of precision, must go via numeric not float8 */
4885                 Numeric         val;
4886
4887                 val = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
4888                                                                                                   Int64GetDatum(value)));
4889                 orgnum = numeric_out_sci(val, Num.post);
4890
4891                 /*
4892                  * numeric_out_sci() does not emit a sign for positive numbers.  We
4893                  * need to add a space in this case so that positive and negative
4894                  * numbers are aligned.  We don't have to worry about NaN here.
4895                  */
4896                 if (*orgnum != '-')
4897                 {
4898                         numstr = (char *) palloc(strlen(orgnum) + 2);
4899                         *numstr = ' ';
4900                         strcpy(numstr + 1, orgnum);
4901                         len = strlen(numstr);
4902                 }
4903                 else
4904                 {
4905                         numstr = orgnum;
4906                         len = strlen(orgnum);
4907                 }
4908         }
4909         else
4910         {
4911                 if (IS_MULTI(&Num))
4912                 {
4913                         double          multi = pow((double) 10, (double) Num.multi);
4914
4915                         value = DatumGetInt64(DirectFunctionCall2(int8mul,
4916                                                                                                           Int64GetDatum(value),
4917                                                                                                    DirectFunctionCall1(dtoi8,
4918                                                                                                         Float8GetDatum(multi))));
4919                         Num.pre += Num.multi;
4920                 }
4921
4922                 orgnum = DatumGetCString(DirectFunctionCall1(int8out,
4923                                                                                                          Int64GetDatum(value)));
4924
4925                 if (*orgnum == '-')
4926                 {
4927                         sign = '-';
4928                         orgnum++;
4929                 }
4930                 else
4931                         sign = '+';
4932                 len = strlen(orgnum);
4933
4934                 if (Num.post)
4935                 {
4936                         numstr = (char *) palloc(len + Num.post + 2);
4937                         strcpy(numstr, orgnum);
4938                         *(numstr + len) = '.';
4939                         memset(numstr + len + 1, '0', Num.post);
4940                         *(numstr + len + Num.post + 1) = '\0';
4941                 }
4942                 else
4943                         numstr = orgnum;
4944
4945                 if (Num.pre > len)
4946                         plen = Num.pre - len;
4947                 else if (len > Num.pre)
4948                 {
4949                         numstr = (char *) palloc(Num.pre + Num.post + 2);
4950                         fill_str(numstr, '#', Num.pre + Num.post + 1);
4951                         *(numstr + Num.pre) = '.';
4952                 }
4953         }
4954
4955         NUM_TOCHAR_finish;
4956         PG_RETURN_TEXT_P(result);
4957 }
4958
4959 /* -----------------
4960  * FLOAT4 to_char()
4961  * -----------------
4962  */
4963 Datum
4964 float4_to_char(PG_FUNCTION_ARGS)
4965 {
4966         float4          value = PG_GETARG_FLOAT4(0);
4967         text       *fmt = PG_GETARG_TEXT_P(1);
4968         NUMDesc         Num;
4969         FormatNode *format;
4970         text       *result;
4971         bool            shouldFree;
4972         int                     len = 0,
4973                                 plen = 0,
4974                                 sign = 0;
4975         char       *numstr,
4976                            *orgnum,
4977                            *p;
4978
4979         NUM_TOCHAR_prepare;
4980
4981         if (IS_ROMAN(&Num))
4982                 numstr = orgnum = int_to_roman((int) rint(value));
4983         else if (IS_EEEE(&Num))
4984         {
4985                 numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
4986                 if (isnan(value) || is_infinite(value))
4987                 {
4988                         /*
4989                          * Allow 6 characters for the leading sign, the decimal point,
4990                          * "e", the exponent's sign and two exponent digits.
4991                          */
4992                         numstr = (char *) palloc(Num.pre + Num.post + 7);
4993                         fill_str(numstr, '#', Num.pre + Num.post + 6);
4994                         *numstr = ' ';
4995                         *(numstr + Num.pre + 1) = '.';
4996                 }
4997                 else
4998                 {
4999                         snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
5000
5001                         /*
5002                          * Swap a leading positive sign for a space.
5003                          */
5004                         if (*orgnum == '+')
5005                                 *orgnum = ' ';
5006
5007                         len = strlen(orgnum);
5008                         numstr = orgnum;
5009                 }
5010         }
5011         else
5012         {
5013                 float4          val = value;
5014
5015                 if (IS_MULTI(&Num))
5016                 {
5017                         float           multi = pow((double) 10, (double) Num.multi);
5018
5019                         val = value * multi;
5020                         Num.pre += Num.multi;
5021                 }
5022
5023                 orgnum = (char *) palloc(MAXFLOATWIDTH + 1);
5024                 snprintf(orgnum, MAXFLOATWIDTH + 1, "%.0f", fabs(val));
5025                 len = strlen(orgnum);
5026                 if (Num.pre > len)
5027                         plen = Num.pre - len;
5028                 if (len >= FLT_DIG)
5029                         Num.post = 0;
5030                 else if (Num.post + len > FLT_DIG)
5031                         Num.post = FLT_DIG - len;
5032                 snprintf(orgnum, MAXFLOATWIDTH + 1, "%.*f", Num.post, val);
5033
5034                 if (*orgnum == '-')
5035                 {                                               /* < 0 */
5036                         sign = '-';
5037                         numstr = orgnum + 1;
5038                 }
5039                 else
5040                 {
5041                         sign = '+';
5042                         numstr = orgnum;
5043                 }
5044                 if ((p = strchr(numstr, '.')))
5045                         len = p - numstr;
5046                 else
5047                         len = strlen(numstr);
5048
5049                 if (Num.pre > len)
5050                         plen = Num.pre - len;
5051                 else if (len > Num.pre)
5052                 {
5053                         numstr = (char *) palloc(Num.pre + Num.post + 2);
5054                         fill_str(numstr, '#', Num.pre + Num.post + 1);
5055                         *(numstr + Num.pre) = '.';
5056                 }
5057         }
5058
5059         NUM_TOCHAR_finish;
5060         PG_RETURN_TEXT_P(result);
5061 }
5062
5063 /* -----------------
5064  * FLOAT8 to_char()
5065  * -----------------
5066  */
5067 Datum
5068 float8_to_char(PG_FUNCTION_ARGS)
5069 {
5070         float8          value = PG_GETARG_FLOAT8(0);
5071         text       *fmt = PG_GETARG_TEXT_P(1);
5072         NUMDesc         Num;
5073         FormatNode *format;
5074         text       *result;
5075         bool            shouldFree;
5076         int                     len = 0,
5077                                 plen = 0,
5078                                 sign = 0;
5079         char       *numstr,
5080                            *orgnum,
5081                            *p;
5082
5083         NUM_TOCHAR_prepare;
5084
5085         if (IS_ROMAN(&Num))
5086                 numstr = orgnum = int_to_roman((int) rint(value));
5087         else if (IS_EEEE(&Num))
5088         {
5089                 numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5090                 if (isnan(value) || is_infinite(value))
5091                 {
5092                         /*
5093                          * Allow 6 characters for the leading sign, the decimal point,
5094                          * "e", the exponent's sign and two exponent digits.
5095                          */
5096                         numstr = (char *) palloc(Num.pre + Num.post + 7);
5097                         fill_str(numstr, '#', Num.pre + Num.post + 6);
5098                         *numstr = ' ';
5099                         *(numstr + Num.pre + 1) = '.';
5100                 }
5101                 else
5102                 {
5103                         snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
5104
5105                         /*
5106                          * Swap a leading positive sign for a space.
5107                          */
5108                         if (*orgnum == '+')
5109                                 *orgnum = ' ';
5110
5111                         len = strlen(orgnum);
5112                         numstr = orgnum;
5113                 }
5114         }
5115         else
5116         {
5117                 float8          val = value;
5118
5119                 if (IS_MULTI(&Num))
5120                 {
5121                         double          multi = pow((double) 10, (double) Num.multi);
5122
5123                         val = value * multi;
5124                         Num.pre += Num.multi;
5125                 }
5126                 orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5127                 len = snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.0f", fabs(val));
5128                 if (Num.pre > len)
5129                         plen = Num.pre - len;
5130                 if (len >= DBL_DIG)
5131                         Num.post = 0;
5132                 else if (Num.post + len > DBL_DIG)
5133                         Num.post = DBL_DIG - len;
5134                 snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.*f", Num.post, val);
5135
5136                 if (*orgnum == '-')
5137                 {                                               /* < 0 */
5138                         sign = '-';
5139                         numstr = orgnum + 1;
5140                 }
5141                 else
5142                 {
5143                         sign = '+';
5144                         numstr = orgnum;
5145                 }
5146                 if ((p = strchr(numstr, '.')))
5147                         len = p - numstr;
5148                 else
5149                         len = strlen(numstr);
5150
5151                 if (Num.pre > len)
5152                         plen = Num.pre - len;
5153                 else if (len > Num.pre)
5154                 {
5155                         numstr = (char *) palloc(Num.pre + Num.post + 2);
5156                         fill_str(numstr, '#', Num.pre + Num.post + 1);
5157                         *(numstr + Num.pre) = '.';
5158                 }
5159         }
5160
5161         NUM_TOCHAR_finish;
5162         PG_RETURN_TEXT_P(result);
5163 }