DCL 3.7.4
Loading...
Searching...
No Matches
PqParam.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#include <stdlib.h> // PqTypes.h _byteswap_
7
8#include <libpq-fe.h>
9#include <catalog/pg_type_d.h>
10
11#include <dcl/Object.h>
12#if __DCL_HAVE_ALLOC_DEBUG
13#undef __DCL_ALLOC_LEVEL
14#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
15#endif
16
17#include <dcl/DateTime.h>
18#include <dcl/InputStream.h>
19#include <dcl/Files.h>
20#include <dcl/SQLCore.h>
21
22#include "PqConnection.h"
23#include "PqQuery.h"
24#include "PqParam.h"
25#include "PqTypes.h"
26
27#define __TRACE_THIS 0
28#if __TRACE_THIS
29#define __DCL_TRACE0_N __DCL_TRACE0
30#define __DCL_TRACE1_N __DCL_TRACE1
31#define __DCL_TRACE2_N __DCL_TRACE2
32#define __DCL_TRACE3_N __DCL_TRACE3
33#define __DCL_TRACE4_N __DCL_TRACE4
34#else
35#define __DCL_TRACE0_N(fmt)
36#define __DCL_TRACE1_N(fmt, arg)
37#define __DCL_TRACE2_N(fmt, arg1, arg2)
38#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
39#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
40#endif
41
42#undef __THIS_FILE__
43static const char_t __THIS_FILE__[] = __T("dcl/sql/PqParam.cpp");
44
45__DCL_BEGIN_NAMESPACE
46
47#define __SET_ERROR(_error) \
48 connection()->setErrorStatus(_error, __THIS_FILE__, __LINE__)
49#define __SET_ERROR_MSG(_message) \
50 conn()->setErrorMessage(_message, __THIS_FILE__, __LINE__)
51
53
54PqParam::PqParam() : Param(NULL)
55{
56 __index = -1;
57 __type = -1;
58}
59
63
64bool PqParam::init(SQL::Query* _queryHandle, int _index, const PGresult* _res)
65{
66 __DCL_ASSERT(Param::__queryHandle == NULL);
67 __DCL_ASSERT(_queryHandle != NULL && _res != NULL);
68
69 Param::__queryHandle = _queryHandle;
70
71 __index = _index;
72 __type = PQparamtype(_res, _index);
73
74 return true;
75}
76
78{
79 Param::__dataType = SQL::typeUnknown;
80 __bytes.clear();
81
82 return true;
83}
84
85const wchar_t* PqParam::serverDataTypeName() const
86{
87 return __dataTypeName(__type);
88}
89
91{
92 Param::__dataType = SQL::typeUnknown;
93}
94
95static inline int __ABS(int _n)
96{
97 return _n < 0 ? -_n : _n;
98}
99
101 _CONST void* _val,
102 size_t _size,
103 SQL::DataType _valType,
104 SQL::DataType _sqlType
105)
106{
107 bool r = false;
108 switch(_valType) {
109 case SQL::typeInteger:
110 r = setInteger(_val, _size);
111 break;
113 r = setUInteger(_val, _size);
114 break;
115 case SQL::typeFloat:
116 r = setFloat(_val, _size);
117 break;
118 case SQL::typeDate:
119 r = setDate((const SQL::Date*)_val, _size);
120 break;
121 case SQL::typeTime:
122 r = setTime((const SQL::Time*)_val, _size);
123 break;
125 r = setTimeStamp((const SQL::TimeStamp*)_val, _size);
126 break;
128 r = setInterval((const SQL::Interval*)_val, _size);
129 break;
130 case SQL::typeText:
131 case SQL::typeBinary:
133 r = setBytes(_val, _size, _valType, _sqlType);
134 break;
135 default: {
137 return false;
138 }
139 }
140
141 if (r) {
142 Param::__dataType = _sqlType;
143 }
144 return r;
145}
146
147bool PqParam::setInteger(const void* _val, size_t _size)
148{
149 int64_t n;
150 switch (_size) {
151 case sizeof(int8_t) : {
152 n = *(int8_t*)_val;
153 break;
154 }
155 case sizeof(int16_t) : {
156 n = *(int16_t*)_val;
157 break;
158 }
159 case sizeof(int32_t) : {
160 n = *(int32_t*)_val;
161 break;
162 }
163 case sizeof(int64_t) : {
164 n = *(int64_t*)_val;
165 break;
166 }
167 default: {
169 return false;
170 }
171 }
172
173 switch (__type) {
174 case BOOLOID: {
175 __data.u8 = n ? 1 : 0;
176 query()->setValue(__index, __type,
177 &__data, sizeof(__data.u8), __FORMAT_BINARY);
178 break;
179 }
180 case INT2OID: {
181 if (n < INT16_MIN || INT16_MAX < n) {
183 return false;
184 }
185 __data.u16 = __htons((uint16_t)(int16_t)n);
186 query()->setValue(__index, __type,
187 &__data, sizeof(__data.u16), __FORMAT_BINARY);
188 break;
189 }
190 case INT4OID: {
191 if (n < INT32_MIN || INT32_MAX < n) {
193 return false;
194 }
195 __data.u32 = __htonl((uint32_t)(int32_t)n);
196 query()->setValue(__index, __type,
197 &__data, sizeof(__data.u32), __FORMAT_BINARY);
198 break;
199 }
200 case INT8OID: {
201 __data.u64 = __htonll((uint64_t)(int64_t)n);
202 query()->setValue(__index, __type,
203 &__data, sizeof(__data.u64), __FORMAT_BINARY);
204 break;
205 }
206 case FLOAT4OID: {
207 __data.u32 = __htonf((float)n);
208 query()->setValue(__index, __type,
209 &__data, sizeof(__data.u32), __FORMAT_BINARY);
210 break;
211 }
212 case FLOAT8OID: {
213 __data.u64 = __htond((double)n);
214 query()->setValue(__index, __type,
215 &__data, sizeof(__data.u64), __FORMAT_BINARY);
216 break;
217 }
218 case MONEYOID:
219 case NUMERICOID:
220 case CHAROID:
221 case BPCHAROID:
222 case VARCHAROID:
223 case TEXTOID: {
224 __bytes = ByteString::valueOf(n);
225 query()->setValue(__index, __type,
226 __bytes.data(), (unsigned)__bytes.length(), __FORMAT_TEXT
227 );
228 break;
229 }
230 default: {
232 return false;
233 }
234 }
235
236 return true;
237}
238
239bool PqParam::setUInteger(const void* _val, size_t _size)
240{
241 uint64_t u;
242 switch (_size) {
243 case sizeof(uint8_t) : {
244 u = *(uint8_t*)_val;
245 break;
246 }
247 case sizeof(uint16_t) : {
248 u = *(uint16_t*)_val;
249 break;
250 }
251 case sizeof(uint32_t) : {
252 u = *(uint32_t*)_val;
253 break;
254 }
255 case sizeof(uint64_t) : {
256 u = *(uint64_t*)_val;
257 break;
258 }
259 default: {
261 return false;
262 }
263 }
264
265 switch (__type) {
266 case BOOLOID: {
267 __data.u8 = u ? 1 : 0;
268 query()->setValue(__index, __type,
269 &__data, sizeof(__data.u8), __FORMAT_BINARY);
270 break;
271 }
272 case INT2OID: {
273 if (UINT16_MAX < u) {
275 return false;
276 }
277 __data.u16 = __htons((uint16_t)u);
278 query()->setValue(__index, __type,
279 &__data, sizeof(__data.u16), __FORMAT_BINARY);
280 break;
281 }
282 case INT4OID: {
283 if (UINT32_MAX < u) {
285 return false;
286 }
287 __data.u32 = __htonl((uint32_t)u);
288 query()->setValue(__index, __type,
289 &__data, sizeof(__data.u32), __FORMAT_BINARY);
290 break;
291 }
292 case INT8OID: {
293 __data.u64 = __htonll((uint64_t)u);
294 query()->setValue(__index, __type,
295 &__data, sizeof(__data.u64), __FORMAT_BINARY);
296 break;
297 }
298 case FLOAT4OID: {
299 __data.u32 = __htonf((float)u);
300 query()->setValue(__index, __type,
301 &__data, sizeof(__data.u32), __FORMAT_BINARY);
302 break;
303 }
304 case FLOAT8OID: {
305 __data.u64 = __htond((double)u);
306 query()->setValue(__index, __type,
307 &__data, sizeof(__data.u64), __FORMAT_BINARY);
308 break;
309 }
310 case MONEYOID:
311 case NUMERICOID:
312 case CHAROID:
313 case BPCHAROID:
314 case VARCHAROID:
315 case TEXTOID: {
316 __bytes = ByteString::valueOf(u);
317 query()->setValue(__index, __type,
318 __bytes.data(), (unsigned)__bytes.length(), __FORMAT_TEXT
319 );
320 break;
321 }
322 default: {
324 return false;
325 }
326 }
327
328 return true;
329}
330
331bool PqParam::setFloat(const void* _val, size_t _size)
332{
333 double d;
334 switch (_size) {
335 case sizeof(float) : {
336 d = *(float*)_val;
337 break;
338 }
339 case sizeof(double) : {
340 d = *(double*)_val;
341 break;
342 }
343 default: {
345 return false;
346 }
347 }
348
349 switch (__type) {
350 case BOOLOID: {
351 __data.u8 = d != 0 ? 1 : 0;
352 query()->setValue(__index, __type,
353 &__data, sizeof(__data.u8), __FORMAT_BINARY);
354 break;
355 }
356 case INT2OID: {
357 if (d < INT16_MIN || INT16_MAX < d) {
359 return false;
360 }
361 __data.u16 = __htons((uint16_t)(int16_t)d);
362 query()->setValue(__index, __type,
363 &__data, sizeof(__data.u16), __FORMAT_BINARY);
364 break;
365 }
366 case INT4OID: {
367 if (d < INT32_MIN || INT32_MAX < d) {
369 return false;
370 }
371 __data.u32 = __htonl((uint32_t)(int32_t)d);
372 query()->setValue(__index, __type,
373 &__data, sizeof(__data.u32), __FORMAT_BINARY);
374 break;
375 }
376 case INT8OID: {
377 __data.u64 = __htonll((uint64_t)(int64_t)d);
378 query()->setValue(__index, __type,
379 &__data, sizeof(__data.u64), __FORMAT_BINARY);
380 break;
381 }
382 case FLOAT4OID: {
383 __data.u32 = __htonf((float)d);
384 query()->setValue(__index, __type,
385 &__data, sizeof(__data.u32), __FORMAT_BINARY);
386 break;
387 }
388 case FLOAT8OID: {
389 __data.u64 = __htond((double)d);
390 query()->setValue(__index, __type,
391 &__data, sizeof(__data.u64), __FORMAT_BINARY);
392 break;
393 }
394 case MONEYOID:
395 case NUMERICOID:
396 case CHAROID:
397 case BPCHAROID:
398 case VARCHAROID:
399 case TEXTOID: {
400 __bytes = ByteString::format((_size == 4 ? "%.8g" : "%.16g"), d);
401 query()->setValue(__index, __type,
402 __bytes.data(), (unsigned)__bytes.length(), __FORMAT_TEXT
403 );
404 break;
405 }
406 default: {
408 return false;
409 }
410 }
411
412 return true;
413}
414
415bool PqParam::setDate(const SQL::Date* _val, size_t _size)
416{
417 if (_size != sizeof(SQL::Date)) {
419 return false;
420 }
421
422 const SQL::Date* val = (const SQL::Date*)_val;
423 ByteStringBuilder sb;
424 sb.format(
425 "%04d-%02d-%02d",
426 __ABS(val->year),
427 val->month,
428 val->day
429 );
430 if (val->year < 0) {
431 sb += " BC";
432 }
433 __bytes = sb.toByteString();
434
435 switch (__type) {
436 case DATEOID:
437 case TIMESTAMPOID:
438 case TIMESTAMPTZOID:
439 case CHAROID:
440 case BPCHAROID:
441 case VARCHAROID:
442 case TEXTOID: {
443 query()->setValue(__index, __type,
444 __bytes.data(), (int)__bytes.length(), __FORMAT_TEXT
445 );
446 break;
447 }
448 default: {
450 return false;
451 }
452 }
453
454 return true;
455}
456
457bool PqParam::setTime(const SQL::Time* _val, size_t _size)
458{
459 if (_size != sizeof(SQL::Time)) {
461 return false;
462 }
463
464 const SQL::Time* val = (const SQL::Time*)_val;
465 if (val->tzoff == INT16_MIN) {
466 __bytes = ByteString::format(
467 "%02d:%02d:%02d.%06d",
468 val->hour,
469 val->min,
470 val->sec,
471 val->frac / 1000
472 );
473 }
474 else {
475 __bytes = ByteString::format(
476 "%02d:%02d:%02d.%06d %+03d:%02d",
477 val->hour,
478 val->min,
479 val->sec,
480 val->frac / 1000,
481 val->tzoff / 60,
482 __ABS(val->tzoff % 60)
483 );
484 }
485
486 switch (__type) {
487 case TIMEOID:
488 case CHAROID:
489 case BPCHAROID:
490 case VARCHAROID:
491 case TEXTOID: {
492 query()->setValue(__index, __type,
493 __bytes.data(), (int)__bytes.length(), __FORMAT_TEXT
494 );
495 break;
496 }
497 default: {
499 return false;
500 }
501 }
502
503 return true;
504}
505
506bool PqParam::setTimeStamp(const SQL::TimeStamp* _val, size_t _size)
507{
508 if (_size != sizeof(SQL::TimeStamp)) {
510 return false;
511 }
512
513 const SQL::TimeStamp* val = (const SQL::TimeStamp*)_val;
514 ByteStringBuilder sb;
515 if (val->tzoff == INT16_MIN) {
516 sb.format(
517 "%04d-%02d-%02d %02d:%02d:%02d.%06d",
518 __ABS(val->year),
519 val->month,
520 val->day,
521 val->hour,
522 val->min,
523 val->sec,
524 val->frac / 1000
525 );
526 }
527 else {
528 sb.format(
529 "%04d-%02d-%02d %02d:%02d:%02d.%06d %+03d:%02d",
530 __ABS(val->year),
531 val->month,
532 val->day,
533 val->hour,
534 val->min,
535 val->sec,
536 val->frac / 1000,
537 val->tzoff / 60,
538 __ABS(val->tzoff % 60)
539 );
540 }
541 if (val->year < 0) {
542 sb += " BC";
543 }
544 __bytes = sb.toByteString();
545
546 switch (__type) {
547 case DATEOID:
548 case TIMESTAMPOID:
549 case TIMESTAMPTZOID:
550 case CHAROID:
551 case BPCHAROID:
552 case VARCHAROID:
553 case TEXTOID: {
554 query()->setValue(__index, __type,
555 __bytes.data(), (int)__bytes.length(), __FORMAT_TEXT
556 );
557 break;
558 }
559 default: {
561 return false;
562 }
563 }
564
565 return true;
566}
567
568bool PqParam::setInterval(const SQL::Interval* _val, size_t _size)
569{
570 if (_size != sizeof(SQL::Interval)) {
572 return false;
573 }
574
575 const SQL::Interval* val = (const SQL::Interval*)_val;
576 if (val->secs || val->fracs >= 0) {
577 __bytes = ByteString::format(
578 "P%dY%dM%dDT%dH%dM%d.%dS",
579 val->years,
580 val->months,
581 val->days,
582 val->hours,
583 val->mins,
584 val->secs,
585 __ABS(val->fracs)
586 );
587 }
588 else {
589 __bytes = ByteString::format(
590 "P%dY%dM%dDT%dH%dM%-0.%dS",
591 val->years,
592 val->months,
593 val->days,
594 val->hours,
595 val->mins,
596 __ABS(val->fracs)
597 );
598 }
599
600 switch (__type) {
601 case INTERVALOID:
602 case CHAROID:
603 case BPCHAROID:
604 case VARCHAROID:
605 case TEXTOID: {
606 query()->setValue(__index, __type,
607 __bytes.data(), (int)__bytes.length(), __FORMAT_TEXT
608 );
609 break;
610 }
611 default: {
613 return false;
614 }
615 }
616
617 return true;
618}
619
621 _CONST void* _val,
622 size_t _size,
623 SQL::DataType _valType,
624 SQL::DataType _sqlType
625)
626{
627 const char* val = (const char*)_val;
628 size_t size = _size;
629 SQL::DataType valType = _valType;
630 if (_valType == SQL::typeInputStream) {
631 try {
632 __bytes = Files::readBytes(*(InputStream*)_val, _size);
633 val = __bytes;
634 size = __bytes.length();
635 }
636 catch (IOException* _e) {
637 __SET_ERROR_MSG(UTF8Encoder::encode(_e->toStringAll()));
638 _e->destroy();
639 return false;
640 }
641 if (_sqlType == SQL::typeBinary
642 || _sqlType == SQL::typeLongBinary
643 || _sqlType == SQL::typeBlob) {
644 valType = SQL::typeBinary;
645 }
646 }
647
648 if (10 * 1024 * 1024 < size) {
650 return false;
651 }
652
653 if (valType == SQL::typeText) {
654 switch (__type) {
655 case BYTEAOID:
656 case CHAROID:
657 case BPCHAROID:
658 case VARCHAROID:
659
660 case TEXTOID:
661 case JSONOID:
662 case XMLOID:
663
664 case TSVECTOROID:
665 case TSQUERYOID:
666 case JSONBOID:
667 case JSONPATHOID: {
668 // 여기서 FORMAT_BINARY는
669 // 서버에서 변환하지 마라! 의미
670 query()->setValue(__index, __type,
671 val, (unsigned)size, __FORMAT_BINARY
672 );
673 break;
674 }
675 case BOOLOID:
676 case INT2OID:
677 case INT4OID:
678 case INT8OID:
679 case FLOAT4OID:
680 case FLOAT8OID:
681 case MONEYOID:
682 case NUMERICOID:
683 case DATEOID:
684 case TIMEOID:
685 case TIMETZOID:
686 case TIMESTAMPOID:
687 case TIMESTAMPTZOID:
688 case INTERVALOID:
689 case BITOID:
690 case VARBITOID:
691
692 case MACADDROID:
693 case INETOID:
694 case CIDROID:
695 case MACADDR8OID:
696
697 case UUIDOID:
698 default: {
699 // 텍스트를 서버에서 적절히 변환해서 사용하라!
700 query()->setValue(__index, __type,
701 val, (unsigned)size, __FORMAT_TEXT
702 );
703 }
704#if 0
705 default: {
707 return false;
708 }
709#endif
710 }
711 }
712 else {
713 // SQL::typeBinary는
714 // 서버에서 변환하지 마라!
715 query()->setValue(__index, __type,
716 val, (unsigned)size, __FORMAT_BINARY
717 );
718 }
719
720 return true;
721}
722
723__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:312
#define INT32_MAX
Definition Config.h:290
#define UINT16_MAX
Definition Config.h:294
wchar_t char_t
Definition Config.h:247
#define INT32_MIN
Definition Config.h:285
#define _CONST
Definition Config.h:325
#define UINT32_MAX
Definition Config.h:295
#define INT16_MAX
Definition Config.h:289
#define INT16_MIN
Definition Config.h:284
#define __SET_ERROR_MSG(_message)
const wchar_t * __dataTypeName(const ifx_sqlvar_t *_sqlvar)
Definition IFXField.cpp:304
IOException *size_t r
Definition MediaInfo.cpp:82
#define __ABS(n)
Definition MyParam.cpp:145
#define __DCL_ASSERT(expr)
Definition Object.h:394
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:245
#define __T(str)
Definition Object.h:60
#define __FORMAT_BINARY
Definition PqQuery.h:7
#define __FORMAT_TEXT
Definition PqQuery.h:6
uint64_t __htond(double _x)
Definition PqTypes.h:78
uint32_t __htonf(float _x)
Definition PqTypes.h:67
__DCL_BEGIN_NAMESPACE uint16_t __htons(uint16_t _x)
Definition PqTypes.h:18
uint64_t __htonll(uint64_t _x)
Definition PqTypes.h:36
uint32_t __htonl(uint32_t _x)
Definition PqTypes.h:27
#define __SET_ERROR(_errorCode)
Definition SQLCore.cpp:149
virtual void destroy()
Definition Exception.cpp:74
String toStringAll() const
Definition Exception.cpp:45
static ByteString readBytes(InputStream &_input, size_t _n=(size_t) -1) __DCL_THROWS1(IOException *)
Definition Files.cpp:397
bool setBytes(_CONST void *_val, size_t _size, SQL::DataType _valType, SQL::DataType _sqlType)
Definition PqParam.cpp:620
virtual bool __setData(_CONST void *_val, size_t _size, SQL::DataType _valType, SQL::DataType _sqlType)
Definition PqParam.cpp:100
bool setFloat(const void *_val, size_t _size)
Definition PqParam.cpp:331
virtual const wchar_t * serverDataTypeName() const
Definition PqParam.cpp:85
bool setTimeStamp(const SQL::TimeStamp *_val, size_t _size)
Definition PqParam.cpp:506
bool init(SQL::Query *_query, int _index, const PGresult *_res)
Definition PqParam.cpp:64
bool setUInteger(const void *_val, size_t _size)
Definition PqParam.cpp:239
virtual ~PqParam()
Definition PqParam.cpp:60
bool onAfterExecute()
Definition PqParam.cpp:77
bool setTime(const SQL::Time *_val, size_t _size)
Definition PqParam.cpp:457
bool setInteger(const void *_val, size_t _size)
Definition PqParam.cpp:147
bool setInterval(const SQL::Interval *_val, size_t _size)
Definition PqParam.cpp:568
PqQuery * query() const
Definition PqParam.h:60
virtual void setNull()
Definition PqParam.cpp:90
bool setDate(const SQL::Date *_val, size_t _size)
Definition PqParam.cpp:415
DataType
Definition SQLCore.h:59
@ typeBinary
Definition SQLCore.h:74
@ typeTime
Definition SQLCore.h:66
@ typeLongBinary
Definition SQLCore.h:76
@ typeUInteger
Definition SQLCore.h:62
@ typeUnknown
Definition SQLCore.h:60
@ typeTimeStamp
Definition SQLCore.h:68
@ typeBlob
Definition SQLCore.h:78
@ typeInputStream
Definition SQLCore.h:81
@ typeInterval
Definition SQLCore.h:70
@ typeDate
Definition SQLCore.h:65
@ typeText
Definition SQLCore.h:73
@ typeFloat
Definition SQLCore.h:63
@ typeInteger
Definition SQLCore.h:61
@ eOutOfRange
Definition SQLCore.h:52
@ eNotSupportDataType
Definition SQLCore.h:48
@ eInvalidDataSize
Definition SQLCore.h:55
@ eInvalidDataType
Definition SQLCore.h:49
int16_t year
Definition SQLCore.h:96
uint8_t month
Definition SQLCore.h:97
uint8_t day
Definition SQLCore.h:98
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
uint8_t hour
Definition SQLCore.h:103
uint8_t sec
Definition SQLCore.h:105
uint32_t frac
Definition SQLCore.h:106
uint8_t min
Definition SQLCore.h:104
int16_t tzoff
Definition SQLCore.h:107
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