DCL 3.7.4
Loading...
Searching...
No Matches
ODBCData Class Referenceabstract

#include <ODBCData.h>

Inheritance diagram for ODBCData:
ODBCField ODBCParam

Static Public Member Functions

static const wchar_t * __TYPE_NAME (SQLSMALLINT _type)
static SQLULEN __TYPE_SIZE (SQLSMALLINT _type, SQLULEN _size)
static size_t __TYPE_ALIGN (size_t _offset, SQLSMALLINT _type)
static SQLSMALLINT __VALUE_TYPE (SQLSMALLINT _type)

Protected Member Functions

virtual ODBCQueryquery () const =0
ODBCConnectionconn () const
 ODBCData ()
SQL::DataType init (BIND *_bind)
const wchar_t * serverDataTypeName () const
bool __getDataSize (size_t *_size, bool _maxsize)
bool __getData (void *_buf, size_t *_size, SQL::DataType _bufType)
bool getInteger (void *_buf, size_t *_size)
bool getUInteger (void *_buf, size_t *_size)
bool getFloat (void *_buf, size_t *_size)
bool getDate (SQL::Date *_buf, size_t *_size)
bool getTime (SQL::Time *_buf, size_t *_size)
bool getTimeStamp (SQL::TimeStamp *_buf, size_t *_size)
bool getInterval (SQL::Interval *_buf, size_t *_size)
bool getBytes (byte_t *_buf, size_t *_size)
bool writeTo (OutputStream *_output, size_t *_size)

Protected Attributes

BIND__bind
size_t __maxsize

Detailed Description

Definition at line 8 of file ODBCData.h.

Constructor & Destructor Documentation

◆ ODBCData()

ODBCData::ODBCData ( )
protected

Definition at line 58 of file ODBCData.cpp.

59{
60 __bind = NULL;
61 __maxsize = 0;
62}
#define NULL
Definition Config.h:312
BIND * __bind
Definition ODBCData.h:11
size_t __maxsize
Definition ODBCData.h:12

Member Function Documentation

◆ __getData()

bool ODBCData::__getData ( void * _buf,
size_t * _size,
SQL::DataType _bufType )
protected

Definition at line 561 of file ODBCData.cpp.

566{
567 switch (_bufType) {
568 case SQL::typeInteger:
569 return getInteger(_buf, _size);
571 return getUInteger(_buf, _size);
572 case SQL::typeFloat:
573 return getFloat(_buf, _size);
574 case SQL::typeDate:
575 return getDate((SQL::Date*)_buf, _size);
576 case SQL::typeTime:
577 return getTime((SQL::Time*)_buf, _size);
579 return getTimeStamp((SQL::TimeStamp*)_buf, _size);
581 return getInterval((SQL::Interval*)_buf, _size);
582 case SQL::typeText:
583 case SQL::typeBinary:
584 return getBytes((byte_t*)_buf, _size);
586 return writeTo((OutputStream*)_buf, _size);
587 default: {
588 __DCL_ASSERT(false); // SQL::Field::getData bug
589 }
590 }
591
592 return true;
593}
unsigned char byte_t
Definition Config.h:246
#define __DCL_ASSERT(expr)
Definition Object.h:394
bool getBytes(byte_t *_buf, size_t *_size)
bool getTimeStamp(SQL::TimeStamp *_buf, size_t *_size)
bool getFloat(void *_buf, size_t *_size)
Definition ODBCData.cpp:956
bool getUInteger(void *_buf, size_t *_size)
Definition ODBCData.cpp:776
bool getInterval(SQL::Interval *_buf, size_t *_size)
bool getDate(SQL::Date *_buf, size_t *_size)
bool writeTo(OutputStream *_output, size_t *_size)
bool getTime(SQL::Time *_buf, size_t *_size)
bool getInteger(void *_buf, size_t *_size)
Definition ODBCData.cpp:595
@ typeBinary
Definition SQLCore.h:74
@ typeTime
Definition SQLCore.h:66
@ typeUInteger
Definition SQLCore.h:62
@ typeTimeStamp
Definition SQLCore.h:68
@ typeInterval
Definition SQLCore.h:70
@ typeDate
Definition SQLCore.h:65
@ typeOutputStream
Definition SQLCore.h:82
@ typeText
Definition SQLCore.h:73
@ typeFloat
Definition SQLCore.h:63
@ typeInteger
Definition SQLCore.h:61

◆ __getDataSize()

bool ODBCData::__getDataSize ( size_t * _size,
bool _maxsize )
protected

Definition at line 454 of file ODBCData.cpp.

455{
456 if (_maxsize) {
457 *_size = __maxsize;
458 return true;
459 }
460
461 if (__bind->valuePtr) {
462 // SQLBindCol로 바인드 되었다.
463 // __DCL_TRACE2_N(L"[%ls] lenORind[%d]\n",
464 // __name.data(), __bind->lenORind);
465 __DCL_ASSERT(__bind->lenORind >= SQL_NULL_DATA);
466#if __USE_POSTGRES_FIX
467 if (__bind->type == SQL_CHAR && (SQLLEN)__bind->size < __bind->lenORind) {
468 __DCL_TRACE1_N(L"[%ls]\n",
469 String::tryString((const char*)__bind->valuePtr, __bind->size).data());
470 // 이미 메모리를 휘저은 상태로 (null)로 조치
471 *_size = (size_t)-1;
472 }
473 else {
474 *_size = __bind->lenORind;
475 }
476#else
477 * _size = __bind->lenORind;
478#endif
479 return true;
480 }
481
482 // SQLBindCol로 바인드 하지 않았다.
483 // bind.size == 0 또는 > 12000 이상인 경우이다.
484 // 필드의 실제 길이를
485 // UTF-8 SQL_C_CHAR 또는 SQL_C_BINARY 단위로 알아낸 후
486 // 필요한 버퍼의 크기를 bind.valueMax 보관한다.
487 // SQLBindCol 바인드된 bind.valueMax의 값 역시 필요한 버퍼의 크기이다.
488 if (__bind->valueMax == 0) {
489 // 필요한 버퍼의 크기가 미정이다.
490 // SQL_WCHAR, WVARCHAR, WLONGVARCHAR의 targetType을 SQL_C_CHAR로 하면 SQL_NO_TOTAL를 반환한다.
491 // SQL_C_WCHAR로 lenORind를 얻은 후 UTF-8 바이트 개수를 계산한다.
492 SQLCHAR c;
493 SQLSMALLINT targetType;
494 switch (__bind->type) {
495 case SQL_CHAR:
496 case SQL_VARCHAR:
497 case SQL_LONGVARCHAR: {
498 targetType = SQL_C_CHAR;
499 break;
500 }
501 case SQL_WCHAR:
502 case SQL_WVARCHAR:
503 case SQL_WLONGVARCHAR: {
504 targetType = SQL_C_WCHAR;
505 break;
506 }
507 case SQL_BINARY:
508 case SQL_VARBINARY:
509 case SQL_LONGVARBINARY:
510 default: {
511 targetType = SQL_C_BINARY;
512 }
513 }
514 SQLRETURN rc = SQLGetData(query()->stmtHandle(), __bind->number,
515 targetType, &c, 0, &(__bind->lenORind));
516 __DCL_TRACE4_N(L"[%ls] rc[%d] lenORind[%d] sizeof(WCHAR)[%d]\n",
517 __name.data(), rc, __bind->lenORind, sizeof(WCHAR));
518 if (!SQL_SUCCEEDED(rc)) {
519 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, query()->stmtHandle());
520 return false;
521 }
522
523 // lenORind >= SQL_NULL_DATA(-1) 이다.
524 // WCHAR to CHAR 이 없으므로 SQL_NO_TOTAL(-4)는 없다.
525 __DCL_ASSERT(__bind->lenORind >= SQL_NULL_DATA);
526
527 // __bind->valueMax 의 값을 변경하여 동적바인드된 상태를 표시한다.
528 // ODBCQuery.cpp: SQLFetch에서 이 값은 0으로 리셋된다.
529 if (__bind->lenORind >= 0) {
530 switch (__bind->type) {
531 case SQL_CHAR:
532 case SQL_VARCHAR:
533 case SQL_LONGVARCHAR: {
534 __bind->valueMax = __bind->lenORind + 1;
535 break;
536 }
537 case SQL_WCHAR:
538 case SQL_WVARCHAR:
539 case SQL_WLONGVARCHAR: {
540 __bind->lenORind = (__bind->lenORind / sizeof(SQLWCHAR)) * 3;
541 __bind->valueMax = __bind->lenORind + 3;
542 break;
543 }
544 case SQL_BINARY:
545 case SQL_VARBINARY:
546 case SQL_LONGVARBINARY:
547 default: {
548 // 주의! valueMax == -1은 SQL_C_BINARY에서 0 이다!!
549 __bind->valueMax = __bind->lenORind == 0
550 ? -1 : __bind->lenORind;
551 }
552 }
553 }
554 }
555 *_size = __bind->lenORind;
556 return true;
557}
#define __DCL_TRACE1_N(fmt, arg)
#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
#define __SET_ERROR_HANDLE(_SQLCODE)
virtual ODBCQuery * query() const =0

