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