DCL 3.7.4
Loading...
Searching...
No Matches
ODBCQuery Class Reference

#include <ODBCQuery.h>

Inheritance diagram for ODBCQuery:
SQL::Query Object

Public Member Functions

 ODBCQuery (ODBCConnection *_connection)
virtual ~ODBCQuery ()
virtual void __destroy ()
virtual bool __prepare (const char *_sql, size_t _sqllen, size_t _paramCount)
virtual bool __execute ()
virtual bool __fetch ()
virtual bool __moreResults (bool *_moreResults)
virtual bool __getField (size_t _index, SQL::Field **_fieldHandleOut)
virtual bool __getParam (size_t _index, SQL::Param **_paramHandleOut)
Public Member Functions inherited from Object
virtual String toString () const
virtual void destroy ()
String className () const
bool isInstanceOf (const std::type_info &typeinfo) const
virtual const std::type_info & typeInfo () const

Protected Member Functions

bool reset ()
bool initFields (SQLSMALLINT _columnCount)
bool initParams (size_t _paramCount)
Protected Member Functions inherited from SQL::Query
 Query (Connection *_connHandle)
virtual ~Query ()
Protected Member Functions inherited from Object
virtual ~Object ()
 Object ()

Protected Attributes

SQLHSTMT __hstmt
BIND__paramBINDs
BIND__fieldBINDs
ODBCParam__params
ODBCField__fields
Protected Attributes inherited from SQL::Query
Connection__connHandle
bool __eof
int64_t __affectedRows
size_t __fieldCount
size_t __paramCount
wchar_t __placeholder
unsigned int __states

Additional Inherited Members

Public Types inherited from SQL::Query
enum  State { stStandBy = (unsigned int) 0x0001 , stPrepared = 0x0002 , stExecuted = 0x0004 , stFetched = 0x0008 }

Detailed Description

Definition at line 44 of file ODBCQuery.h.

Constructor & Destructor Documentation

◆ ODBCQuery()

ODBCQuery::ODBCQuery ( ODBCConnection * _connection)

◆ ~ODBCQuery()

ODBCQuery::~ODBCQuery ( )
virtual

Definition at line 78 of file ODBCQuery.cpp.

79{
80#ifdef __DCL_DEBUG
81 if (!reset()) {
82 char buf[256];
83 size_t buflen = sizeof(buf) - 1;
84 bool b = conn()->__getErrorMessage(buf, &buflen);
85 buf[b ? buflen : 0] = '\0';
86 __DCL_TRACE1(L"Warning! Query reset error! %hs\n", buf);
87 }
88#else
89 (void)reset();
90#endif
91}
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:399
bool reset()
Definition ODBCQuery.cpp:98

Member Function Documentation

◆ __destroy()

void ODBCQuery::__destroy ( )
virtual

Implements SQL::Query.

Definition at line 93 of file ODBCQuery.cpp.

94{
95 delete this;
96}

◆ __execute()

bool ODBCQuery::__execute ( )
virtual

Implements SQL::Query.

Definition at line 447 of file ODBCQuery.cpp.

