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