DCL 3.7.4
Loading...
Searching...
No Matches
PqTypes.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#ifdef __APPLE__
4#include <libkern/OSByteOrder.h>
5#endif
6
7#include <errno.h> // errno
8#include <stdlib.h> // strol
9#include <string.h> // memset
10
11#include <libpq-fe.h>
12#include <catalog/pg_type_d.h>
13
14#include <dcl/Object.h>
15#if __DCL_HAVE_ALLOC_DEBUG
16#undef __DCL_ALLOC_LEVEL
17#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
18#endif
19
20#include <dcl/SQLCore.h>
21#include "PqTypes.h"
22
23#define __TRACE_THIS 0
24#if __TRACE_THIS
25#define __DCL_TRACE0_N __DCL_TRACE0
26#define __DCL_TRACE1_N __DCL_TRACE1
27#define __DCL_TRACE2_N __DCL_TRACE2
28#define __DCL_TRACE3_N __DCL_TRACE3
29#define __DCL_TRACE4_N __DCL_TRACE4
30#else
31#define __DCL_TRACE0_N(fmt)
32#define __DCL_TRACE1_N(fmt, arg)
33#define __DCL_TRACE2_N(fmt, arg1, arg2)
34#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
35#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
36#endif
37
38#if __DCL_HAVE_THIS_FILE__
39#undef __THIS_FILE__
40static const char_t __THIS_FILE__[] = __T("dcl/sql/PqTypes.cpp");
41#endif
42
43__DCL_BEGIN_NAMESPACE
44
48static inline char __nibble__(char _c)
49{
50 if ('0' <= _c && _c <= '9')
51 return _c - '0';
52 else if ('a' <= _c && _c <= 'f')
53 return _c - 'a' + (char)10;
54 else if ('A' <= _c && _c <= 'F')
55 return _c - 'A' + (char)10;
56 return (char)-1;
57}
58
60 const char* _src, const char*& _srcend,
61 char* _dst, char*& _dstend
62)
63{
64 __DCL_ASSERT(_src && _srcend && _dst && _dstend);
65#ifndef __DCL_DEBUG
66 if (!(_src && _srcend && _dst && _dstend)) {
67 return false;
68 }
69#endif
70
71 bool r = true;
72 if (__is_hex_escaped(_src)) {
73 _src++; _src++;
74 }
75
76 while (_src + 1 < _srcend && _dst < _dstend) {
77 char high, low;
78 high = __nibble__(*_src++);
79 if (high == (char)-1) {
80 // invalid char
81 r = false;
82 continue;
83 }
84 low = __nibble__(*_src++);
85 if (low == (char)-1) {
86 // invali char
87 r = false;
88 continue;
89 }
90 *_dst++ = (high << 4) | low;
91 }
92
93 _srcend = _src;
94 _dstend = _dst;
95 return r;
96}
97
98static inline bool __is_first_oct_digit(char _c)
99{
100 return '0' <= _c && _c <= '3';
101}
102
103static inline bool __is_oct_digit(char _c)
104{
105 return '0' <= _c && _c <= '7';
106}
107
109 const char* _src, const char*& _srcend,
110 char* _dst, char*& _dstend
111)
112{
113 __DCL_ASSERT(_src && _srcend && _dst && _dstend);
114#ifndef __DCL_DEBUG
115 if (!(_src && _srcend && _dst && _dstend)) {
116 return false;
117 }
118#endif
119 bool r = true;
120 while (_src < _srcend && _dst < _dstend) {
121 if (*_src == '\\') {
122 _src++;
123 if (_src < _srcend) {
124 if (*_src == '\\') {
125 *_dst++ = *_src;
126 continue;
127 }
128 if ((_src + 3) < _srcend) {
129 if (__is_first_oct_digit(*(_src))
130 && __is_oct_digit(*(_src + 1))
131 && __is_oct_digit(*(_src + 2))
132 ) {
133 unsigned char c = (*_src++ - '0');
134 c = (c << 3) | (*_src++ - '0');
135 c = (c << 3) | (*_src++ - '0');
136 *_dst++ = c;
137 }
138 else {
139 // invalid char
140 r = false;
141 continue;
142 }
143
144 }
145 }
146 else {
147 // invalid last char
148 r = false;
149 }
150 }
151 else {
152 *_dst++ = *_src++;
153 }
154 }
155
156 _srcend = _src;
157 _dstend = _dst;
158 return r;
159}
160
161static int32_t __fraction_normalize(long _n)
162{
163 if (_n > 999999999) {
164 // fraction이 999,999,999 보다 크면 오류값이다.
165 _n = 0;
166 }
167 int divider = 10;
168 for (; ; ) {
169 if (!(_n / divider))
170 break;
171 divider *= 10;
172 }
173 return _n * (1000000000 / divider);
174}
175
177 const char* _s, const char** _endptr,
179)
180{
181 __DCL_ASSERT(_s);
182#ifndef __DCL_DEBUG
183 if (!_s) {
184 if (_endptr) {
185 *_endptr = _s;
186 }
187 return false;
188 }
189#endif
190
191#define __START 0
192#define __yyyy 1
193#define __MM 2
194#define __dd 3
195#define __HH 4
196#define __mm 5
197#define __ss 6
198#define __SSS 7
199#define __ZH 8
200#define __Zm 9
201#define __Zs 10
202#define __BC 11
203#define __DONE 12
204
205 int state = __START; // yyyy-MM-dd'T'HH:mm:ss.SSSZ
206 memset(&_r, 0, sizeof(_r));
207 _r.tzoff = INT16_MIN;
208
209 bool r = true;
210 char* endptr = (char*)_s;
211 for (; ; ) {
212 errno = 0;
213 const char* nptr = endptr;
214 long n = strtol(nptr, &endptr, 10);
215 if (errno == ERANGE) {
216 // invalid string
217 r = false;
218 break;
219 }
220 if (state == __START) {
221 if (*endptr == '-') {
222 state = __yyyy;
223 }
224 else if (*endptr == ':') {
225 state = __HH;
226 }
227 else {
228 // invalid string
229 r = false;
230 break;
231 }
232 }
233 else if (*endptr == 'B') {
234 state = __BC;
235 }
236 else {
237 // '\0' == *endptr || strchr("- T:.+", *endptr)
238 state++;
239 }
240
241 __DCL_TRACE4_N(L"state[%2d] n[%10d] [%p][%hc]\n",
242 state, n, endptr, *endptr ? *endptr : '$');
243 switch (state) {
244 case __yyyy:
245 _r.year = (int16_t)n;
246 break;
247 case __MM:
248 _r.month = (uint8_t)n;
249 break;
250 case __dd:
251 _r.day = (uint8_t)n;
252 break;
253 case __HH:
254 _r.hour = (uint8_t)n;
255 break;
256 case __mm:
257 _r.min = (uint8_t)n;
258 break;
259 case __ss:
260 _r.sec = (uint8_t)n;
261 break;
262 case __SSS:
263 _r.frac = __fraction_normalize(n);
264 break;
265 case __ZH:
266 _r.tzoff = (int16_t)(n * 60);
267 break;
268 case __Zm:
269 _r.tzoff += (int16_t)n;
270 break;
271 case __Zs:
272 // +08:27:52 BC PostgreSQL Bug!! ignore
273 break;
274 case __BC: {
275 __DCL_ASSERT(*(endptr + 1) == 'C');
276 _r.year *= -1;
277 state = __DONE;
278 break;
279 }
280 default: {
281 __DCL_ASSERT(false);
282 }
283 }
284
285 if (*endptr == '\0' || state == __DONE) {
286 break;
287 }
288 else {
289 __DCL_TRACE1_N(L"[%hs]\n", (*endptr ? endptr : "(nil)"));
290 if ((state == __ss || state == __SSS)
291 && (*endptr == '+' || *endptr == '-')
292 ) {
293 state = __SSS;
294 // 부호와 함께 strtol 후 __ZH 상태가 된다.
295 }
296 else {
297 endptr++;
298 }
299 }
300 }
301
302 if (_endptr) {
303 *_endptr = endptr;
304 }
305 return r;
306}
307
309 const char* _s, const char** _endptr,
310 SQL::Interval& _r
311)
312{
313 __DCL_ASSERT(_s);
314#ifndef __DCL_DEBUG
315 if (!_s) {
316 if (_endptr) {
317 *_endptr = _s;
318 }
319 return false;
320 }
321#endif
322
323 if (*_s != 'P') {
324 // invalid string
325 if (_endptr) {
326 *_endptr = _s;
327 }
328 return false;
329 }
330 _s++;
331
332#define __P0 0
333#define __PT 1
334#define __PTDOT 2
335#define __PDONE 3
336
337 bool r = true;
338 int state = __P0; // P3Y6M4DT12H30M5S
339 memset(&_r, 0, sizeof(_r));
340
341 char dotsign = '+'; // '.'에서 부호를 보관해야 SSS 사용할 수 있다.
342 char* endptr = (char*)_s;
343 for (; ; ) {
344 errno = 0;
345 const char* nptr = endptr;
346 long n = strtol(nptr, &endptr, 10);
347 if (errno == ERANGE) {
348 // invalid string
349 r = false;
350 break;
351 }
352 __DCL_TRACE4_N(L"state[%d] [%p][%hc] [%d]\n",
353 state, endptr, (*endptr ? *endptr : '$'), n);
354 switch (*endptr) {
355 case 'Y':
356 _r.years = (int32_t)n;
357 break;
358 case 'M':
359 if (state == __PT) {
360 _r.mins = (int8_t)n;
361 }
362 else {
363 _r.months = (int8_t)n;
364 }
365 break;
366 case 'D':
367 _r.days = (int32_t)n;
368 break;
369 case 'T':
370 state = __PT;
371 break;
372 case 'H':
373 _r.hours = (int8_t)n;
374 break;
375 case '.':
376 state = __PTDOT;
377 dotsign = *nptr;
378 _r.secs = (int8_t)n;
379 break;
380 case 'S': {
381 if (state == __PTDOT) {
382 _r.fracs = __fraction_normalize(n)
383 * (dotsign == '-' ? -1 : 1);
384 }
385 else {
386 _r.secs = (int8_t)n;
387 }
388 state = __PDONE;
389 break;
390 }
391 case '\0': {
392 state = __PDONE;
393 break;
394 }
395 default: {
396 // invalid string
397 r = false;
398 state = __PDONE;
399 }
400 }
401
402 if (state == __PDONE) {
403 break;
404 }
405 else {
406 endptr++;
407 }
408 }
409
410 if (_endptr) {
411 *_endptr = endptr;
412 }
413 return r;
414}
415
416#define SQLTYPE_NAME(_oid, name) case _oid : return L ## name
417
418const wchar_t* __dataTypeName(Oid _oid)
419{
420 switch (_oid) {
421 SQLTYPE_NAME(BOOLOID, "BOOL"); // 16
422 SQLTYPE_NAME(BYTEAOID, "BYTEA"); // 17
423 SQLTYPE_NAME(CHAROID, "CHAR"); // 18
424 SQLTYPE_NAME(NAMEOID, "NAME"); // 19
425 SQLTYPE_NAME(INT8OID, "INT8"); // 20
426 SQLTYPE_NAME(INT2OID, "INT2"); // 21
427 SQLTYPE_NAME(INT4OID, "INT4"); // 23
428
429 SQLTYPE_NAME(TEXTOID, "TEXT"); // 25
430 SQLTYPE_NAME(JSONOID, "JSON"); // 114
431 SQLTYPE_NAME(XMLOID, "XML"); // 142
432
433 SQLTYPE_NAME(POINTOID, "POINT"); // 600
434 SQLTYPE_NAME(LSEGOID, "LSEG"); // 601
435 SQLTYPE_NAME(PATHOID, "PATH"); // 602
436 SQLTYPE_NAME(BOXOID, "BOX"); // 603
437 SQLTYPE_NAME(POLYGONOID, "POLYGON"); // 604
438 SQLTYPE_NAME(LINEOID, "LINE"); // 628
439
440 SQLTYPE_NAME(FLOAT4OID, "FLOAT4"); // 700
441 SQLTYPE_NAME(FLOAT8OID, "FLOAT8"); // 701
442
443 SQLTYPE_NAME(UNKNOWNOID, "UNKNOWN"); // 705
444
445 SQLTYPE_NAME(CIRCLEOID, "CIRCLE"); // 718
446
447 SQLTYPE_NAME(MONEYOID, "MONEY"); // 790
448
449 SQLTYPE_NAME(MACADDROID, "MACADDR"); // 829
450 SQLTYPE_NAME(INETOID, "INET"); // 869
451 SQLTYPE_NAME(CIDROID, "CIDR"); // 650
452 SQLTYPE_NAME(MACADDR8OID, "MACADDR8"); // 774
453
454 SQLTYPE_NAME(BPCHAROID, "BPCHAR"); // 1042
455 SQLTYPE_NAME(VARCHAROID, "VARCHAR"); // 1043
456 SQLTYPE_NAME(DATEOID, "DATE"); // 1082
457 SQLTYPE_NAME(TIMEOID, "TIME"); // 1083
458 SQLTYPE_NAME(TIMESTAMPOID, "TIMESTAMP"); // 1183
459 SQLTYPE_NAME(TIMESTAMPTZOID, "TIMESTAMPTZ"); // 1184
460 SQLTYPE_NAME(INTERVALOID, "INTERVAL"); // 1186
461 SQLTYPE_NAME(TIMETZOID, "TIMETZ"); // 1266
462
463 SQLTYPE_NAME(BITOID, "BIT"); // 1560
464 SQLTYPE_NAME(VARBITOID, "VARBIT"); // 1562
465
466 SQLTYPE_NAME(NUMERICOID, "NUMERIC"); // 1700
467
468 SQLTYPE_NAME(UUIDOID, "UUID"); // 2950
469 SQLTYPE_NAME(TSVECTOROID, "TSVECTOR"); // 3614
470 SQLTYPE_NAME(TSQUERYOID, "TSQUERY"); // 3615
471 SQLTYPE_NAME(JSONBOID, "JSONB"); // 3802
472 SQLTYPE_NAME(JSONPATHOID, "JSONPATHO"); // 4072
473
474 SQLTYPE_NAME(ANYOID, "ANY"); // 2276
475 SQLTYPE_NAME(ANYARRAYOID, "ANYARRAY"); // 2277
476 SQLTYPE_NAME(VOIDOID, "VOID"); // 2278
477
478 SQLTYPE_NAME(BOOLARRAYOID, "BOOLARRAY"); // 1000
479 SQLTYPE_NAME(BYTEAARRAYOID, "BYTEAARRAY"); //
480 SQLTYPE_NAME(CHARARRAYOID, "CHARARRAY"); //
481 SQLTYPE_NAME(NAMEARRAYOID, "NAMEARRAY"); //
482 SQLTYPE_NAME(INT8ARRAYOID, "INT8ARRAY"); //
483 SQLTYPE_NAME(INT2ARRAYOID, "INT2ARRAY"); // 1005
484 SQLTYPE_NAME(INT2VECTORARRAYOID, "INT2VECTORARRAY"); // 1006
485 SQLTYPE_NAME(INT4ARRAYOID, "INT4ARRAY"); // 1007
486 SQLTYPE_NAME(TEXTARRAYOID, "TEXTARRAY"); // 1009
487 SQLTYPE_NAME(OIDARRAYOID, "OIDARRAY"); // 1028
488 SQLTYPE_NAME(TIDARRAYOID, "TIDARRAY"); //
489 SQLTYPE_NAME(XIDARRAYOID, "XIDARRAY"); //
490 SQLTYPE_NAME(CIDARRAYOID, "CIDARRAY"); // 1012
491 SQLTYPE_NAME(OIDVECTORARRAYOID, "OIDVECTORARRAY"); // 1013
492 SQLTYPE_NAME(JSONARRAYOID, "JSONARRAY"); // 199
493 SQLTYPE_NAME(XMLARRAYOID, "XMLARRAY"); // 143
494 SQLTYPE_NAME(XID8ARRAYOID, "XID8ARRAY"); //
495 SQLTYPE_NAME(POINTARRAYOID, "POINTARRAY"); // 1017
496 SQLTYPE_NAME(LSEGARRAYOID, "LSEGARRAY"); //
497 SQLTYPE_NAME(PATHARRAYOID, "PATHARRAY"); //
498 SQLTYPE_NAME(BOXARRAYOID, "BOXARRAY"); //
499 SQLTYPE_NAME(POLYGONARRAYOID, "POLYGONARRAY"); //
500 SQLTYPE_NAME(LINEARRAYOID, "LINEARRAY"); //
501 SQLTYPE_NAME(FLOAT4ARRAYOID, "FLOAT4ARRAY"); // 1021
502 SQLTYPE_NAME(FLOAT8ARRAYOID, "FLOAT8ARRAY"); //
503 SQLTYPE_NAME(CIRCLEARRAYOID, "CIRCLEARRAY"); //
504 SQLTYPE_NAME(MONEYARRAYOID, "MONEYARRAY"); // 719
505 SQLTYPE_NAME(MACADDRARRAYOID, "MACADDRARRAY"); //
506 SQLTYPE_NAME(INETARRAYOID, "INETARRAY"); //
507 SQLTYPE_NAME(CIDRARRAYOID, "CIDRARRAY"); //
508 SQLTYPE_NAME(MACADDR8ARRAYOID, "MACADDR8ARRAY"); //
509 SQLTYPE_NAME(ACLITEMARRAYOID, "ACLITEMARRAY"); //
510 SQLTYPE_NAME(BPCHARARRAYOID, "BPCHARARRAY"); //
511 SQLTYPE_NAME(VARCHARARRAYOID, "VARCHARARRAY"); //
512 SQLTYPE_NAME(DATEARRAYOID, "DATEARRAY"); //
513 SQLTYPE_NAME(TIMEARRAYOID, "TIMEARRAY"); //
514 SQLTYPE_NAME(TIMESTAMPARRAYOID, "TIMESTAMPARRAY"); //
515 SQLTYPE_NAME(TIMESTAMPTZARRAYOID, "TIMESTAMPTZARRAY"); //
516 SQLTYPE_NAME(INTERVALARRAYOID, "INTERVALARRAY"); //
517 SQLTYPE_NAME(TIMETZARRAYOID, "TIMETZARRAY"); //
518 SQLTYPE_NAME(BITARRAYOID, "BITARRAY"); //
519 SQLTYPE_NAME(VARBITARRAYOID, "VARBITARRAY"); //
520 SQLTYPE_NAME(NUMERICARRAYOID, "NUMERICARRAY"); //
521 SQLTYPE_NAME(REFCURSORARRAYOID, "REFCURSORARRAY"); //
522 SQLTYPE_NAME(UUIDARRAYOID, "UUIDARRAY"); //
523 SQLTYPE_NAME(TSVECTORARRAYOID, "TSVECTORARRAY"); //
524 SQLTYPE_NAME(GTSVECTORARRAYOID, "GTSVECTORARRAY"); //
525 SQLTYPE_NAME(TSQUERYARRAYOID, "TSQUERYARRAY"); //
526 SQLTYPE_NAME(JSONBARRAYOID, "JSONBARRAY"); //
527 SQLTYPE_NAME(JSONPATHARRAYOID, "JSONPATHARRAY"); //
528 default: return L"Unknown Type (Binary Mapped)";
529 }
530}
531
532__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
wchar_t char_t
Definition Config.h:247
#define INT16_MIN
Definition Config.h:284
IOException *size_t r
Definition MediaInfo.cpp:82
#define __DCL_ASSERT(expr)
Definition Object.h:394
#define __T(str)
Definition Object.h:60
#define __SSS
#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
Definition PqTypes.cpp:35
#define __DONE
#define __PTDOT
#define __yyyy
#define SQLTYPE_NAME(_oid, name)
Definition PqTypes.cpp:416
#define __Zm
bool __unescape_hex(const char *_src, const char *&_srcend, char *_dst, char *&_dstend)
Definition PqTypes.cpp:59
bool __unescape_oct(const char *_src, const char *&_srcend, char *_dst, char *&_dstend)
Definition PqTypes.cpp:108
bool __decode_timestamp_iso(const char *_s, const char **_endptr, SQL::TimeStamp &_r)
Definition PqTypes.cpp:176
#define __MM
#define __P0
#define __BC
#define __dd
#define __DCL_TRACE1_N(fmt, arg)
Definition PqTypes.cpp:32
#define __mm
#define __START
#define __PDONE
#define __Zs
#define __ZH
#define __HH
#define __PT
bool __decode_interval_iso(const char *_s, const char **_endptr, SQL::Interval &_r)
Definition PqTypes.cpp:308
#define __ss
const wchar_t * __dataTypeName(Oid _oid)
Definition PqTypes.cpp:418
bool __is_hex_escaped(const char *_src)
Definition PqTypes.h:111
int32_t years
Definition SQLCore.h:126
int32_t days
Definition SQLCore.h:128
int8_t hours
Definition SQLCore.h:129
int8_t mins
Definition SQLCore.h:130
int32_t fracs
Definition SQLCore.h:132
int8_t months
Definition SQLCore.h:127
int8_t secs
Definition SQLCore.h:131
uint32_t frac
Definition SQLCore.h:118
int16_t tzoff
Definition SQLCore.h:119
uint8_t min
Definition SQLCore.h:116
uint8_t sec
Definition SQLCore.h:117
uint8_t hour
Definition SQLCore.h:115
uint8_t day
Definition SQLCore.h:114
int16_t year
Definition SQLCore.h:112
uint8_t month
Definition SQLCore.h:113