448{
449 // execute 전 매번 bind 한다.
450 for (size_t i = 0; i < Query::__paramCount; i++) {
451 if (!__params[i].onBeforeExecute())
452 return false;
453 }
454
455 SQLRETURN rc = SQLExecute(__hstmt);
456 switch (rc) {
457 case SQL_NO_DATA: {
458 // update, insert, or delete statement that does not affect any rows
459 Query::__affectedRows = 0;
460 return true;
461 }
462 case SQL_NEED_DATA: {
463 __DCL_TRACE0_N(L"SQL_NEED_DATA\n");
464 SQLPOINTER ptr;
465 while ((rc = SQLParamData(__hstmt, &ptr)) == SQL_NEED_DATA) {
466 if (!(((ODBCParam*)ptr)->onNeedData())) {
467 return false;
468 }
469 }
470 __DCL_ASSERT(rc == SQL_SUCCESS);
471 break;
472 }
473 case SQL_SUCCESS: {
474 break;
475 }
476#if 0
477 // SQLState 22001는 SQL_ERROR 이다.
478 case SQL_SUCCESS_WITH_INFO: {
479 // 22001 String data, right truncation
480 bool ignore = true;
481 SQLSMALLINT RecNumber = 0;
482 SQLINTEGER NativeError;
483 SQLCHAR SQLState[SQL_SQLSTATE_SIZE + 1];
484 SQLCHAR ErrorMsg[1024];
485 SQLSMALLINT ErrorMsgLen;
486 while ((rc = SQLGetDiagRecA(
487 SQL_HANDLE_STMT, __hstmt, ++RecNumber, SQLState, &NativeError,
488 ErrorMsg, __countof(ErrorMsg, SQLCHAR), &ErrorMsgLen
489 )) == SQL_SUCCESS) {
490 __DCL_TRACE4_N(L"Param [%2d] [%5hs] [%2d %hs]\n",
491 RecNumber, SQLState, ErrorMsgLen, ErrorMsg);
492 if (memcmp(SQLState, "22001", 5)) {
493 ignore = false;
494 break;
495 }
496 }
497 __DCL_TRACE2_N(L"%d %d\n", rc, RecNumber);
498 __DCL_ASSERT(rc == SQL_NO_DATA);
499 if (ignore) {
500 break;
501 }
502 }
503#endif
504 default: {
505 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
506 return false;
507 }
508 }
509
510 // execute 후 파라미터 값을 nil로 설정한다.
511 for (size_t i = 0; i < Query::__paramCount; i++) {
512 if (!__params[i].onAfterExecute()) {
513 return false;
514 }
515 }
516
517 SQLSMALLINT columnCount = 0;
518 rc = SQLNumResultCols(__hstmt, &columnCount);
519 if (!SQL_SUCCEEDED(rc)) {
520 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
521 return false;
522 }
523 __SET_INFO_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
524
525 // UPDATE, INSERT, DELETE만 eof 이어야 한다.
526 // 필드가 있는 경우, fetch에서 eof를 판별한다.
527 Query::__eof = columnCount == 0;
528 Query::__affectedRows = -1;
529
530 if (columnCount) {
531 // SELECT
532 if (!initFields(columnCount)) {
533 return false;
534 }
535 }
536 else {
537 // MariaDB SELECT에서 rowCount의 값이 있다.
538 // UPDATE, INSERT, DELETE, etc, ...
539 SQLLEN rowCount;
540 rc = SQLRowCount(__hstmt, &rowCount);
541 if (!SQL_SUCCEEDED(rc)) {
542 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
543 return false;
544 }
545 __SET_INFO_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
546 Query::__affectedRows = rowCount;
547 }
548 __DCL_TRACE1_N(L"affectedRows[%zd]\n", Query::__affectedRows);
549
550 return true;
551}
#define __countof(array, type)
Definition Config.h:336
#define __DCL_TRACE1_N(fmt, arg)
#define __DCL_TRACE2_N(fmt, arg1, arg2)
#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
#define __DCL_TRACE0_N(fmt)
#define __SET_ERROR_HANDLE(_SQLCODE)
#define __SET_INFO_HANDLE(_rc, _htype, _handle)
#define __DCL_ASSERT(expr)
Definition Object.h:394
ODBCParam * __params
Definition ODBCQuery.h:57
SQLHSTMT __hstmt
Definition ODBCQuery.h:52
bool initFields(SQLSMALLINT _columnCount)

◆ __fetch()

bool ODBCQuery::__fetch ( )
virtual

Implements SQL::Query.

Definition at line 553 of file ODBCQuery.cpp.

554{
555 __DCL_ASSERT(!Query::__eof);
556 SQLRETURN rc = SQLFetch(__hstmt);
557
558 // SQLFetch의 결과를 확인하기 앞서,
559 // bind.size == 0 또는 > 12000 인 경우에 대하여
560 // SQLGetData 호출 상태를 리셋한다.
561 for (size_t i = 0; i < Query::__fieldCount; i++) {
562 BIND& bind = __fieldBINDs[i];
563 if (bind.valuePtr == NULL) {
564 bind.valueMax = 0;
565 }
566 }
567
568 switch (rc) {
569 case SQL_NO_DATA: {
570 Query::__eof = true;
571 return true;
572 }
573 case SQL_SUCCESS_WITH_INFO: {
574 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
575 /*
576 * SQLSTATE
577 * 01000 일반 경고
578 * 01004 문자열 데이터, 오른쪽 잘림
579 * 01S07 분수 잘림
580 */
581 }
582 case SQL_SUCCESS: {
583 return true;
584 }
585 default: {
586 ;
587 }
588 }
589
590 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
591 return false;
592}
#define NULL
Definition Config.h:312
struct __BIND BIND
BIND * __fieldBINDs
Definition ODBCQuery.h:55
SQLLEN valueMax
Definition ODBCQuery.h:37
SQLPOINTER valuePtr
Definition ODBCQuery.h:36