◆ __TYPE_ALIGN()

size_t ODBCData::__TYPE_ALIGN ( size_t _offset,
SQLSMALLINT _type )
static

Definition at line 350 of file ODBCData.cpp.

351{
352 size_t size = 0;
353 switch (_type) {
354 case SQL_BIT:
355 case SQL_TINYINT:
356 size = sizeof(int8_t);
357 break;
358 case SQL_SMALLINT:
359 size = sizeof(int16_t);
360 break;
361 case SQL_INTEGER:
362 size = sizeof(int32_t);
363 break;
364 case SQL_INFX_BIGINT:
365 case SQL_BIGINT:
366 size = sizeof(int64_t);
367 break;
368 case SQL_REAL:
369 size = sizeof(float);
370 break;
371 case SQL_FLOAT:
372 case SQL_DOUBLE:
373 size = sizeof(double);
374 break;
375 case SQL_TYPE_DATE:
376 case SQL_TYPE_TIME:
377 case SQL_TYPE_TIMESTAMP:
378 case SQL_INTERVAL_YEAR:
379 case SQL_INTERVAL_MONTH:
380 case SQL_INTERVAL_DAY:
381 case SQL_INTERVAL_HOUR:
382 case SQL_INTERVAL_MINUTE:
383 case SQL_INTERVAL_SECOND:
384 case SQL_INTERVAL_YEAR_TO_MONTH:
385 case SQL_INTERVAL_DAY_TO_HOUR:
386 case SQL_INTERVAL_DAY_TO_MINUTE:
387 case SQL_INTERVAL_DAY_TO_SECOND:
388 case SQL_INTERVAL_HOUR_TO_MINUTE:
389 case SQL_INTERVAL_HOUR_TO_SECOND:
390 case SQL_INTERVAL_MINUTE_TO_SECOND:
391 case SQL_SS_TIME2:
392 case SQL_SS_TIMESTAMPOFFSET:
393 size = sizeof(long);
394 break;
395 default:
396 size = sizeof(char);
397 }
398 return (_offset + size - 1) & ~(size - 1);
399}
#define SQL_INFX_BIGINT
Definition ODBCQuery.h:7

◆ __TYPE_NAME()

const wchar_t * ODBCData::__TYPE_NAME ( SQLSMALLINT _type)
static

Definition at line 190 of file ODBCData.cpp.

