DCL 3.7.4
Loading...
Searching...
No Matches
OciData.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <oci.h>
4
5#include <stdlib.h> // strtoll, strtoull
6#include <string.h> // memcpy, strncpy
7
8#include <dcl/Object.h>
9#if __DCL_HAVE_ALLOC_DEBUG
10#undef __DCL_ALLOC_LEVEL
11#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
12#endif
13
14#include <dcl/Numeric.h>
16#include <dcl/SQLCore.h>
17
18#include "OciConnection.h"
19#include "OciQuery.h"
20#include "OciData.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#undef __THIS_FILE__
38static const char_t __THIS_FILE__[] = __T("dcl/sql/OciData.cpp");
39
40__DCL_BEGIN_NAMESPACE
41
42#define __SET_ERROR_HANDLE(_error, _status, _OCIError) \
43 conn()->setErrorHandle(_error, _status, _OCIError, \
44 true, __THIS_FILE__, __LINE__)
45#define __SET_ERROR_MSG(_msg) \
46 conn()->setErrorMessage(_msg, __THIS_FILE__, __LINE__)
47
49{
50 __position = 0;
51 __dynamicMode = OCI_DEFAULT;
52
53 __valueType = SQLT_CHR;
54 __descType = 0;
56 __valueSize = 0;
57 __indicator = -1;
59 __returnCode = 0;
61
63 __dataSize = 0;
64 __maxDataSize = 0;
65}
66
68{
71 // OciData::__bytesOutput = NULL;
72 }
73}
74
76{
77 // after fetch
78 // after execute in outbind
79 if (__indicator == -1)
80 return true;
81
82 sword status = OCI_SUCCESS;
83 switch(__valueType) {
84 case SQLT_CHR:
85 case SQLT_AFC:
86 case SQLT_BIN:
87 // case SQLT_RDD: SQLT_CHR로
88 // See. OciField::init, OciData::__TYPE_SIZE
89 case SQLT_LNG:
90 case SQLT_LBI: {
91 if (__dynamicMode == OCI_DEFAULT) {
92 // OCIDefineByPos OCI_DEFAULT만 __actualLength에 있다.
94 }
95 else {
96 // OCI_DYNAMIC_FETCH, OCI_DATA_AT_EXEC3
97 // OutBind 파라미터의 __dynamicMode는 모두 OCI_DATA_AT_EXEC 이다.
98 // OCI_LAST_PIECE 이전은 __bytesOutput에 보관되어 있다.
99 // OCI_LAST_PIECE 길이는 __callbackActualLength에 있다.
100 __dataSize = (__bytesOutput ? __bytesOutput->size() : 0)
102 }
103 break;
104 }
105 case SQLT_CLOB:
106 case SQLT_BLOB:
107 case SQLT_CFILE:
108 case SQLT_BFILE: {
109 ub4 len = 0;
110 if (__descType == OCI_DTYPE_FILE) {
111 status = OCILobFileOpen(
112 conn()->svcHandle(), // OCISvcCtx *svchp
113 conn()->errorHandle(), // OCIError *errhp
114 *(OCILobLocator**)__valuePtr, // OCILobLocator *filep
115 OCI_FILE_READONLY // ub1 mode
116 );
117 if (status != OCI_SUCCESS) {
118 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
119 return false;
120 }
121 }
122
123 status = OCILobGetLength(
124 conn()->svcHandle(), // OCISvcCtx *svchp
125 conn()->errorHandle(), // OCIError *errhp
126 *(OCILobLocator**)__valuePtr, // OCILobLocator *locp
127 &len // ub4 *lenp
128 );
129 if (status != OCI_SUCCESS) {
130 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
131 return false;
132 }
133
134 if (__descType == OCI_DTYPE_FILE) {
135 status = OCILobFileClose(
136 conn()->svcHandle(), // OCISvcCtx *svchp
137 conn()->errorHandle(), // OCIError *errhp
138 *(OCILobLocator**)__valuePtr // OCILobLocator *locp
139 );
140 if (status != OCI_SUCCESS) {
141 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
142 return false;
143 }
144 }
145
146 switch (__valueType) {
147 case SQLT_CLOB:
148 case SQLT_CFILE:
149 __dataSize = len * 3; // UTF-8
150 break;
151 default:
152 __dataSize = len;
153 }
154 break;
155 }
156 default: {
158 }
159 }
160
161 return true;
162}
163
164const wchar_t* OciData::serverDataTypeName() const
165{
167}
168
169bool OciData::getDataSize(size_t* _size, bool _maxsize)
170{
171 if (_maxsize) {
172 *_size = OciData::__maxDataSize;
173 return true;
174 }
175#if 0
176 if (query()->stmtType() == OCI_STMT_SELECT) {
177 if (!query()->inState(SQL::Query::stFetched)) {
179 return false;
180 }
181 }
182 else {
183 if (!query()->inState(SQL::Query::stExecuted)) {
185 return false;
186 }
187 }
188#endif
189 *_size = __indicator == -1 ? (size_t)-1 : OciData::__dataSize;
190 return true;
191}
192
193bool OciData::getData(void* _buf, size_t* _size, SQL::DataType _bufType)
194{
195#if 0
196 if (query()->stmtType() == OCI_STMT_SELECT) {
197 if (!query()->inState(SQL::Query::stFetched)) {
199 return false;
200 }
201 }
202 else {
203 if (!query()->inState(SQL::Query::stExecuted)) {
205 return false;
206 }
207 }
208#endif
209 if (__indicator == -1) {
211 return false;
212 }
213
214 switch(_bufType) {
215 case SQL::typeInteger:
216 case SQL::typeUInteger: {
217 return getInteger(_buf, _size, _bufType);
218 }
219 case SQL::typeFloat: {
220 return getFloat(_buf, _size);
221 }
222 case SQL::typeDate: {
223 if (*_size != sizeof(SQL::Date)) {
224 *_size = sizeof(SQL::Date);
226 return false;
227 }
229 bool r = getTimeStamp(&ts);
230 if (r) {
231 SQL::Date* p = (SQL::Date*)_buf;
232 p->year = ts.year;
233 p->month = ts.month;
234 p->day = ts.day;
235 }
236 return r;
237 }
238 case SQL::typeTime: {
239 if (*_size != sizeof(SQL::typeTime)) {
240 *_size = sizeof(SQL::typeTime);
242 return false;
243 }
245 bool r = getTimeStamp(&ts);
246 if (r) {
247 SQL::Time* p = (SQL::Time*)_buf;
248 p->hour = ts.hour;
249 p->min = ts.min;
250 p->sec = ts.sec;
251 p->frac = ts.frac;
252 p->tzoff = ts.tzoff;
253 }
254 return r;
255 }
256 case SQL::typeTimeStamp: {
257 if (*_size != sizeof(SQL::TimeStamp)) {
258 *_size = sizeof(SQL::TimeStamp);
260 return false;
261 }
262 return getTimeStamp((SQL::TimeStamp*)_buf);
263 }
264 case SQL::typeInterval: {
265 if (*_size != sizeof(SQL::Interval)) {
266 *_size = sizeof(SQL::Interval);
268 return false;
269 }
270 return getInterval((SQL::Interval*)_buf);
271 }
272 case SQL::typeText: {
273 if (__valueType == SQLT_VNU) {
274 return getNumericText((char*)_buf, _size);
275 }
276 }
277 case SQL::typeBinary: {
278 return getBytes((byte_t*)_buf, _size);
279 }
281 return writeTo((OutputStream*)_buf, _size);
282 }
283 default: {
284 __DCL_ASSERT(false); // SQL::Field::getData bug
285 }
286 }
287
288 return true;
289}
290
291bool OciData::getInteger(void* _buf, size_t* _size, SQL::DataType _bufType)
292{
293 __DCL_ASSERT(__valueType == SQLT_VNU); // OciField::init bug
294
295 sword status = OCI_SUCCESS;
296 if (*_size <= sizeof(int64_t /* 2025-02-03 월 int32_t */)) {
297 status = OCINumberToInt(
298 conn()->errorHandle(), // OCIError *err,
299 (CONST OCINumber*)__valuePtr, // CONST OCINumber *number,
300 *_size, // uword rsl_length,
301 _bufType == SQL::typeInteger ? // uword rsl_flag,
302 OCI_NUMBER_SIGNED : OCI_NUMBER_UNSIGNED,
303 _buf // dvoid *rsl
304 );
305 if (status != OCI_SUCCESS) {
306 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
307 return false;
308 }
309 }
310 else {
311 *_size = sizeof(int64_t);
313 return false;
314 }
315
316 return true;
317}
318
319bool OciData::getFloat(void* _buf, size_t* _size)
320{
321 switch (__valueType) {
322 case SQLT_BFLOAT: {
323 switch (*_size) {
324 case sizeof(float): {
325 *(float*)_buf = *(float*)__valuePtr;
326 break;
327 }
328 case sizeof(double) : {
329 *(double*)_buf = *(float*)__valuePtr;
330 break;
331 }
332 default: {
333 *_size = sizeof(float);
335 return false;
336 }
337 }
338 break;
339 }
340 case SQLT_BDOUBLE: {
341 switch (*_size) {
342 case sizeof(double) : {
343 *(double*)_buf = *(double*)__valuePtr;
344 break;
345 }
346 default: {
347 *_size = sizeof(double);
349 return false;
350 }
351 }
352 break;
353 }
354 case SQLT_VNU: {
355 if (*_size <= sizeof(long double)) {
356 // long double 의 storage size
357 // MSVC/WIN32 8
358 // GCC/Linux 12
359 sword status = OCINumberToReal(
360 conn()->errorHandle(), // OCIError *err,
361 (CONST OCINumber*)__valuePtr, // CONST OCINumber *number,
362 *_size, // uword rsl_length,
363 _buf // dvoid *rsl
364 );
365 if (status != OCI_SUCCESS) {
366 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
367 return false;
368 }
369 }
370 else {
371 *_size = sizeof(double);
373 return false;
374 }
375 break;
376 }
377 default: {
378 __DCL_ASSERT(false);
379 }
380 }
381
382 return true;
383}
384
385bool OciData::getNumericText(char* pBuf, size_t* _size)
386{
387 __DCL_ASSERT(__valueType == SQLT_VNU); // OciField::init bug
388
389 ub4 n = 133;
390 ByteBuffer* buf = ByteBuffer::create_e(n);
391 sword status = OCINumberToText(
392 conn()->errorHandle(), // OCIError *err,
393 (CONST OCINumber*)__valuePtr, // CONST OCINumber *number,
394 (const OraText*)"TM", // CONST OraText *fmt,
395 2, // ub4 fmt_length,
396 NULL, // CONST OraText *nls_params,
397 0, // ub4 nls_p_length,
398 &n, // ub4 *buf_size,
399 (text*)buf->data() // text *buf
400 );
401 if (status != OCI_SUCCESS) {
402 if (buf->__allocLength < n) {
403 ByteBuffer::extend(buf, n);
404 }
405 status = OCINumberToText(
406 conn()->errorHandle(), // OCIError *err,
407 (CONST OCINumber*)__valuePtr, // CONST OCINumber *number,
408 (CONST OraText*)"TM", // CONST OraText *fmt,
409 2, // ub4 fmt_length,
410 NULL, // CONST OraText *nls_params,
411 0, // ub4 nls_p_length,
412 &n, // ub4 *buf_size,
413 (text*)buf->data() // text *buf
414 );
415 }
416 if (status != OCI_SUCCESS) {
417 buf->release();
418 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
419 return false;
420 }
421
422 buf->__dataLength = n;
423 ByteString s = buf;
424 buf->release();
425
426 if (*_size < (size_t)s.length()) {
427 *_size = (size_t)s.length();
429 return false;
430 }
431
432 strncpy(pBuf, s.data(), s.length());
433 if (*_size > (size_t)s.length()) {
434 *_size = (size_t)s.length();
435 pBuf[*_size] = '\0';
436 }
437
438 return true;
439}
440
442{
443 sb2 year = 0;
444 ub1 month = 0;
445 ub1 day = 0;
446 ub1 hour = 0;
447 ub1 min = 0;
448 ub1 sec = 0;
449 ub4 fsec = 0;
450
451 _buf->tzoff = INT16_MIN;
452
453 sword status = OCI_SUCCESS;
454 switch(__valueType) {
455 // case SQLT_DAT :
456 case SQLT_ODT: {
457 OCIDateGetDate(
458 (CONST OCIDate*)__valuePtr, // const OCIDate *date
459 &year, // sb2 *year
460 &month, // ub1 *month
461 &day // ub1 *day
462 );
463 OCIDateGetTime(
464 (CONST OCIDate*)__valuePtr, // const OCIDate *date
465 &hour, // ub1 *hour
466 &min, // ub1 *min
467 &sec // ub1 *sec
468 );
469 break;
470 }
471 case SQLT_TIMESTAMP :
472 case SQLT_TIMESTAMP_TZ :
473 case SQLT_TIMESTAMP_LTZ: {
474 status = OCIDateTimeGetDate(
475 conn()->sessionHandle(), // dvoid *hndl,
476 conn()->errorHandle(), // OCIError *err,
477 *(CONST OCIDateTime**)__valuePtr, // CONST OCIDateTime *datetime,
478 &year, // sb2 *year,
479 &month, // ub1 *month,
480 &day // ub1 *day
481 );
482 if (status == OCI_SUCCESS)
483 status = OCIDateTimeGetTime(
484 conn()->sessionHandle(), // dvoid *hndl,
485 conn()->errorHandle(), // OCIError *err,
486 *(OCIDateTime**)__valuePtr, // OCIDateTime *datetime,
487 &hour, // ub1 *hour,
488 &min, // ub1 *min,
489 &sec, // ub1 *sec,
490 &fsec // ub4 *fsec
491 );
492 if (status == OCI_SUCCESS && __valueType != SQLT_TIMESTAMP) {
493 sb1 tzHour = 0;
494 sb1 tzMin = 0;
495 status = OCIDateTimeGetTimeZoneOffset(
496 conn()->sessionHandle(), // dvoid *hndl,
497 conn()->errorHandle(), // OCIError *err,
498 *(CONST OCIDateTime**)__valuePtr, // CONST OCIDateTime *datetime,
499 &tzHour, // sb1 *hour,
500 &tzMin // sb1 *min,
501 );
502 if (status != OCI_SUCCESS) {
503 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
504 return false;
505 }
506 // __DCL_TRACE2_N("TZ : %+03d:%02d\n", hour, min);
507 _buf->tzoff = tzHour * 60 + tzMin;
508 }
509 break;
510 }
511 default: {
512 __DCL_ASSERT(false); // OciField::init bug
513 }
514 }
515
516 _buf->year = year;
517 _buf->month = month;
518 _buf->day = day;
519 _buf->hour = hour;
520 _buf->min = min;
521 _buf->sec = sec;
522 _buf->frac = fsec;
523
524 return true;
525}
526
528{
529 sb4 year = 0;
530 sb4 month = 0;
531 sb4 day = 0;
532 sb4 hour = 0;
533 sb4 min = 0;
534 sb4 sec = 0;
535 sb4 fsec = 0;
536 sword status = OCI_SUCCESS;
537
538 switch(__valueType) {
539 case SQLT_INTERVAL_YM: {
540 status = OCIIntervalGetYearMonth(
541 conn()->sessionHandle(), // dvoid *hndl,
542 conn()->errorHandle(), // OCIError *err,
543 &year, // sb4 *yr,
544 &month, // sb4 *mnth,
545 *(CONST OCIInterval**)__valuePtr // CONST OCIInterval *interval
546 );
547 break;
548 }
549 case SQLT_INTERVAL_DS: {
550 status = OCIIntervalGetDaySecond(
551 conn()->sessionHandle(), // dvoid *hndl,
552 conn()->errorHandle(), // OCIError *err,
553 &day, // sb4 *dy,
554 &hour, // sb4 *hr,
555 &min, // sb4 *mm,
556 &sec, // sb4 *ss,
557 &fsec, // sb4 *fsec,
558 *(CONST OCIInterval**)__valuePtr // CONST OCIInterval *interval
559 );
560 break;
561 }
562 default: {
563 __DCL_ASSERT(false); // OciField::init bug
564 }
565 }
566
567 if (status != OCI_SUCCESS) {
568 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
569 return false;
570 }
571
572 _buf->years = year;
573 _buf->months = month;
574 _buf->days = day;
575 _buf->hours = hour;
576 _buf->mins = min;
577 _buf->secs = sec;
578 _buf->fracs = fsec;
579 return true;
580}
581
582inline size_t __MIN(size_t x, size_t y)
583{
584 return x < y ? x : y;
585}
586
587bool OciData::getBytes(byte_t* _buf, size_t* _size)
588{
589 switch(__valueType) {
590 case SQLT_RDD: {
591 if (*_size < __dataSize) {
592 *_size = __dataSize;
594 return false;
595 }
596 }
597 case SQLT_CHR :
598 case SQLT_AFC :
599 case SQLT_BIN :
600 case SQLT_LNG :
601 case SQLT_LBI: {
602 size_t total = 0;
603 if (__dynamicMode == OCI_DEFAULT) {
605 total = __MIN(__actualLength, *_size);
606 memcpy(_buf, __valuePtr, total);
607 }
608 else {
609 // __dataSize는 __bytesOutput + __callbackActualLength
610 if (__bytesOutput) {
611 total = __MIN(__bytesOutput->size(), *_size);
612 memcpy(_buf, __bytesOutput->data(), total);
613 }
614 size_t copy = __MIN(__callbackActualLength, *_size - total);
615 memcpy(_buf + total, __valuePtr, copy);
616 total += copy;
617 }
618 if (total < *_size) {
619 *(_buf + total) = '\0';
620 }
621 *_size = total;
622 break;
623 }
624 case SQLT_CLOB:
625 case SQLT_BLOB:
626 case SQLT_CFILE:
627 case SQLT_BFILE: {
628 if (*_size && __dataSize)
629 return getBytesFromLob(_buf, _size);
630 else
631 *_size = 0;
632 break;
633 }
634 default: {
635 __DCL_ASSERT(false); // OciField::init bug
636 }
637 }
638
639 return true;
640}
641
642bool OciData::writeTo(OutputStream* _output, size_t* _size)
643{
644 switch(__valueType) {
645 case SQLT_RDD: {
646 if (*_size < __dataSize) {
647 *_size = __dataSize;
649 return false;
650 }
651 }
652 case SQLT_CHR:
653 case SQLT_AFC:
654 case SQLT_BIN:
655 case SQLT_LNG:
656 case SQLT_LBI: {
657 try {
658 size_t total = 0;
659 if (__dynamicMode == OCI_DEFAULT) {
661 total = __MIN(__actualLength, *_size);
662 _output->write(__valuePtr, total);
663 }
664 else {
665 // __dataSize는 __bytesOutput + __callbackActualLength
666 if (__bytesOutput) {
667 total = __MIN(__bytesOutput->size(), *_size);
668 _output->write(__bytesOutput->data(), total);
669 }
670 size_t copy = __MIN(__callbackActualLength, *_size - total);
671 _output->write(__valuePtr, copy);
672 total += copy;
673 }
674 *_size = total;
675 }
676 catch (IOException* e) {
677 e->destroy();
678 return false;
679 }
680 break;
681 }
682 case SQLT_CLOB :
683 case SQLT_BLOB :
684 case SQLT_CFILE :
685 case SQLT_BFILE: {
686 if (*_size && __dataSize)
687 return writeToFromLob(_output, _size);
688 else
689 *_size = 0;
690 break;
691 }
692 default: {
693 __DCL_ASSERT(false); // OciField::init bug
694 }
695 }
696
697 return true;
698}
699
700bool OciData::getBytesFromLob(byte_t* _buf, size_t* _size)
701{
702 __DCL_ASSERT(__valueType == SQLT_CLOB
703 || __valueType == SQLT_BLOB
704 || __valueType == SQLT_BFILE
705 || __valueType == SQLT_CFILE
706 );
707
708 sword status = OCI_SUCCESS;
709 if (__descType == OCI_DTYPE_FILE) {
710 status = OCILobFileOpen(
711 conn()->svcHandle(), // OCISvcCtx *svchp
712 conn()->errorHandle(), // OCIError *errhp
713 *(OCILobLocator**)__valuePtr, // OCILobLocator *locp
714 OCI_FILE_READONLY // ub1 mode
715 );
716 if (status != OCI_SUCCESS) {
717 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
718 return false;
719 }
720 }
721
722 // Lob로부터 csfrm를 확인한다.
723 // BLOB(0), CLOB(1), NCLOB(2) 이다.
724 // OCILobRead 호출에서 csfrm 값이 다르면, ORA-24806: LOB form mismatch 로 실패한다.
725 // NCLOB를 NLS_LANG을 적용하여 변환하여 읽어라
726 ub1 csfrm = 0;
727 status = OCILobCharSetForm(
728 conn()->envHandle(), // OCIEnv *envhp
729 conn()->errorHandle(), // OCIError *errhp
730 *(OCILobLocator**)__valuePtr, // const OCILobLocator *locp
731 &csfrm // ub1 *csfrm
732 );
733 if (status != OCI_SUCCESS) {
734 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
735 return false;
736 }
737 __DCL_TRACE2_N(L"__dataSize[%zd] csfrm[%d]\n", __dataSize, csfrm);
738
739 bool r = true;
740 size_t total = 0;
741 while(total < *_size) {
742 byte_t* buf = _buf + total;
743 size_t bufl = *_size - total;
744 ub4 byte_amt = bufl;
745 //ub8 char_amt = byte_amt / 3;
746 //ub1 piece = total == 0 ? OCI_FIRST_PIECE : OCI_NEXT_PIECE;
747 status = OCILobRead( // 2
748 conn()->svcHandle(), // OCISvcCtx *svchp
749 conn()->errorHandle(), // OCIError *errhp
750 *((OCILobLocator**)__valuePtr), // OCILobLocator *locp
751 &byte_amt, // ub8 *byte_amtp
752 // NULL, // ub8 *char_amtp
753 1 + total, // ub8 offset
754 buf, // void *bufp
755 bufl, // ub8 bufl
756 // piece, // ub1 piece
757 NULL, // void *ctxp
758 (OCICallbackLobRead)NULL, // OCICallbackLobRead2 (cbfp)
759 0, // ub2 csid
760 csfrm // ub1 csfrm
761 );
762 if (status == OCI_ERROR) {
763 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
764 r = false;
765 break;
766 }
767
768 // OCI_SUCCESS, OCI_NEED_DATA
769 if (byte_amt) {
770 total += byte_amt;
771 }
772 else {
773 break; // done
774 }
775 }
776
777 if (__descType == OCI_DTYPE_FILE) {
778 if (r) {
779 status = OCILobFileClose(
780 conn()->svcHandle(), // OCISvcCtx *svchp
781 conn()->errorHandle(), // OCIError *errhp
782 *(OCILobLocator**)__valuePtr // OCILobLocator *locp
783 );
784 if (status != OCI_SUCCESS) {
785 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
786 return false;
787 }
788 }
789 else {
790 // 이전에 에러가 발생했다. Close 만 시킨다.
791 status = OCILobFileClose(
792 conn()->svcHandle(), // OCISvcCtx *svchp
793 conn()->errorHandle2(), // OCIError *errhp
794 *(OCILobLocator**)__valuePtr // OCILobLocator *locp
795 );
796 if (status != OCI_SUCCESS) {
797 __DCL_TRACE0(__T("Warning - OCILobFileClose Fail!\n"));
798 }
799 }
800 }
801
802 if (total < *_size) {
803 *(_buf + total) = '\0';
804 }
805 *_size = total;
806 return r;
807}
808
809bool OciData::writeToFromLob(OutputStream* _output, size_t* _size)
810{
811 __DCL_ASSERT(__valueType == SQLT_CLOB
812 || __valueType == SQLT_BLOB
813 || __valueType == SQLT_BFILE
814 || __valueType == SQLT_CFILE
815 );
816
817 sword status = OCI_SUCCESS;
818 if (__descType == OCI_DTYPE_FILE) {
819 status = OCILobFileOpen(
820 conn()->svcHandle(), // OCISvcCtx *svchp
821 conn()->errorHandle(), // OCIError *errhp
822 *(OCILobLocator**)__valuePtr, // OCILobLocator *filep
823 OCI_FILE_READONLY // ub1 mode
824 );
825 if (status != OCI_SUCCESS) {
826 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
827 return false;
828 }
829 }
830
831 // Lob로부터 csfrm를 확인한다.
832 // BLOB(0), CLOB(1), NCLOB(2) 이다.
833 // OCILobRead 호출에서 csfrm 값이 다르면, ORA-24806: LOB form mismatch 로 실패한다.
834 // NCLOB를 NLS_LANG을 적용하여 변환하여 읽어라
835 ub1 csfrm = 0;
836 status = OCILobCharSetForm(
837 conn()->envHandle(), // OCIEnv *envhp
838 conn()->errorHandle(), // OCIError *errhp
839 *(OCILobLocator**)__valuePtr, // const OCILobLocator *locp
840 &csfrm // ub1 *csfrm
841 );
842 if (status != OCI_SUCCESS) {
843 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
844 return false;
845 }
846 __DCL_TRACE2_N(L"__dataSize[%zd] csfrm[%d]\n", __dataSize, csfrm);
847
848 bool r = true;
849 size_t total = 0;
850 char buf[4096];
851 while(total < *_size) {
852 size_t bufl = __MIN(*_size - total, sizeof(buf));
853 ub4 byte_amt = bufl;
854 status = OCILobRead( // 2
855 conn()->svcHandle(), // OCISvcCtx *svchp
856 conn()->errorHandle(), // OCIError *errhp
857 *((OCILobLocator**)__valuePtr), // OCILobLocator *locp
858 &byte_amt, // oraub8 *byte_amtp,
859 // NULL, // oraub8 *char_amtp
860 1 + total, // oraub8 offset
861 buf, // void *bufp
862 bufl, // oraub8 bufl
863 // piece, // ub1 piece
864 NULL, // void *ctxp
865 (OCICallbackLobRead)NULL, // OCICallbackLobRead2 (cbfp)
866 0, // ub2 csid
867 csfrm // ub1 csfrm
868 );
869 if (status == OCI_ERROR) {
870 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
871 r = false;
872 break;
873 }
874
875 // OCI_SUCCESS, OCI_NEED_DATA
876 if (byte_amt) {
877 try {
878 _output->write(buf, byte_amt);
879 }
880 catch(IOException* e) {
881 e->destroy();
882 r = false;
883 break;
884 }
885
886 total += byte_amt;
887 }
888 else {
889 break; // done
890 }
891 }
892
893 if (__descType == OCI_DTYPE_FILE) {
894 if (r) {
895 status = OCILobFileClose(
896 conn()->svcHandle(), // OCISvcCtx *svchp
897 conn()->errorHandle(), // OCIError *errhp
898 *(OCILobLocator**)__valuePtr // OCILobLocator *filep
899 );
900 if (status != OCI_SUCCESS) {
901 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
902 return false;
903 }
904 }
905 else {
906 // 이전에 에러가 발생했다. Close 만 시킨다.
907 status = OCILobFileClose(
908 conn()->svcHandle(), // OCISvcCtx *svchp
909 conn()->errorHandle2(), // OCIError *errhp
910 *(OCILobLocator**)__valuePtr // OCILobLocator *filep
911 );
912 if (status != OCI_SUCCESS) {
913 __DCL_TRACE0(__T("Warning - OCILobFileClose Fail!\n"));
914 }
915 }
916 }
917
918 *_size = total;
919 return r;
920}
921
922#define SQLTYPE_NAME(_sqlt, _name) case _sqlt : return L ## _name
923
924const wchar_t* OciData::__TYPE_NAME(ub2 _sqlt)
925{
926 switch(_sqlt) {
927 SQLTYPE_NAME(SQLT_NUM, "NUMBER");
928 SQLTYPE_NAME(SQLT_VNU, "NUMBER");
929 SQLTYPE_NAME(SQLT_IBFLOAT, "BFLOAT");
930 SQLTYPE_NAME(SQLT_IBDOUBLE, "DOUBLE");
931 SQLTYPE_NAME(SQLT_DAT, "DATE");
932 SQLTYPE_NAME(SQLT_ODT, "DATE");
933 SQLTYPE_NAME(SQLT_TIMESTAMP, "TIMESTAMP");
934 SQLTYPE_NAME(SQLT_TIMESTAMP_TZ, "TIMESTAMP WITH TIME ZONE");
935 SQLTYPE_NAME(SQLT_TIMESTAMP_LTZ, "TIMESTAMP WITH LOCAL TIME ZONE");
936 SQLTYPE_NAME(SQLT_INTERVAL_YM, "INTERVAL YEAR TO MONTH");
937 SQLTYPE_NAME(SQLT_INTERVAL_DS, "INTERVAL DAY TO SECOND");
938 SQLTYPE_NAME(SQLT_CHR, "VARCHAR2");
939 SQLTYPE_NAME(SQLT_AFC, "CHAR");
940 SQLTYPE_NAME(SQLT_BIN, "RAW");
941 SQLTYPE_NAME(SQLT_LNG, "LONG");
942 SQLTYPE_NAME(SQLT_LBI, "LONG RAW");
943 SQLTYPE_NAME(SQLT_CLOB, "CLOB");
944 SQLTYPE_NAME(SQLT_BLOB, "BLOB");
945 SQLTYPE_NAME(SQLT_BFILE, "BFILE");
946 SQLTYPE_NAME(SQLT_CFILE, "CFILE");
947 SQLTYPE_NAME(SQLT_RDD, "ROWID");
948 }
949 return L"Unknown Type: Driver is not Support";
950}
951
952ub4 OciData::__TYPE_SIZE(ub2 _sqlt, ub4 _size)
953{
954 ub4 size = 0;
955 switch (_sqlt) {
956 case SQLT_NUM:
957 case SQLT_VNU:
958 size = sizeof(OCINumber);
959 break;
960 case SQLT_IBFLOAT:
961 size = sizeof(float);
962 break;
963 case SQLT_IBDOUBLE:
964 size = sizeof(double);
965 break;
966 case SQLT_DAT:
967 case SQLT_ODT:
968 size = sizeof(OCIDate);
969 break;
970 case SQLT_LNG:
971 case SQLT_LBI:
973 break;
974 case SQLT_TIMESTAMP:
975 case SQLT_TIMESTAMP_TZ:
976 case SQLT_TIMESTAMP_LTZ:
977 case SQLT_INTERVAL_YM:
978 case SQLT_INTERVAL_DS:
979 case SQLT_CLOB:
980 case SQLT_BLOB:
981 case SQLT_CFILE:
982 case SQLT_BFILE:
983 size = sizeof(void*);
984 break;
985 case SQLT_RDD:
986 size = OCI_ROWID_LEN;
987 break;
988 case SQLT_CHR:
989 case SQLT_AFC:
990 case SQLT_BIN:
991 default:
992 size = _size;
993 }
994 return size;
995}
996
997size_t OciData::__TYPE_ALIGN(size_t _offset, ub2 _sqlt)
998{
999 size_t size = 0;
1000 switch (_sqlt) {
1001 case SQLT_IBFLOAT:
1002 size = sizeof(float);
1003 break;
1004 case SQLT_IBDOUBLE:
1005 size = sizeof(double);
1006 break;
1007 case SQLT_NUM:
1008 case SQLT_VNU: // struct OCINumber
1009 case SQLT_DAT:
1010 case SQLT_ODT: // struct OCIDate
1011 size = sizeof(long);
1012 break;
1013 case SQLT_TIMESTAMP: // OCIDateTime*
1014 case SQLT_TIMESTAMP_TZ:
1015 case SQLT_TIMESTAMP_LTZ:
1016 case SQLT_INTERVAL_YM: // OCIInterval*
1017 case SQLT_INTERVAL_DS:
1018 case SQLT_CLOB: // OCILobLocator*
1019 case SQLT_BLOB:
1020 case SQLT_CFILE:
1021 case SQLT_BFILE:
1022 size = sizeof(void*);
1023 break;
1024 case SQLT_RDD:
1025 case SQLT_LNG:
1026 case SQLT_LBI:
1027 case SQLT_CHR:
1028 case SQLT_AFC:
1029 case SQLT_BIN:
1030 default:
1031 size = sizeof(char);
1032 }
1033 return (_offset + size - 1) & ~(size - 1);
1034}
1035
1036__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:312
wchar_t char_t
Definition Config.h:247
unsigned char byte_t
Definition Config.h:246
#define INT16_MIN
Definition Config.h:284
#define __DCL_TRACE2_N(fmt, arg1, arg2)
#define __SET_ERROR_HANDLE(_SQLCODE)
#define SQLTYPE_NAME(_dataType, name)
Definition IFXField.cpp:302
IOException *size_t r
Definition MediaInfo.cpp:82
#define __DCL_TRACE0(psz)
Definition Object.h:398
#define __DCL_ASSERT(expr)
Definition Object.h:394
#define __T(str)
Definition Object.h:60
size_t __MIN(size_t x, size_t y)
Definition OciData.cpp:582
#define __DYNAMIC_BUFFER_SIZE
Definition OciData.h:11
virtual void destroy()
Definition Exception.cpp:74
sb2 __indicator
Definition OciData.h:24
bool getBytes(byte_t *_buf, size_t *_size)
Definition OciData.cpp:587
ub2 __valueType
Definition OciData.h:22
bool writeToFromLob(OutputStream *_output, size_t *_size)
Definition OciData.cpp:809
sb4 __valueSize
Definition OciData.h:21
OciData()
Definition OciData.cpp:48
ub2 __actualLength
Definition OciData.h:25
static const wchar_t * __TYPE_NAME(ub2 _sqlt)
Definition OciData.cpp:924
virtual OciQuery * query() const =0
bool getBytesFromLob(byte_t *_buf, size_t *_size)
Definition OciData.cpp:700
bool getFloat(void *_buf, size_t *_size)
Definition OciData.cpp:319
static size_t __TYPE_ALIGN(size_t _offset, ub2 _sqlt)
Definition OciData.cpp:997
bool onAfterFetch()
Definition OciData.cpp:75
ub4 __dynamicMode
Definition OciData.h:17
bool getDataSize(size_t *_size, bool _maxsize)
Definition OciData.cpp:169
bool getInteger(void *_buf, size_t *_size, SQL::DataType _bufType)
Definition OciData.cpp:291
bool getInterval(SQL::Interval *_buf)
Definition OciData.cpp:527
bool getTimeStamp(SQL::TimeStamp *_buf)
Definition OciData.cpp:441
bool getNumericText(char *_buf, size_t *_size)
Definition OciData.cpp:385
void * __valuePtr
Definition OciData.h:20
size_t __dataSize
Definition OciData.h:30
ub4 __position
Definition OciData.h:16
ub2 __returnCode
Definition OciData.h:26
static ub4 __TYPE_SIZE(ub2 _sqlt, ub4 _size)
Definition OciData.cpp:952
bool getData(void *_buf, size_t *_size, SQL::DataType _bufType)
Definition OciData.cpp:193
ub4 __callbackActualLength
Definition OciData.h:27
size_t __maxDataSize
Definition OciData.h:31
~OciData()
Definition OciData.cpp:67
OciConnection * conn() const
Definition OciData.h:67
ub4 __descType
Definition OciData.h:19
BytesOutputStream * __bytesOutput
Definition OciData.h:29
const wchar_t * serverDataTypeName() const
Definition OciData.cpp:164
bool writeTo(OutputStream *_buf, size_t *_size)
Definition OciData.cpp:642
DataType
Definition SQLCore.h:59
@ 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
@ eNotExecuted
Definition SQLCore.h:42
@ eInvalidBufferSize
Definition SQLCore.h:50
@ eServerError
Definition SQLCore.h:21
@ eNotFetched
Definition SQLCore.h:43
@ eValueIsNull
Definition SQLCore.h:47
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