◆ __getField()

bool ODBCQuery::__getField ( size_t _index,
SQL::Field ** _fieldHandleOut )
virtual

Implements SQL::Query.

Definition at line 662 of file ODBCQuery.cpp.

663{
664 __DCL_ASSERT(Query::__fieldCount > 0);
665 __DCL_ASSERT((0 <= _index) && (_index < Query::__fieldCount));
666 *_fieldHandleOut = &__fields[_index];
667 return true;
668}
ODBCField * __fields
Definition ODBCQuery.h:58

◆ __getParam()

bool ODBCQuery::__getParam ( size_t _index,
SQL::Param ** _paramHandleOut )
virtual

Implements SQL::Query.

Definition at line 670 of file ODBCQuery.cpp.

671{
672 __DCL_ASSERT(Query::__paramCount > 0);
673 __DCL_ASSERT((0 <= _index) && (_index < Query::__paramCount));
674 *_paramHandleOut = &__params[_index];
675 return true;
676}

◆ __moreResults()

bool ODBCQuery::__moreResults ( bool * _moreResults)
virtual

Reimplemented from SQL::Query.

Definition at line 594 of file ODBCQuery.cpp.

595{
596 if (__fields) {
597 __DCL_ASSERT(Query::__fieldCount > 0);
598 delete[] __fields;
599 __fields = NULL;
600 Query::__fieldCount = 0;
601 }
602
603 if (__fieldBINDs) {
604 free(__fieldBINDs);
606 }
607
608 SQLRETURN rc = SQLMoreResults(__hstmt);
609 switch (rc) {
610 case SQL_NO_DATA: {
611 Query::__affectedRows = (size_t)-1;
612 Query::__eof = true;
613 *_moreResults = false;
614 return true;
615 }
616 case SQL_SUCCESS: {
617 *_moreResults = true;
618 break;
619 }
620 default: {
621 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
622 return false;
623 }
624 }
625
626 SQLSMALLINT columnCount = 0;
627 rc = SQLNumResultCols(__hstmt, &columnCount);
628 if (!SQL_SUCCEEDED(rc)) {
629 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
630 return false;
631 }
632 __SET_INFO_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
633
634 // UPDATE, INSERT, DELETE만 eof 이어야 한다.
635 // 필드가 있는 경우, fetch에서 eof를 판별한다.
636 Query::__eof = columnCount == 0;
637 Query::__affectedRows = -1;
638
639 if (columnCount) {
640 // SELECT
641 if (!initFields(columnCount)) {
642 return false;
643 }
644 }
645 else {
646 // MariaDB SELECT에서 rowCount의 값이 있다.
647 // UPDATE, INSERT, DELETE, etc, ...
648 SQLLEN rowCount;
649 rc = SQLRowCount(__hstmt, &rowCount);
650 if (!SQL_SUCCEEDED(rc)) {
651 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
652 return false;
653 }
654 __SET_INFO_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
655 Query::__affectedRows = rowCount;
656 }
657 __DCL_TRACE1_N(L"affectedRows[%zd]\n", Query::__affectedRows);
658
659 return true;
660}

◆ __prepare()

bool ODBCQuery::__prepare ( const char * _sql,
size_t _sqllen,
size_t _paramCount )
virtual

Implements SQL::Query.

Definition at line 414 of file ODBCQuery.cpp.