191{
192#define SQLTYPE_NAME(SQL_TYPE, name) case SQL_TYPE : return name
193 switch (_type) {
194 // sql.h: 187 SQL data type codes
195 SQLTYPE_NAME(SQL_UNKNOWN_TYPE, L"UNKNOWN"); // 0
196 SQLTYPE_NAME(SQL_CHAR, L"CHAR"); // 1
197 SQLTYPE_NAME(SQL_NUMERIC, L"NUMERIC"); // 2
198 SQLTYPE_NAME(SQL_DECIMAL, L"DECIMAL"); // 3
199 SQLTYPE_NAME(SQL_INTEGER, L"INTEGER"); // 4
200 SQLTYPE_NAME(SQL_SMALLINT, L"SMALLINT"); // 5
201 SQLTYPE_NAME(SQL_FLOAT, L"FLOAT"); // 6
202 SQLTYPE_NAME(SQL_REAL, L"REAL"); // 7
203 SQLTYPE_NAME(SQL_DOUBLE, L"DOUBLE"); // 8
204#if (ODBCVER >= 0x0300)
205 SQLTYPE_NAME(SQL_DATETIME, L"DATETIME"); // 9
206#endif
207 SQLTYPE_NAME(SQL_VARCHAR, L"VARCHAR"); // 12
208#if (ODBCVER >= 0x0300)
209 SQLTYPE_NAME(SQL_TYPE_DATE, L"TYPE_DATE"); // 91
210 SQLTYPE_NAME(SQL_TYPE_TIME, L"TYPE_TIME"); // 92
211 SQLTYPE_NAME(SQL_TYPE_TIMESTAMP, L"TYPE_TIMESTAMP"); // 93
212#endif
213 // sqlext.h: 416 SQL extended datatypes
214#if (ODBCVER < 0x0300)
215 SQLTYPE_NAME(SQL_DATE, L"DATE"); // 9
216#endif
217#if (ODBCVER >= 0x0300)
218 SQLTYPE_NAME(SQL_INTERVAL, L"INTERVAL"); // 10
219#endif
220#if (ODBCVER < 0x0300)
221 SQLTYPE_NAME(SQL_TIME, L"TIME"); // 10
222 SQLTYPE_NAME(SQL_TIMESTAMP, L"TIMESTAMP"); // 11
223#endif
224 SQLTYPE_NAME(SQL_LONGVARCHAR, L"LONGVARCHAR"); // -1
225 SQLTYPE_NAME(SQL_BINARY, L"BINARY"); // -2
226 SQLTYPE_NAME(SQL_VARBINARY, L"VARBINARY"); // -3
227 SQLTYPE_NAME(SQL_LONGVARBINARY, L"LONGVARBINARY"); // -4
228 SQLTYPE_NAME(SQL_BIGINT, L"BIGINT"); // -5
229 SQLTYPE_NAME(SQL_TINYINT, L"TINYINT"); // -6
230 SQLTYPE_NAME(SQL_BIT, L"BIT"); // -7
231#if (ODBCVER >= 0x0300)
232 SQLTYPE_NAME(SQL_GUID, L"GUID"); // -11
233#endif
234 SQLTYPE_NAME(SQL_INTERVAL_YEAR, L"INTERVAL_YEAR"); // 100 + 1
235 SQLTYPE_NAME(SQL_INTERVAL_MONTH, L"INTERVAL_MONTH"); // 100 + 2
236 SQLTYPE_NAME(SQL_INTERVAL_DAY, L"INTERVAL_DAY"); // 100 + 3
237 SQLTYPE_NAME(SQL_INTERVAL_HOUR, L"INTERVAL_HOUR"); // 100 + 4
238 SQLTYPE_NAME(SQL_INTERVAL_MINUTE, L"INTERVAL_MINUTE"); // 100 + 5
239 SQLTYPE_NAME(SQL_INTERVAL_SECOND, L"INTERVAL_SECOND"); // 100 + 6
240 SQLTYPE_NAME(SQL_INTERVAL_YEAR_TO_MONTH, L"INTERVAL_YEAR_TO_MONTH"); // 100 + 7
241 SQLTYPE_NAME(SQL_INTERVAL_DAY_TO_HOUR, L"INTERVAL_DAY_TO_HOUR"); // 100 + 8
242 SQLTYPE_NAME(SQL_INTERVAL_DAY_TO_MINUTE, L"INTERVAL_DAY_TO_MINUTE"); // 100 + 9
243 SQLTYPE_NAME(SQL_INTERVAL_DAY_TO_SECOND, L"INTERVAL_DAY_TO_SECOND"); // 100 + 10
244 SQLTYPE_NAME(SQL_INTERVAL_HOUR_TO_MINUTE, L"INTERVAL_HOUR_TO_MINUTE"); // 100 + 11
245 SQLTYPE_NAME(SQL_INTERVAL_HOUR_TO_SECOND, L"INTERVAL_HOUR_TO_SECOND"); // 100 + 12
246 SQLTYPE_NAME(SQL_INTERVAL_MINUTE_TO_SECOND, L"INTERVAL_MINUTE_TO_SECOND"); // 100 + 13
247 // sqlucode.h: 27
248 SQLTYPE_NAME(SQL_WCHAR, L"WCHAR"); // -8
249 SQLTYPE_NAME(SQL_WVARCHAR, L"WVARCHAR"); // -9
250 SQLTYPE_NAME(SQL_WLONGVARCHAR, L"WLONGVARCHAR"); // -10
251 // msodbcsql.h: 478
252 SQLTYPE_NAME(SQL_SS_UDT, L"SS_UDT"); // -151 GEOGRAPHY, GEOMETRY
253 SQLTYPE_NAME(SQL_SS_TIME2, L"SS_TIME2"); // -154 TIME(7)
254 SQLTYPE_NAME(SQL_SS_TIMESTAMPOFFSET, L"SS_TIMESTAMPOFFSET"); // -155 DATETIMEOFFSET(7)
255 // ${INFORMIXDIR}/incl/cli/infxcli.h: 125
256 SQLTYPE_NAME(SQL_INFX_BIGINT, L"INFX_BIGINT"); // -114
257 default: return L"Unknown Type (Binary Mapped)";
258 }
259}
#define SQLTYPE_NAME(_dataType, name)
Definition IFXField.cpp:302

◆ __TYPE_SIZE()

SQLULEN ODBCData::__TYPE_SIZE ( SQLSMALLINT _type,
SQLULEN _size )
static

Definition at line 261 of file ODBCData.cpp.

262{
263 size_t size = 0;
264 switch (_type) {
265 case SQL_BIT:
266 case SQL_TINYINT:
267 size = sizeof(int8_t);
268 break;
269 case SQL_SMALLINT:
270 size = sizeof(int16_t);
271 break;
272 case SQL_INTEGER:
273 size = sizeof(int32_t);
274 break;
275 case SQL_INFX_BIGINT:
276 case SQL_BIGINT:
277 size = sizeof(int64_t);
278 break;
279 case SQL_REAL:
280 size = sizeof(float);
281 break;
282 case SQL_FLOAT:
283 case SQL_DOUBLE:
284 size = sizeof(double);
285 break;
286 case SQL_TYPE_DATE:
287 size = sizeof(DATE_STRUCT);
288 break;
289 case SQL_TYPE_TIME:
290 size = sizeof(TIME_STRUCT);
291 break;
292 case SQL_TYPE_TIMESTAMP:
293 size = sizeof(TIMESTAMP_STRUCT);
294 break;
295 case SQL_SS_TIME2:
296 size = sizeof(SQL_SS_TIME2_STRUCT);
297 break;
298 case SQL_SS_TIMESTAMPOFFSET:
299 size = sizeof(SQL_SS_TIMESTAMPOFFSET_STRUCT);
300 break;
301 case SQL_INTERVAL_YEAR:
302 case SQL_INTERVAL_MONTH:
303 case SQL_INTERVAL_DAY:
304 case SQL_INTERVAL_HOUR:
305 case SQL_INTERVAL_MINUTE:
306 case SQL_INTERVAL_SECOND:
307 case SQL_INTERVAL_YEAR_TO_MONTH:
308 case SQL_INTERVAL_DAY_TO_HOUR:
309 case SQL_INTERVAL_DAY_TO_MINUTE:
310 case SQL_INTERVAL_DAY_TO_SECOND:
311 case SQL_INTERVAL_HOUR_TO_MINUTE:
312 case SQL_INTERVAL_HOUR_TO_SECOND:
313 case SQL_INTERVAL_MINUTE_TO_SECOND:
314 size = sizeof(SQL_INTERVAL_STRUCT);
315 break;
316 case SQL_CHAR:
317 case SQL_VARCHAR:
318 case SQL_LONGVARCHAR:
319 // WCHAR기준 4000문자까지만 버퍼를 할당하여 SQLBindCol 바인드한다.
320 // SQL_C_DEFAULT SQL_C_CHAR는 경우 버퍼의 크기는 '\0' 문자를 포함해야 한다.
321 size = 0 < _size && _size <= 12000 ? _size + 1 : 0;
322 break;
323 case SQL_NUMERIC:
324 case SQL_DECIMAL:
325 size = _size + 2 + 1; // 부호, 소숫점
326 break;
327 case SQL_GUID:
328 size = _size * 2;
329 break;
330 case SQL_WCHAR:
331 case SQL_WVARCHAR:
332 case SQL_WLONGVARCHAR:
333 // WCHAR기준 4000문자까지만 버퍼를 할당하여 SQLBindCol 바인드한다.
334 // SQL_C_DEFAULT SQL_C_CHAR는 경우 버퍼의 크기는 '\0' 문자를 포함해야 한다.
335 // UTF-8 적용하면 최대 (3 * 4000)바이트가 된다.
336 size = 0 < _size && _size <= 4000 ? (_size + 1) * 3 : 0;
337 break;
338 case SQL_BINARY:
339 case SQL_VARBINARY:
340 case SQL_LONGVARBINARY:
341 case SQL_SS_UDT:
342 default:
343 // WCHAR기준 4000문자까지만 버퍼를 할당하여 SQLBindCol 바인드한다.
344 // SQL_C_DEFAULT SQL_C_BINARY는 '\0' 문자를 포함하지 않는다.
345 size = 0 < _size && _size <= 12000 ? _size : 0;
346 }
347 return size;
348}

