DCL 3.7.4
Loading...
Searching...
No Matches
OciField.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <oci.h>
4
5#include <dcl/Object.h>
6#if __DCL_HAVE_ALLOC_DEBUG
7#undef __DCL_ALLOC_LEVEL
8#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
9#endif
10
11#include <dcl/OutputStream.h>
13#include <dcl/Charset.h>
14#include <dcl/SQLCore.h>
15
16#include "OciConnection.h"
17#include "OciQuery.h"
18#include "OciField.h"
19
20#define __TRACE_THIS 0
21#if __TRACE_THIS
22#define __DCL_TRACE0_N __DCL_TRACE0
23#define __DCL_TRACE1_N __DCL_TRACE1
24#define __DCL_TRACE2_N __DCL_TRACE2
25#define __DCL_TRACE3_N __DCL_TRACE3
26#define __DCL_TRACE4_N __DCL_TRACE4
27#define __DCL_TRACE5_N __DCL_TRACE5
28#else
29#define __DCL_TRACE0_N(fmt)
30#define __DCL_TRACE1_N(fmt, arg)
31#define __DCL_TRACE2_N(fmt, arg1, arg2)
32#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
33#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
34#define __DCL_TRACE5_N(fmt, arg1, arg2, arg3, arg4, arg5)
35#endif
36
37#undef __THIS_FILE__
38static const char_t __THIS_FILE__[] = __T("dcl/sql/OciField.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
51 : Field(NULL)
52{
53 __sqlt = 0;
54}
55
57{
60 conn()->DescriptorFree(
61 *(void**)OciData::__valuePtr,
63 ) == OCI_SUCCESS
64 );
65 }
66}
67
69{
70 return (OciQuery*)Field::__queryHandle;
71}
72
73bool OciField::init(SQL::Query* _queryHandle, ub4 _position,
74 ub2 _sqlt, void* _buf, ub2 _buflen
75)
76{
77 __DCL_ASSERT(_queryHandle != NULL);
78 Field::__queryHandle = _queryHandle;
79 OciData::__position = _position; // 1, 2, 3, ...
80 __sqlt = _sqlt;
81
82 OCIParam* param = NULL;
83 sword status = OCIParamGet(
84 query()->stmtHandle(), // const void *hndlp
85 OCI_HTYPE_STMT, // ub4 htype
86 conn()->errorHandle(), // OCIError *errhp
87 (dvoid**)&param, // void **parmdpp
88 _position // ub4 pos
89 );
90 if (status != OCI_SUCCESS) {
91 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
92 return false;
93 }
94
95 text* name = NULL;
96 ub4 size = 0;
97 status = OCIAttrGet(
98 param, // const void *trgthndlp
99 OCI_DTYPE_PARAM, // ub4 trghndltyp
100 &name, // void *attributep
101 &size, // ub4 *sizep
102 OCI_ATTR_NAME, // ub4 attrtype
103 conn()->errorHandle() // OCIError *errhp
104 );
105 if (status != OCI_SUCCESS) {
106 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
107 return false;
108 }
109
110 try {
111 Field::__name = UTF8Decoder::decode((const char*)name, size);
112 }
113 catch (CharsetConvertException* _e) {
114 __SET_ERROR_MSG(UTF8Encoder::encode(_e->toStringAll()));
115 _e->destroy();
116 return false;
117 }
118
119 sb2 precision = 0;
120 size = sizeof(precision);
121 status = OCIAttrGet(
122 param, // const void *trgthndlp
123 OCI_DTYPE_PARAM, // ub4 trghndltyp
124 &precision, // void *attributep
125 &size, // ub4 *sizep
126 OCI_ATTR_PRECISION, // ub4 attrtype
127 conn()->errorHandle() // OCIError *errhp
128 );
129 __DCL_ASSERT(size == sizeof(precision));
130 if (status != OCI_SUCCESS) {
131 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
132 return false;
133 }
134
135 sb1 scale = 0;
136 size = sizeof(scale);
137 status = OCIAttrGet(
138 param, // const void *trgthndlp
139 OCI_DTYPE_PARAM, // ub4 trghndltyp
140 &scale, // void *attributep
141 &size, // ub4 *sizep
142 OCI_ATTR_SCALE, // ub4 attrtype
143 conn()->errorHandle() // OCIError *errhp
144 );
145 __DCL_ASSERT(size == sizeof(scale));
146 if (status != OCI_SUCCESS) {
147 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
148 return false;
149 }
150
151 Field::__precision = precision;
152 Field::__scale = scale;
153
154#ifdef __DCL_DEBUG
155 // ub2 dataSize 이었었는데, Assert failed 되었다.
156 // 반환값의 범위는 0 ~ 4000이다.
157 ub4 dataSize = 0;
158 size = sizeof(dataSize);
159 status = OCIAttrGet(
160 param, // const void *trgthndlp
161 OCI_DTYPE_PARAM, // ub4 trghndltyp
162 &dataSize, // void *attributep
163 &size, // ub4 *sizep
164 OCI_ATTR_DATA_SIZE, // ub4 attrtype
165 conn()->errorHandle() // OCIError *errhp
166 );
167 __DCL_ASSERT(size == sizeof(dataSize));
168 if (status != OCI_SUCCESS) {
169 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
170 return false;
171 }
172 __DCL_TRACE5_N(L"Field [%2d] size [%6d %3d,%3d] [%ls]\n",
173 __position, dataSize, precision, scale, __name.data());
174#endif
175
176 OciData::__dynamicMode = OCI_DEFAULT;
177 OciData::__valueSize = _buflen;
178 OciData::__valueType = _sqlt;
179 switch(_sqlt) {
180 case SQLT_NUM: {
181 OciData::__valueType = SQLT_VNU;
182 // between 1.0 x 10^-130 and 9.9...9 x 10^125
183 // (38 nines followed by 88 zeroes)
185 Field::__dataType = SQL::typeNumeric;
186 break;
187 }
188 case SQLT_IBFLOAT: {
189 OciData::__valueType = SQLT_BFLOAT;
190 OciData::__maxDataSize = sizeof(float);
191 Field::__dataType = SQL::typeFloat;
192 break;
193 }
194 case SQLT_IBDOUBLE: {
195 OciData::__valueType = SQLT_BDOUBLE;
196 OciData::__maxDataSize = sizeof(double);
197 Field::__dataType = SQL::typeFloat;
198 break;
199 }
200 case SQLT_DAT: {
201 OciData::__valueType = SQLT_ODT;
203 Field::__dataType = SQL::typeTimeStamp;
204 break;
205 }
206 case SQLT_TIMESTAMP: {
207 OciData::__descType = OCI_DTYPE_TIMESTAMP;
209 Field::__dataType = SQL::typeTimeStamp;
210 break;
211 }
212 case SQLT_TIMESTAMP_TZ: {
213 OciData::__descType = OCI_DTYPE_TIMESTAMP_TZ;
215 Field::__dataType = SQL::typeTimeStampTz;
216 break;
217 }
218 case SQLT_TIMESTAMP_LTZ: {
219 OciData::__descType = OCI_DTYPE_TIMESTAMP_LTZ;
221 Field::__dataType = SQL::typeTimeStampTz;
222 break;
223 }
224 case SQLT_INTERVAL_YM: {
225 OciData::__descType = OCI_DTYPE_INTERVAL_YM;
227 Field::__dataType = SQL::typeIntervalYm;
228 break;
229 }
230 case SQLT_INTERVAL_DS: {
231 OciData::__descType = OCI_DTYPE_INTERVAL_DS;
233 Field::__dataType = SQL::typeIntervalDs;
234 break;
235 }
236 case SQLT_RDD: {
237 // oci.h
238 // #define OCI_ROWID_LEN 23
239 // ROWID를 CHR로 받으면 base64로 인코딩되어 리턴한다.
240 // 초기 버퍼를 3의 배수로 정한다.
241 OciData::__valueType = SQLT_CHR;
242 OciData::__maxDataSize = _buflen;
243 Field::__dataType = SQL::typeText;
244 break;
245 }
246 case SQLT_CHR: { // VARCHAR2, NVARCHAR2
247 OciData::__maxDataSize = _buflen; // 4000
248 Field::__dataType = SQL::typeText;
249 break;
250 }
251 case SQLT_AFC: { // CHAR, NCHAR, ANSI Fixed Char
252 OciData::__maxDataSize = _buflen; // 2000
253 Field::__dataType = SQL::typeText;
254 break;
255 }
256 case SQLT_BIN: {
257 OciData::__maxDataSize = _buflen; // 2000
258 Field::__dataType = SQL::typeBinary;
259 break;
260 }
261 case SQLT_LNG: {
262 OciData::__dynamicMode = OCI_DYNAMIC_FETCH;
265 Field::__dataType = SQL::typeLongText;
266 break;
267 }
268 case SQLT_LBI: {
269 OciData::__dynamicMode = OCI_DYNAMIC_FETCH;
272 Field::__dataType = SQL::typeLongBinary;
273 break;
274 }
275 case SQLT_CLOB: {
276 OciData::__descType = OCI_DTYPE_LOB;
278 Field::__dataType = SQL::typeClob;
279 break;
280 }
281 case SQLT_BLOB: {
282 OciData::__descType = OCI_DTYPE_LOB;
284 Field::__dataType = SQL::typeBlob;
285 break;
286 }
287 case SQLT_CFILE: {
288 OciData::__descType = OCI_DTYPE_FILE;
290 Field::__dataType = SQL::typeClob;
291 break;
292 }
293 case SQLT_BFILE: {
294 OciData::__descType = OCI_DTYPE_FILE;
296 Field::__dataType = SQL::typeBlob;
297 break;
298 }
299 default: {
300#ifdef __DCL_DEBUG
301 __DCL_ASSERT(false);
302#else
304 return false;
305#endif
306 }
307 }
308
309#if 0
310 // 이 지점에서 반환하면 Segmentation fault
311 // 이유를 모르겠다!
312 // 위 switch 시작에서 반환하면 문제가 없다.
313 // OCIExecute에서 스택에 흔적을 남겼을까?
314 // 2025-12-27
315 if (_position > 2) {
317 return false;
318 }
319#endif
320
321 OciData::__valuePtr = _buf;
322 OciData::__actualLength = _buflen;
323
325 status = conn()->DescriptorAlloc(
326 (dvoid**)OciData::__valuePtr,
328 );
329 if (status != OCI_SUCCESS) {
331 return false;
332 }
333 }
334
335 OCIDefine* defnp = NULL;
336 if (OciData::__dynamicMode == OCI_DEFAULT) {
337 status = OCIDefineByPos(
338 query()->stmtHandle(), // OCIStmt *stmtp,
339 &defnp, // OCIDefine **defnpp,
340 conn()->errorHandle(), // OCIError *errhp,
341 OciData::__position, // ub4 position,
342 OciData::__valuePtr, // dvoid *valuep,
343 OciData::__valueSize, // sb4 value_sz,
344 OciData::__valueType, // ub2 dty,
345 &(OciData::__indicator), // dvoid *indp,
346 &(OciData::__actualLength), // ub2 *rlenp,
347 &(OciData::__returnCode), // ub2 *rcodep,
348 OciData::__dynamicMode // ub4 mode
349 );
350 }
351 else {
352 // OCI_DYNAMIC_FETCH
353 status = OCIDefineByPos(
354 query()->stmtHandle(), // OCIStmt *stmtp,
355 &defnp, // OCIDefine **defnpp,
356 conn()->errorHandle(), // OCIError *errhp,
357 OciData::__position, // ub4 position,
358 NULL, // dvoid *valuep,
359 OciData::__valueSize, // sb4 value_sz,
360 OciData::__valueType, // ub2 dty,
361 NULL, // dvoid *indp,
362 NULL, // ub2 *rlenp,
363 NULL, // ub2 *rcodep,
364 OciData::__dynamicMode // ub4 mode
365 );
366 if (status == OCI_SUCCESS) {
367 status = OCIDefineDynamic(
368 defnp, // OCIDefine *defnp,
369 conn()->errorHandle(), // OCIError *errhp,
370 this, // dvoid *octxp,
371 defineCallback // OCICallbackDefine(ocbfp)
372 );
373 }
374 }
375 if (status != OCI_SUCCESS) {
376 __SET_ERROR_HANDLE(SQL::eServerError, status, conn()->errorHandle());
377 return false;
378 }
379
380 return true;
381}
382
383const wchar_t* OciField::serverDataTypeName() const
384{
385 return OciData::__TYPE_NAME(__sqlt);
386}
387
388bool OciField::__getDataSize(size_t* _size, bool _maxsize)
389{
390 return OciData::getDataSize(_size, _maxsize);
391}
392
394 void* _buf,
395 size_t* _size,
396 SQL::DataType _bufType
397)
398{
399#if __TRACE_THIS && 0
400 __DCL_TRACE3_N(L"Field::__name[%ls] _bufType[%3d] _size[%zd]\n",
401 Field::__name.data(), _bufType, *_size);
402 bool r = OciData::getData(_buf, _size, _bufType);
403 __DCL_TRACE3_N(L"Field::__name[%ls] _bufType[%3d] _size[%zd]\n",
404 Field::__name.data(), _bufType, *_size);
405 if (_bufType == SQL::typeText) {
406 __DCL_TRACE1_N(L"_buf[%ls]\n",
407 String::tryString((const char*) _buf, *_size).data());
408 }
409 return r;
410#else
411 return OciData::getData(_buf, _size, _bufType);
412#endif
413}
414
416 dvoid* _octxp,
417 OCIDefine* _defnp,
418 ub4 _iter,
419 dvoid** _bufpp,
420 ub4** _alenpp,
421 ub1* _piecep,
422 dvoid** _indpp,
423 ub2** _rcodepp
424)
425{
426 return ((OciField*)_octxp)->defineCallback(
427 _defnp,
428 _iter,
429 _bufpp,
430 _alenpp,
431 _piecep,
432 _indpp,
433 _rcodepp
434 );
435}
436
438 OCIDefine* _defnp,
439 ub4 _iter,
440 dvoid** _bufpp,
441 ub4** _alenpp,
442 ub1* _piecep,
443 dvoid** _indpp,
444 ub2** _rcodepp
445)
446{
447 __DCL_ASSERT(OciData::__dynamicMode == OCI_DYNAMIC_FETCH);
448
449#if defined(__DCL_DEBUG) && 0
450 switch(*_piecep) {
451 case OCI_ONE_PIECE:
452 __DCL_TRACE1_N(L"OCI_ONE_PIECE [%d]\n", __position);
453 break;
454 case OCI_FIRST_PIECE:
455 __DCL_TRACE1_N(L"OCI_FIRST_PIECE [%d]\n", __position);
456 break;
457 case OCI_NEXT_PIECE:
458 __DCL_TRACE1_N(L"OCI_NEXT_PIECE [%d]\n", __position);
459 break;
460 case OCI_LAST_PIECE:
461 __DCL_TRACE1_N(L"OCI_LAST_PIECE [%d]\n", __position);
462 }
463#endif
464
465 if (*_piecep == OCI_ONE_PIECE)
466 *_piecep = OCI_FIRST_PIECE;
467
468 if (*_piecep == OCI_FIRST_PIECE) {
470 OciData::__bytesOutput->reset();
471 }
472 else {
477 return OCI_ERROR;
478 }
479
480 }
482 try {
483 // 이전 PIECE 데이터를 보관한다.
485 }
486 catch(IOException* _cause) {
487 __SET_ERROR_MSG(UTF8Encoder::encode(_cause->toStringAll()));
488 _cause->destroy();
489 return OCI_ERROR;
490 }
491 }
492
493 // OCI_DYNAMIC_FETCH에서 버퍼의 크기는 __actualLength에 보관되어있다.
496 *_bufpp = OciData::__valuePtr;
498 *_indpp = &(OciData::__indicator);
499 *_rcodepp = &(OciData::__returnCode);
500
501 return OCI_CONTINUE;
502}
503
504__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:312
#define INT32_MAX
Definition Config.h:290
wchar_t char_t
Definition Config.h:247
#define UINT32_MAX
Definition Config.h:295
#define __DCL_TRACE1_N(fmt, arg)
#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
#define __SET_ERROR_MSG(_message)
#define __SET_ERROR_HANDLE(_SQLCODE)
IOException *size_t r
Definition MediaInfo.cpp:82
#define __DCL_TRACE5_N(fmt, arg1, arg2, arg3, arg4, arg5)
Definition ODBCQuery.cpp:44
#define __DCL_VERIFY(expr)
Definition Object.h:396
#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 __DYNAMIC_BUFFER_SIZE
Definition OciData.h:11
virtual void destroy()
Definition Exception.cpp:74
String toStringAll() const
Definition Exception.cpp:45
sword DescriptorAlloc(void **_descpp, ub4 _type, size_t _xtramem_sz=0, void **_usrmempp=NULL)
sb2 __indicator
Definition OciData.h:24
ub2 __valueType
Definition OciData.h:22
sb4 __valueSize
Definition OciData.h:21
ub2 __actualLength
Definition OciData.h:25
static const wchar_t * __TYPE_NAME(ub2 _sqlt)
Definition OciData.cpp:924
virtual OciQuery * query() const =0
ub4 __dynamicMode
Definition OciData.h:17
bool getDataSize(size_t *_size, bool _maxsize)
Definition OciData.cpp:169
void * __valuePtr
Definition OciData.h:20
ub4 __position
Definition OciData.h:16
ub2 __returnCode
Definition OciData.h:26
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
OciConnection * conn() const
Definition OciData.h:67
ub4 __descType
Definition OciData.h:19
BytesOutputStream * __bytesOutput
Definition OciData.h:29
static sb4 defineCallback(dvoid *_octxp, OCIDefine *_defnp, ub4 _iter, dvoid **_bufpp, ub4 **_alenpp, ub1 *_piecep, dvoid **_indpp, ub2 **_rcodepp)
Definition OciField.cpp:415
virtual ~OciField()
Definition OciField.cpp:56
bool init(SQL::Query *_query, ub4 _position, ub2 _type, void *_buf, ub2 _buflen)
Definition OciField.cpp:73
virtual bool __getData(void *_buf, size_t *_size, SQL::DataType _bufType)
Definition OciField.cpp:393
virtual const wchar_t * serverDataTypeName() const
Definition OciField.cpp:383
virtual bool __getDataSize(size_t *_size, bool _maxsize)
Definition OciField.cpp:388
String __name
Definition SQLCore.h:187
DataType
Definition SQLCore.h:59
@ typeBinary
Definition SQLCore.h:74
@ typeClob
Definition SQLCore.h:77
@ typeNumeric
Definition SQLCore.h:64
@ typeLongBinary
Definition SQLCore.h:76
@ typeTimeStamp
Definition SQLCore.h:68
@ typeBlob
Definition SQLCore.h:78
@ typeTimeStampTz
Definition SQLCore.h:69
@ typeIntervalDs
Definition SQLCore.h:72
@ typeText
Definition SQLCore.h:73
@ typeFloat
Definition SQLCore.h:63
@ typeIntervalYm
Definition SQLCore.h:71
@ typeLongText
Definition SQLCore.h:75
@ eOutOfMemory
Definition SQLCore.h:24
@ eNotSupportDataType
Definition SQLCore.h:48
@ eServerError
Definition SQLCore.h:21