418{
419 if (!reset()) {
420 return false;
421 }
422
424 __DCL_ASSERT(_sqllen <= INT32_MAX);
425
426 SQLRETURN rc = SQLAllocHandle(SQL_HANDLE_STMT, conn()->connHandle(), &__hstmt);
427 if (rc != SQL_SUCCESS) {
428 __SET_ERROR_HANDLE(rc, SQL_HANDLE_DBC, conn()->connHandle());
429 return false;
430 }
431
432 rc = SQLPrepareA(__hstmt, (SQLCHAR*) _sql, (SQLINTEGER) _sqllen);
433 if (!SQL_SUCCEEDED(rc)) {
434 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
435 return false;
436 }
437 __SET_INFO_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
438
439 if (_paramCount > 0) {
440 if (!initParams(_paramCount))
441 return false;
442 }
443
444 return true;
445}
#define INT32_MAX
Definition Config.h:290
bool initParams(size_t _paramCount)

◆ initFields()

bool ODBCQuery::initFields ( SQLSMALLINT _columnCount)
protected

Definition at line 288 of file ODBCQuery.cpp.

289{
291 && (_columnCount > 0)
292 && (Query::__fieldCount == 0)
293 && (__fields == NULL)
294 && (__fieldBINDs == NULL)
295 );
296
297 StringArray names;
298 size_t alloc = sizeof(BIND) * _columnCount;
299 __DCL_TRACE1_N(L"fieldBINDs alloc [%zd]\n", alloc);
300 __fieldBINDs = (BIND*)malloc(alloc);
301 if (!__fieldBINDs) {
303 return false;
304 }
305 memset(__fieldBINDs, 0, alloc);
306
307 BIND* bind = __fieldBINDs;
308 for (SQLSMALLINT i = 0; i < _columnCount; i++, bind++) {
309 bind->number = i + 1;
310 SQLCHAR _name[256];
311 SQLCHAR* name = _name;
312 SQLSMALLINT length = sizeof(_name);
313 SQLRETURN rc = SQLDescribeColA(__hstmt, bind->number,
314 name, length, &length,
315 &(bind->type), &(bind->size), &(bind->scale), &(bind->nullable));
316 if (rc == SQL_SUCCESS_WITH_INFO) {
317 name = (SQLCHAR*)alloca(++length);
318 rc = SQLDescribeColA(__hstmt, bind->number, name, length, &length,
319 &(bind->type), &(bind->size), &(bind->scale), &(bind->nullable));
320 }
321 if (rc != SQL_SUCCESS) {
322 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
323 return false;
324 }
325 SQLLEN numAttr = 0;
326 rc = SQLColAttributeA(__hstmt, bind->number,
327 SQL_DESC_PRECISION, NULL, 0, NULL, &numAttr);
328 if (rc != SQL_SUCCESS) {
329 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
330 return false;
331 }
332 bind->precision = (SQLSMALLINT)numAttr;
333
334 __DCL_TRACE6_N(L"Field [%2d] size [%10d %4d,%4d] type [%4d %hs]\n",
335 bind->number,
336 bind->size, bind->precision, bind->scale,
337 bind->type, name
338 );
339
340 try {
341 names.add(UTF8Decoder::decode((const char*)name, length).toUpperCase());
342 }
343 catch (CharsetConvertException* _e) {
344 __SET_ERROR_MSG(UTF8Encoder::encode(_e->toStringAll()));
345 _e->destroy();
346 return false;
347 }
348
350 }
351
352 // __fieldBINDs에 적용할, 레코드 버퍼 크기를 계산한다.
353 size_t offset = 0;
354 bind = __fieldBINDs;
355 for (SQLSMALLINT i = 0; i < _columnCount; i++, bind++) {
356 offset = ODBCData::__TYPE_ALIGN(offset, bind->type);
357 // 다음에서 bind.size == 0 또는 > 12000 인 경우에 valueMax는 0이다.
358 // 이것은 SQLFetch가 아닌 SQLGetData를 사용하여 필드값을 얻는다.
359 bind->valueMax = ODBCData::__TYPE_SIZE(bind->type, bind->size);
360 __DCL_TRACE5_N(L"Field [%2d] offset [%10zd %5d ] type [%4d %ls]\n",
361 bind->number, offset, bind->valueMax, bind->type, names[i].data());
362 offset += bind->valueMax;
363 }
364
365 __DCL_TRACE1_N(L"fieldsBuffer size [%zd]\n", offset);
366 // 모든 필드의 __TYPE_SIZE(field) == 0 인 경우가 있을 수 있다.
367 // 모든 필드가 12000 바이트를 초과하는 VARCHAR, VARBINARY, TEXT, BLOB이면
368 // offset의 값이 0이다.
369 if (offset > 0) {
370 __fieldBINDs = (BIND*)realloc(__fieldBINDs, alloc + offset);
371 if (__fieldBINDs == NULL) {
373 return false;
374 }
375 }
376
377 char* buffer = (char*)(__fieldBINDs + _columnCount);
378 __DCL_TRACE2_N(L"__fieldBINDs[%p] buffer[%p]\n", __fieldBINDs, buffer);
379 offset = 0;
380 bind = __fieldBINDs;
381 for (SQLSMALLINT i = 0; i < _columnCount; i++, bind++) {
382 offset = ODBCData::__TYPE_ALIGN(offset, bind->type);
383 if (bind->valueMax) {
384 // SQLBindCol 바인드 대상만 버퍼를 할당한다.
385 // valueMax가 0인 경우는 SQLGetData로 데이터의 실제 크기를 알아낸다.
386 bind->valuePtr = buffer + offset;
387 offset += bind->valueMax;
388
389 SQLRETURN rc = SQLBindCol(__hstmt, bind->number, bind->valueType,
390 bind->valuePtr, bind->valueMax, &bind->lenORind);
391 if (rc != SQL_SUCCESS) {
392 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
393 return false;
394 }
395 }
396 }
397
398 Query::__fieldCount = _columnCount;
399 __fields = new ODBCField[Query::__fieldCount];
400 if (!__fields) {
402 return false;
403 }
404
405 bind = __fieldBINDs;
406 for (size_t i = 0; i < Query::__fieldCount; i++, bind++) {
407 if (!__fields[i].init(this, bind, names[i]))
408 return false;
409 }
410
411 return true;
412}
#define __SET_ERROR_MSG(_message)
#define __DCL_TRACE6_N(fmt, arg1, arg2, arg3, arg4, arg5, arg6)
Definition ODBCQuery.cpp:45
#define __DCL_TRACE5_N(fmt, arg1, arg2, arg3, arg4, arg5)
Definition ODBCQuery.cpp:44
#define __SET_ERROR(_errorCode)
Definition SQLCore.cpp:149
virtual void destroy()
Definition Exception.cpp:74
String toStringAll() const
Definition Exception.cpp:45
static SQLULEN __TYPE_SIZE(SQLSMALLINT _type, SQLULEN _size)
Definition ODBCData.cpp:261
static SQLSMALLINT __VALUE_TYPE(SQLSMALLINT _type)
Definition ODBCData.cpp:401
static size_t __TYPE_ALIGN(size_t _offset, SQLSMALLINT _type)
Definition ODBCData.cpp:350
@ eOutOfMemory
Definition SQLCore.h:24
SQLUSMALLINT number
Definition ODBCQuery.h:27
SQLSMALLINT nullable
Definition ODBCQuery.h:33
SQLLEN lenORind
Definition ODBCQuery.h:38
SQLSMALLINT type
Definition ODBCQuery.h:29
SQLULEN size
Definition ODBCQuery.h:30
SQLSMALLINT scale
Definition ODBCQuery.h:32
SQLSMALLINT valueType
Definition ODBCQuery.h:35
SQLSMALLINT precision
Definition ODBCQuery.h:31