◆ __VALUE_TYPE()

SQLSMALLINT ODBCData::__VALUE_TYPE ( SQLSMALLINT _type)
static

Definition at line 401 of file ODBCData.cpp.

402{
403 SQLSMALLINT valueType = SQL_C_DEFAULT;
404 switch (_type) {
405#if __USE_POSTGRES_FIX
406 // money를 SQL_FLOAT로 하고
407 // SQL_C_DEFAULT로 바인드 하면 문자열로 처리하는 것을 FIX
408 case SQL_FLOAT: {
409 valueType = SQL_C_DOUBLE;
410 break;
411 }
412#endif
413#if __USE_INFORMIX_FIX
414 // ibm.csdk.4.50.12.12 (2025-09-27)
415 // SQL_C_DEFAULT로 바인드하면 문자열로 처리하는 것를 FIX
416 // 이것은 MariaDB BIGINT UNSIGNED를 사용하지 못하게 함
417 case SQL_INFX_BIGINT:
418 case SQL_BIGINT: {
419 valueType = SQL_C_SBIGINT;
420 break;
421 }
422#endif
423#if __USE_POSTGRES_FIX
424 // SQL_C_BINARY로 처리하는 겻을 FIX
425 case SQL_GUID:
426#endif
427 case SQL_CHAR: // 1
428 case SQL_VARCHAR: // 12
429 case SQL_LONGVARCHAR: // -1
430 case SQL_WCHAR: // -8
431 case SQL_WVARCHAR: // -9
432 case SQL_WLONGVARCHAR: { // -10
433 valueType = SQL_C_CHAR;
434 break;
435 }
436 case SQL_BINARY: // -2
437 case SQL_VARBINARY: // -3
438 case SQL_LONGVARBINARY: { // -4
439 valueType = SQL_C_BINARY;
440 break;
441 }
442 default: {
443 valueType = SQL_C_DEFAULT;
444 }
445 }
446 return valueType;
447}

◆ conn()

ODBCConnection * ODBCData::conn ( ) const
inlineprotected

Definition at line 48 of file ODBCData.h.

49{
50 return query()->conn();
51}

◆ getBytes()

bool ODBCData::getBytes ( byte_t * _buf,
size_t * _size )
protected

Definition at line 1190 of file ODBCData.cpp.

1191{
1192 if (__bind->valueMax == 0) {
1193 // 필요한 버퍼의 크기가 미정이다.
1194 // __bind->valuePtr == NULL 일 것이다.
1195 size_t size;
1196 if (!__getDataSize(&size, false)) {
1197 return false;
1198 }
1199 if (size == (size_t)-1) {
1201 return false;
1202 }
1203 }
1204
1205 __DCL_ASSERT(__bind->lenORind >= 0);
1206 //__DCL_TRACE3_N(L"valueLen[%zd] lengthInd[%zd] *_size[%zd]\n",
1207 // __bind->valueMax, __bind->lenORind, *_size);
1208
1209 if (__bind->valuePtr) {
1210 // SQLBindCol로 바인드 되었다.
1211 // 이것을 복사한다.
1212 memcpy(_buf, __bind->valuePtr, __MIN(__bind->lenORind, *_size));
1213 if ((size_t)__bind->lenORind < *_size) {
1214 *(_buf + __bind->lenORind) = '\0';
1215 }
1216 *_size = __bind->lenORind;
1217 return true;
1218 }
1219
1220 // SQLBindCol로 바인드 하지 않았다.
1221 // bind.size == 0 또는 > 12000 이상인 경우이다.
1222 // bind.valueMax > 0, == -1
1223 SQLLEN lenORind;
1224 SQLRETURN rc = SQLGetData(query()->stmtHandle(), __bind->number,
1225 __bind->valueType, _buf, *_size, &lenORind);
1226 if (!SQL_SUCCEEDED(rc)) {
1227 // 데이터의 실제길이보다 *_size가 작아서
1228 // SQL_SUCCESS_WITH_INFO 01004 문자열 데이터, 오른쪽 잘림
1229 // 은 무시한다.
1230 // 데이터가 typeText인 경우 UTF8::decode Illegal bytes sequence 가능성이 있다.
1231 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, query()->stmtHandle());
1232 return false;
1233 }
1234 if (rc == SQL_SUCCESS_WITH_INFO
1235 && __bind->valueType == SQL_C_CHAR
1236 && *_size == (size_t)__bind->lenORind
1237 && *_size > 0
1238 //&& (lenORind == *_size || lenORind == SQL_NO_TOTAL)
1239 //&& *(_buf + *_size - 1) == '\0'
1240 ) {
1241 __DCL_TRACE4_N(L"*_size[%zd] lenORind[%d] [%x] [%ls]\n",
1242 *_size, lenORind, *(_buf + *_size - 1),
1243 String::tryString((const char*)_buf, __MIN(*_size, 40)).data()
1244 );
1245 __DCL_ASSERT(((size_t)lenORind == *_size || lenORind == SQL_NO_TOTAL)
1246 && (*(_buf + *_size - 3) == '\0'
1247 || *(_buf + *_size - 2) == '\0'
1248 || *(_buf + *_size - 1) == '\0')
1249 );
1250 // 주의!! 이 코드는 모든 문자잘림을 해결하지 못한다.
1251 // 적어도 실제길이 만큼의 버퍼크기라는 조건하에
1252 // '\0'로 교체된 마지막 1 ~ 3 바이트를 읽어서 추가한다.
1253 // Oracle의 NCLOB만 3이다. 2025-12-15
1254
1255 // ODBC는
1256 // SQL_C_CHAR, SQL_C_WCHAR에서 SQLGetData의 버퍼의 크기는
1257 // 실제 데이터의 길이에 '\0' 문자 1을 추가한 길이어야 한다.
1258
1259 // SQL_WCHAR, SQL_WVARCHAR, SQL_WLONGVARCHAR에서
1260 // lenORind는 SQL_NO_TOTAL(-4) 이고 WCHAR 2문자 버퍼가 필요하다.
1261 char buf[6];
1262 SQLLEN lenORind_;
1263 rc = SQLGetData(query()->stmtHandle(), __bind->number,
1264 __bind->valueType, buf, sizeof(buf), &lenORind_);
1265 if (rc != SQL_SUCCESS) {
1266 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, query()->stmtHandle());
1267 return false;
1268 }
1269 __DCL_ASSERT(1 <= lenORind_ && lenORind_ <= 3);
1270 memcpy(_buf + *_size - lenORind_, buf, lenORind_);
1271 }
1272 __DCL_TRACE2_N(L"lenORind[%d][%ls]\n",
1273 lenORind, String::tryString((const char*)_buf, __MIN(*_size, 40)).data());
1274 if (0 <= lenORind && (size_t)lenORind < *_size) {
1275 *_size = lenORind;
1276 *(_buf + *_size) = '\0';
1277 }
1278 return true;
1279}
#define __DCL_TRACE2_N(fmt, arg1, arg2)
#define __SET_ERROR(_errorCode)
Definition SQLCore.cpp:149
bool __getDataSize(size_t *_size, bool _maxsize)
Definition ODBCData.cpp:454
@ eValueIsNull
Definition SQLCore.h:47
size_t __MIN(size_t x, size_t y)
Definition size_t.h:27

