DCL 4.1
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);
360 return getInterval((SQL::Interval*)_pv, _psize);
361 case SQL::typeText:
362 case SQL::typeBinary: {
363 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_DECIMAL)
364 || __TYPE_IS(MYSQL_TYPE_NEWDECIMAL)
365 || __TYPE_IS(MYSQL_TYPE_BIT)
366 || __TYPE_IS(MYSQL_TYPE_JSON)
367 || __TYPE_IS(MYSQL_TYPE_ENUM)
368 || __TYPE_IS(MYSQL_TYPE_SET)
369 || __TYPE_IS(MYSQL_TYPE_VAR_STRING)
370 || __TYPE_IS(MYSQL_TYPE_STRING)
371 || __TYPE_IS(MYSQL_TYPE_GEOMETRY)
372 || __TYPE_IS(MYSQL_TYPE_TINY_BLOB)
373 || __TYPE_IS(MYSQL_TYPE_BLOB)
374 || __TYPE_IS(MYSQL_TYPE_MEDIUM_BLOB)
375 || __TYPE_IS(MYSQL_TYPE_LONG_BLOB)
376 );
377 if (*_psize < __bind->length_value) {
379 return false;
380 }
381 if (__bind->buffer_length) {
382 // 버퍼가 할당되어 있으면, 이것을 복사한다.
383 memcpy(_pv, __bind->buffer, __bind->length_value);
384 }
385 else {
386 __DCL_TRACE2_N(L"b[%u][%u]\n",
387 __bind->buffer_length, __bind->length_value);
388 MYSQL_BIND bind;
389 memset(&bind, 0, sizeof(bind));
390 bind.buffer = _pv;
391 bind.buffer_length = *_psize;
392 if (mysql_stmt_fetch_column(query()->stmt(), &bind, __index, 0)) {
393 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
394 mysql_stmt_errno(query()->stmt()),
395 mysql_stmt_error(query()->stmt())));
396 return false;
397 }
398 }
399 if (*_psize > __bind->length_value)
400 *((char*)_pv + __bind->length_value) = '\0';
401 *_psize = __bind->length_value;
402 break;
403 }
405 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_DECIMAL)
406 || __TYPE_IS(MYSQL_TYPE_NEWDECIMAL)
407 || __TYPE_IS(MYSQL_TYPE_BIT)
408 || __TYPE_IS(MYSQL_TYPE_JSON)
409 || __TYPE_IS(MYSQL_TYPE_ENUM)
410 || __TYPE_IS(MYSQL_TYPE_SET)
411 || __TYPE_IS(MYSQL_TYPE_VAR_STRING)
412 || __TYPE_IS(MYSQL_TYPE_STRING)
413 || __TYPE_IS(MYSQL_TYPE_GEOMETRY)
414 || __TYPE_IS(MYSQL_TYPE_TINY_BLOB)
415 || __TYPE_IS(MYSQL_TYPE_BLOB)
416 || __TYPE_IS(MYSQL_TYPE_MEDIUM_BLOB)
417 || __TYPE_IS(MYSQL_TYPE_LONG_BLOB)
418 );
419 if (__bind->length_value < *_psize) {
420 *_psize = __bind->length_value;
421 }
422 try {
423 char buf[4096];
424 MYSQL_BIND bind;
425 memset(&bind, 0, sizeof(bind));
426 bind.buffer = buf;
427 bind.length = &bind.length_value;
428 unsigned long total = 0;
429 while (total < *_psize) {
430 bind.buffer_length = __MIN(sizeof(buf), *_psize - total);
431 if (mysql_stmt_fetch_column(query()->stmt(),
432 &bind, __index, total)) {
433 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
434 mysql_stmt_errno(query()->stmt()),
435 mysql_stmt_error(query()->stmt())));
436 return false;
437 }
438 ((OutputStream*)_pv)->write(bind.buffer, bind.buffer_length);
439 total += bind.buffer_length;
440 __DCL_TRACE2_N(L"mysql_stmt_fetch_column [%u][%u]\n",
441 bind.buffer_length, bind.length_value);
442 }
443 }
444 catch (IOException* e) {
445 __SET_ERROR_MSG(UTF8Encoder::encode(e->toStringAll()));
446 e->destroy();
447 return false;
448 }
449 break;
450 }
451 default :
452 __DCL_ASSERT(false); // SQL::Field::getData bug
453 }
454
455 return true;
456}
457
458bool MyField::getInteger(void* _pv, size_t* _psize)
459{
460 __DCL_ASSERT(!(__field->flags & UNSIGNED_FLAG));
461
462 switch (__field->type) {
463 case MYSQL_TYPE_TINY: {
464 switch (*_psize) {
465 case sizeof(int8_t) : {
466 *(int8_t*)_pv = *(int8_t*)__bind->buffer;
467 break;
468 }
469 case sizeof(int16_t) : {
470 *(int16_t*)_pv = *(int8_t*)__bind->buffer;
471 break;
472 }
473 case sizeof(int32_t) : {
474 *(int32_t*)_pv = *(int8_t*)__bind->buffer;
475 break;
476 }
477 case sizeof(int64_t) : {
478 *(int64_t*)_pv = *(int8_t*)__bind->buffer;
479 break;
480 }
481 default: {
482 *_psize = sizeof(int8_t);
484 return false;
485 }
486 }
487 break;
488 }
489 case MYSQL_TYPE_YEAR :
490 case MYSQL_TYPE_SHORT : {
491 switch (*_psize) {
492 case sizeof(int16_t) : {
493 *(int16_t*)_pv = *(int16_t*)__bind->buffer;
494 break;
495 }
496 case sizeof(int32_t) : {
497 *(int32_t*)_pv = *(int16_t*)__bind->buffer;
498 break;
499 }
500 case sizeof(int64_t) : {
501 *(int64_t*)_pv = *(int16_t*)__bind->buffer;
502 break;
503 }
504 default: {
505 *_psize = sizeof(int16_t);
507 return false;
508 }
509 }
510 break;
511 }
512 case MYSQL_TYPE_INT24 :
513 case MYSQL_TYPE_LONG : {
514 switch (*_psize) {
515 case sizeof(int32_t) : {
516 *(int32_t*)_pv = *(int32_t*)__bind->buffer;
517 break;
518 }
519 case sizeof(int64_t) : {
520 *(int64_t*)_pv = *(int32_t*)__bind->buffer;
521 break;
522 }
523 default: {
524 *_psize = sizeof(int32_t);
526 return false;
527 }
528 }
529 break;
530 }
531 case MYSQL_TYPE_LONGLONG : {
532 switch (*_psize) {
533 case sizeof(int64_t) : {
534 *(int64_t*)_pv = *(int64_t*)__bind->buffer;
535 break;
536 }
537 default: {
538 *_psize = sizeof(int64_t);
540 return false;
541 }
542 }
543 break;
544 }
545 case MYSQL_TYPE_DECIMAL:
546 case MYSQL_TYPE_NEWDECIMAL: {
547 char* endptr;
548 long long n;
549 if ((Field::__precision - Field::__scale) < 20) {
550 n = strtoll((char*)__bind->buffer, &endptr, 10);
551 if (n == LLONG_MAX || n == LLONG_MIN) {
552 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
554 return false;
555 }
556 }
557 else {
558 double d = strtod((char*)__bind->buffer, &endptr);
559 if (+HUGE_VAL == d || -HUGE_VAL == d || !(DBL_MIN < d)) {
560 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
562 return false;
563 }
564
565 double i;
566 (void)modf(d, &i); // 정수부분만, 반환값(소수)는 버림
567 if (i < LLONG_MIN || LLONG_MAX < i) {
569 return false;
570 }
571 n = (long long)i;
572 }
573
574 switch (*_psize) {
575 case sizeof(int8_t) : {
576 if (n < INT8_MIN || INT8_MAX < n) {
578 return false;
579 }
580 *(int8_t*)_pv = (int8_t)n;
581 break;
582 }
583 case sizeof(int16_t) : {
584 if (n < INT16_MIN || INT16_MAX < n) {
586 return false;
587 }
588 *(int16_t*)_pv = (int16_t)n;
589 break;
590 }
591 case sizeof(int32_t) : {
592 if (n < INT32_MIN || INT32_MAX < n) {
594 return false;
595 }
596 *(int32_t*)_pv = (int32_t)n;
597 break;
598 }
599 case sizeof(int64_t) : {
600 *(int64_t*)_pv = (int64_t)n;
601 break;
602 }
603 default: {
604 *_psize = sizeof(int64_t);
606 return false;
607 }
608 }
609 break;
610 }
611 default: {
612 __DCL_ASSERT(false); // MyField::init bug
613 }
614 }
615
616 return true;
617}
618
619bool MyField::getUInteger(void* _pv, size_t* _psize)
620{
621 __DCL_ASSERT(__field->flags & UNSIGNED_FLAG);
622
623 switch (__field->type) {
624 case MYSQL_TYPE_TINY : {
625 switch (*_psize) {
626 case sizeof(uint8_t) : {
627 *(uint8_t*)_pv = *(uint8_t*)__bind->buffer;
628 break;
629 }
630 case sizeof(uint16_t) : {
631 *(uint16_t*)_pv = *(uint8_t*)__bind->buffer;
632 break;
633 }
634 case sizeof(uint32_t) : {
635 *(uint32_t*)_pv = *(uint8_t*)__bind->buffer;
636 break;
637 }
638 case sizeof(uint64_t) : {
639 *(uint64_t*)_pv = *(uint8_t*)__bind->buffer;
640 break;
641 }
642 default: {
643 *_psize = sizeof(uint8_t);
645 return false;
646 }
647 }
648 break;
649 }
650 case MYSQL_TYPE_YEAR :
651 case MYSQL_TYPE_SHORT: {
652 switch (*_psize) {
653 case sizeof(uint16_t) : {
654 *(uint16_t*)_pv = *(uint16_t*)__bind->buffer;
655 break;
656 }
657 case sizeof(uint32_t) : {
658 *(uint32_t*)_pv = *(uint16_t*)__bind->buffer;
659 break;
660 }
661 case sizeof(uint64_t) : {
662 *(uint64_t*)_pv = *(uint16_t*)__bind->buffer;
663 break;
664 }
665 default: {
666 *_psize = sizeof(uint16_t);
668 return false;
669 }
670 }
671 break;
672 }
673 case MYSQL_TYPE_INT24:
674 case MYSQL_TYPE_LONG: {
675 switch (*_psize) {
676 case sizeof(uint32_t) : {
677 *(uint32_t*)_pv = *(uint32_t*)__bind->buffer;
678 break;
679 }
680 case sizeof(uint64_t) : {
681 *(uint64_t*)_pv = *(uint32_t*)__bind->buffer;
682 break;
683 }
684 default: {
685 *_psize = sizeof(uint32_t);
687 return false;
688 }
689 }
690 break;
691 }
692 case MYSQL_TYPE_LONGLONG: {
693 switch (*_psize) {
694 case sizeof(uint64_t) : {
695 *(uint64_t*)_pv = *(uint64_t*)__bind->buffer;
696 break;
697 }
698 default: {
699 *_psize = sizeof(uint32_t);
701 return false;
702 }
703 }
704 break;
705 }
706 case MYSQL_TYPE_DECIMAL :
707 case MYSQL_TYPE_NEWDECIMAL : {
708 char* endptr;
709 unsigned long long u;
710 if ((Field::__precision - Field::__scale) < 20) {
711 u = strtoull((char*)__bind->buffer, &endptr, 10);
712 if (u == ULONG_MAX) {
713 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
715 return false;
716 }
717 }
718 else {
719 double d = strtod((char*)__bind->buffer, &endptr);
720 if (+HUGE_VAL == d || -HUGE_VAL == d || !(DBL_MIN < d)) {
721 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
723 return false;
724 }
725
726 double i;
727 modf(d, &i); // 정수부분만, 반환값(소수)는 버림
728 if (i < 0 || ULONG_MAX < i) {
730 return false;
731 }
732 u = (unsigned long long)i;
733 }
734
735 switch (*_psize) {
736 case sizeof(uint8_t): {
737 if (UINT8_MAX < u) {
739 return false;
740 }
741 *(uint8_t*)_pv = (uint8_t)u;
742 break;
743 }
744 case sizeof(uint16_t): {
745 if (UINT16_MAX < u) {
747 return false;
748 }
749 *(uint16_t*)_pv = (uint16_t)u;
750 break;
751 }
752 case sizeof(uint32_t): {
753 if (UINT32_MAX < u) {
755 return false;
756 }
757 *(uint32_t*)_pv = (uint32_t)u;
758 break;
759 }
760 case sizeof(uint64_t): {
761 *(uint64_t*)_pv = (uint64_t)u;
762 break;
763 }
764 default: {
765 *_psize = sizeof(uint64_t);
767 return false;
768 }
769 }
770 break;
771 }
772 default: {
773 __DCL_ASSERT(false); // MyField::init bug
774 }
775 }
776
777 return true;
778}
779
780bool MyField::getFloat(void* _pv, size_t* _psize)
781{
782 switch (__field->type) {
783 case MYSQL_TYPE_FLOAT: {
784 switch (*_psize) {
785 case sizeof(float): {
786 *(float*)_pv = *(float*)__bind->buffer;
787 break;
788 }
789 case sizeof(double): {
790 *(double*)_pv = *(float*)__bind->buffer;
791 break;
792 }
793 default: {
794 *_psize = sizeof(float);
796 return false;
797 }
798 }
799 break;
800 }
801 case MYSQL_TYPE_DOUBLE: {
802 switch (*_psize) {
803 case sizeof(double) : {
804 *(double*)_pv = *(double*)__bind->buffer;
805 break;
806 }
807 default: {
808 *_psize = sizeof(double);
810 return false;
811 }
812 }
813 break;
814 }
815 case MYSQL_TYPE_DECIMAL:
816 case MYSQL_TYPE_NEWDECIMAL: {
817 char* endptr;
818 double d = strtod((char*)__bind->buffer, &endptr);
819 if (+HUGE_VAL == d || -HUGE_VAL == d || !(DBL_MIN < d)) {
820 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
822 return false;
823 }
824
825 switch (*_psize) {
826 case sizeof(float): {
827 if (d < FLT_MIN || FLT_MAX < d) {
829 return false;
830 }
831 *(float*)_pv = (float) d;
832 break;
833 }
834 case sizeof(double): {
835 if (d < DBL_MIN || DBL_MAX < d) {
837 return false;
838 }
839 *(double*)_pv = (double)d;
840 break;
841 }
842 default : {
843 *_psize = sizeof(double);
845 return false;
846 }
847 }
848 break;
849 }
850 default : {
851 __DCL_ASSERT(false); // MyField::init bug
852 }
853 }
854
855 return true;
856}
857
858bool MyField::getDate(SQL::Date* _pv, size_t* _psize)
859{
860 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_DATE));
861
862 if (*_psize != sizeof(SQL::Date)) {
863 *_psize = sizeof(SQL::Date);
865 return false;
866 }
867
868 MYSQL_TIME* s = (MYSQL_TIME*)__bind->buffer;
869 _pv->year = s->year * (s->neg ? -1 : 1);
870 _pv->month = s->month;
871 _pv->day = s->day;
872
873 return true;
874}
875
876bool MyField::getTimeStamp(SQL::TimeStamp* _pv, size_t* _psize)
877{
878 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_DATETIME)
879 || __TYPE_IS(MYSQL_TYPE_TIMESTAMP));
880
881 if (*_psize != sizeof(SQL::TimeStamp)) {
883 return false;
884 }
885
886 MYSQL_TIME* s = (MYSQL_TIME*)__bind->buffer;
887 _pv->year = s->year * (s->neg ? -1 : 1);
888 _pv->month = s->month;
889 _pv->day = s->day;
890 _pv->hour = s->hour;
891 _pv->min = s->minute;
892 _pv->sec = s->second;
893 _pv->frac = s->second_part * 1000;
894 _pv->tzoff = INT16_MIN;
895
896 return true;
897}
898
899bool MyField::getTime(SQL::Time* _pv, size_t* _psize)
900{
901 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_TIME));
902
903 if (*_psize != sizeof(SQL::Time)) {
904 *_psize = sizeof(SQL::Time);
906 return false;
907 }
908
909 MYSQL_TIME* s = (MYSQL_TIME*)__bind->buffer;
910 _pv->hour = s->hour;
911 _pv->min = s->minute;
912 _pv->sec = s->second;
913 _pv->frac = s->second_part * 1000;
914 _pv->tzoff = INT16_MIN;
915
916 return true;
917}
918
919bool MyField::getInterval(SQL::Interval* _pv, size_t* _psize)
920{
921 __DCL_ASSERT(__TYPE_IS(MYSQL_TYPE_TIME));
922
923 if (*_psize != sizeof(SQL::Interval)) {
924 *_psize = sizeof(SQL::Interval);
926 return false;
927 }
928
929 MYSQL_TIME* s = (MYSQL_TIME*)__bind->buffer;
930 int8_t sign = s->neg ? -1 : 1;
931 _pv->years = 0;
932 _pv->months = 0;
933 _pv->days = s->hour / 24 * sign;
934 _pv->hours = s->hour % 24 * sign;
935 _pv->mins = s->minute * sign;
936 _pv->secs = s->second * sign;
937 _pv->fracs = s->second_part * 1000 * sign;
938
939 return true;
940}
941
942__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:153
void CharsetConvertException *size_t n
Definition SQLField.cpp:254
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:876
bool getTime(SQL::Time *_pv, size_t *_psize)
Definition MyField.cpp:899
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:919
bool getInteger(void *_pv, size_t *_psize)
Definition MyField.cpp:458
MyQuery * query() const
Definition MyField.h:67
bool getDate(SQL::Date *_pv, size_t *_psize)
Definition MyField.cpp:858
bool getUInteger(void *_pv, size_t *_psize)
Definition MyField.cpp:619
bool getFloat(void *_pv, size_t *_psize)
Definition MyField.cpp:780
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:185
DataType
Definition SQLCore.h:62
@ typeBinary
Definition SQLCore.h:77
@ typeNumeric
Definition SQLCore.h:67
@ typeTime
Definition SQLCore.h:69
@ typeLongBinary
Definition SQLCore.h:79
@ typeUInteger
Definition SQLCore.h:65
@ typeUnknown
Definition SQLCore.h:63
@ typeTimeStamp
Definition SQLCore.h:71
@ typeTimeStampTz
Definition SQLCore.h:72
@ typeInterval
Definition SQLCore.h:73
@ typeIntervalDs
Definition SQLCore.h:75
@ typeDate
Definition SQLCore.h:68
@ typeOutputStream
Definition SQLCore.h:85
@ typeText
Definition SQLCore.h:76
@ typeFloat
Definition SQLCore.h:66
@ typeInteger
Definition SQLCore.h:64
@ typeIntervalYm
Definition SQLCore.h:74
@ typeLongText
Definition SQLCore.h:78
@ 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
int16_t year
Definition SQLCore.h:97
uint8_t month
Definition SQLCore.h:98
uint8_t day
Definition SQLCore.h:99
int32_t years
Definition SQLCore.h:127
int32_t days
Definition SQLCore.h:129
int8_t hours
Definition SQLCore.h:130
int8_t mins
Definition SQLCore.h:131
int32_t fracs
Definition SQLCore.h:133
int8_t months
Definition SQLCore.h:128
int8_t secs
Definition SQLCore.h:132
uint8_t hour
Definition SQLCore.h:104
uint8_t sec
Definition SQLCore.h:106
uint32_t frac
Definition SQLCore.h:107
uint8_t min
Definition SQLCore.h:105
int16_t tzoff
Definition SQLCore.h:108
uint32_t frac
Definition SQLCore.h:119
int16_t tzoff
Definition SQLCore.h:120
uint8_t min
Definition SQLCore.h:117
uint8_t sec
Definition SQLCore.h:118
uint8_t hour
Definition SQLCore.h:116
uint8_t day
Definition SQLCore.h:115
int16_t year
Definition SQLCore.h:113
uint8_t month
Definition SQLCore.h:114