DCL 4.0
Loading...
Searching...
No Matches
MyField.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <float.h> // FLT_MIN, FLT_MAX
4#include <math.h> // modf
5#include <string.h> // memcpy
6
7#include <dcl/Object.h>
8#if __DCL_HAVE_ALLOC_DEBUG
9#undef __DCL_ALLOC_LEVEL
10#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
11#endif
12
13#include <dcl/size_t.h>
14#include <dcl/SQLCore.h>
15#include <dcl/OutputStream.h>
16#include <dcl/Charset.h>
17
18#include "MyConnection.h"
19#include "MyQuery.h"
20#include "MyField.h"
21
22#define __TRACE_THIS 0
23#if __TRACE_THIS
24#define __DCL_TRACE0_N __DCL_TRACE0
25#define __DCL_TRACE1_N __DCL_TRACE1
26#define __DCL_TRACE2_N __DCL_TRACE2
27#define __DCL_TRACE3_N __DCL_TRACE3
28#define __DCL_TRACE4_N __DCL_TRACE4
29#else
30#define __DCL_TRACE0_N(fmt)
31#define __DCL_TRACE1_N(fmt, arg)
32#define __DCL_TRACE2_N(fmt, arg1, arg2)
33#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
34#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
35#endif
36
37#if __DCL_HAVE_THIS_FILE__
38#undef __THIS_FILE__
39static const wchar_t __THIS_FILE__[] = __T("dcl/sql/MyField.cpp");
40#endif
41
42__DCL_BEGIN_NAMESPACE
43
45
47 : Field(NULL)
48{
49 __index = 0;
50 __field = NULL;
51 __bind = NULL;
52}
53
55{
56 __DCL_TRACE1_N(L"~MyField [%ls]\n", Field::__name.data());
57}
58
59bool MyField::init(SQL::Query* _queryHandle,
60 unsigned int _index, MYSQL_FIELD* _field, MYSQL_BIND* _bind)
61{
62 __DCL_ASSERT((_queryHandle != NULL) && (_field != NULL));
63
64 Field::__queryHandle = _queryHandle;
65 __index = _index;
66 __field = _field;
67 __bind = _bind;
68
69 try {
70 Field::__name = UTF8Decoder::decode(_field->name).toUpperCase();
71 }
72 catch (CharsetConvertException* _e) {
73 __SET_ERROR_MSG(UTF8Encoder::encode(_e->toStringAll()));
74 _e->destroy();
75 return false;
76 }
77
78 __DCL_TRACE2_N(L"[%ls] decimals[%u]\n", __name.data(), _field->decimals);
79 Field::__scale = _field->decimals;
80
81 enum enum_field_types _type = __field->type;
82 unsigned int _flags = __field->flags;
83
84 switch(_type) {
85 case MYSQL_TYPE_TINY: {
86 if (_flags & UNSIGNED_FLAG) {
87 Field::__precision = _field->length;
88 Field::__dataType = SQL::typeUInteger;
89 }
90 else {
91 Field::__precision = _field->length - 1;
92 Field::__dataType = SQL::typeInteger;
93 }
94 __maxsize = sizeof(int8_t);
95 break;
96 }
97 case MYSQL_TYPE_YEAR:
98 case MYSQL_TYPE_SHORT: {
99 if (_flags & UNSIGNED_FLAG) {
100 Field::__precision = _field->length;
101 Field::__dataType = SQL::typeUInteger;
102 }
103 else {
104 Field::__precision = _field->length - 1;
105 Field::__dataType = SQL::typeInteger;
106 }
107 __maxsize = sizeof(int16_t);
108 break;
109 }
110 case MYSQL_TYPE_INT24:
111 case MYSQL_TYPE_LONG: {
112 if (_flags & UNSIGNED_FLAG) {
113 Field::__precision = _field->length;
114 Field::__dataType = SQL::typeUInteger;
115 }
116 else {
117 Field::__precision = _field->length - 1;
118 Field::__dataType = SQL::typeInteger;
119 }
120 __maxsize = sizeof(int32_t);
121 break;
122 }
123 case MYSQL_TYPE_LONGLONG: {
124 if (_flags & UNSIGNED_FLAG) {
125 Field::__precision = _field->length;
126 Field::__dataType = SQL::typeUInteger;
127 }
128 else {
129 Field::__precision = _field->length - 1;
130 Field::__dataType = SQL::typeInteger;
131 }
132 __maxsize = sizeof(int64_t);
133 break;
134 }
135 case MYSQL_TYPE_FLOAT: {
136 Field::__precision = _field->length - 1;
137 Field::__dataType = SQL::typeFloat;
138 __maxsize = sizeof(float);
139 break;
140 }
141 case MYSQL_TYPE_DOUBLE: {
142 Field::__precision = _field->length - 1;
143 Field::__dataType = SQL::typeFloat;
144 __maxsize = sizeof(double);
145 break;
146 }
147 case MYSQL_TYPE_NULL: {
148 Field::__dataType = SQL::typeUnknown;
149 __maxsize = 0;
150 break;
151 }
152 case MYSQL_TYPE_TIMESTAMP:
153 case MYSQL_TYPE_DATETIME:
154 case MYSQL_TYPE_TIMESTAMP2:
155 case MYSQL_TYPE_DATETIME2: {
156 Field::__precision = _field->length;
157 Field::__dataType = SQL::typeTimeStamp;
158 __maxsize = sizeof(SQL::TimeStamp);
159 break;
160 }
161 case MYSQL_TYPE_DATE:
162 case MYSQL_TYPE_NEWDATE : {
163 Field::__precision = _field->length;
164 Field::__dataType = SQL::typeDate;
165 __maxsize = sizeof(SQL::Date);
166 break;
167 }
168 case MYSQL_TYPE_TIME:
169 case MYSQL_TYPE_TIME2: {
170 Field::__precision = _field->length - 2;
171 Field::__dataType = SQL::typeIntervalDs;
172 __maxsize = sizeof(SQL::Interval);
173 break;
174 }
175 case MYSQL_TYPE_DECIMAL:
176 case MYSQL_TYPE_NEWDECIMAL: {
177 Field::__precision = _field->length - (_field->decimals == 0 ? 1 : 2);
178 Field::__dataType = SQL::typeNumeric;
179 __maxsize = _field->length;
180 break;
181 }
182 case MYSQL_TYPE_BIT: {
183 Field::__precision = _field->length;
184 Field::__dataType = SQL::typeBinary;
185 __maxsize = sizeof(int64_t);
186 break;
187 }
188 case MYSQL_TYPE_JSON:
189 case MYSQL_TYPE_ENUM:
190 case MYSQL_TYPE_SET:
191 case MYSQL_TYPE_VAR_STRING:
192 case MYSQL_TYPE_STRING:
193 case MYSQL_TYPE_GEOMETRY: {
194 Field::__dataType = _flags & BINARY_FLAG ?
196 __maxsize = _field->length;
197 break;
198 }
199 case MYSQL_TYPE_TINY_BLOB :
200 case MYSQL_TYPE_BLOB :
201 case MYSQL_TYPE_MEDIUM_BLOB :
202 case MYSQL_TYPE_LONG_BLOB: {
203 if (_flags & BINARY_FLAG) {
204 Field::__dataType = _field->length <= ((uint16_t)-1 * 3) ?
206 }
207 else {
208 Field::__dataType = _field->length <= ((uint16_t)-1 * 3) ?
210 }
211 __maxsize = _field->length;
212 break;
213 }
214 default: {
215 __DCL_ASSERT(false);
216 }
217 }
218
219 return true;
220}
221
222#define SQLTYPE_NAME(type, name) case type : return name
223
224const wchar_t* __dataTypeName(enum_field_types _type, unsigned int _flags)
225{
226 switch(_type) {
227 SQLTYPE_NAME(MYSQL_TYPE_DECIMAL, L"DECIMAL");
228 case MYSQL_TYPE_TINY :
229 if (_flags & UNSIGNED_FLAG)
230 return L"TINYINT UNSIGNED";
231 return L"TINYINT";
232 case MYSQL_TYPE_SHORT :
233 if (_flags & UNSIGNED_FLAG)
234 return L"SMALLINT UNSIGNED";
235 return L"SMALLINT";
236 case MYSQL_TYPE_LONG:
237 if (_flags & UNSIGNED_FLAG)
238 return L"INTEGER UNSIGNED";
239 return L"INTEGER";
240 SQLTYPE_NAME(MYSQL_TYPE_FLOAT, L"FLOAT");
241 SQLTYPE_NAME(MYSQL_TYPE_DOUBLE, L"DOUBLE");
242 SQLTYPE_NAME(MYSQL_TYPE_NULL, L"NULL-TYPE");
243 SQLTYPE_NAME(MYSQL_TYPE_TIMESTAMP, L"TIMESTAMP");
244 case MYSQL_TYPE_LONGLONG:
245 if (_flags & UNSIGNED_FLAG)
246 return L"BIGINT UNSIGNED";
247 return L"BIGINT";
248 case MYSQL_TYPE_INT24 :
249 if (_flags & UNSIGNED_FLAG)
250 return L"MEDIUMINT UNSIGNED";
251 return L"MEDIUMINT";
252 SQLTYPE_NAME(MYSQL_TYPE_DATE, L"DATE");
253 SQLTYPE_NAME(MYSQL_TYPE_TIME, L"TIME");
254 SQLTYPE_NAME(MYSQL_TYPE_DATETIME, L"DATETIME");
255 SQLTYPE_NAME(MYSQL_TYPE_YEAR, L"YEAR");
256 SQLTYPE_NAME(MYSQL_TYPE_NEWDATE, L"NEWDATE");
257 SQLTYPE_NAME(MYSQL_TYPE_VARCHAR, L"VARCHAR");
258 SQLTYPE_NAME(MYSQL_TYPE_BIT, L"BIT");
259 SQLTYPE_NAME(MYSQL_TYPE_TIMESTAMP2, L"TIMESTAMP2");
260 SQLTYPE_NAME(MYSQL_TYPE_DATETIME2, L"DATETIME");
261 SQLTYPE_NAME(MYSQL_TYPE_TIME2, L"TIME2");
262 SQLTYPE_NAME(MYSQL_TYPE_JSON, L"JSON");
263 SQLTYPE_NAME(MYSQL_TYPE_NEWDECIMAL, L"NEWDECIMAL");
264 SQLTYPE_NAME(MYSQL_TYPE_ENUM, L"ENUM");
265 SQLTYPE_NAME(MYSQL_TYPE_SET, L"SET");
266 case MYSQL_TYPE_TINY_BLOB : // 2^8
267 if (_flags & BINARY_FLAG)
268 return L"TINYBLOB";
269 return L"TINYTEXT";
270 case MYSQL_TYPE_MEDIUM_BLOB: // 2^24
271 if (_flags & BINARY_FLAG)
272 return L"MEDIUMBLOB";
273 return L"MEDIUMTEXT";
274 case MYSQL_TYPE_LONG_BLOB: // 2^32
275 if (_flags & BINARY_FLAG)
276 return L"LONGBLOB";
277 return L"LONGTEXT";
278 case MYSQL_TYPE_BLOB : // 2^16
279 if (_flags & BINARY_FLAG)
280 return L"BLOB";
281 return L"TEXT";
282 SQLTYPE_NAME(MYSQL_TYPE_VAR_STRING, L"VAR STRING");
283 SQLTYPE_NAME(MYSQL_TYPE_STRING, L"STRING");
284 SQLTYPE_NAME(MYSQL_TYPE_GEOMETRY, L"GEOMETRY");
285 SQLTYPE_NAME(MAX_NO_FIELD_TYPES, L"MAX_NO_FIELD_TYPES");
286 default:
287 ;
288 }
289 return L"Unknown Type: Driver Not Support";
290}
291
292const wchar_t* MyField::serverDataTypeName() const
293{
294 return __dataTypeName(__field->type, __field->flags);
295}
296
297bool MyField::isNull() const
298{
299 if (!query()->inState(SQL::Query::stFetched)) {
300 return true;
301 }
302 return __bind->is_null_value;
303}
304
305bool MyField::__getDataSize(size_t* _psize, bool _maxsize)
306{
307 if (_maxsize) {
308 *_psize = __maxsize;
309 return true;
310 }
311
312 if (!query()->inState(SQL::Query::stFetched)) {
314 return false;
315 }
316
317 switch (Field::__dataType) {
318 case SQL::typeInteger:
320 case SQL::typeFloat:
321 case SQL::typeDate:
322 case SQL::typeTime:
328 *_psize = __maxsize;
329 break;
330 default:
331 *_psize = __bind->length_value;
332 }
333
334 return true;
335}
336
337#define __TYPE_IS(_type) (__field->type == _type)
338
339bool MyField::__getData(void* _pv, size_t* _psize, SQL::DataType _dataType)
340{
341 if (!query()->inState(SQL::Query::stFetched)) {
343 return false;
344 }
345
346 switch(_dataType) {
347 case SQL::typeInteger :
348 return getInteger(_pv, _psize);
349 case SQL::typeUInteger :
350 return getUInteger(_pv, _psize);
351 case SQL::typeFloat :
352 return getFloat(_pv, _psize);
353 case SQL::typeDate :
354 return getDate((SQL::Date*)_pv, _psize);
355 case SQL::typeTimeStamp :
356 return getTimeStamp((SQL::TimeStamp*)_pv, _psize);
357 case SQL::typeTime:
358 return getTime((SQL::Time*)_pv, _psize);
362 return getInterval((SQL::Interval*)_pv, _psize);
363 case SQL::typeText:
364 case SQL::typeBinary :
365 case SQL::typeLongText :
366 case SQL::typeLongBinary : {
367 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_DECIMAL)
368 || __TYPE_IS(MYSQL_TYPE_NEWDECIMAL)
369 || __TYPE_IS(MYSQL_TYPE_BIT)
370 || __TYPE_IS(MYSQL_TYPE_JSON)
371 || __TYPE_IS(MYSQL_TYPE_ENUM)
372 || __TYPE_IS(MYSQL_TYPE_SET)
373 || __TYPE_IS(MYSQL_TYPE_VAR_STRING)
374 || __TYPE_IS(MYSQL_TYPE_STRING)
375 || __TYPE_IS(MYSQL_TYPE_GEOMETRY)
376 || __TYPE_IS(MYSQL_TYPE_TINY_BLOB)
377 || __TYPE_IS(MYSQL_TYPE_BLOB)
378 || __TYPE_IS(MYSQL_TYPE_MEDIUM_BLOB)
379 || __TYPE_IS(MYSQL_TYPE_LONG_BLOB)
380 );
381 if (*_psize < __bind->length_value) {
383 return false;
384 }
385 if (__bind->buffer_length) {
386 // 버퍼가 할당되어 있으면, 이것을 복사한다.
387 memcpy(_pv, __bind->buffer, __bind->length_value);
388 }
389 else {
390 __DCL_TRACE2_N(L"b[%u][%u]\n",
391 __bind->buffer_length, __bind->length_value);
392 MYSQL_BIND bind;
393 memset(&bind, 0, sizeof(bind));
394 bind.buffer = _pv;
395 bind.buffer_length = *_psize;
396 if (mysql_stmt_fetch_column(query()->stmt(), &bind, __index, 0)) {
397 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
398 mysql_stmt_errno(query()->stmt()),
399 mysql_stmt_error(query()->stmt())));
400 return false;
401 }
402 }
403 if (*_psize > __bind->length_value)
404 *((char*)_pv + __bind->length_value) = '\0';
405 *_psize = __bind->length_value;
406 break;
407 }
409 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_DECIMAL)
410 || __TYPE_IS(MYSQL_TYPE_NEWDECIMAL)
411 || __TYPE_IS(MYSQL_TYPE_BIT)
412 || __TYPE_IS(MYSQL_TYPE_JSON)
413 || __TYPE_IS(MYSQL_TYPE_ENUM)
414 || __TYPE_IS(MYSQL_TYPE_SET)
415 || __TYPE_IS(MYSQL_TYPE_VAR_STRING)
416 || __TYPE_IS(MYSQL_TYPE_STRING)
417 || __TYPE_IS(MYSQL_TYPE_GEOMETRY)
418 || __TYPE_IS(MYSQL_TYPE_TINY_BLOB)
419 || __TYPE_IS(MYSQL_TYPE_BLOB)
420 || __TYPE_IS(MYSQL_TYPE_MEDIUM_BLOB)
421 || __TYPE_IS(MYSQL_TYPE_LONG_BLOB)
422 );
423 if (__bind->length_value < *_psize) {
424 *_psize = __bind->length_value;
425 }
426 try {
427 char buf[4096];
428 MYSQL_BIND bind;
429 memset(&bind, 0, sizeof(bind));
430 bind.buffer = buf;
431 bind.length = &bind.length_value;
432 unsigned long total = 0;
433 while (total < *_psize) {
434 bind.buffer_length = __MIN(sizeof(buf), *_psize - total);
435 if (mysql_stmt_fetch_column(query()->stmt(),
436 &bind, __index, total)) {
437 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
438 mysql_stmt_errno(query()->stmt()),
439 mysql_stmt_error(query()->stmt())));
440 return false;
441 }
442 ((OutputStream*)_pv)->write(bind.buffer, bind.buffer_length);
443 total += bind.buffer_length;
444 __DCL_TRACE2_N(L"mysql_stmt_fetch_column [%u][%u]\n",
445 bind.buffer_length, bind.length_value);
446 }
447 }
448 catch (IOException* e) {
449 __SET_ERROR_MSG(UTF8Encoder::encode(e->toStringAll()));
450 e->destroy();
451 return false;
452 }
453 break;
454 }
455 default :
456 __DCL_ASSERT(false); // SQL::Field::getData bug
457 }
458
459 return true;
460}
461
462bool MyField::getInteger(void* _pv, size_t* _psize)
463{
464 __DCL_ASSERT(!(__field->flags & UNSIGNED_FLAG));
465
466 switch (__field->type) {
467 case MYSQL_TYPE_TINY: {
468 switch (*_psize) {
469 case sizeof(int8_t) : {
470 *(int8_t*)_pv = *(int8_t*)__bind->buffer;
471 break;
472 }
473 case sizeof(int16_t) : {
474 *(int16_t*)_pv = *(int8_t*)__bind->buffer;
475 break;
476 }
477 case sizeof(int32_t) : {
478 *(int32_t*)_pv = *(int8_t*)__bind->buffer;
479 break;
480 }
481 case sizeof(int64_t) : {
482 *(int64_t*)_pv = *(int8_t*)__bind->buffer;
483 break;
484 }
485 default: {
486 *_psize = sizeof(int8_t);
488 return false;
489 }
490 }
491 break;
492 }
493 case MYSQL_TYPE_YEAR :
494 case MYSQL_TYPE_SHORT : {
495 switch (*_psize) {
496 case sizeof(int16_t) : {
497 *(int16_t*)_pv = *(int16_t*)__bind->buffer;
498 break;
499 }
500 case sizeof(int32_t) : {
501 *(int32_t*)_pv = *(int16_t*)__bind->buffer;
502 break;
503 }
504 case sizeof(int64_t) : {
505 *(int64_t*)_pv = *(int16_t*)__bind->buffer;
506 break;
507 }
508 default: {
509 *_psize = sizeof(int16_t);
511 return false;
512 }
513 }
514 break;
515 }
516 case MYSQL_TYPE_INT24 :
517 case MYSQL_TYPE_LONG : {
518 switch (*_psize) {
519 case sizeof(int32_t) : {
520 *(int32_t*)_pv = *(int32_t*)__bind->buffer;
521 break;
522 }
523 case sizeof(int64_t) : {
524 *(int64_t*)_pv = *(int32_t*)__bind->buffer;
525 break;
526 }
527 default: {
528 *_psize = sizeof(int32_t);
530 return false;
531 }
532 }
533 break;
534 }
535 case MYSQL_TYPE_LONGLONG : {
536 switch (*_psize) {
537 case sizeof(int64_t) : {
538 *(int64_t*)_pv = *(int64_t*)__bind->buffer;
539 break;
540 }
541 default: {
542 *_psize = sizeof(int64_t);
544 return false;
545 }
546 }
547 break;
548 }
549 case MYSQL_TYPE_DECIMAL:
550 case MYSQL_TYPE_NEWDECIMAL: {
551 char* endptr;
552 long long n;
553 if ((Field::__precision - Field::__scale) < 20) {
554 n = strtoll((char*)__bind->buffer, &endptr, 10);
555 if (n == LLONG_MAX || n == LLONG_MIN) {
556 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
558 return false;
559 }
560 }
561 else {
562 double d = strtod((char*)__bind->buffer, &endptr);
563 if (+HUGE_VAL == d || -HUGE_VAL == d || !(DBL_MIN < d)) {
564 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
566 return false;
567 }
568
569 double i;
570 (void)modf(d, &i); // 정수부분만, 반환값(소수)는 버림
571 if (i < LLONG_MIN || LLONG_MAX < i) {
573 return false;
574 }
575 n = (long long)i;
576 }
577
578 switch (*_psize) {
579 case sizeof(int8_t) : {
580 if (n < INT8_MIN || INT8_MAX < n) {
582 return false;
583 }
584 *(int8_t*)_pv = (int8_t)n;
585 break;
586 }
587 case sizeof(int16_t) : {
588 if (n < INT16_MIN || INT16_MAX < n) {
590 return false;
591 }
592 *(int16_t*)_pv = (int16_t)n;
593 break;
594 }
595 case sizeof(int32_t) : {
596 if (n < INT32_MIN || INT32_MAX < n) {
598 return false;
599 }
600 *(int32_t*)_pv = (int32_t)n;
601 break;
602 }
603 case sizeof(int64_t) : {
604 *(int64_t*)_pv = (int64_t)n;
605 break;
606 }
607 default: {
608 *_psize = sizeof(int64_t);
610 return false;
611 }
612 }
613 break;
614 }
615 default: {
616 __DCL_ASSERT(false); // MyField::init bug
617 }
618 }
619
620 return true;
621}
622
623bool MyField::getUInteger(void* _pv, size_t* _psize)
624{
625 __DCL_ASSERT(__field->flags & UNSIGNED_FLAG);
626
627 switch (__field->type) {
628 case MYSQL_TYPE_TINY : {
629 switch (*_psize) {
630 case sizeof(uint8_t) : {
631 *(uint8_t*)_pv = *(uint8_t*)__bind->buffer;
632 break;
633 }
634 case sizeof(uint16_t) : {
635 *(uint16_t*)_pv = *(uint8_t*)__bind->buffer;
636 break;
637 }
638 case sizeof(uint32_t) : {
639 *(uint32_t*)_pv = *(uint8_t*)__bind->buffer;
640 break;
641 }
642 case sizeof(uint64_t) : {
643 *(uint64_t*)_pv = *(uint8_t*)__bind->buffer;
644 break;
645 }
646 default: {
647 *_psize = sizeof(uint8_t);
649 return false;
650 }
651 }
652 break;
653 }
654 case MYSQL_TYPE_YEAR :
655 case MYSQL_TYPE_SHORT: {
656 switch (*_psize) {
657 case sizeof(uint16_t) : {
658 *(uint16_t*)_pv = *(uint16_t*)__bind->buffer;
659 break;
660 }
661 case sizeof(uint32_t) : {
662 *(uint32_t*)_pv = *(uint16_t*)__bind->buffer;
663 break;
664 }
665 case sizeof(uint64_t) : {
666 *(uint64_t*)_pv = *(uint16_t*)__bind->buffer;
667 break;
668 }
669 default: {
670 *_psize = sizeof(uint16_t);
672 return false;
673 }
674 }
675 break;
676 }
677 case MYSQL_TYPE_INT24:
678 case MYSQL_TYPE_LONG: {
679 switch (*_psize) {
680 case sizeof(uint32_t) : {
681 *(uint32_t*)_pv = *(uint32_t*)__bind->buffer;
682 break;
683 }
684 case sizeof(uint64_t) : {
685 *(uint64_t*)_pv = *(uint32_t*)__bind->buffer;
686 break;
687 }
688 default: {
689 *_psize = sizeof(uint32_t);
691 return false;
692 }
693 }
694 break;
695 }
696 case MYSQL_TYPE_LONGLONG: {
697 switch (*_psize) {
698 case sizeof(uint64_t) : {
699 *(uint64_t*)_pv = *(uint64_t*)__bind->buffer;
700 break;
701 }
702 default: {
703 *_psize = sizeof(uint32_t);
705 return false;
706 }
707 }
708 break;
709 }
710 case MYSQL_TYPE_DECIMAL :
711 case MYSQL_TYPE_NEWDECIMAL : {
712 char* endptr;
713 unsigned long long u;
714 if ((Field::__precision - Field::__scale) < 20) {
715 u = strtoull((char*)__bind->buffer, &endptr, 10);
716 if (u == ULONG_MAX) {
717 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
719 return false;
720 }
721 }
722 else {
723 double d = strtod((char*)__bind->buffer, &endptr);
724 if (+HUGE_VAL == d || -HUGE_VAL == d || !(DBL_MIN < d)) {
725 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
727 return false;
728 }
729
730 double i;
731 modf(d, &i); // 정수부분만, 반환값(소수)는 버림
732 if (i < 0 || ULONG_MAX < i) {
734 return false;
735 }
736 u = (unsigned long long)i;
737 }
738
739 switch (*_psize) {
740 case sizeof(uint8_t): {
741 if (UINT8_MAX < u) {
743 return false;
744 }
745 *(uint8_t*)_pv = (uint8_t)u;
746 break;
747 }
748 case sizeof(uint16_t): {
749 if (UINT16_MAX < u) {
751 return false;
752 }
753 *(uint16_t*)_pv = (uint16_t)u;
754 break;
755 }
756 case sizeof(uint32_t): {
757 if (UINT32_MAX < u) {
759 return false;
760 }
761 *(uint32_t*)_pv = (uint32_t)u;
762 break;
763 }
764 case sizeof(uint64_t): {
765 *(uint64_t*)_pv = (uint64_t)u;
766 break;
767 }
768 default: {
769 *_psize = sizeof(uint64_t);
771 return false;
772 }
773 }
774 break;
775 }
776 default: {
777 __DCL_ASSERT(false); // MyField::init bug
778 }
779 }
780
781 return true;
782}
783
784bool MyField::getFloat(void* _pv, size_t* _psize)
785{
786 switch (__field->type) {
787 case MYSQL_TYPE_FLOAT: {
788 switch (*_psize) {
789 case sizeof(float): {
790 *(float*)_pv = *(float*)__bind->buffer;
791 break;
792 }
793 case sizeof(double): {
794 *(double*)_pv = *(float*)__bind->buffer;
795 break;
796 }
797 default: {
798 *_psize = sizeof(float);
800 return false;
801 }
802 }
803 break;
804 }
805 case MYSQL_TYPE_DOUBLE: {
806 switch (*_psize) {
807 case sizeof(double) : {
808 *(double*)_pv = *(double*)__bind->buffer;
809 break;
810 }
811 default: {
812 *_psize = sizeof(double);
814 return false;
815 }
816 }
817 break;
818 }
819 case MYSQL_TYPE_DECIMAL:
820 case MYSQL_TYPE_NEWDECIMAL: {
821 char* endptr;
822 double d = strtod((char*)__bind->buffer, &endptr);
823 if (+HUGE_VAL == d || -HUGE_VAL == d || !(DBL_MIN < d)) {
824 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
826 return false;
827 }
828
829 switch (*_psize) {
830 case sizeof(float): {
831 if (d < FLT_MIN || FLT_MAX < d) {
833 return false;
834 }
835 *(float*)_pv = (float) d;
836 break;
837 }
838 case sizeof(double): {
839 if (d < DBL_MIN || DBL_MAX < d) {
841 return false;
842 }
843 *(double*)_pv = (double)d;
844 break;
845 }
846 default : {
847 *_psize = sizeof(double);
849 return false;
850 }
851 }
852 break;
853 }
854 default : {
855 __DCL_ASSERT(false); // MyField::init bug
856 }
857 }
858
859 return true;
860}
861
862bool MyField::getDate(SQL::Date* _pv, size_t* _psize)
863{
864 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_DATE));
865
866 if (*_psize != sizeof(SQL::Date)) {
867 *_psize = sizeof(SQL::Date);
869 return false;
870 }
871
872 MYSQL_TIME* s = (MYSQL_TIME*)__bind->buffer;
873 _pv->nYear = s->year * (s->neg ? -1 : 1);
874 _pv->nMonth = s->month;
875 _pv->nDay = s->day;
876
877 return true;
878}
879
880bool MyField::getTimeStamp(SQL::TimeStamp* _pv, size_t* _psize)
881{
882 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_DATETIME)
883 || __TYPE_IS(MYSQL_TYPE_TIMESTAMP));
884
885 if (*_psize != sizeof(SQL::TimeStamp)) {
887 return false;
888 }
889
890 MYSQL_TIME* s = (MYSQL_TIME*)__bind->buffer;
891 _pv->nYear = s->year * (s->neg ? -1 : 1);
892 _pv->nMonth = s->month;
893 _pv->nDay = s->day;
894 _pv->nHour = s->hour;
895 _pv->nMin = s->minute;
896 _pv->nSec = s->second;
897 _pv->nFrac = s->second_part * 1000;
898 _pv->nTzMin = -1;
899
900 return true;
901}
902
903bool MyField::getTime(SQL::Time* _pv, size_t* _psize)
904{
905 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_TIME));
906
907 if (*_psize != sizeof(SQL::Time)) {
908 *_psize = sizeof(SQL::Time);
910 return false;
911 }
912
913 MYSQL_TIME* s = (MYSQL_TIME*)__bind->buffer;
914 _pv->nHour = s->hour;
915 _pv->nMin = s->minute;
916 _pv->nSec = s->second;
917 _pv->nFrac = s->second_part * 1000;
918
919 return true;
920}
921
922bool MyField::getInterval(SQL::Interval* _pv, size_t* _psize)
923{
924 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_TIME));
925
926 if (*_psize != sizeof(SQL::Interval)) {
927 *_psize = sizeof(SQL::Interval);
929 return false;
930 }
931
932 MYSQL_TIME* s = (MYSQL_TIME*)__bind->buffer;
933 int8_t sign = s->neg ? -1 : 1;
934 _pv->nYears = 0;
935 _pv->nMonths = 0;
936 _pv->nDays = s->hour / 24 * sign;
937 _pv->nHours = s->hour % 24 * sign;
938 _pv->nMins = s->minute * sign;
939 _pv->nSecs = s->second * sign;
940 _pv->nFracs = s->second_part * 1000 * sign;
941
942 return true;
943}
944
945__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
#define INT32_MAX
Definition Config.h:318
#define UINT16_MAX
Definition Config.h:322
#define INT32_MIN
Definition Config.h:313
#define INT8_MIN
Definition Config.h:311
#define INT8_MAX
Definition Config.h:316
#define UINT32_MAX
Definition Config.h:323
#define INT16_MAX
Definition Config.h:317
#define INT16_MIN
Definition Config.h:312
#define UINT8_MAX
Definition Config.h:321
#define __DCL_TRACE1_N(fmt, arg)
#define __DCL_TRACE2_N(fmt, arg1, arg2)
#define __SET_ERROR_MSG(_message)
#define __TYPE_IS(_type)
Definition MyField.cpp:337
#define SQLTYPE_NAME(type, name)
Definition MyField.cpp:222
const wchar_t * __dataTypeName(enum_field_types _type, unsigned int _flags)
Definition MyField.cpp:224
const wchar_t * __dataTypeName(enum_field_types _type, unsigned int _flags)
Definition MyField.cpp:224
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:228
#define __T(str)
Definition Object.h:44
ByteBuffer * buf
#define __SET_ERROR(_errorCode)
Definition SQLCore.cpp:150
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
virtual void destroy()
Definition Exception.cpp:74
String toStringAll() const
Definition Exception.cpp:45
virtual bool isNull() const
Definition MyField.cpp:297
bool getTimeStamp(SQL::TimeStamp *_pv, size_t *_psize)
Definition MyField.cpp:880
bool getTime(SQL::Time *_pv, size_t *_psize)
Definition MyField.cpp:903
bool init(SQL::Query *_query, unsigned int _index, MYSQL_FIELD *_field, MYSQL_BIND *_bind)
Definition MyField.cpp:59
virtual bool __getDataSize(size_t *_psize, bool _maxsize)
Definition MyField.cpp:305
virtual const wchar_t * serverDataTypeName() const
Definition MyField.cpp:292
bool getInterval(SQL::Interval *_pv, size_t *_psize)
Definition MyField.cpp:922
bool getInteger(void *_pv, size_t *_psize)
Definition MyField.cpp:462
MyQuery * query() const
Definition MyField.h:67
bool getDate(SQL::Date *_pv, size_t *_psize)
Definition MyField.cpp:862
bool getUInteger(void *_pv, size_t *_psize)
Definition MyField.cpp:623
bool getFloat(void *_pv, size_t *_psize)
Definition MyField.cpp:784
virtual bool __getData(void *_pv, size_t *_psize, SQL::DataType _dataType)
Definition MyField.cpp:339
virtual ~MyField()
Definition MyField.cpp:54
String __name
Definition SQLCore.h:183
DataType
Definition SQLCore.h:62
@ typeBinary
Definition SQLCore.h:76
@ typeNumeric
Definition SQLCore.h:67
@ typeTime
Definition SQLCore.h:69
@ typeLongBinary
Definition SQLCore.h:78
@ typeUInteger
Definition SQLCore.h:65
@ typeUnknown
Definition SQLCore.h:63
@ typeTimeStamp
Definition SQLCore.h:70
@ typeTimeStampTz
Definition SQLCore.h:71
@ typeInterval
Definition SQLCore.h:72
@ typeIntervalDs
Definition SQLCore.h:74
@ typeDate
Definition SQLCore.h:68
@ typeOutputStream
Definition SQLCore.h:84
@ typeText
Definition SQLCore.h:75
@ typeFloat
Definition SQLCore.h:66
@ typeInteger
Definition SQLCore.h:64
@ typeIntervalYm
Definition SQLCore.h:73
@ typeLongText
Definition SQLCore.h:77
@ eOutOfRange
Definition SQLCore.h:52
@ eInvalidBufferSize
Definition SQLCore.h:50
@ eServerError
Definition SQLCore.h:21
@ eNotFetched
Definition SQLCore.h:43
size_t __MIN(size_t x, size_t y)
Definition size_t.h:27
uint8_t nMonth
Definition SQLCore.h:97
int16_t nYear
Definition SQLCore.h:96
uint8_t nDay
Definition SQLCore.h:98
int8_t nHours
Definition SQLCore.h:128
int32_t nFracs
Definition SQLCore.h:131
int8_t nSecs
Definition SQLCore.h:130
int8_t nMins
Definition SQLCore.h:129
int32_t nYears
Definition SQLCore.h:125
int8_t nMonths
Definition SQLCore.h:126
int32_t nDays
Definition SQLCore.h:127
uint8_t nHour
Definition SQLCore.h:103
uint8_t nMin
Definition SQLCore.h:104
uint8_t nSec
Definition SQLCore.h:105
uint32_t nFrac
Definition SQLCore.h:106
int16_t nYear
Definition SQLCore.h:111
uint8_t nDay
Definition SQLCore.h:113
uint8_t nHour
Definition SQLCore.h:114
int16_t nTzMin
Definition SQLCore.h:118
uint8_t nSec
Definition SQLCore.h:116
uint8_t nMonth
Definition SQLCore.h:112
uint8_t nMin
Definition SQLCore.h:115
uint32_t nFrac
Definition SQLCore.h:117