◆ getDate()

bool ODBCData::getDate ( SQL::Date * _buf,
size_t * _size )
protected

Definition at line 1042 of file ODBCData.cpp.

1043{
1044 __DCL_ASSERT(__TYPE_IS(SQL_TYPE_DATE));
1045
1046 if (*_size != sizeof(SQL::Date)) {
1047 *_size = sizeof(SQL::Date);
1049 return false;
1050 }
1051
1052 DATE_STRUCT* s = (DATE_STRUCT*)__bind->valuePtr;
1053 _buf->year = s->year;
1054 _buf->month = s->month;
1055 _buf->day = s->day;
1056
1057 return true;
1058}
#define __TYPE_IS(_type)
Definition MyField.cpp:339
@ eInvalidBufferSize
Definition SQLCore.h:50
int16_t year
Definition SQLCore.h:96
uint8_t month
Definition SQLCore.h:97
uint8_t day
Definition SQLCore.h:98

◆ getFloat()

bool ODBCData::getFloat ( void * _buf,
size_t * _size )
protected

Definition at line 956 of file ODBCData.cpp.

957{
958 switch (__bind->type) {
959 case SQL_REAL: {
960 switch (*_size) {
961 case sizeof(float) : {
962 *(float*)_buf = *(float*)__bind->valuePtr;
963 break;
964 }
965 case sizeof(double) : {
966 *(double*)_buf = *(float*)__bind->valuePtr;
967 break;
968 }
969 default: {
970 *_size = sizeof(float);
972 return false;
973 }
974 }
975 break;
976 }
977 case SQL_FLOAT:
978 case SQL_DOUBLE: {
979 switch (*_size) {
980 case sizeof(double) : {
981 *(double*)_buf = *(double*)__bind->valuePtr;
982 break;
983 }
984 default: {
985 *_size = sizeof(double);
987 return false;
988 }
989 }
990 break;
991 }
992 case SQL_NUMERIC:
993 case SQL_DECIMAL: {
994 errno = 0;
995 char* endptr = NULL;
996 double d = strtod((char*)__bind->valuePtr, &endptr);
997 if (errno == ERANGE) {
999 +HUGE_VAL == d || -HUGE_VAL == d // overflow
1000 || !(DBL_MIN < d) // underflow
1001 );
1002 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
1004 return false;
1005 }
1006 #if __UNNEED__
1007 else if (errno == EINVAL) {
1008 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
1010 return false;
1011 }
1012 #endif
1013 switch (*_size) {
1014 case sizeof(float) : {
1015 if (d < -FLT_MAX || FLT_MAX < d) {
1017 return false;
1018 }
1019 *(float*)_buf = (float)d;
1020 break;
1021 }
1022 case sizeof(double) : {
1023 *(double*)_buf = (double)d;
1024 break;
1025 }
1026 default: {
1027 *_size = sizeof(double);
1029 return false;
1030 }
1031 }
1032 break;
1033 }
1034 default: {
1035 __DCL_ASSERT(false); // ODBCData::init bug
1036 }
1037 }
1038
1039 return true;
1040}
@ eOutOfRange
Definition SQLCore.h:52
@ eInvalidData
Definition SQLCore.h:54

◆ getInteger()

bool ODBCData::getInteger ( void * _buf,
size_t * _size )
protected

Definition at line 595 of file ODBCData.cpp.

596{
597 switch (__bind->type) {
598 case SQL_BIT:
599 case SQL_TINYINT: {
600 switch (*_size) {
601 case sizeof(int8_t) : {
602 *(int8_t*)_buf = *(int8_t*)__bind->valuePtr;
603 break;
604 }
605 case sizeof(int16_t) : {
606 *(int16_t*)_buf = *(int8_t*)__bind->valuePtr;
607 break;
608 }
609 case sizeof(int32_t) : {
610 *(int32_t*)_buf = *(int8_t*)__bind->valuePtr;
611 break;
612 }
613 case sizeof(int64_t) : {
614 *(int64_t*)_buf = *(int8_t*)__bind->valuePtr;
615 break;
616 }
617 default: {
618 *_size = sizeof(int8_t);
620 return false;
621 }
622 }
623 break;
624 }
625 case SQL_SMALLINT: {
626 switch (*_size) {
627 case sizeof(int16_t) : {
628 *(int16_t*)_buf = *(int16_t*)__bind->valuePtr;
629 break;
630 }
631 case sizeof(int32_t) : {
632 *(int32_t*)_buf = *(int16_t*)__bind->valuePtr;
633 break;
634 }
635 case sizeof(int64_t) : {
636 *(int64_t*)_buf = *(int16_t*)__bind->valuePtr;
637 break;
638 }
639 default: {
640 *_size = sizeof(int16_t);
642 return false;
643 }
644 }
645 break;
646 }
647 case SQL_INTEGER: {
648 switch (*_size) {
649 case sizeof(int32_t) : {
650 *(int32_t*)_buf = *(int32_t*)__bind->valuePtr;
651 break;
652 }
653 case sizeof(int64_t) : {
654 *(int64_t*)_buf = *(int32_t*)__bind->valuePtr;
655 break;
656 }
657 default: {
658 *_size = sizeof(int32_t);
660 return false;
661 }
662 }
663 break;
664 }
665 case SQL_INFX_BIGINT:
666 case SQL_BIGINT: {
667 switch (*_size) {
668 case sizeof(int64_t) : {
669 *(int64_t*)_buf = *(int64_t*)__bind->valuePtr;
670 break;
671 }
672 default: {
673 *_size = sizeof(int64_t);
675 return false;
676 }
677 }
678 break;
679 }
680 case SQL_NUMERIC:
681 case SQL_DECIMAL: {
682 errno = 0;
683 char* endptr = NULL;
684 long long n;
685 if ((__bind->precision - __bind->scale) < 20) {
686 n = strtoll((char*)__bind->valuePtr, &endptr, 10);
687 if (errno == ERANGE) {
689 n == LLONG_MAX || n == LLONG_MIN // overflow
690 );
691 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
693 return false;
694 }
695 #define __UNNEED__ 0
696 #if __UNNEED__
697 else if (errno == EINVAL) {
698 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
700 return false;
701 }
702 #endif
703 }
704 else {
705 double d = strtod((char*)__bind->valuePtr, &endptr);
706 if (errno == ERANGE) {
708 +HUGE_VAL == d || -HUGE_VAL == d // overflow
709 || !(DBL_MIN < d) // underflow
710 );
711 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
713 return false;
714 }
715 #if __UNNEED__
716 else if (errno == EINVAL) {
717 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
719 return false;
720 }
721 #endif
722 double i;
723 (void)modf(d, &i); // 정수부분만, 반환값(소수)는 버림
724 if (i < (double)LLONG_MIN || (double)LLONG_MAX < i) {
726 return false;
727 }
728 n = (long long)i;
729 }
730
731 switch (*_size) {
732 case sizeof(int8_t) : {
733 if (n < INT8_MIN || INT8_MAX < n) {
735 return false;
736 }
737 *(int8_t*)_buf = (int8_t)n;
738 break;
739 }
740 case sizeof(int16_t) : {
741 if (n < INT16_MIN || INT16_MAX < n) {
743 return false;
744 }
745 *(int16_t*)_buf = (int16_t)n;
746 break;
747 }
748 case sizeof(int32_t) : {
749 if (n < INT32_MIN || INT32_MAX < n) {
751 return false;
752 }
753 *(int32_t*)_buf = (int32_t)n;
754 break;
755 }
756 case sizeof(int64_t) : {
757 *(int64_t*)_buf = (int64_t)n;
758 break;
759 }
760 default: {
761 *_size = sizeof(int64_t);
763 return false;
764 }
765 }
766 break;
767 }
768 default: {
769 __DCL_ASSERT(false); // ODBCData::init bug
770 }
771 }
772
773 return true;
774}
#define INT32_MAX
Definition Config.h:290
#define INT32_MIN
Definition Config.h:285
#define INT8_MIN
Definition Config.h:283
#define INT8_MAX
Definition Config.h:288
#define INT16_MAX
Definition Config.h:289
#define INT16_MIN
Definition Config.h:284