◆ initParams()

bool ODBCQuery::initParams ( size_t _paramCount)
protected

Definition at line 143 of file ODBCQuery.cpp.

144{
146 && (_paramCount > 0)
147 && (Query::__paramCount == 0)
148 && (__params == NULL)
149 && (__paramBINDs == NULL)
150 );
151
152 SQLSMALLINT paramCount = 0;
153 SQLRETURN rc = SQLNumParams(__hstmt, &paramCount);
154 __DCL_ASSERT((size_t)paramCount == _paramCount);
155
156 size_t alloc = sizeof(BIND) * paramCount;
157 __DCL_TRACE1_N(L"paramBINDs alloc [%zd]\n", alloc);
158 __paramBINDs = (BIND*)malloc(alloc);
159 if (!__paramBINDs) {
161 return false;
162 }
163 memset(__paramBINDs, 0, alloc);
164
165 SQLHDESC hdesc = NULL;
166 SQLINTEGER len = sizeof(hdesc);
167 rc = SQLGetStmtAttr(__hstmt, SQL_ATTR_IMP_PARAM_DESC, &hdesc, len, &len);
168 if (rc != SQL_SUCCESS) {
169 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
170 return false;
171 }
172
173 BIND* bind = __paramBINDs;
174 for (SQLSMALLINT i = 0; i < paramCount; i++, bind++) {
175 bind->number = i + 1;
176#if 0
177 SQLCHAR name[1];
178 SQLSMALLINT namelen = sizeof(name);
179 SQLSMALLINT subtype;
180 rc = SQLGetDescRecA(hdesc, bind->number, name, namelen, &namelen,
181 &(bind->type), &subtype, (SQLLEN*)&(bind->size),
182 &(bind->precision), &(bind->scale), &(bind->nullable));
183 if (rc != SQL_SUCCESS) {
184 // SQLDescribeParam호출 없이 SQLGetDescRecA가 호출되면
185 // SQL_NO_DATA
186 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
187 return false;
188 }
189#else
190 rc = SQLDescribeParam(__hstmt, bind->number,
191 &(bind->type), &(bind->size), &(bind->scale), &(bind->nullable));
192 if (rc != SQL_SUCCESS) {
193 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
194 return false;
195 }
196 SQLULEN numAttr = 0;
197 rc = SQLGetDescFieldA(hdesc, bind->number, SQL_DESC_PRECISION, &numAttr, 0, NULL);
198 if (rc != SQL_SUCCESS) {
199 __SET_ERROR_HANDLE(rc, SQL_HANDLE_STMT, __hstmt);
200 return false;
201 }
202 bind->precision = (SQLSMALLINT)numAttr;
203#endif
204 __DCL_TRACE6_N(L"Param [%2d] size [%10d %4d,%4d] type [%4d %ls]\n",
205 bind->number,
206 bind->size, bind->precision, bind->scale,
207 bind->type, ODBCData::__TYPE_NAME(bind->type)
208 );
209
210#if __USE_SS_PARAM_FIX
211 switch (bind->type) {
212 case SQL_SS_TIME2: {
213 bind->type = SQL_TYPE_TIME;
214 break;
215 }
216 case SQL_SS_TIMESTAMPOFFSET: {
217 bind->type = SQL_TYPE_TIMESTAMP;
218 }
219 }
220#endif
221 // 파라미터가 NULL인 경우에도 valueType은 SQL_UNKNOWN이 될 수 없다.
222 // See. ODBCParam::setNull
223 bind->valueType = SQL_C_DEFAULT;
224 bind->lenORind = SQL_NULL_DATA;
225 }
226
227#define __TYPE_PARAM_SIZE(_type, _size) \
228 __MAX(ODBCData::__TYPE_SIZE(_type, _size), sizeof(PARAM_BUFFER_MINIMAL))
229#define __TYPE_PARAM_ALIGN(_offset) \
230 ((_offset + sizeof(long) - 1) & ~(sizeof(long) - 1))
231
232 // __paramBINDs에 적용할, 레코드 버퍼 크기를 계산한다.
233 size_t offset = 0;
234 bind = __paramBINDs;
235 for (SQLSMALLINT i = 0; i < paramCount; i++, bind++) {
236 offset = __TYPE_PARAM_ALIGN(offset);
237 // 다음에서 bind.size == 0 또는 > 12000 인 경우에 valueMax는 0이다.
238 // 이것은 SQLExecute가 아닌 SQLGetData를 사용하여 필드값을 얻는다.
239 bind->valueMax = __TYPE_PARAM_SIZE(bind->type, bind->size);
240 __DCL_TRACE5_N(L"Param [%2d] offset [%10zd %5d ] type [%4d %ls]\n",
241 bind->number, offset, bind->valueMax, bind->type, ODBCData::__TYPE_NAME(bind->type));
242 offset += bind->valueMax;
243 }
244
245 __DCL_TRACE1_N(L"paramBuffer size [%zd]\n", offset);
246 // 모든 필드의 __TYPE_SIZEM(field) == 0 인 경우가 있을 수 있다.
247 // 모든 필드가 12000 바이트를 초과하는 VARCHAR, VARBINARY, TEXT, BLOB이면
248 // offset의 값이 0이다.
249 // 파라미터의 최소 버퍼 크기는 sizeof(PARAM_BUFFER_MINIMAL) 이다.
250 if (offset > 0) {
251 __paramBINDs = (BIND*)realloc(__paramBINDs, alloc + offset);
252 if (__paramBINDs == NULL) {
254 return false;
255 }
256 }
257
258 char* buffer = (char*)(__paramBINDs + paramCount);
259 __DCL_TRACE2_N(L"__paramBINDs[%p] buffer[%p]\n", __paramBINDs, buffer);
260 offset = 0;
261 bind = __paramBINDs;
262 for (SQLSMALLINT i = 0; i < paramCount; i++, bind++) {
263 offset = __TYPE_PARAM_ALIGN(offset);
264 if (bind->valueMax) {
265 // SQLBindCol 바인드 대상만 버퍼를 할당한다.
266 // valueMax가 0인 경우는 SQLGetData로 데이터의 실제 크기를 알아낸다.
267 bind->valuePtr = buffer + offset;
268 offset += bind->valueMax;
269 }
270 }
271
272 Query::__paramCount = paramCount;
273 __params = new ODBCParam[Query::__paramCount];
274 if (__params == NULL) {
276 return false;
277 }
278
279 bind = __paramBINDs;
280 for(size_t i = 0; i < Query::__paramCount; i++, bind++) {
281 if (!__params[i].init(this, bind))
282 return false;
283 }
284
285 return true;
286}
#define __TYPE_PARAM_ALIGN(_offset)
#define __TYPE_PARAM_SIZE(_type, _size)
static const wchar_t * __TYPE_NAME(SQLSMALLINT _type)
Definition ODBCData.cpp:190
BIND * __paramBINDs
Definition ODBCQuery.h:54

