PostgreSQL Source Code: src/backend/utils/adt/formatting.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60#ifdef DEBUG_TO_FROM_CHAR
61#define DEBUG_elog_output DEBUG3
62#endif
63
65
66#include <ctype.h>
68#include <math.h>
70#include <limits.h>
71#include <wctype.h>
72
73#ifdef USE_ICU
74#include <unicode/ustring.h>
75#endif
76
93
94
95
96
97
98
99#define DCH_FLAG 0x1
100#define NUM_FLAG 0x2
101#define STD_FLAG 0x4
102
103
104
105
106
107#define KeyWord_INDEX_SIZE ('~' - ' ')
108#define KeyWord_INDEX_FILTER(_c) ((_c) <= ' ' || (_c) >= '~' ? 0 : 1)
109
110
111
112
113
114#define DCH_MAX_ITEM_SIZ 12
115#define NUM_MAX_ITEM_SIZ 8
116
117
118
119
120
121
122typedef struct
123{
129
130
131
132
133
134
135
136
137typedef enum
138{
143
144typedef struct
145{
152
153typedef struct
154{
160
161#define NODE_TYPE_END 1
162#define NODE_TYPE_ACTION 2
163#define NODE_TYPE_CHAR 3
164#define NODE_TYPE_SEPARATOR 4
165#define NODE_TYPE_SPACE 5
166
167#define SUFFTYPE_PREFIX 1
168#define SUFFTYPE_POSTFIX 2
169
170#define CLOCK_24_HOUR 0
171#define CLOCK_12_HOUR 1
172
173
174
175
176
177
179 "January", "February", "March", "April", "May", "June", "July",
180 "August", "September", "October", "November", "December", NULL
181};
182
184 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
185};
186
187
188
189
190
191
192
193
194#define ADJUST_YEAR(year, is_interval) ((is_interval) ? (year) : ((year) <= 0 ? -((year) - 1) : (year)))
195
196#define A_D_STR "A.D."
197#define a_d_STR "a.d."
198#define AD_STR "AD"
199#define ad_STR "ad"
200
201#define B_C_STR "B.C."
202#define b_c_STR "b.c."
203#define BC_STR "BC"
204#define bc_STR "bc"
205
206
207
208
209
210
211
212
213
214
215
218
219
220
221
222
223#define A_M_STR "A.M."
224#define a_m_STR "a.m."
225#define AM_STR "AM"
226#define am_STR "am"
227
228#define P_M_STR "P.M."
229#define p_m_STR "p.m."
230#define PM_STR "PM"
231#define pm_STR "pm"
232
233
234
235
236
237
238
239
240
241
242
245
246
247
248
249
250
251
253{"XII", "XI", "X", "IX", "VIII", "VII", "VI", "V", "IV", "III", "II", "I", NULL};
254
256{"xii", "xi", "x", "ix", "viii", "vii", "vi", "v", "iv", "iii", "ii", "i", NULL};
257
258
259
260
261
262static const char *const rm1[] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", NULL};
263static const char *const rm10[] = {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", NULL};
264static const char *const rm100[] = {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", NULL};
265
266
267
268
269
270#define IS_VALID_SUB_COMB(curr, next) \
271 (((curr) == 'I' && ((next) == 'V' || (next) == 'X')) || \
272 ((curr) == 'X' && ((next) == 'L' || (next) == 'C')) || \
273 ((curr) == 'C' && ((next) == 'D' || (next) == 'M')))
274
275
276
277
278#define ROMAN_VAL(r) \
279 ((r) == 'I' ? 1 : \
280 (r) == 'V' ? 5 : \
281 (r) == 'X' ? 10 : \
282 (r) == 'L' ? 50 : \
283 (r) == 'C' ? 100 : \
284 (r) == 'D' ? 500 : \
285 (r) == 'M' ? 1000 : 0)
286
287
288
289
290#define MAX_ROMAN_LEN 15
291
292
293
294
295
296static const char *const numTH[] = {"ST", "ND", "RD", "TH", NULL};
297static const char *const numth[] = {"st", "nd", "rd", "th", NULL};
298
299
300
301
302
303#define TH_UPPER 1
304#define TH_LOWER 2
305
306
307
308
309
310typedef struct
311{
322
323
324
325
326
327#define NUM_F_DECIMAL (1 << 1)
328#define NUM_F_LDECIMAL (1 << 2)
329#define NUM_F_ZERO (1 << 3)
330#define NUM_F_BLANK (1 << 4)
331#define NUM_F_FILLMODE (1 << 5)
332#define NUM_F_LSIGN (1 << 6)
333#define NUM_F_BRACKET (1 << 7)
334#define NUM_F_MINUS (1 << 8)
335#define NUM_F_PLUS (1 << 9)
336#define NUM_F_ROMAN (1 << 10)
337#define NUM_F_MULTI (1 << 11)
338#define NUM_F_PLUS_POST (1 << 12)
339#define NUM_F_MINUS_POST (1 << 13)
340#define NUM_F_EEEE (1 << 14)
341
342#define NUM_LSIGN_PRE (-1)
343#define NUM_LSIGN_POST 1
344#define NUM_LSIGN_NONE 0
345
346
347
348
349
350#define IS_DECIMAL(_f) ((_f)->flag & NUM_F_DECIMAL)
351#define IS_LDECIMAL(_f) ((_f)->flag & NUM_F_LDECIMAL)
352#define IS_ZERO(_f) ((_f)->flag & NUM_F_ZERO)
353#define IS_BLANK(_f) ((_f)->flag & NUM_F_BLANK)
354#define IS_FILLMODE(_f) ((_f)->flag & NUM_F_FILLMODE)
355#define IS_BRACKET(_f) ((_f)->flag & NUM_F_BRACKET)
356#define IS_MINUS(_f) ((_f)->flag & NUM_F_MINUS)
357#define IS_LSIGN(_f) ((_f)->flag & NUM_F_LSIGN)
358#define IS_PLUS(_f) ((_f)->flag & NUM_F_PLUS)
359#define IS_ROMAN(_f) ((_f)->flag & NUM_F_ROMAN)
360#define IS_MULTI(_f) ((_f)->flag & NUM_F_MULTI)
361#define IS_EEEE(_f) ((_f)->flag & NUM_F_EEEE)
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381#define DCH_CACHE_OVERHEAD \
382 MAXALIGN(sizeof(bool) + sizeof(int))
383#define NUM_CACHE_OVERHEAD \
384 MAXALIGN(sizeof(bool) + sizeof(int) + sizeof(NUMDesc))
385
386#define DCH_CACHE_SIZE \
387 ((2048 - DCH_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
388#define NUM_CACHE_SIZE \
389 ((1024 - NUM_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
390
391#define DCH_CACHE_ENTRIES 20
392#define NUM_CACHE_ENTRIES 20
393
394typedef struct
395{
402
403typedef struct
404{
411
412
414static int n_DCHCache = 0;
415static int DCHCounter = 0;
416
417
419static int n_NUMCache = 0;
420static int NUMCounter = 0;
421
422
423
424
425
426typedef struct
427{
457
458#define ZERO_tmfc(_X) memset(_X, 0, sizeof(TmFromChar))
459
461{
464};
465
466
467
468
469
470#ifdef DEBUG_TO_FROM_CHAR
471#define DEBUG_TMFC(_X) \
472 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", \
473 (_X)->mode, (_X)->hh, (_X)->pm, (_X)->mi, (_X)->ss, (_X)->ssss, \
474 (_X)->d, (_X)->dd, (_X)->ddd, (_X)->mm, (_X)->ms, (_X)->year, \
475 (_X)->bc, (_X)->ww, (_X)->w, (_X)->cc, (_X)->j, (_X)->us, \
476 (_X)->yysz, (_X)->clock)
477#define DEBUG_TM(_X) \
478 elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\
479 (_X)->tm_sec, (_X)->tm_year,\
480 (_X)->tm_min, (_X)->tm_wday, (_X)->tm_hour, (_X)->tm_yday,\
481 (_X)->tm_mday, (_X)->tm_isdst, (_X)->tm_mon)
482#else
483#define DEBUG_TMFC(_X)
484#define DEBUG_TM(_X)
485#endif
486
487
488
489
490
491
492
493
494
496{
506};
507
509{
514
515#define tmtcTm(_X) (&(_X)->tm)
516#define tmtcTzn(_X) ((_X)->tzn)
517#define tmtcFsec(_X) ((_X)->fsec)
518
519
520#define COPY_tm(_DST, _SRC) \
521do { \
522 (_DST)->tm_sec = (_SRC)->tm_sec; \
523 (_DST)->tm_min = (_SRC)->tm_min; \
524 (_DST)->tm_hour = (_SRC)->tm_hour; \
525 (_DST)->tm_mday = (_SRC)->tm_mday; \
526 (_DST)->tm_mon = (_SRC)->tm_mon; \
527 (_DST)->tm_year = (_SRC)->tm_year; \
528 (_DST)->tm_wday = (_SRC)->tm_wday; \
529 (_DST)->tm_yday = (_SRC)->tm_yday; \
530 (_DST)->tm_gmtoff = (_SRC)->tm_gmtoff; \
531} while(0)
532
533
534#define ZERO_tm(_X) \
535do { \
536 memset(_X, 0, sizeof(*(_X))); \
537 (_X)->tm_mday = (_X)->tm_mon = 1; \
538} while(0)
539
540#define ZERO_tmtc(_X) \
541do { \
542 ZERO_tm( tmtcTm(_X) ); \
543 tmtcFsec(_X) = 0; \
544 tmtcTzn(_X) = NULL; \
545} while(0)
546
547
548
549
550
551#define INVALID_FOR_INTERVAL \
552do { \
553 if (is_interval) \
554 ereport(ERROR, \
555 (errcode(ERRCODE_INVALID_DATETIME_FORMAT), \
556 errmsg("invalid format specification for an interval value"), \
557 errhint("Intervals are not tied to specific calendar dates."))); \
558} while(0)
559
560
561
562
563
564
565
566
567
568#define DCH_S_FM 0x01
569#define DCH_S_TH 0x02
570#define DCH_S_th 0x04
571#define DCH_S_SP 0x08
572#define DCH_S_TM 0x10
573
574
575
576
577
578#define S_THth(_s) ((((_s) & DCH_S_TH) || ((_s) & DCH_S_th)) ? 1 : 0)
579#define S_TH(_s) (((_s) & DCH_S_TH) ? 1 : 0)
580#define S_th(_s) (((_s) & DCH_S_th) ? 1 : 0)
581#define S_TH_TYPE(_s) (((_s) & DCH_S_TH) ? TH_UPPER : TH_LOWER)
582
583
584#define S_FM(_s) (((_s) & DCH_S_FM) ? 1 : 0)
585#define S_SP(_s) (((_s) & DCH_S_SP) ? 1 : 0)
586#define S_TM(_s) (((_s) & DCH_S_TM) ? 1 : 0)
587
588
589
590
591
592#define TM_SUFFIX_LEN 2
593
602
603 {NULL, 0, 0, 0}
604};
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635typedef enum
636{
749
750
753
754typedef enum
755{
792
793
796
797
798
799
800
802
915
916
917 {NULL, 0, 0, 0, 0}
918};
919
920
921
922
923
924
925
927
929 {".", 1, NUM_DEC},
930 {"0", 1, NUM_0},
931 {"9", 1, NUM_9},
932 {"B", 1, NUM_B},
933 {"C", 1, NUM_C},
934 {"D", 1, NUM_D},
935 {"EEEE", 4, NUM_E},
936 {"FM", 2, NUM_FM},
937 {"G", 1, NUM_G},
938 {"L", 1, NUM_L},
939 {"MI", 2, NUM_MI},
940 {"PL", 2, NUM_PL},
942 {"RN", 2, NUM_RN},
943 {"SG", 2, NUM_SG},
946 {"TH", 2, NUM_TH},
947 {"V", 1, NUM_V},
948 {"b", 1, NUM_B},
949 {"c", 1, NUM_C},
950 {"d", 1, NUM_D},
951 {"eeee", 4, NUM_E},
952 {"fm", 2, NUM_FM},
953 {"g", 1, NUM_G},
954 {"l", 1, NUM_L},
955 {"mi", 2, NUM_MI},
956 {"pl", 2, NUM_PL},
958 {"rn", 2, NUM_rn},
959 {"sg", 2, NUM_SG},
962 {"th", 2, NUM_th},
963 {"v", 1, NUM_V},
964
965
966 {NULL, 0, 0}
967};
968
969
970
971
972
973
975
976
977
978
979
980 -1, -1, -1, -1, -1, -1, -1, -1,
981 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
982 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
983 -1, -1, -1, -1, -1, DCH_A_D, DCH_B_C, DCH_CC, DCH_DAY, -1,
984 DCH_FF1, -1, DCH_HH24, DCH_IDDD, DCH_J, -1, -1, DCH_MI, -1, DCH_OF,
985 DCH_P_M, DCH_Q, DCH_RM, DCH_SSSSS, DCH_TZH, DCH_US, -1, DCH_WW, -1, DCH_Y_YYY,
986 -1, -1, -1, -1, -1, -1, -1, DCH_a_d, DCH_b_c, DCH_cc,
987 DCH_day, -1, DCH_ff1, -1, DCH_hh24, DCH_iddd, DCH_j, -1, -1, DCH_mi,
988 -1, DCH_of, DCH_p_m, DCH_q, DCH_rm, DCH_sssss, DCH_tzh, DCH_us, -1, DCH_ww,
990
991
992};
993
994
995
996
997
999
1000
1001
1002
1003
1004 -1, -1, -1, -1, -1, -1, -1, -1,
1005 -1, -1, -1, -1, NUM_COMMA, -1, NUM_DEC, -1, NUM_0, -1,
1006 -1, -1, -1, -1, -1, -1, -1, NUM_9, -1, -1,
1007 -1, -1, -1, -1, -1, -1, NUM_B, NUM_C, NUM_D, NUM_E,
1008 NUM_FM, NUM_G, -1, -1, -1, -1, NUM_L, NUM_MI, -1, -1,
1009 NUM_PL, -1, NUM_RN, NUM_SG, NUM_TH, -1, NUM_V, -1, -1, -1,
1010 -1, -1, -1, -1, -1, -1, -1, -1, NUM_b, NUM_c,
1011 NUM_d, NUM_e, NUM_fm, NUM_g, -1, -1, -1, -1, NUM_l, NUM_mi,
1012 -1, -1, NUM_pl, -1, NUM_rn, NUM_sg, NUM_th, -1, NUM_v, -1,
1013 -1, -1, -1, -1, -1, -1
1014
1015
1016};
1017
1018
1019
1020
1021
1023{
1026
1033
1037
1043
1050
1051
1052#define DCH_DATED 0x01
1053#define DCH_TIMED 0x02
1054#define DCH_ZONED 0x04
1055
1056
1057
1058
1059
1060
1061#define OVERLOAD_TEST (Np->inout_p >= Np->inout + input_len)
1062#define AMOUNT_TEST(s) (Np->inout_p <= Np->inout + (input_len - (s)))
1063
1064
1065
1066
1067
1068
1070 const int *index);
1076
1081
1082#ifdef DEBUG_TO_FROM_CHAR
1083static void dump_index(const KeyWord *k, const int *index);
1084static void dump_node(FormatNode *node, int max);
1085#endif
1086
1087static const char *get_th(char *num, int type);
1092 Node *escontext);
1094 Node *escontext);
1098 Node *escontext);
1103 const char *const *array,
1104 char **localized_array, Oid collid,
1108 int *fprec, uint32 *flags, Node *escontext);
1109static char *fill_str(char *str, int c, int max);
1118 char *number, int input_len, int to_char_out_pre_spaces,
1126
1127
1128
1129
1130
1131
1132
1133
1136{
1137 int poz;
1138
1140 return NULL;
1141
1142 if ((poz = *(index + (*str - ' '))) > -1)
1143 {
1144 const KeyWord *k = kw + poz;
1145
1146 do
1147 {
1148 if (strncmp(str, k->name, k->len) == 0)
1149 return k;
1150 k++;
1151 if (!k->name)
1152 return NULL;
1153 } while (*str == *k->name);
1154 }
1155 return NULL;
1156}
1157
1160{
1162
1163 for (s = suf; s->name != NULL; s++)
1164 {
1166 continue;
1167
1168 if (strncmp(str, s->name, s->len) == 0)
1169 return s;
1170 }
1171 return NULL;
1172}
1173
1174static bool
1176{
1177
1178 return (*str > 0x20 && *str < 0x7F &&
1179 !(*str >= 'A' && *str <= 'Z') &&
1180 !(*str >= 'a' && *str <= 'z') &&
1181 !(*str >= '0' && *str <= '9'));
1182}
1183
1184
1185
1186
1187
1188static void
1190{
1192 return;
1193
1196 (errcode(ERRCODE_SYNTAX_ERROR),
1197 errmsg("\"EEEE\" must be the last pattern used")));
1198
1200 {
1204 (errcode(ERRCODE_SYNTAX_ERROR),
1205 errmsg("\"9\" must be ahead of \"PR\"")));
1207 {
1209 break;
1210 }
1212 ++num->post;
1213 else
1214 ++num->pre;
1215 break;
1216
1220 (errcode(ERRCODE_SYNTAX_ERROR),
1221 errmsg("\"0\" must be ahead of \"PR\"")));
1223 {
1226 }
1228 ++num->pre;
1229 else
1230 ++num->post;
1231
1233 break;
1234
1236 if (num->pre == 0 && num->post == 0 && ((num)))
1238 break;
1239
1243
1247 (errcode(ERRCODE_SYNTAX_ERROR),
1248 errmsg("multiple decimal points")));
1251 (errcode(ERRCODE_SYNTAX_ERROR),
1252 errmsg("cannot use \"V\" and decimal point together")));
1254 break;
1255
1258 break;
1259
1263 (errcode(ERRCODE_SYNTAX_ERROR),
1264 errmsg("cannot use \"S\" twice")));
1267 (errcode(ERRCODE_SYNTAX_ERROR),
1268 errmsg("cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together")));
1270 {
1275 }
1277 {
1281 }
1282 break;
1283
1287 (errcode(ERRCODE_SYNTAX_ERROR),
1288 errmsg("cannot use \"S\" and \"MI\" together")));
1292 break;
1293
1297 (errcode(ERRCODE_SYNTAX_ERROR),
1298 errmsg("cannot use \"S\" and \"PL\" together")));
1302 break;
1303
1307 (errcode(ERRCODE_SYNTAX_ERROR),
1308 errmsg("cannot use \"S\" and \"SG\" together")));
1311 break;
1312
1316 (errcode(ERRCODE_SYNTAX_ERROR),
1317 errmsg("cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together")));
1319 break;
1320
1325 (errcode(ERRCODE_SYNTAX_ERROR),
1326 errmsg("cannot use \"RN\" twice")));
1328 break;
1329
1333 break;
1334
1338 (errcode(ERRCODE_SYNTAX_ERROR),
1339 errmsg("cannot use \"V\" and decimal point together")));
1341 break;
1342
1346 (errcode(ERRCODE_SYNTAX_ERROR),
1347 errmsg("cannot use \"EEEE\" twice")));
1352 (errcode(ERRCODE_SYNTAX_ERROR),
1353 errmsg("\"EEEE\" is incompatible with other formats"),
1354 errdetail("\"EEEE\" may only be used together with digit and decimal point patterns.")));
1356 break;
1357 }
1358
1362 (errcode(ERRCODE_SYNTAX_ERROR),
1363 errmsg("\"RN\" is incompatible with other formats"),
1364 errdetail("\"RN\" may only be used together with \"FM\".")));
1365}
1366
1367
1368
1369
1370
1371
1372
1373
1374static void
1377{
1379
1380#ifdef DEBUG_TO_FROM_CHAR
1381 elog(DEBUG_elog_output, "to_char/number(): run parser");
1382#endif
1383
1384 n = node;
1385
1386 while (*str)
1387 {
1388 int suffix = 0;
1390
1391
1392
1393
1396 {
1397 suffix |= s->id;
1398 if (s->len)
1400 }
1401
1402
1403
1404
1406 {
1411
1412
1413
1414
1417
1418
1419
1420
1423 {
1425 if (s->len)
1427 }
1428
1429 n++;
1430 }
1431 else if (*str)
1432 {
1433 int chlen;
1434
1436 {
1437
1438
1439
1440
1441
1442 if (strchr("-./,':; ", *str) == NULL)
1444 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
1445 errmsg("invalid datetime format separator: \"%s\"",
1447
1448 if (*str == ' ')
1450 else
1452
1455 n->key = NULL;
1457 n++;
1459 }
1460 else if (*str == '"')
1461 {
1462
1463
1464
1466 while (*str)
1467 {
1468 if (*str == '"')
1469 {
1471 break;
1472 }
1473
1474 if (*str == '\\' && *(str + 1))
1480 n->key = NULL;
1482 n++;
1483 str += chlen;
1484 }
1485 }
1486 else
1487 {
1488
1489
1490
1491
1492 if (*str == '\\' && *(str + 1) == '"')
1495
1498 else if (isspace((unsigned char) *str))
1500 else
1502
1505 n->key = NULL;
1507 n++;
1508 str += chlen;
1509 }
1510 }
1511 }
1512
1515}
1516
1517
1518
1519
1520
1521#ifdef DEBUG_TO_FROM_CHAR
1522
1523#define DUMP_THth(_suf) (S_TH(_suf) ? "TH" : (S_th(_suf) ? "th" : " "))
1524#define DUMP_FM(_suf) (S_FM(_suf) ? "FM" : " ")
1525
1526static void
1528{
1530 int a;
1531
1532 elog(DEBUG_elog_output, "to_from-char(): DUMP FORMAT");
1533
1534 for (a = 0, n = node; a <= max; n++, a++)
1535 {
1537 elog(DEBUG_elog_output, "%d:\t NODE_TYPE_ACTION '%s'\t(%s,%s)",
1540 elog(DEBUG_elog_output, "%d:\t NODE_TYPE_CHAR '%s'",
1543 {
1544 elog(DEBUG_elog_output, "%d:\t NODE_TYPE_END", a);
1545 return;
1546 }
1547 else
1548 elog(DEBUG_elog_output, "%d:\t unknown NODE!", a);
1549 }
1550}
1551#endif
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562static const char *
1564{
1565 int len = strlen(num),
1566 last;
1567
1568 last = *(num + (len - 1));
1569 if (!isdigit((unsigned char) last))
1571 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1572 errmsg("\"%s\" is not a number", num)));
1573
1574
1575
1576
1577
1578 if ((len > 1) && (num[len - 2] == '1'))
1579 last = 0;
1580
1581 switch (last)
1582 {
1583 case '1':
1585 return numTH[0];
1586 return numth[0];
1587 case '2':
1589 return numTH[1];
1590 return numth[1];
1591 case '3':
1593 return numTH[2];
1594 return numth[2];
1595 default:
1597 return numTH[3];
1598 return numth[3];
1599 }
1600}
1601
1602
1603
1604
1605
1606
1607static char *
1609{
1610 if (dest != num)
1611 strcpy(dest, num);
1613 return dest;
1614}
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636char *
1638{
1639 char *result;
1641
1642 if (!buff)
1643 return NULL;
1644
1646 {
1647
1648
1649
1650
1652 (errcode(ERRCODE_INDETERMINATE_COLLATION),
1653 errmsg("could not determine which collation to use for %s function",
1654 "lower()"),
1655 errhint("Use the COLLATE clause to set the collation explicitly.")));
1656 }
1657
1659
1660
1662 {
1664 }
1665 else
1666 {
1667 const char *src = buff;
1668 size_t srclen = nbytes;
1669 size_t dstsize;
1670 char *dst;
1671 size_t needed;
1672
1673
1674 dstsize = srclen + 1;
1675 dst = palloc(dstsize);
1676
1677 needed = pg_strlower(dst, dstsize, src, srclen, mylocale);
1678 if (needed + 1 > dstsize)
1679 {
1680
1681 dstsize = needed + 1;
1682 dst = repalloc(dst, dstsize);
1683 needed = pg_strlower(dst, dstsize, src, srclen, mylocale);
1684 Assert(needed + 1 <= dstsize);
1685 }
1686
1687 Assert(dst[needed] == '\0');
1688 result = dst;
1689 }
1690
1691 return result;
1692}
1693
1694
1695
1696
1697
1698
1699
1700char *
1702{
1703 char *result;
1705
1706 if (!buff)
1707 return NULL;
1708
1710 {
1711
1712
1713
1714
1716 (errcode(ERRCODE_INDETERMINATE_COLLATION),
1717 errmsg("could not determine which collation to use for %s function",
1718 "upper()"),
1719 errhint("Use the COLLATE clause to set the collation explicitly.")));
1720 }
1721
1723
1724
1726 {
1728 }
1729 else
1730 {
1731 const char *src = buff;
1732 size_t srclen = nbytes;
1733 size_t dstsize;
1734 char *dst;
1735 size_t needed;
1736
1737
1738 dstsize = srclen + 1;
1739 dst = palloc(dstsize);
1740
1741 needed = pg_strupper(dst, dstsize, src, srclen, mylocale);
1742 if (needed + 1 > dstsize)
1743 {
1744
1745 dstsize = needed + 1;
1746 dst = repalloc(dst, dstsize);
1747 needed = pg_strupper(dst, dstsize, src, srclen, mylocale);
1748 Assert(needed + 1 <= dstsize);
1749 }
1750
1751 Assert(dst[needed] == '\0');
1752 result = dst;
1753 }
1754
1755 return result;
1756}
1757
1758
1759
1760
1761
1762
1763
1764char *
1766{
1767 char *result;
1769
1770 if (!buff)
1771 return NULL;
1772
1774 {
1775
1776
1777
1778
1780 (errcode(ERRCODE_INDETERMINATE_COLLATION),
1781 errmsg("could not determine which collation to use for %s function",
1782 "initcap()"),
1783 errhint("Use the COLLATE clause to set the collation explicitly.")));
1784 }
1785
1787
1788
1790 {
1792 }
1793 else
1794 {
1795 const char *src = buff;
1796 size_t srclen = nbytes;
1797 size_t dstsize;
1798 char *dst;
1799 size_t needed;
1800
1801
1802 dstsize = srclen + 1;
1803 dst = palloc(dstsize);
1804
1805 needed = pg_strtitle(dst, dstsize, src, srclen, mylocale);
1806 if (needed + 1 > dstsize)
1807 {
1808
1809 dstsize = needed + 1;
1810 dst = repalloc(dst, dstsize);
1811 needed = pg_strtitle(dst, dstsize, src, srclen, mylocale);
1812 Assert(needed + 1 <= dstsize);
1813 }
1814
1815 Assert(dst[needed] == '\0');
1816 result = dst;
1817 }
1818
1819 return result;
1820}
1821
1822
1823
1824
1825
1826
1827
1828char *
1830{
1831 char *result;
1833
1834 if (!buff)
1835 return NULL;
1836
1838 {
1839
1840
1841
1842
1844 (errcode(ERRCODE_INDETERMINATE_COLLATION),
1845 errmsg("could not determine which collation to use for %s function",
1846 "lower()"),
1847 errhint("Use the COLLATE clause to set the collation explicitly.")));
1848 }
1849
1852 (errcode(ERRCODE_SYNTAX_ERROR),
1853 errmsg("Unicode case folding can only be performed if server encoding is UTF8")));
1854
1856
1857
1859 {
1861 }
1862 else
1863 {
1864 const char *src = buff;
1865 size_t srclen = nbytes;
1866 size_t dstsize;
1867 char *dst;
1868 size_t needed;
1869
1870
1871 dstsize = srclen + 1;
1872 dst = palloc(dstsize);
1873
1874 needed = pg_strfold(dst, dstsize, src, srclen, mylocale);
1875 if (needed + 1 > dstsize)
1876 {
1877
1878 dstsize = needed + 1;
1879 dst = repalloc(dst, dstsize);
1880 needed = pg_strfold(dst, dstsize, src, srclen, mylocale);
1881 Assert(needed + 1 <= dstsize);
1882 }
1883
1884 Assert(dst[needed] == '\0');
1885 result = dst;
1886 }
1887
1888 return result;
1889}
1890
1891
1892
1893
1894
1895
1896
1897char *
1899{
1900 char *result;
1901 char *p;
1902
1903 if (!buff)
1904 return NULL;
1905
1906 result = pnstrdup(buff, nbytes);
1907
1908 for (p = result; *p; p++)
1910
1911 return result;
1912}
1913
1914
1915
1916
1917
1918
1919
1920char *
1922{
1923 char *result;
1924 char *p;
1925
1926 if (!buff)
1927 return NULL;
1928
1929 result = pnstrdup(buff, nbytes);
1930
1931 for (p = result; *p; p++)
1933
1934 return result;
1935}
1936
1937
1938
1939
1940
1941
1942
1943char *
1945{
1946 char *result;
1947 char *p;
1948 int wasalnum = false;
1949
1950 if (!buff)
1951 return NULL;
1952
1953 result = pnstrdup(buff, nbytes);
1954
1955 for (p = result; *p; p++)
1956 {
1957 char c;
1958
1959 if (wasalnum)
1961 else
1963
1964 wasalnum = ((c >= 'A' && c <= 'Z') ||
1965 (c >= 'a' && c <= 'z') ||
1967 }
1968
1969 return result;
1970}
1971
1972
1973
1974static char *
1976{
1978}
1979
1980static char *
1982{
1984}
1985
1986static char *
1988{
1990}
1991
1992static char *
1994{
1996}
1997
1998static char *
2000{
2002}
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013#define SKIP_THth(ptr, _suf) \
2014 do { \
2015 if (S_THth(_suf)) \
2016 { \
2017 if (*(ptr)) (ptr) += pg_mblen(ptr); \
2018 if (*(ptr)) (ptr) += pg_mblen(ptr); \
2019 } \
2020 } while (0)
2021
2022
2023#ifdef DEBUG_TO_FROM_CHAR
2024
2025
2026
2027
2028
2029static void
2030dump_index(const KeyWord *k, const int *index)
2031{
2032 int i,
2033 count = 0,
2034 free_i = 0;
2035
2036 elog(DEBUG_elog_output, "TO-FROM_CHAR: Dump KeyWord Index:");
2037
2039 {
2041 {
2042 elog(DEBUG_elog_output, "\t%c: %s, ", i + 32, k[index[i]].name);
2043 count++;
2044 }
2045 else
2046 {
2047 free_i++;
2048 elog(DEBUG_elog_output, "\t(%d) %c %d", i, i + 32, index[i]);
2049 }
2050 }
2051 elog(DEBUG_elog_output, "\n\t\tUsed positions: %d,\n\t\tFree positions: %d",
2052 count, free_i);
2053}
2054#endif
2055
2056
2057
2058
2059
2060static bool
2062{
2064 return false;
2065
2067 return true;
2068
2069
2070
2071
2072 n++;
2073
2074
2076 return true;
2077
2079 {
2081 return false;
2082
2083 return true;
2084 }
2085 else if (n->character[1] == '\0' &&
2086 isdigit((unsigned char) n->character[0]))
2087 return false;
2088
2089 return true;
2090}
2091
2092
2093static int
2095{
2096
2097
2098
2099
2100
2101 if (year < 70)
2102 return year + 2000;
2103
2104 else if (year < 100)
2105 return year + 1900;
2106
2107 else if (year < 520)
2108 return year + 2000;
2109
2110 else if (year < 1000)
2111 return year + 1000;
2112 else
2113 return year;
2114}
2115
2116
2117static int
2119{
2120 int len = 0;
2121
2122 while (*str && isspace((unsigned char) *str))
2123 {
2126 }
2127 return len;
2128}
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139static bool
2141 Node *escontext)
2142{
2144 {
2147 else if (tmfc->mode != mode)
2148 ereturn(escontext, false,
2149 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2150 errmsg("invalid combination of date conventions"),
2151 errhint("Do not mix Gregorian and ISO week date "
2152 "conventions in a formatting template.")));
2153 }
2154 return true;
2155}
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166static bool
2168 Node *escontext)
2169{
2171 ereturn(escontext, false,
2172 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2173 errmsg("conflicting values for \"%s\" field in formatting string",
2175 errdetail("This value contradicts a previous setting "
2176 "for the same field type.")));
2178 return true;
2179}
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202static int
2204 Node *escontext)
2205{
2206 long result;
2208 const char *init = *src;
2209 int used;
2210
2211
2212
2213
2215
2217 used = (int) strlcpy(copy, *src, len + 1);
2218
2220 {
2221
2222
2223
2224
2225 char *endptr;
2226
2227 errno = 0;
2228 result = strtol(init, &endptr, 10);
2229 *src = endptr;
2230 }
2231 else
2232 {
2233
2234
2235
2236
2237 char *last;
2238
2239 if (used < len)
2241 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2242 errmsg("source string too short for \"%s\" formatting field",
2244 errdetail("Field requires %d characters, but only %d remain.",
2245 len, used),
2246 errhint("If your source string is not fixed-width, "
2247 "try using the \"FM\" modifier.")));
2248
2249 errno = 0;
2250 result = strtol(copy, &last, 10);
2251 used = last - copy;
2252
2253 if (used > 0 && used < len)
2255 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2256 errmsg("invalid value \"%s\" for \"%s\"",
2258 errdetail("Field requires %d characters, but only %d could be parsed.",
2259 len, used),
2260 errhint("If your source string is not fixed-width, "
2261 "try using the \"FM\" modifier.")));
2262
2263 *src += used;
2264 }
2265
2266 if (*src == init)
2268 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2269 errmsg("invalid value \"%s\" for \"%s\"",
2271 errdetail("Value must be an integer.")));
2272
2273 if (errno == ERANGE || result < INT_MIN || result > INT_MAX)
2275 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2276 errmsg("value for \"%s\" in source string is out of range",
2278 errdetail("Value must be in the range %d to %d.",
2279 INT_MIN, INT_MAX)));
2280
2281 if (dest != NULL)
2282 {
2284 return -1;
2285 }
2286
2287 return *src - init;
2288}
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299static int
2301 Node *escontext)
2302{
2304}
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317static int
2319{
2320 unsigned char firstc;
2321 const char *const *a;
2322
2323 *len = 0;
2324
2325
2327 return -1;
2328
2329
2331
2332 for (a = array; *a != NULL; a++)
2333 {
2334 const char *p;
2335 const char *n;
2336
2337
2339 continue;
2340
2341
2342 for (p = *a + 1, n = name + 1;; p++, n++)
2343 {
2344
2345 if (*p == '\0')
2346 {
2348 return a - array;
2349 }
2350
2351 if (*n == '\0')
2352 break;
2353
2356 break;
2357 }
2358 }
2359
2360 return -1;
2361}
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374static int
2376{
2377 char **a;
2378 char *upper_name;
2379 char *lower_name;
2380
2381 *len = 0;
2382
2383
2385 return -1;
2386
2387
2388
2389
2390
2391 for (a = array; *a != NULL; a++)
2392 {
2393 int element_len = strlen(*a);
2394
2395 if (strncmp(name, *a, element_len) == 0)
2396 {
2397 *len = element_len;
2398 return a - array;
2399 }
2400 }
2401
2402
2403
2404
2405
2407 lower_name = str_tolower(upper_name, strlen(upper_name), collid);
2408 pfree(upper_name);
2409
2410 for (a = array; *a != NULL; a++)
2411 {
2412 char *upper_element;
2413 char *lower_element;
2414 int element_len;
2415
2416
2418 lower_element = str_tolower(upper_element, strlen(upper_element),
2420 pfree(upper_element);
2421 element_len = strlen(lower_element);
2422
2423
2424 if (strncmp(lower_name, lower_element, element_len) == 0)
2425 {
2426 *len = element_len;
2427 pfree(lower_element);
2428 pfree(lower_name);
2429 return a - array;
2430 }
2431 pfree(lower_element);
2432 }
2433
2434 pfree(lower_name);
2435 return -1;
2436}
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458static bool
2460 char **localized_array, Oid collid,
2462{
2463 int len;
2464
2465 if (localized_array == NULL)
2467 else
2469
2470 if (len <= 0)
2471 {
2472
2473
2474
2475
2476 char *copy = pstrdup(*src);
2477 char *c;
2478
2480 {
2482 {
2483 *c = '\0';
2484 break;
2485 }
2486 }
2487
2488 ereturn(escontext, false,
2489 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2490 errmsg("invalid value \"%s\" for \"%s\"",
2492 errdetail("The given value did not match any of "
2493 "the allowed values for this field.")));
2494 }
2495 *src += len;
2496 return true;
2497}
2498
2499
2500
2501
2502
2503
2504static void
2506{
2508 char *s;
2510 int i;
2511
2512
2514
2515 s = out;
2517 {
2519 {
2521 s += strlen(s);
2522 continue;
2523 }
2524
2526 {
2531 s += strlen(s);
2532 break;
2537 s += strlen(s);
2538 break;
2543 s += strlen(s);
2544 break;
2549 s += strlen(s);
2550 break;
2553
2554
2555
2556
2557
2564 s += strlen(s);
2565 break;
2571 s += strlen(s);
2572 break;
2578 s += strlen(s);
2579 break;
2585 s += strlen(s);
2586 break;
2587
2588#define DCH_to_char_fsec(frac_fmt, frac_val) \
2589 sprintf(s, frac_fmt, (int) (frac_val)); \
2590 if (S_THth(n->suffix)) \
2591 str_numth(s, s, S_TH_TYPE(n->suffix)); \
2592 s += strlen(s)
2593
2594 case DCH_FF1:
2596 break;
2597 case DCH_FF2:
2599 break;
2601 case DCH_MS:
2603 break;
2604 case DCH_FF4:
2606 break;
2607 case DCH_FF5:
2609 break;
2611 case DCH_US:
2613 break;
2614#undef DCH_to_char_fsec
2622 s += strlen(s);
2623 break;
2627 {
2628
2630
2631 strcpy(s, p);
2633 s += strlen(s);
2634 }
2635 break;
2639 {
2641 s += strlen(s);
2642 }
2643 break;
2649 s += strlen(s);
2650 break;
2655 s += strlen(s);
2656 break;
2663 s += strlen(s);
2665 {
2668 s += strlen(s);
2669 }
2670 break;
2675 s += strlen(s);
2676 break;
2681 s += strlen(s);
2682 break;
2687 s += strlen(s);
2688 break;
2693 s += strlen(s);
2694 break;
2698 break;
2700 {
2702
2704 strcpy(s, str);
2705 else
2707 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2708 errmsg("localized string format value too long")));
2709 }
2710 else
2713 s += strlen(s);
2714 break;
2718 break;
2720 {
2722
2724 strcpy(s, str);
2725 else
2727 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2728 errmsg("localized string format value too long")));
2729 }
2730 else
2733 s += strlen(s);
2734 break;
2738 break;
2740 {
2742
2744 strcpy(s, str);
2745 else
2747 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2748 errmsg("localized string format value too long")));
2749 }
2750 else
2753 s += strlen(s);
2754 break;
2758 break;
2760 {
2762
2764 strcpy(s, str);
2765 else
2767 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2768 errmsg("localized string format value too long")));
2769 }
2770 else
2772 s += strlen(s);
2773 break;
2777 break;
2779 {
2781
2783 strcpy(s, str);
2784 else
2786 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2787 errmsg("localized string format value too long")));
2788 }
2789 else
2791 s += strlen(s);
2792 break;
2796 break;
2798 {
2800
2802 strcpy(s, str);
2803 else
2805 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2806 errmsg("localized string format value too long")));
2807 }
2808 else
2810 s += strlen(s);
2811 break;
2817 s += strlen(s);
2818 break;
2822 {
2824
2826 strcpy(s, str);
2827 else
2829 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2830 errmsg("localized string format value too long")));
2831 }
2832 else
2835 s += strlen(s);
2836 break;
2840 {
2842
2844 strcpy(s, str);
2845 else
2847 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2848 errmsg("localized string format value too long")));
2849 }
2850 else
2853 s += strlen(s);
2854 break;
2858 {
2860
2862 strcpy(s, str);
2863 else
2865 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2866 errmsg("localized string format value too long")));
2867 }
2868 else
2871 s += strlen(s);
2872 break;
2876 {
2878
2880 strcpy(s, str);
2881 else
2883 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2884 errmsg("localized string format value too long")));
2885 }
2886 else
2888 s += strlen(s);
2889 break;
2893 {
2895
2897 strcpy(s, str);
2898 else
2900 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2901 errmsg("localized string format value too long")));
2902 }
2903 else
2905 s += strlen(s);
2906 break;
2910 {
2912
2914 strcpy(s, str);
2915 else
2917 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2918 errmsg("localized string format value too long")));
2919 }
2920 else
2922 s += strlen(s);
2923 break;
2932 s += strlen(s);
2933 break;
2938 s += strlen(s);
2939 break;
2945 s += strlen(s);
2946 break;
2952 s += strlen(s);
2953 break;
2959 s += strlen(s);
2960 break;
2966 s += strlen(s);
2967 break;
2970 break;
2974 s += strlen(s);
2975 break;
2977 if (is_interval)
2979 else
2980 {
2982
2984 else
2985
2987 }
2988 if (i <= 99 && i >= -99)
2990 else
2994 s += strlen(s);
2995 break;
3002 s += strlen(s);
3003 break;
3014 is_interval)));
3017 s += strlen(s);
3018 break;
3029 is_interval)) % 1000);
3032 s += strlen(s);
3033 break;
3044 is_interval)) % 100);
3047 s += strlen(s);
3048 break;
3057 is_interval)) % 10);
3060 s += strlen(s);
3061 break;
3063
3065
3066
3067
3068
3069
3071 break;
3072 else
3073 {
3074 int mon = 0;
3075 const char *const *months;
3076
3079 else
3081
3082
3083
3084
3085
3086
3088 {
3089
3090
3091
3092
3094 }
3096 {
3097
3098
3099
3100
3101
3102 mon = -1 * (tm->tm_mon + 1);
3103 }
3104 else
3105 {
3106
3107
3108
3109
3110
3112 }
3113
3116 s += strlen(s);
3117 }
3118 break;
3123 s += strlen(s);
3124 break;
3129 s += strlen(s);
3130 break;
3131 }
3132 }
3133
3134 *s = '\0';
3135}
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151static void
3154{
3156 const char *s;
3157 int len,
3159 bool fx_mode = std;
3160
3161
3162 int extra_skip = 0;
3163
3164
3166
3167 for (n = node, s = in; n->type != NODE_TYPE_END && *s != '\0'; n++)
3168 {
3169
3170
3171
3172
3175 {
3176 while (*s != '\0' && isspace((unsigned char) *s))
3177 {
3178 s++;
3179 extra_skip++;
3180 }
3181 }
3182
3184 {
3185 if (std)
3186 {
3187
3188
3189
3190
3192
3194 s++;
3195 else
3197 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3198 errmsg("unmatched format separator \"%c\"",
3200 }
3201 else if (!fx_mode)
3202 {
3203
3204
3205
3206
3207
3208
3209 extra_skip--;
3211 {
3212 s++;
3213 extra_skip++;
3214 }
3215 }
3216 else
3217 {
3218
3219
3220
3221
3222
3223
3225 }
3226 continue;
3227 }
3229 {
3230
3231
3232
3233
3234
3235 if (!fx_mode)
3236 {
3237
3238
3239
3240
3241
3242
3243 if (extra_skip > 0)
3244 extra_skip--;
3245 else
3247 }
3248 else
3249 {
3251
3252
3253
3254
3256 strncmp(s, n->character, chlen) != 0)
3258 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3259 errmsg("unmatched format character \"%s\"",
3261
3262 s += chlen;
3263 }
3264 continue;
3265 }
3266
3268 return;
3269
3271 {
3273 fx_mode = true;
3274 break;
3281 n, escontext))
3282 return;
3284 return;
3286 break;
3293 n, escontext))
3294 return;
3296 return;
3298 break;
3302 return;
3305 break;
3308 return;
3310 break;
3313 return;
3315 break;
3318 return;
3320 break;
3321 case DCH_MS:
3323 if (len < 0)
3324 return;
3325
3326
3327
3328
3329 out->ms *= len == 1 ? 100 :
3330 len == 2 ? 10 : 1;
3331
3333 break;
3341
3342 case DCH_US:
3345 out->ff, n, escontext);
3346 if (len < 0)
3347 return;
3348
3349 out->us *= len == 1 ? 100000 :
3350 len == 2 ? 10000 :
3351 len == 3 ? 1000 :
3352 len == 4 ? 100 :
3353 len == 5 ? 10 : 1;
3354
3356 break;
3359 return;
3361 break;
3364 {
3365 int tzlen;
3366
3369 &out->tzp);
3370 if (tzlen > 0)
3371 {
3373
3374 if (out->tzp)
3376 out->tzsign = 0;
3377 s += tzlen;
3378 break;
3379 }
3380 else if (isalpha((unsigned char) *s))
3381 {
3382
3383
3384
3385
3386
3387
3389 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3390 errmsg("invalid value \"%s\" for \"%s\"",
3392 errdetail("Time zone abbreviation is not recognized.")));
3393 }
3394
3395 }
3396
3398
3399
3400 if (*s == '+' || *s == '-' || *s == ' ')
3401 {
3402 out->tzsign = *s == '-' ? -1 : +1;
3403 s++;
3404 }
3405 else
3406 {
3407 if (extra_skip > 0 && *(s - 1) == '-')
3409 else
3411 }
3413 return;
3414 if (*s == ':')
3415 {
3416 s++;
3418 escontext) < 0)
3419 return;
3420 }
3421 break;
3423
3424
3425
3426
3427
3428
3429
3430
3431 if (*s == '+' || *s == '-' || *s == ' ')
3432 {
3433 out->tzsign = *s == '-' ? -1 : +1;
3434 s++;
3435 }
3436 else
3437 {
3438 if (extra_skip > 0 && *(s - 1) == '-')
3440 else
3442 }
3443
3445 return;
3446 break;
3448
3452 return;
3453 break;
3460 n, escontext))
3461 return;
3463 return;
3464 break;
3471 n, escontext))
3472 return;
3474 return;
3475 break;
3482 n, escontext))
3483 return;
3485 return;
3486 break;
3493 n, escontext))
3494 return;
3496 return;
3497 break;
3500 return;
3502 break;
3509 n, escontext))
3510 return;
3512 return;
3513 out->d++;
3514 break;
3521 n, escontext))
3522 return;
3524 return;
3525 out->d++;
3526 break;
3529 return;
3531 break;
3534 return;
3536 break;
3539 return;
3541 break;
3544 return;
3546 break;
3549 return;
3550
3551 if (++out->d > 7)
3552 out->d = 1;
3554 break;
3558 return;
3560 break;
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3574 return;
3576 break;
3579 return;
3581 break;
3583 {
3584 int matched,
3585 years,
3586 millennia,
3587 nch;
3588
3589 matched = sscanf(s, "%d,%03d%n", &millennia, &years, &nch);
3590 if (matched < 2)
3592 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3593 errmsg("invalid input string for \"Y,YYY\"")));
3594
3595
3599 (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3600 errmsg("value for \"Y,YYY\" in source string is out of range")));
3601
3603 return;
3604 out->yysz = 4;
3605 s += nch;
3607 }
3608 break;
3612 return;
3613 out->yysz = 4;
3615 break;
3619 if (len < 0)
3620 return;
3621 if (len < 4)
3623 out->yysz = 3;
3625 break;
3629 if (len < 0)
3630 return;
3631 if (len < 4)
3633 out->yysz = 2;
3635 break;
3639 if (len < 0)
3640 return;
3641 if (len < 4)
3643 out->yysz = 1;
3645 break;
3650 n, escontext))
3651 return;
3653 escontext))
3654 return;
3655 break;
3658 return;
3660 break;
3663 return;
3665 break;
3666 }
3667
3668
3669 if (!fx_mode)
3670 {
3671 extra_skip = 0;
3672 while (*s != '\0' && isspace((unsigned char) *s))
3673 {
3674 s++;
3675 extra_skip++;
3676 }
3677 }
3678 }
3679
3680
3681
3682
3683
3684 if (std)
3685 {
3688 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3689 errmsg("input string is too short for datetime format")));
3690
3691 while (*s != '\0' && isspace((unsigned char) *s))
3692 s++;
3693
3694 if (*s != '\0')
3696 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3697 errmsg("trailing characters remain in input string after datetime format")));
3698 }
3699}
3700
3701
3702
3703
3704
3705
3706
3707
3708static inline void
3710{
3712 {
3716 }
3717}
3718
3719
3720
3721
3722static int
3724{
3726 int flags = 0;
3727
3729 {
3731 continue;
3732
3734 {
3736 break;
3750 case DCH_MS:
3751 case DCH_US:
3760 break;
3767 break;
3811 break;
3812 }
3813 }
3814
3815 return flags;
3816}
3817
3818
3821{
3823
3824
3826
3827
3828
3829
3831 {
3833
3834#ifdef DEBUG_TO_FROM_CHAR
3835 elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
3836#endif
3838 {
3840 {
3842 if (!ent->valid)
3843 {
3844 old = ent;
3845 break;
3846 }
3848 old = ent;
3849 }
3850 }
3851#ifdef DEBUG_TO_FROM_CHAR
3852 elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
3853#endif
3854 old->valid = false;
3857
3858 return old;
3859 }
3860 else
3861 {
3862#ifdef DEBUG_TO_FROM_CHAR
3864#endif
3868 ent->valid = false;
3870 ent->std = std;
3872
3874 return ent;
3875 }
3876}
3877
3878
3881{
3882
3884
3886 {
3888
3889 if (ent->valid && strcmp(ent->str, str) == 0 && ent->std == std)
3890 {
3892 return ent;
3893 }
3894 }
3895
3896 return NULL;
3897}
3898
3899
3902{
3904
3906 {
3907
3908
3909
3910
3911
3913
3916
3917 ent->valid = true;
3918 }
3919 return ent;
3920}
3921
3922
3923
3924
3925
3926
3927static text *
3929{
3931 char *fmt_str,
3932 *result;
3933 bool incache;
3934 int fmt_len;
3936
3937
3938
3939
3941 fmt_len = strlen(fmt_str);
3942
3943
3944
3945
3947 *result = '\0';
3948
3950 {
3951
3952
3953
3954
3955 incache = false;
3956
3958
3961 }
3962 else
3963 {
3964
3965
3966
3968
3969 incache = true;
3971 }
3972
3973
3975
3976 if (!incache)
3978
3980
3981
3983
3985 return res;
3986}
3987
3988
3989
3990
3991
3992
3993
3994
3995
3998{
4001 *res;
4003 struct pg_tm tt;
4005 int thisdate;
4006
4009
4012
4015 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4016 errmsg("timestamp out of range")));
4017
4018
4020 tt.tm_wday = (thisdate + 1) % 7;
4022
4024
4027
4029}
4030
4033{
4036 *res;
4038 int tz;
4039 struct pg_tm tt;
4041 int thisdate;
4042
4045
4048
4051 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4052 errmsg("timestamp out of range")));
4053
4054
4056 tt.tm_wday = (thisdate + 1) % 7;
4058
4060
4063
4065}
4066
4067
4068
4069
4070
4071
4074{
4077 *res;
4081 *itm = &tt;
4082
4085
4088
4097
4098
4100
4103
4105}
4106
4107
4108
4109
4110
4111
4112
4113
4116{
4121 int tz;
4125 int fprec;
4126
4128 &tm, &fsec, &ftz, &fprec, NULL, NULL);
4129
4130
4133 else
4135
4138 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4139 errmsg("timestamp out of range")));
4140
4141
4142 if (fprec)
4144
4146}
4147
4148
4149
4150
4151
4152
4155{
4163
4165 &tm, &fsec, &ftz, NULL, NULL, NULL);
4166
4167
4170 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4171 errmsg("date out of range: \"%s\"",
4173
4175
4176
4179 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4180 errmsg("date out of range: \"%s\"",
4182
4184}
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4203 Oid *typid, int32 *typmod, int *tz,
4204 Node *escontext)
4205{
4209 int fprec;
4211
4213 &tm, &fsec, &ftz, &fprec, &flags, escontext))
4214 return (Datum) 0;
4215
4216 *typmod = fprec ? fprec : -1;
4217
4219 {
4221 {
4223 {
4225
4227 {
4229 }
4230 else
4231 {
4232
4233
4234
4235
4236
4238
4240 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4241 errmsg("missing time zone in input string for type timestamptz")));
4242 }
4243
4246 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4247 errmsg("timestamptz out of range")));
4248
4250
4251 *typid = TIMESTAMPTZOID;
4253 }
4254 else
4255 {
4257
4260 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4261 errmsg("timestamp out of range")));
4262
4264
4265 *typid = TIMESTAMPOID;
4267 }
4268 }
4269 else
4270 {
4272 {
4274 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4275 errmsg("datetime format is zoned but not timed")));
4276 }
4277 else
4278 {
4280
4281
4284 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4285 errmsg("date out of range: \"%s\"",
4287
4290
4291
4294 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4295 errmsg("date out of range: \"%s\"",
4297
4298 *typid = DATEOID;
4300 }
4301 }
4302 }
4304 {
4306 {
4308
4310 {
4312 }
4313 else
4314 {
4315
4316
4317
4318
4319
4321
4323 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4324 errmsg("missing time zone in input string for type timetz")));
4325 }
4326
4327 if (tm2timetz(&tm, fsec, *tz, result) != 0)
4329 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4330 errmsg("timetz out of range")));
4331
4333
4334 *typid = TIMETZOID;
4336 }
4337 else
4338 {
4340
4341 if (tm2time(&tm, fsec, &result) != 0)
4343 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4344 errmsg("time out of range")));
4345
4347
4348 *typid = TIMEOID;
4350 }
4351 }
4352 else
4353 {
4355 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4356 errmsg("datetime format is not dated and not timed")));
4357 }
4358}
4359
4360
4361
4362
4363
4364bool
4366{
4367 bool incache;
4368 int fmt_len = strlen(fmt_str);
4369 int result;
4371
4373 {
4374
4375
4376
4377
4378 incache = false;
4379
4381
4384 }
4385 else
4386 {
4387
4388
4389
4391
4392 incache = true;
4394 }
4395
4397
4398 if (!incache)
4400
4402}
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427static bool
4430 int *fprec, uint32 *flags, Node *escontext)
4431{
4434 int fmt_len;
4435 char *date_str;
4436 int fmask;
4437 bool incache = false;
4438
4440 Assert(fsec != NULL);
4441
4443
4446 *fsec = 0;
4448 if (fprec)
4449 *fprec = 0;
4450 if (flags)
4451 *flags = 0;
4452 fmask = 0;
4453
4455
4456 if (fmt_len)
4457 {
4458 char *fmt_str;
4459
4461
4463 {
4464
4465
4466
4467
4469
4472 }
4473 else
4474 {
4475
4476
4477
4479
4480 incache = true;
4482 }
4483
4484#ifdef DEBUG_TO_FROM_CHAR
4485
4486
4487#endif
4488
4492 goto fail;
4493
4494 if (flags)
4496
4497 if (!incache)
4498 {
4501 }
4502 }
4503
4505
4506
4507
4508
4509 if (tmfc.ssss)
4510 {
4512
4518 }
4519
4520 if (tmfc.ss)
4522 if (tmfc.mi)
4524 if (tmfc.hh)
4526
4528 {
4530 {
4532 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4533 errmsg("hour \"%d\" is invalid for the 12-hour clock",
4535 errhint("Use the 24-hour clock, or give an hour between 1 and 12.")));
4536 goto fail;
4537 }
4538
4543 }
4544
4545 if (tmfc.year)
4546 {
4547
4548
4549
4550
4551
4552
4553 if (tmfc.cc && tmfc.yysz <= 2)
4554 {
4555 if (tmfc.bc)
4559 {
4560 int tmp;
4561
4562 if (tmfc.cc >= 0)
4563 {
4564
4565 tmp = tmfc.cc - 1;
4568 {
4571 escontext);
4572 goto fail;
4573 }
4574 }
4575 else
4576 {
4577
4578 tmp = tmfc.cc + 1;
4582 {
4585 escontext);
4586 goto fail;
4587 }
4588 }
4589 }
4590 else
4591 {
4592
4593 tm->tm_year = tmfc.cc * 100 + ((tmfc.cc >= 0) ? 0 : 1);
4594 }
4595 }
4596 else
4597 {
4598
4600 if (tmfc.bc)
4602
4605 }
4607 }
4608 else if (tmfc.cc)
4609 {
4610
4611 if (tmfc.bc)
4613 if (tmfc.cc >= 0)
4614 {
4615
4616
4619 {
4622 escontext);
4623 goto fail;
4624 }
4625 }
4626 else
4627 {
4628
4629
4632 {
4635 escontext);
4636 goto fail;
4637 }
4638 }
4640 }
4641
4642 if (tmfc.j)
4643 {
4646 }
4647
4648 if (tmfc.ww)
4649 {
4651 {
4652
4653
4654
4655
4656 if (tmfc.d)
4658 else
4661 }
4662 else
4663 {
4664
4668 {
4670 date_str, "timestamp", escontext);
4671 goto fail;
4672 }
4673 }
4674 }
4675
4676 if (tmfc.w)
4677 {
4678
4682 {
4684 date_str, "timestamp", escontext);
4685 goto fail;
4686 }
4687 }
4688 if (tmfc.dd)
4689 {
4692 }
4693 if (tmfc.mm)
4694 {
4697 }
4698
4700 {
4701
4702
4703
4704
4705
4706
4707
4709 {
4711 (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4712 errmsg("cannot calculate day of year without year information")));
4713 goto fail;
4714 }
4715
4717 {
4718 int j0;
4719
4721
4724 }
4725 else
4726 {
4727 const int *y;
4728 int i;
4729
4730 static const int ysum[2][13] = {
4731 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
4732 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
4733
4735
4737 {
4739 break;
4740 }
4743
4746
4748 }
4749 }
4750
4751 if (tmfc.ms)
4752 {
4753 int tmp = 0;
4754
4755
4758 {
4760 date_str, "timestamp", escontext);
4761 goto fail;
4762 }
4763 }
4764 if (tmfc.us)
4765 *fsec += tmfc.us;
4766 if (fprec)
4767 *fprec = tmfc.ff;
4768
4769
4770 if (fmask != 0)
4771 {
4772
4773 int dterr = ValidateDate(fmask, true, false, false, tm);
4774
4775 if (dterr != 0)
4776 {
4777
4778
4779
4780
4781
4783 date_str, "timestamp", escontext);
4784 goto fail;
4785 }
4786 }
4787
4788
4793 {
4795 date_str, "timestamp", escontext);
4796 goto fail;
4797 }
4798
4799
4800
4801
4802
4803
4805 {
4806
4809 {
4811 date_str, "timestamp", escontext);
4812 goto fail;
4813 }
4814
4817
4818 if (tmfc.tzsign > 0)
4820 }
4821 else if (tmfc.has_tz)
4822 {
4823
4825 if (tmfc.tzp == NULL)
4826 {
4827
4829 }
4830 else
4831 {
4832
4834 tmfc.tzp);
4835 }
4836 }
4837
4839
4840 if (format && !incache)
4842 pfree(date_str);
4843
4844 return true;
4845
4846fail:
4847 if (format && !incache)
4849 pfree(date_str);
4850
4851 return false;
4852}
4853
4854
4855
4856
4857
4858
4859
4860static char *
4862{
4864 *(str + max) = '\0';
4865 return str;
4866}
4867
4868#define zeroize_NUM(_n) \
4869do { \
4870 (_n)->flag = 0; \
4871 (_n)->lsign = 0; \
4872 (_n)->pre = 0; \
4873 (_n)->post = 0; \
4874 (_n)->pre_lsign_num = 0; \
4875 (_n)->need_locale = 0; \
4876 (_n)->multi = 0; \
4877 (_n)->zero_start = 0; \
4878 (_n)->zero_end = 0; \
4879} while(0)
4880
4881
4882static inline void
4884{
4886 {
4890 }
4891}
4892
4893
4896{
4898
4899
4901
4902
4903
4904
4906 {
4908
4909#ifdef DEBUG_TO_FROM_CHAR
4910 elog(DEBUG_elog_output, "Cache is full (%d)", n_NUMCache);
4911#endif
4913 {
4915 {
4917 if (!ent->valid)
4918 {
4919 old = ent;
4920 break;
4921 }
4923 old = ent;
4924 }
4925 }
4926#ifdef DEBUG_TO_FROM_CHAR
4927 elog(DEBUG_elog_output, "OLD: \"%s\" AGE: %d", old->str, old->age);
4928#endif
4929 old->valid = false;
4932
4933 return old;
4934 }
4935 else
4936 {
4937#ifdef DEBUG_TO_FROM_CHAR
4939#endif
4943 ent->valid = false;
4946
4948 return ent;
4949 }
4950}
4951
4952
4955{
4956
4958
4960 {
4962
4963 if (ent->valid && strcmp(ent->str, str) == 0)
4964 {
4966 return ent;
4967 }
4968 }
4969
4970 return NULL;
4971}
4972
4973
4976{
4978
4980 {
4981
4982
4983
4984
4985
4987
4989
4992
4993 ent->valid = true;
4994 }
4995 return ent;
4996}
4997
4998
4999
5000
5001
5004{
5006 char *str;
5007
5009
5011 {
5012
5013
5014
5015
5017
5018 *shouldFree = true;
5019
5021
5024 }
5025 else
5026 {
5027
5028
5029
5031
5032 *shouldFree = false;
5033
5035
5036
5037
5038
5048 }
5049
5050#ifdef DEBUG_TO_FROM_CHAR
5051
5053#endif
5054
5057}
5058
5059
5060
5061
5062
5063
5064
5065static char *
5067{
5068 int len,
5069 num;
5070 char *p,
5071 *result,
5072 numstr[12];
5073
5075 *result = '\0';
5076
5077
5078
5079
5080
5081
5082 if (number > 3999 || number < 1)
5083 {
5085 return result;
5086 }
5087
5088
5089 len = snprintf(numstr, sizeof(numstr), "%d", number);
5091
5092 for (p = numstr; *p != '\0'; p++, --len)
5093 {
5094 num = *p - ('0' + 1);
5095 if (num < 0)
5096 continue;
5097
5098 switch (len)
5099 {
5100 case 4:
5101 while (num-- >= 0)
5102 strcat(result, "M");
5103 break;
5104 case 3:
5105 strcat(result, rm100[num]);
5106 break;
5107 case 2:
5108 strcat(result, rm10[num]);
5109 break;
5110 case 1:
5111 strcat(result, rm1[num]);
5112 break;
5113 }
5114 }
5115 return result;
5116}
5117
5118
5119
5120
5121
5122
5123
5124
5125static int
5127{
5128 int result = 0;
5129 int len;
5132 int repeatCount = 1;
5133 int vCount = 0,
5134 lCount = 0,
5135 dCount = 0;
5136 bool subtractionEncountered = false;
5137 int lastSubtractedValue = 0;
5138
5139
5140
5141
5142
5145
5146
5147
5148
5149
5150
5151
5153 {
5155 int currValue = ROMAN_VAL(currChar);
5156
5157 if (currValue == 0)
5158 break;
5159 romanChars[len] = currChar;
5160 romanValues[len] = currValue;
5162 }
5163
5164 if (len == 0)
5165 return -1;
5166
5167
5168 for (int i = 0; i < len; i++)
5169 {
5170 char currChar = romanChars[i];
5171 int currValue = romanValues[i];
5172
5173
5174
5175
5176
5177 if (subtractionEncountered && currValue >= lastSubtractedValue)
5178 return -1;
5179
5180
5181
5182
5183
5184 if ((vCount && currValue >= ROMAN_VAL('V')) ||
5185 (lCount && currValue >= ROMAN_VAL('L')) ||
5186 (dCount && currValue >= ROMAN_VAL('D')))
5187 return -1;
5188 if (currChar == 'V')
5189 vCount++;
5190 else if (currChar == 'L')
5191 lCount++;
5192 else if (currChar == 'D')
5193 dCount++;
5194
5196 {
5197
5198 char nextChar = romanChars[i + 1];
5199 int nextValue = romanValues[i + 1];
5200
5201
5202
5203
5204
5205
5206 if (currValue < nextValue)
5207 {
5209 return -1;
5210
5211
5212
5213
5214
5215 if (repeatCount > 1)
5216 return -1;
5217
5218
5219
5220
5221
5222
5223 if ((vCount && nextValue >= ROMAN_VAL('V')) ||
5224 (lCount && nextValue >= ROMAN_VAL('L')) ||
5225 (dCount && nextValue >= ROMAN_VAL('D')))
5226 return -1;
5227 if (nextChar == 'V')
5228 vCount++;
5229 else if (nextChar == 'L')
5230 lCount++;
5231 else if (nextChar == 'D')
5232 dCount++;
5233
5234
5235
5236
5237
5238 i++;
5239
5240
5241 repeatCount = 1;
5242 subtractionEncountered = true;
5243 lastSubtractedValue = currValue;
5244 result += (nextValue - currValue);
5245 }
5246 else
5247 {
5248
5249 if (currChar == nextChar)
5250 {
5251 repeatCount++;
5252 if (repeatCount > 3)
5253 return -1;
5254 }
5255 else
5256 repeatCount = 1;
5257 result += currValue;
5258 }
5259 }
5260 else
5261 {
5262
5263 result += currValue;
5264 }
5265 }
5266
5267 return result;
5268}
5269
5270
5271
5272
5273
5274
5275static void
5277{
5279 {
5280 struct lconv *lconv;
5281
5282
5283
5284
5286
5287
5288
5289
5290 if (lconv->negative_sign && *lconv->negative_sign)
5292 else
5294
5295 if (lconv->positive_sign && *lconv->positive_sign)
5297 else
5299
5300
5301
5302
5303 if (lconv->decimal_point && *lconv->decimal_point)
5304 Np->decimal = lconv->decimal_point;
5305
5306 else
5308
5311
5312
5313
5314
5315
5316
5317
5318
5319 if (lconv->thousands_sep && *lconv->thousands_sep)
5321
5322 else if (strcmp(Np->decimal, ",") != 0)
5324 else
5326
5327
5328
5329
5330 if (lconv->currency_symbol && *lconv->currency_symbol)
5332 else
5334 }
5335 else
5336 {
5337
5338
5339
5343
5346 }
5347}
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357static char *
5359{
5360 char *result,
5361 *p = strchr(num, '.');
5362
5363#ifdef DEBUG_TO_FROM_CHAR
5364 elog(DEBUG_elog_output, "get_last_relevant_decnum()");
5365#endif
5366
5367 if (!p)
5368 return NULL;
5369
5370 result = p;
5371
5372 while (*(++p))
5373 {
5374 if (*p != '0')
5375 result = p;
5376 }
5377
5378 return result;
5379}
5380
5381
5382
5383
5384
5385static void
5387{
5388 bool isread = false;
5389
5390#ifdef DEBUG_TO_FROM_CHAR
5391 elog(DEBUG_elog_output, " --- scan start --- id=%s",
5392 (id == NUM_0 || id == NUM_9) ? "NUM_0/9" : id == NUM_DEC ? "NUM_DEC" : "???");
5393#endif
5394
5396 return;
5397
5398 if (*Np->inout_p == ' ')
5400
5402 return;
5403
5404
5405
5406
5409 {
5410#ifdef DEBUG_TO_FROM_CHAR
5411 elog(DEBUG_elog_output, "Try read sign (%c), locale positive: %s, negative: %s",
5413#endif
5414
5415
5416
5417
5419 {
5420 int x = 0;
5421
5422#ifdef DEBUG_TO_FROM_CHAR
5423 elog(DEBUG_elog_output, "Try read locale pre-sign (%c)", *Np->inout_p);
5424#endif
5428 {
5431 }
5435 {
5438 }
5439 }
5440 else
5441 {
5442#ifdef DEBUG_TO_FROM_CHAR
5443 elog(DEBUG_elog_output, "Try read simple sign (%c)", *Np->inout_p);
5444#endif
5445
5446
5447
5448
5451 {
5452 *Np->number = '-';
5454 }
5455 else if (*Np->inout_p == '+')
5456 {
5457 *Np->number = '+';
5459 }
5460 }
5461 }
5462
5464 return;
5465
5466#ifdef DEBUG_TO_FROM_CHAR
5467 elog(DEBUG_elog_output, "Scan for numbers (%c), current number: '%s'", *Np->inout_p, Np->number);
5468#endif
5469
5470
5471
5472
5473 if (isdigit((unsigned char) *Np->inout_p))
5474 {
5476 return;
5477
5480
5483 else
5485
5486 isread = true;
5487
5488#ifdef DEBUG_TO_FROM_CHAR
5489 elog(DEBUG_elog_output, "Read digit (%c)", *Np->inout_p);
5490#endif
5491 }
5493 {
5494
5495
5496
5497
5498
5499 int x = strlen(Np->decimal);
5500
5501#ifdef DEBUG_TO_FROM_CHAR
5502 elog(DEBUG_elog_output, "Try read decimal point (%c)",
5504#endif
5506 {
5511 isread = true;
5512 }
5513 }
5514
5516 return;
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5528 {
5529
5530
5531
5532
5533
5535 (Np->inout_p + 1) < Np->inout + input_len &&
5536 !isdigit((unsigned char) *(Np->inout_p + 1)))
5537 {
5538 int x;
5539 char *tmp = Np->inout_p++;
5540
5541#ifdef DEBUG_TO_FROM_CHAR
5542 elog(DEBUG_elog_output, "Try read locale post-sign (%c)", *Np->inout_p);
5543#endif
5547 {
5550 }
5554 {
5557 }
5558 if (*Np->number == ' ')
5559
5561 }
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573 else if (isread == false && IS_LSIGN(Np->Num) == false &&
5575 {
5576#ifdef DEBUG_TO_FROM_CHAR
5577 elog(DEBUG_elog_output, "Try read simple post-sign (%c)", *Np->inout_p);
5578#endif
5579
5580
5581
5582
5584
5586 }
5587 }
5588}
5589
5590#define IS_PREDEC_SPACE(_n) \
5591 (IS_ZERO((_n)->Num)==false && \
5592 (_n)->number == (_n)->number_p && \
5593 *(_n)->number == '0' && \
5594 (_n)->Num->post != 0)
5595
5596
5597
5598
5599
5600static void
5602{
5603 int end;
5604
5606 return;
5607
5608
5609
5610#ifdef DEBUG_TO_FROM_CHAR
5611
5612
5613
5614
5615
5616 elog(DEBUG_elog_output,
5617 "SIGN_WROTE: %d, CURRENT: %d, NUMBER_P: \"%s\", INOUT: \"%s\"",
5622#endif
5624
5625
5626
5627
5628
5632 {
5634 {
5636 {
5637 if (Np->sign == '-')
5639 else
5643 }
5644 }
5646 {
5647 *Np->inout_p = Np->sign == '+' ? ' ' : '<';
5650 }
5651 else if (Np->sign == '+')
5652 {
5654 {
5655 *Np->inout_p = ' ';
5657 }
5659 }
5660 else if (Np->sign == '-')
5661 {
5665 }
5666 }
5667
5668
5669
5670
5671
5673 {
5676 {
5677
5678
5679
5681 {
5682 *Np->inout_p = ' ';
5684 }
5685 }
5689 {
5690
5691
5692
5693 *Np->inout_p = '0';
5696 }
5697 else
5698 {
5699
5700
5701
5703 {
5705 {
5708 }
5709
5710
5711
5712
5715 {
5718 }
5719 }
5720 else
5721 {
5722
5723
5724
5727 ;
5728
5729
5730
5731
5733 {
5735 {
5738 }
5739
5740
5741
5742
5744 {
5747 }
5748 }
5749 else
5750 {
5754 }
5755 }
5756
5759 }
5760
5762
5765
5766 if (Np->num_curr + 1 == end)
5767 {
5769 {
5770 *Np->inout_p = Np->sign == '+' ? ' ' : '>';
5772 }
5774 {
5775 if (Np->sign == '-')
5777 else
5780 }
5781 }
5782 }
5783
5785}
5786
5787
5788
5789
5790static void
5792{
5793 while (n-- > 0)
5794 {
5796 break;
5797 if (strchr("0123456789.,+-", *Np->inout_p) != NULL)
5798 break;
5800 }
5801}
5802
5803static char *
5805 char *number, int input_len, int to_char_out_pre_spaces,
5807{
5810 *Np = &_Np;
5811 const char *pattern;
5812 int pattern_len;
5813
5815
5816 Np->Num = Num;
5818 Np->number = number;
5819 Np->inout = inout;
5824
5827
5829 {
5832 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5833 errmsg("\"EEEE\" not supported for input")));
5834 return strcpy(inout, number);
5835 }
5836
5837
5838
5839
5840 if (is_to_char)
5841 {
5843
5844
5846 {
5848 Np->sign_wrote = false;
5849 else
5850 Np->sign_wrote = true;
5851 }
5852 else
5853 {
5854 if (Np->sign != '-')
5855 {
5857 Np->Num->flag &= ~NUM_F_BRACKET;
5858 }
5859
5861 Np->sign_wrote = true;
5862 else
5863 Np->sign_wrote = false;
5864
5867 }
5868 }
5869 else
5870 Np->sign = false;
5871
5872
5873
5874
5876
5877 if (is_to_char)
5878 {
5880
5882 {
5884
5885
5886
5887
5888
5889
5890
5892 {
5893 int last_zero_pos;
5894 char *last_zero;
5895
5896
5897 last_zero_pos = strlen(Np->number) - 1;
5898 last_zero_pos = Min(last_zero_pos,
5900 last_zero = Np->number + last_zero_pos;
5903 }
5904 }
5905
5908 }
5909 else
5910 {
5912 *Np->number = ' ';
5913 *(Np->number + 1) = '\0';
5914 }
5915
5918
5919#ifdef DEBUG_TO_FROM_CHAR
5920 elog(DEBUG_elog_output,
5921 "\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",
5939 );
5940#endif
5941
5942
5943
5944
5946
5947
5948
5949
5952 else
5953 Np->number_p = Np->number + 1;
5954
5956 {
5958 {
5959
5960
5961
5962
5963
5965 break;
5966 }
5967
5968
5969
5970
5972 {
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5986 {
5992 {
5994 continue;
5995 }
5996 else
5997 {
5999 break;
6000 }
6001
6004 {
6006 {
6008 continue;
6009 else
6011 }
6012 else
6014 }
6015 else
6016 {
6018 {
6020 continue;
6021 }
6022 if (*Np->inout_p != ',')
6023 continue;
6024 }
6025 break;
6026
6029 pattern_len = strlen(pattern);
6031 {
6033 {
6035 continue;
6036 else
6037 {
6038
6040 memset(Np->inout_p, ' ', pattern_len);
6041 Np->inout_p += pattern_len - 1;
6042 }
6043 }
6044 else
6045 {
6046 strcpy(Np->inout_p, pattern);
6047 Np->inout_p += pattern_len - 1;
6048 }
6049 }
6050 else
6051 {
6053 {
6055 continue;
6056 }
6057
6058
6059
6060
6061
6062
6063
6065 strncmp(Np->inout_p, pattern, pattern_len) == 0)
6066 Np->inout_p += pattern_len - 1;
6067 else
6068 continue;
6069 }
6070 break;
6071
6075 {
6076 strcpy(Np->inout_p, pattern);
6077 Np->inout_p += strlen(pattern) - 1;
6078 }
6079 else
6080 {
6082 continue;
6083 }
6084 break;
6085
6089 {
6090 const char *number_p;
6091
6094 else
6097 strcpy(Np->inout_p, number_p);
6098 else
6101 }
6102 else
6103 {
6104 int roman_result = roman_to_int(Np, input_len);
6105 int numlen;
6106
6107 if (roman_result < 0)
6109 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
6110 errmsg("invalid Roman numeral")));
6115 continue;
6116 }
6117 break;
6118
6122 continue;
6123
6125 {
6128 }
6129 else
6130 {
6131
6133 continue;
6134 }
6135 break;
6136
6140 continue;
6141
6143 {
6146 }
6147 else
6148 {
6149
6151 continue;
6152 }
6153 break;
6154
6157 {
6158 if (Np->sign == '-')
6161 continue;
6162 else
6164 }
6165 else
6166 {
6167 if (*Np->inout_p == '-')
6169 else
6170 {
6172 continue;
6173 }
6174 }
6175 break;
6176
6179 {
6180 if (Np->sign == '+')
6183 continue;
6184 else
6186 }
6187 else
6188 {
6189 if (*Np->inout_p == '+')
6191 else
6192 {
6194 continue;
6195 }
6196 }
6197 break;
6198
6202 else
6203 {
6204 if (*Np->inout_p == '-')
6206 else if (*Np->inout_p == '+')
6208 else
6209 {
6211 continue;
6212 }
6213 }
6214 break;
6215
6216 default:
6217 continue;
6218 break;
6219 }
6220 }
6221 else
6222 {
6223
6224
6225
6226
6227
6228
6230 {
6233 }
6234 else
6235 {
6237 }
6238 continue;
6239 }
6241 }
6242
6244 {
6246 return Np->inout;
6247 }
6248 else
6249 {
6250 if (*(Np->number_p - 1) == '.')
6252 else
6254
6255
6256
6257
6259
6260#ifdef DEBUG_TO_FROM_CHAR
6261 elog(DEBUG_elog_output, "TO_NUMBER (number): '%s'", Np->number);
6262#endif
6264 }
6265}
6266
6267
6268
6269
6270
6271
6272#define NUM_TOCHAR_prepare \
6273do { \
6274 int len = VARSIZE_ANY_EXHDR(fmt); \
6275 if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ) \
6276 PG_RETURN_TEXT_P(cstring_to_text("")); \
6277 result = (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
6278 format = NUM_cache(len, &Num, fmt, &shouldFree); \
6279} while (0)
6280
6281
6282
6283
6284
6285#define NUM_TOCHAR_finish \
6286do { \
6287 int len; \
6288 \
6289 NUM_processor(format, &Num, VARDATA(result), numstr, 0, out_pre_spaces, sign, true, PG_GET_COLLATION()); \
6290 \
6291 if (shouldFree) \
6292 pfree(format); \
6293 \
6294
6295
6296
6297
6298 \
6299 len = strlen(VARDATA(result)); \
6300 SET_VARSIZE(result, len + VARHDRSZ); \
6301} while (0)
6302
6303
6305
6306
6309{
6315 char *numstr;
6316 bool shouldFree;
6317 int len = 0;
6319 precision;
6320
6322
6325
6327
6329
6332
6335
6336 if (shouldFree)
6338
6343
6345 {
6349
6354 result,
6356 }
6357
6359 return result;
6360}
6361
6362
6364
6365
6368{
6373 text *result;
6374 bool shouldFree;
6375 int out_pre_spaces = 0,
6377 char *numstr,
6378 *orgnum,
6379 *p;
6380
6382
6383
6384
6385
6387 {
6389 bool err;
6390
6391
6393
6394 if (err)
6397 }
6399 {
6401
6402
6403
6404
6405
6406
6407
6408 if (strcmp(orgnum, "NaN") == 0 ||
6409 strcmp(orgnum, "Infinity") == 0 ||
6410 strcmp(orgnum, "-Infinity") == 0)
6411 {
6412
6413
6414
6415
6416 numstr = (char *) palloc(Num.pre + Num.post + 7);
6418 *numstr = ' ';
6419 *(numstr + Num.pre + 1) = '.';
6420 }
6421 else if (*orgnum != '-')
6422 {
6423 numstr = (char *) palloc(strlen(orgnum) + 2);
6424 *numstr = ' ';
6425 strcpy(numstr + 1, orgnum);
6426 }
6427 else
6428 {
6429 numstr = orgnum;
6430 }
6431 }
6432 else
6433 {
6434 int numstr_pre_len;
6437
6439 {
6442
6450 }
6451
6457
6458 if (*orgnum == '-')
6459 {
6461 numstr = orgnum + 1;
6462 }
6463 else
6464 {
6466 numstr = orgnum;
6467 }
6468
6469 if ((p = strchr(numstr, '.')))
6470 numstr_pre_len = p - numstr;
6471 else
6472 numstr_pre_len = strlen(numstr);
6473
6474
6475 if (numstr_pre_len < Num.pre)
6476 out_pre_spaces = Num.pre - numstr_pre_len;
6477
6478 else if (numstr_pre_len > Num.pre)
6479 {
6480 numstr = (char *) palloc(Num.pre + Num.post + 2);
6482 *(numstr + Num.pre) = '.';
6483 }
6484 }
6485
6488}
6489
6490
6492
6493
6496{
6501 text *result;
6502 bool shouldFree;
6503 int out_pre_spaces = 0,
6505 char *numstr,
6506 *orgnum;
6507
6509
6510
6511
6512
6516 {
6517
6519
6521
6522
6523
6524
6525 if (*orgnum == '+')
6526 *orgnum = ' ';
6527
6528 numstr = orgnum;
6529 }
6530 else
6531 {
6532 int numstr_pre_len;
6533
6535 {
6539 }
6540 else
6541 {
6544 }
6545
6546 if (*orgnum == '-')
6547 {
6549 orgnum++;
6550 }
6551 else
6553
6554 numstr_pre_len = strlen(orgnum);
6555
6556
6557 if (Num.post)
6558 {
6559 numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
6560 strcpy(numstr, orgnum);
6561 *(numstr + numstr_pre_len) = '.';
6562 memset(numstr + numstr_pre_len + 1, '0', Num.post);
6563 *(numstr + numstr_pre_len + Num.post + 1) = '\0';
6564 }
6565 else
6566 numstr = orgnum;
6567
6568
6569 if (numstr_pre_len < Num.pre)
6570 out_pre_spaces = Num.pre - numstr_pre_len;
6571
6572 else if (numstr_pre_len > Num.pre)
6573 {
6574 numstr = (char *) palloc(Num.pre + Num.post + 2);
6576 *(numstr + Num.pre) = '.';
6577 }
6578 }
6579
6582}
6583
6584
6586
6587
6590{
6595 text *result;
6596 bool shouldFree;
6597 int out_pre_spaces = 0,
6599 char *numstr,
6600 *orgnum;
6601
6603
6604
6605
6606
6608 {
6610
6611
6612 if (value <= PG_INT32_MAX && value >= PG_INT32_MIN)
6614 else
6617 }
6619 {
6620
6623
6624
6625
6626
6627
6628
6629 if (*orgnum != '-')
6630 {
6631 numstr = (char *) palloc(strlen(orgnum) + 2);
6632 *numstr = ' ';
6633 strcpy(numstr + 1, orgnum);
6634 }
6635 else
6636 {
6637 numstr = orgnum;
6638 }
6639 }
6640 else
6641 {
6642 int numstr_pre_len;
6643
6645 {
6646 double multi = pow((double) 10, (double) Num.multi);
6647
6653 }
6654
6657
6658 if (*orgnum == '-')
6659 {
6661 orgnum++;
6662 }
6663 else
6665
6666 numstr_pre_len = strlen(orgnum);
6667
6668
6669 if (Num.post)
6670 {
6671 numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
6672 strcpy(numstr, orgnum);
6673 *(numstr + numstr_pre_len) = '.';
6674 memset(numstr + numstr_pre_len + 1, '0', Num.post);
6675 *(numstr + numstr_pre_len + Num.post + 1) = '\0';
6676 }
6677 else
6678 numstr = orgnum;
6679
6680
6681 if (numstr_pre_len < Num.pre)
6682 out_pre_spaces = Num.pre - numstr_pre_len;
6683
6684 else if (numstr_pre_len > Num.pre)
6685 {
6686 numstr = (char *) palloc(Num.pre + Num.post + 2);
6688 *(numstr + Num.pre) = '.';
6689 }
6690 }
6691
6694}
6695
6696
6698
6699
6702{
6707 text *result;
6708 bool shouldFree;
6709 int out_pre_spaces = 0,
6711 char *numstr,
6712 *p;
6713
6715
6717 {
6719
6720
6722
6725 else
6728 }
6730 {
6732 {
6733
6734
6735
6736
6737 numstr = (char *) palloc(Num.pre + Num.post + 7);
6739 *numstr = ' ';
6740 *(numstr + Num.pre + 1) = '.';
6741 }
6742 else
6743 {
6745
6746
6747
6748
6749 if (*numstr == '+')
6750 *numstr = ' ';
6751 }
6752 }
6753 else
6754 {
6756 char *orgnum;
6757 int numstr_pre_len;
6758
6760 {
6761 float multi = pow((double) 10, (double) Num.multi);
6762
6765 }
6766
6768 numstr_pre_len = strlen(orgnum);
6769
6770
6771 if (numstr_pre_len >= FLT_DIG)
6772 Num.post = 0;
6773 else if (numstr_pre_len + Num.post > FLT_DIG)
6774 Num.post = FLT_DIG - numstr_pre_len;
6776
6777 if (*orgnum == '-')
6778 {
6780 numstr = orgnum + 1;
6781 }
6782 else
6783 {
6785 numstr = orgnum;
6786 }
6787
6788 if ((p = strchr(numstr, '.')))
6789 numstr_pre_len = p - numstr;
6790 else
6791 numstr_pre_len = strlen(numstr);
6792
6793
6794 if (numstr_pre_len < Num.pre)
6795 out_pre_spaces = Num.pre - numstr_pre_len;
6796
6797 else if (numstr_pre_len > Num.pre)
6798 {
6799 numstr = (char *) palloc(Num.pre + Num.post + 2);
6801 *(numstr + Num.pre) = '.';
6802 }
6803 }
6804
6807}
6808
6809
6811
6812
6815{
6820 text *result;
6821 bool shouldFree;
6822 int out_pre_spaces = 0,
6824 char *numstr,
6825 *p;
6826
6828
6830 {
6832
6833
6835
6838 else
6841 }
6843 {
6845 {
6846
6847
6848
6849
6850 numstr = (char *) palloc(Num.pre + Num.post + 7);
6852 *numstr = ' ';
6853 *(numstr + Num.pre + 1) = '.';
6854 }
6855 else
6856 {
6858
6859
6860
6861
6862 if (*numstr == '+')
6863 *numstr = ' ';
6864 }
6865 }
6866 else
6867 {
6869 char *orgnum;
6870 int numstr_pre_len;
6871
6873 {
6874 double multi = pow((double) 10, (double) Num.multi);
6875
6878 }
6879
6881 numstr_pre_len = strlen(orgnum);
6882
6883
6884 if (numstr_pre_len >= DBL_DIG)
6885 Num.post = 0;
6886 else if (numstr_pre_len + Num.post > DBL_DIG)
6887 Num.post = DBL_DIG - numstr_pre_len;
6889
6890 if (*orgnum == '-')
6891 {
6893 numstr = orgnum + 1;
6894 }
6895 else
6896 {
6898 numstr = orgnum;
6899 }
6900
6901 if ((p = strchr(numstr, '.')))
6902 numstr_pre_len = p - numstr;
6903 else
6904 numstr_pre_len = strlen(numstr);
6905
6906
6907 if (numstr_pre_len < Num.pre)
6908 out_pre_spaces = Num.pre - numstr_pre_len;
6909
6910 else if (numstr_pre_len > Num.pre)
6911 {
6912 numstr = (char *) palloc(Num.pre + Num.post + 2);
6914 *(numstr + Num.pre) = '.';
6915 }
6916 }
6917
6920}
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
void DateTimeParseError(int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, Node *escontext)
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
void j2date(int jd, int *year, int *month, int *day)
const char *const months[]
int date2j(int year, int month, int day)
int DecodeTimezoneAbbrevPrefix(const char *str, int *offset, pg_tz **tz)
int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
char * numeric_out_sci(Numeric num, int scale)
int32 numeric_int4_opt_error(Numeric num, bool *have_error)
Datum numeric_round(PG_FUNCTION_ARGS)
Numeric int64_to_numeric(int64 val)
Datum numeric_power(PG_FUNCTION_ARGS)
Datum numeric_out(PG_FUNCTION_ARGS)
Datum numeric_in(PG_FUNCTION_ARGS)
Datum numeric_mul(PG_FUNCTION_ARGS)
void isoweek2date(int woy, int *year, int *mon, int *mday)
int isoweek2j(int year, int week)
int date2isoweek(int year, int mon, int mday)
bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
int date2isoyearday(int year, int mon, int mday)
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
void isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
void interval2itm(Interval span, struct pg_itm *itm)
int date2isoyear(int year, int mon, int mday)
#define FLOAT4_FITS_IN_INT32(num)
#define FLOAT8_FITS_IN_INT32(num)
#define MemSet(start, val, len)
#define OidIsValid(objectId)
#define INTERVAL_NOT_FINITE(i)
#define IS_VALID_JULIAN(y, m, d)
#define TIMESTAMP_NOT_FINITE(j)
#define POSTGRES_EPOCH_JDATE
int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
static Datum DateADTGetDatum(DateADT X)
#define PG_RETURN_DATEADT(x)
static Datum TimeTzADTPGetDatum(const TimeTzADT *X)
static Datum TimeADTGetDatum(TimeADT X)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereturn(context, dummy_value,...)
#define errsave(context,...)
#define ereport(elevel,...)
void err(int eval, const char *fmt,...)
Datum Int64GetDatum(int64 X)
Datum Float8GetDatum(float8 X)
#define PG_GETARG_TEXT_PP(n)
#define DirectFunctionCall2(func, arg1, arg2)
#define PG_GETARG_FLOAT8(n)
#define DirectFunctionCall1(func, arg1)
#define PG_GETARG_INT64(n)
#define PG_RETURN_TEXT_P(x)
#define PG_GETARG_INT32(n)
#define PG_GETARG_FLOAT4(n)
#define DirectFunctionCall3(func, arg1, arg2, arg3)
#define PG_GET_COLLATION()
static void DCH_from_char(FormatNode *node, const char *in, TmFromChar *out, Oid collid, bool std, Node *escontext)
#define NUM_TOCHAR_prepare
Datum to_timestamp(PG_FUNCTION_ARGS)
static NUMCacheEntry * NUMCache[NUM_CACHE_ENTRIES]
static bool is_next_separator(FormatNode *n)
static const int DCH_index[KeyWord_INDEX_SIZE]
static char * fill_str(char *str, int c, int max)
static char * NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, int input_len, int to_char_out_pre_spaces, int sign, bool is_to_char, Oid collid)
#define SKIP_THth(ptr, _suf)
#define IS_VALID_SUB_COMB(curr, next)
char * str_initcap(const char *buff, size_t nbytes, Oid collid)
static bool do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, struct pg_tm *tm, fsec_t *fsec, struct fmt_tz *tz, int *fprec, uint32 *flags, Node *escontext)
static bool from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode, Node *escontext)
static const KeyWord NUM_keywords[]
static char * str_numth(char *dest, char *num, int type)
static bool from_char_seq_search(int *dest, const char **src, const char *const *array, char **localized_array, Oid collid, FormatNode *node, Node *escontext)
static void parse_format(FormatNode *node, const char *str, const KeyWord *kw, const KeySuffix *suf, const int *index, uint32 flags, NUMDesc *Num)
#define DCH_to_char_fsec(frac_fmt, frac_val)
static void NUMDesc_prepare(NUMDesc *num, FormatNode *n)
static void DCH_prevent_counter_overflow(void)
static void NUM_numpart_to_char(NUMProc *Np, int id)
static int seq_search_localized(const char *name, char **array, int *len, Oid collid)
static void NUM_numpart_from_char(NUMProc *Np, int id, int input_len)
static NUMCacheEntry * NUM_cache_getnew(const char *str)
bool datetime_format_has_tz(const char *fmt_str)
static NUMCacheEntry * NUM_cache_fetch(const char *str)
Datum float4_to_char(PG_FUNCTION_ARGS)
#define NUM_CACHE_ENTRIES
#define ADJUST_YEAR(year, is_interval)
static int from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *node, Node *escontext)
static char * str_tolower_z(const char *buff, Oid collid)
#define NUM_TOCHAR_finish
static char * asc_toupper_z(const char *buff)
static DCHCacheEntry * DCH_cache_getnew(const char *str, bool std)
char * asc_initcap(const char *buff, size_t nbytes)
static const KeySuffix * suff_search(const char *str, const KeySuffix *suf, int type)
char * asc_toupper(const char *buff, size_t nbytes)
static int adjust_partial_year_to_2020(int year)
static char * get_last_relevant_decnum(char *num)
static const KeyWord * index_seq_search(const char *str, const KeyWord *kw, const int *index)
static const KeySuffix DCH_suff[]
@ FROM_CHAR_DATE_GREGORIAN
Datum to_date(PG_FUNCTION_ARGS)
static char * str_toupper_z(const char *buff, Oid collid)
static const char *const numth[]
char * str_casefold(const char *buff, size_t nbytes, Oid collid)
Datum timestamp_to_char(PG_FUNCTION_ARGS)
static int roman_to_int(NUMProc *Np, int input_len)
static void NUM_prevent_counter_overflow(void)
static const int NUM_index[KeyWord_INDEX_SIZE]
static const char *const rm100[]
static int seq_search_ascii(const char *name, const char *const *array, int *len)
Datum float8_to_char(PG_FUNCTION_ARGS)
static const char *const months_full[]
#define INVALID_FOR_INTERVAL
#define NODE_TYPE_SEPARATOR
char * asc_tolower(const char *buff, size_t nbytes)
Datum parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict, Oid *typid, int32 *typmod, int *tz, Node *escontext)
Datum numeric_to_char(PG_FUNCTION_ARGS)
static const char *const adbc_strings_long[]
Datum int4_to_char(PG_FUNCTION_ARGS)
static const char *const days_short[]
static void NUM_prepare_locale(NUMProc *Np)
static int DCH_datetime_type(FormatNode *node)
static const char *const rm10[]
static char * str_initcap_z(const char *buff, Oid collid)
#define KeyWord_INDEX_FILTER(_c)
static void NUM_eat_non_data_chars(NUMProc *Np, int n, int input_len)
static NUMCacheEntry * NUM_cache_search(const char *str)
Datum timestamptz_to_char(PG_FUNCTION_ARGS)
static const char *const ampm_strings[]
char * str_toupper(const char *buff, size_t nbytes, Oid collid)
#define KeyWord_INDEX_SIZE
static DCHCacheEntry * DCH_cache_search(const char *str, bool std)
static void DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
static bool from_char_set_int(int *dest, const int value, const FormatNode *node, Node *escontext)
static int strspace_len(const char *str)
Datum numeric_to_number(PG_FUNCTION_ARGS)
static DCHCacheEntry * DCHCache[DCH_CACHE_ENTRIES]
#define IS_PREDEC_SPACE(_n)
Datum int8_to_char(PG_FUNCTION_ARGS)
#define DCH_CACHE_ENTRIES
static FormatNode * NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
static const KeyWord DCH_keywords[]
static const char *const numTH[]
static const char *const rm1[]
static char * asc_tolower_z(const char *buff)
static const char *const rm_months_upper[]
static const char *const rm_months_lower[]
static const char * get_th(char *num, int type)
static const char *const adbc_strings[]
static char * int_to_roman(int number)
static int from_char_parse_int(int *dest, const char **src, FormatNode *node, Node *escontext)
static text * datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
static DCHCacheEntry * DCH_cache_fetch(const char *str, bool std)
#define COPY_tm(_DST, _SRC)
char * str_tolower(const char *buff, size_t nbytes, Oid collid)
static const char *const ampm_strings_long[]
Datum interval_to_char(PG_FUNCTION_ARGS)
static bool is_separator_char(const char *str)
Assert(PointerIsAligned(start, uint64))
#define DTERR_TZDISP_OVERFLOW
#define DTERR_FIELD_OVERFLOW
Datum int8out(PG_FUNCTION_ARGS)
Datum int8mul(PG_FUNCTION_ARGS)
Datum dtoi8(PG_FUNCTION_ARGS)
Datum int4out(PG_FUNCTION_ARGS)
static bool pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
if(TABLE==NULL||TABLE_index==NULL)
int GetDatabaseEncoding(void)
int pg_mbstrlen(const char *mbstr)
int pg_mblen(const char *mbstr)
void * MemoryContextAllocZero(MemoryContext context, Size size)
char * pstrdup(const char *in)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
MemoryContext TopMemoryContext
char * pnstrdup(const char *in, Size len)
#define SOFT_ERROR_OCCURRED(escontext)
static Numeric DatumGetNumeric(Datum X)
#define PG_GETARG_NUMERIC(n)
static Datum NumericGetDatum(Numeric X)
static PgChecksumMode mode
void cache_locale_time(void)
char * localized_full_months[12+1]
pg_locale_t pg_newlocale_from_collation(Oid collid)
size_t pg_strfold(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
size_t pg_strlower(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
struct lconv * PGLC_localeconv(void)
size_t pg_strtitle(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
char * localized_abbrev_months[12+1]
char * localized_full_days[7+1]
size_t pg_strupper(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
char * localized_abbrev_days[7+1]
#define MAX_MULTIBYTE_CHAR_LEN
PGDLLIMPORT pg_tz * session_timezone
unsigned char pg_ascii_tolower(unsigned char ch)
unsigned char pg_ascii_toupper(unsigned char ch)
size_t strlcpy(char *dst, const char *src, size_t siz)
static int64 DatumGetInt64(Datum X)
static Datum ObjectIdGetDatum(Oid X)
static char * DatumGetCString(Datum X)
static Datum CStringGetDatum(const char *X)
static Datum Int32GetDatum(int32 X)
char * psprintf(const char *fmt,...)
bool scanner_isspace(char ch)
FormatNode format[DCH_CACHE_SIZE+1]
char str[DCH_CACHE_SIZE+1]
char character[MAX_MULTIBYTE_CHAR_LEN+1]
FromCharDateMode date_mode
char str[NUM_CACHE_SIZE+1]
FormatNode format[NUM_CACHE_SIZE+1]
static Datum TimestampTzGetDatum(TimestampTz X)
static Datum TimestampGetDatum(Timestamp X)
#define PG_GETARG_TIMESTAMP(n)
#define PG_RETURN_TIMESTAMP(x)
#define PG_GETARG_INTERVAL_P(n)
#define VARSIZE_ANY_EXHDR(PTR)
text * cstring_to_text(const char *s)
char * text_to_cstring(const text *t)