◆ getInterval()

bool ODBCData::getInterval ( SQL::Interval * _buf,
size_t * _size )
protected

Definition at line 1130 of file ODBCData.cpp.

1131{
1132 // 2025-12-09
1133 // Informix fraction이 항상 0이다.
1134 // MSSQL INTERVAL 타입이 없다.
1135 // Oracle SQLExecute SQL_ERROR(-1), SQLGetDiagRec SQL_NO_DATA(100)으로 사용할 수 없다.
1136 // PostgreSQL VARCHAR로 처리한다.
1137
1138 if (*_size != sizeof(SQL::Interval)) {
1139 *_size = sizeof(SQL::Interval);
1141 return false;
1142 }
1143
1144 SQL_INTERVAL_STRUCT* s = (SQL_INTERVAL_STRUCT*)__bind->valuePtr;
1145 __DCL_TRACE3_N(L"bind.type[%d] type[%d] sign[%d]\n",
1146 __bind->type, s->interval_type, s->interval_sign);
1147
1148 int8_t sign = s->interval_sign ? -1 : 1;
1149 switch (__bind->type) {
1150 case SQL_INTERVAL_YEAR:
1151 case SQL_INTERVAL_MONTH:
1152 case SQL_INTERVAL_YEAR_TO_MONTH: {
1153 SQL_YEAR_MONTH_STRUCT* intval = &(s->intval.year_month);
1154 _buf->years = intval->year * sign;
1155 _buf->months = intval->month * sign;
1156 _buf->days = 0;
1157 _buf->hours = 0;
1158 _buf->mins = 0;
1159 _buf->secs = 0;
1160 _buf->fracs = 0;
1161 break;
1162 }
1163 case SQL_INTERVAL_DAY:
1164 case SQL_INTERVAL_HOUR:
1165 case SQL_INTERVAL_MINUTE:
1166 case SQL_INTERVAL_SECOND:
1167 case SQL_INTERVAL_DAY_TO_HOUR:
1168 case SQL_INTERVAL_DAY_TO_MINUTE:
1169 case SQL_INTERVAL_DAY_TO_SECOND:
1170 case SQL_INTERVAL_HOUR_TO_MINUTE:
1171 case SQL_INTERVAL_HOUR_TO_SECOND:
1172 case SQL_INTERVAL_MINUTE_TO_SECOND: {
1173 SQL_DAY_SECOND_STRUCT* intval = &(s->intval.day_second);
1174 _buf->years = 0;
1175 _buf->months = 0;
1176 _buf->days = intval->day * sign;
1177 _buf->hours = intval->hour * sign;
1178 _buf->mins = intval->minute * sign;
1179 _buf->secs = intval->second * sign;
1180 _buf->fracs = intval->fraction * sign;
1181 break;
1182 }
1183 default: {
1184 __DCL_ASSERT(false);
1185 }
1186 }
1187 return true;
1188}
#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
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

◆ getTime()

bool ODBCData::getTime ( SQL::Time * _buf,
size_t * _size )
protected

Definition at line 1060 of file ODBCData.cpp.

1061{
1062 __DCL_ASSERT(__TYPE_IS(SQL_TYPE_TIME)
1063 || __TYPE_IS(SQL_SS_TIME2));
1064
1065 if (*_size != sizeof(SQL::Time)) {
1066 *_size = sizeof(SQL::Time);
1068 return false;
1069 }
1070
1071 if (__bind->type == SQL_TYPE_TIME) {
1072 TIME_STRUCT* s = (TIME_STRUCT*)__bind->valuePtr;
1073 _buf->hour = s->hour;
1074 _buf->min = s->minute;
1075 _buf->sec = s->second;
1076 _buf->frac = 0;
1077 _buf->tzoff = INT16_MIN;
1078 }
1079 else {
1080 SQL_SS_TIME2_STRUCT* s =
1081 (SQL_SS_TIME2_STRUCT*)__bind->valuePtr;
1082 _buf->hour = s->hour;
1083 _buf->min = s->minute;
1084 _buf->sec = s->second;
1085 _buf->frac = s->fraction;
1086 _buf->tzoff = INT16_MIN;
1087 }
1088
1089 return true;
1090}
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

◆ getTimeStamp()

bool ODBCData::getTimeStamp ( SQL::TimeStamp * _buf,
size_t * _size )
protected

Definition at line 1092 of file ODBCData.cpp.

1093{
1094 __DCL_ASSERT(__TYPE_IS(SQL_TYPE_TIMESTAMP)
1095 || __TYPE_IS(SQL_SS_TIMESTAMPOFFSET));
1096
1097 if (*_size != sizeof(SQL::TimeStamp)) {
1099 return false;
1100 }
1101
1102 if (__bind->type == SQL_TYPE_TIME) {
1103 TIMESTAMP_STRUCT* s =
1104 (TIMESTAMP_STRUCT*)__bind->valuePtr;
1105 _buf->year = s->year;
1106 _buf->month = s->month;
1107 _buf->day = s->day;
1108 _buf->hour = s->hour;
1109 _buf->min = s->minute;
1110 _buf->sec = s->second;
1111 _buf->frac = s->fraction;
1112 _buf->tzoff = INT16_MIN;
1113 }
1114 else {
1115 SQL_SS_TIMESTAMPOFFSET_STRUCT* s =
1116 (SQL_SS_TIMESTAMPOFFSET_STRUCT*)__bind->valuePtr;
1117 _buf->year = s->year;
1118 _buf->month = s->month;
1119 _buf->day = s->day;
1120 _buf->hour = s->hour;
1121 _buf->min = s->minute;
1122 _buf->sec = s->second;
1123 _buf->frac = s->fraction;
1124 _buf->tzoff = s->timezone_hour * 60 + s->timezone_minute;
1125 }
1126
1127 return true;
1128}
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