◆ reset()

bool ODBCQuery::reset ( )
protected

Definition at line 98 of file ODBCQuery.cpp.

99{
100 Query::__eof = true;
101 Query::__affectedRows = -1;
102
103 if (__fields) {
104 __DCL_ASSERT(Query::__fieldCount > 0);
105 delete[] __fields;
106 __fields = NULL;
107 Query::__fieldCount = 0;
108 }
109
110 if (__params) {
111 __DCL_ASSERT(Query::__paramCount > 0);
112 delete[] __params;
113 __params = NULL;
114 Query::__paramCount = 0;
115 }
116
117 if (__fieldBINDs) {
118 free(__fieldBINDs);
120 }
121
122 if (__paramBINDs) {
123 free(__paramBINDs);
125 }
126
127 bool r = true;
128 if (__hstmt) {
129 SQLRETURN rc_ = SQLFreeStmt(__hstmt, SQL_CLOSE);
130 if (rc_ != SQL_SUCCESS) {
131 __DCL_TRACE1_N(L"SQLFreeStmt(STMT) Fail! [%d]\n", rc_);
132 }
133 rc_ = SQLFreeHandle(SQL_HANDLE_STMT, __hstmt);
134 if (rc_ != SQL_SUCCESS) {
135 __DCL_TRACE1_N(L"SQLFreeHandle(STMT) Fail! [%d]\n", rc_);
136 }
137 __hstmt = NULL;
138 }
139
140 return r;
141}
IOException *size_t r
Definition MediaInfo.cpp:82

Member Data Documentation

◆ __fieldBINDs

BIND* ODBCQuery::__fieldBINDs
protected

Definition at line 55 of file ODBCQuery.h.

◆ __fields

ODBCField* ODBCQuery::__fields
protected

Definition at line 58 of file ODBCQuery.h.

◆ __hstmt

SQLHSTMT ODBCQuery::__hstmt
protected

Definition at line 52 of file ODBCQuery.h.

◆ __paramBINDs

BIND* ODBCQuery::__paramBINDs
protected

Definition at line 54 of file ODBCQuery.h.

◆ __params

ODBCParam* ODBCQuery::__params
protected

Definition at line 57 of file ODBCQuery.h.


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