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