◆ getUInteger()

bool ODBCData::getUInteger ( void * _buf,
size_t * _size )
protected

Definition at line 776 of file ODBCData.cpp.

777{
778 switch (__bind->type) {
779 case SQL_BIT:
780 case SQL_TINYINT: {
781 switch (*_size) {
782 case sizeof(uint8_t) : {
783 *(uint8_t*)_buf = *(uint8_t*)__bind->valuePtr;
784 break;
785 }
786 case sizeof(uint16_t) : {
787 *(uint16_t*)_buf = *(uint8_t*)__bind->valuePtr;
788 break;
789 }
790 case sizeof(uint32_t) : {
791 *(uint32_t*)_buf = *(uint8_t*)__bind->valuePtr;
792 break;
793 }
794 case sizeof(uint64_t) : {
795 *(uint64_t*)_buf = *(uint8_t*)__bind->valuePtr;
796 break;
797 }
798 default: {
799 *_size = sizeof(uint8_t);
801 return false;
802 }
803 }
804 break;
805 }
806 case SQL_SMALLINT: {
807 switch (*_size) {
808 case sizeof(uint16_t) : {
809 *(uint16_t*)_buf = *(uint16_t*)__bind->valuePtr;
810 break;
811 }
812 case sizeof(uint32_t) : {
813 *(uint32_t*)_buf = *(uint16_t*)__bind->valuePtr;
814 break;
815 }
816 case sizeof(uint64_t) : {
817 *(uint64_t*)_buf = *(uint16_t*)__bind->valuePtr;
818 break;
819 }
820 default: {
821 *_size = sizeof(uint16_t);
823 return false;
824 }
825 }
826 break;
827 }
828 case SQL_INTEGER: {
829 switch (*_size) {
830 case sizeof(uint32_t) : {
831 *(uint32_t*)_buf = *(uint32_t*)__bind->valuePtr;
832 break;
833 }
834 case sizeof(uint64_t) : {
835 *(uint64_t*)_buf = *(uint32_t*)__bind->valuePtr;
836 break;
837 }
838 default: {
839 *_size = sizeof(uint32_t);
841 return false;
842 }
843 }
844 break;
845 }
846 case SQL_INFX_BIGINT:
847 case SQL_BIGINT: {
848 switch (*_size) {
849 case sizeof(uint64_t) : {
850 *(uint64_t*)_buf = *(uint64_t*)__bind->valuePtr;
851 break;
852 }
853 default: {
854 *_size = sizeof(uint32_t);
856 return false;
857 }
858 }
859 break;
860 }
861 case SQL_NUMERIC:
862 case SQL_DECIMAL: {
863 errno = 0;
864 char* endptr = NULL;
865 unsigned long long u;
866 if ((__bind->precision - __bind->scale) <= 20) {
867 u = strtoull((char*)__bind->valuePtr, &endptr, 10);
868 if (errno == ERANGE) {
870 u == ULONG_MAX // overflow
871 );
872 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
874 return false;
875 }
876 #if __UNNEED__
877 else if (errno == EINVAL) {
878 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
880 return false;
881 }
882 #endif
883 }
884 else {
885 double d = strtod((char*)__bind->valuePtr, &endptr);
886 if (errno == ERANGE) {
888 +HUGE_VAL == d || -HUGE_VAL == d // overflow
889 || !(DBL_MIN < d) // underflow
890 );
891 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
893 return false;
894 }
895 #if __UNNEED__
896 else if (errno == EINVAL) {
897 // API 버그 또는 서버로부터 수신된 값에 오류가 있다.
899 return false;
900 }
901 #endif
902 double i;
903 modf(d, &i); // 정수부분만, 반환값(소수)는 버림
904 if (i < 0 || (double)ULONG_MAX < i) {
906 return false;
907 }
908 u = (unsigned long long)i;
909 }
910
911 switch (*_size) {
912 case sizeof(uint8_t) : {
913 if (UINT8_MAX < u) {
915 return false;
916 }
917 *(uint8_t*)_buf = (uint8_t)u;
918 break;
919 }
920 case sizeof(uint16_t) : {
921 if (UINT16_MAX < u) {
923 return false;
924 }
925 *(uint16_t*)_buf = (uint16_t)u;
926 break;
927 }
928 case sizeof(uint32_t) : {
929 if (UINT32_MAX < u) {
931 return false;
932 }
933 *(uint32_t*)_buf = (uint32_t)u;
934 break;
935 }
936 case sizeof(uint64_t) : {
937 *(uint64_t*)_buf = (uint64_t)u;
938 break;
939 }
940 default: {
941 *_size = sizeof(uint64_t);
943 return false;
944 }
945 }
946 break;
947 }
948 default: {
949 __DCL_ASSERT(false); // ODBCData::init bug
950 }
951 }
952
953 return true;
954}
#define UINT16_MAX
Definition Config.h:294
#define UINT32_MAX
Definition Config.h:295
#define UINT8_MAX
Definition Config.h:293

◆ init()

SQL::DataType ODBCData::init ( BIND * _bind)
protected

Definition at line 64 of file ODBCData.cpp.

65{
67 switch (_bind->type) {
68 case SQL_BIT:
69 case SQL_TINYINT: {
71 __maxsize = sizeof(int8_t);
72 break;
73 }
74 case SQL_SMALLINT: {
76 __maxsize = sizeof(int16_t);
77 break;
78 }
79 case SQL_INTEGER: {
81 __maxsize = sizeof(int32_t);
82 break;
83 }
84 case SQL_INFX_BIGINT:
85 case SQL_BIGINT: {
87 __maxsize = sizeof(int64_t);
88 break;
89 }
90 case SQL_REAL: {
92 __maxsize = sizeof(float);
93 break;
94 }
95 case SQL_FLOAT:
96 case SQL_DOUBLE: {
98 __maxsize = sizeof(double);
99 break;
100 }
101 // case SQL_DATETIME: // 9 ODBCVER >= 0x0300
102 case SQL_TYPE_TIMESTAMP: { // 93 ODBCVER >= 0x0300
104 __maxsize = sizeof(SQL::TimeStamp);
105 break;
106 }
107 // case SQL_DATE: // 9
108 case SQL_TYPE_DATE: { // 92 ODBCVER >= 0x0300
110 __maxsize = sizeof(SQL::Date);
111 break;
112 }
113 // case SQL_TIME: // 10
114 case SQL_TYPE_TIME: { // 92
116 __maxsize = sizeof(SQL::Time);
117 break;
118 }
119 // case SQL_INTERVAL: // 10 ODBCVER >= 0x0300
120 case SQL_INTERVAL_YEAR:
121 case SQL_INTERVAL_MONTH:
122 case SQL_INTERVAL_DAY:
123 case SQL_INTERVAL_HOUR:
124 case SQL_INTERVAL_MINUTE:
125 case SQL_INTERVAL_SECOND:
126 case SQL_INTERVAL_YEAR_TO_MONTH:
127 case SQL_INTERVAL_DAY_TO_HOUR:
128 case SQL_INTERVAL_DAY_TO_MINUTE:
129 case SQL_INTERVAL_DAY_TO_SECOND:
130 case SQL_INTERVAL_HOUR_TO_MINUTE:
131 case SQL_INTERVAL_HOUR_TO_SECOND:
132 case SQL_INTERVAL_MINUTE_TO_SECOND: {
134 __maxsize = sizeof(SQL::Interval);
135 break;
136 }
137 case SQL_NUMERIC:
138 case SQL_DECIMAL: {
140 __maxsize = 133; // Oracle between 1.0 x 10^-130 and 1.0 x 10^126
141 break;
142 }
143 case SQL_GUID:
144 case SQL_CHAR:
145 case SQL_VARCHAR:
146 case SQL_LONGVARCHAR: {
148 __maxsize = _bind->size ? _bind->size : INT32_MAX;
149 break;
150 }
151 case SQL_WCHAR:
152 case SQL_WVARCHAR:
153 case SQL_WLONGVARCHAR: {
154 r = SQL::typeText; // UTF-8
155 __maxsize = _bind->size ? _bind->size : INT32_MAX;
156 break;
157 }
158 case SQL_BINARY:
159 case SQL_VARBINARY:
160 case SQL_LONGVARBINARY: {
162 __maxsize = _bind->size ? _bind->size : INT32_MAX;
163 break;
164 }
165 case SQL_SS_UDT: { // GEOGRAPHY, GEOMETRY
167 __maxsize = _bind->size ? _bind->size : INT32_MAX;
168 break;
169 }
170 case SQL_SS_TIME2: { // -154 TIME(7)
172 __maxsize = sizeof(SQL::Time);
173 break;
174 }
175 case SQL_SS_TIMESTAMPOFFSET: { // -155 DATETIMEOFFSET
177 __maxsize = sizeof(SQL::TimeStamp);
178 break;
179 }
180 default:
181 case SQL_UNKNOWN_TYPE: {
182 __DCL_ASSERT(false);
183 }
184 }
185
186 __bind = _bind;
187 return r;
188}
IOException *size_t r
Definition MediaInfo.cpp:82
DataType
Definition SQLCore.h:59
@ typeNumeric
Definition SQLCore.h:64
@ typeUnknown
Definition SQLCore.h:60
@ typeTimeStampTz
Definition SQLCore.h:69
SQLSMALLINT type
Definition ODBCQuery.h:29
SQLULEN size
Definition ODBCQuery.h:30

◆ query()

virtual ODBCQuery * ODBCData::query ( ) const
protectedpure virtual

Implemented in ODBCParam.

◆ serverDataTypeName()

const wchar_t * ODBCData::serverDataTypeName ( ) const
protected

Definition at line 449 of file ODBCData.cpp.

450{
451 return ODBCData::__TYPE_NAME(__bind->type);
452}
static const wchar_t * __TYPE_NAME(SQLSMALLINT _type)
Definition ODBCData.cpp:190

◆ writeTo()

bool ODBCData::writeTo ( OutputStream * _output,
size_t * _size )
protected

Definition at line 1281 of file ODBCData.cpp.

1282{
1283 if (__bind->valueMax == 0) {
1284 size_t n;
1285 if (!__getDataSize(&n, false)) {
1286 return false;
1287 }
1288 if (n == (size_t)-1) {
1290 return false;
1291 }
1292 }
1293
1294 __DCL_ASSERT(__bind->lenORind >= 0);
1295 //__DCL_TRACE3_N(L"valueLen[%zd] lengthInd[%zd] *_size[%zd]\n",
1296 // __bind->valueMax, __bind->lenORind, *_size);
1297
1298 if ((size_t)__bind->lenORind < *_size) {
1299 *_size = __bind->lenORind;
1300 }
1301
1302 if (__bind->valuePtr) {
1303 // SQLBindCol로 바인드 되었다.
1304 // 이것을 복사한다.
1305 try {
1306 _output->write(__bind->valuePtr, *_size);
1307 }
1308 catch (IOException* _e) {
1309 __SET_ERROR_MSG(UTF8Encoder::encode(_e->toStringAll()));
1310 _e->destroy();
1311 return false;
1312 }
1313 return true;
1314 }
1315
1316 // SQLBindCol로 바인드 하지 않았다.
1317 // bind.size == 0 또는 > 12000 이상인 경우이다.
1318
1319 try {
1320 size_t total = 0;
1321 while (total < *_size) {
1322 char buf[4096];
1323 SQLLEN lenORind;
1324 SQLRETURN rc = SQLGetData(query()->stmtHandle(), __bind->number,
1325 __bind->valueType, buf, sizeof(buf), &lenORind);
1326 if (SQL_SUCCEEDED(rc)) {
1327 if (rc == SQL_SUCCESS_WITH_INFO
1328 && __bind->valueType == SQL_C_CHAR
1329 //&& (lenORind == sizeof(buf) || lenORind == SQL_NO_TOTAL)
1330 //&& buf[sizeof(buf) - 1] == '\0'
1331 ) {
1333 (lenORind == sizeof(buf) || lenORind == SQL_NO_TOTAL)
1334 && buf[sizeof(buf) - 1] == '\0'
1335 );
1336 lenORind = sizeof(buf) - 1;
1337 }
1338 lenORind = __MIN(lenORind, *_size - total);
1339 _output->write(buf, lenORind);
1340 total += lenORind;
1341 }
1342 else if (rc == SQL_NO_DATA) {
1343 break;
1344 }
1345 else {
1346 // SQL_ERROR(-1), SQL_INVALID_HANDLE(-2), SQL_STILL_EXECUTING(2)
1347 __DCL_TRACE2_N(L"SQLGetData rc[%d] lenORind[%d]\n", rc, lenORind);
1348 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, query()->stmtHandle());
1349 return false;
1350 }
1351 }
1352 }
1353 catch (IOException* _e) {
1354 __SET_ERROR_MSG(UTF8Encoder::encode(_e->toStringAll()));
1355 _e->destroy();
1356 return false;
1357 }
1358 return true;
1359}
#define __SET_ERROR_MSG(_message)
virtual void destroy()
Definition Exception.cpp:74
String toStringAll() const
Definition Exception.cpp:45

Member Data Documentation

◆ __bind

BIND* ODBCData::__bind
protected

Definition at line 11 of file ODBCData.h.

◆ __maxsize

size_t ODBCData::__maxsize
protected

Definition at line 12 of file ODBCData.h.


The documentation for this class was generated from the following files: