DCL 4.0
Loading...
Searching...
No Matches
MyQuery Class Reference

#include <MyQuery.h>

Inheritance diagram for MyQuery:
SQL::Query Object

Public Member Functions

 MyQuery (MyConnection *pConnection)
virtual ~MyQuery ()
virtual void __destroy ()
virtual bool __prepare (const char *_sql, size_t _sqllen, size_t _paramCount)
virtual bool __execute ()
virtual bool __fetch ()
virtual bool __nextResult ()
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 ()
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

MYSQL_STMT * __stmt
MYSQL_BIND * __inBINDs
MYSQL_BIND * __outBINDs
void * __outBuffer
MyParam__params
MyField__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 = 0x0001 , stPrepared = 0x0002 , stExecuted = 0x0004 , stFetched = 0x0008 }

Detailed Description

Definition at line 9 of file MyQuery.h.

Constructor & Destructor Documentation

◆ MyQuery()

MyQuery::MyQuery ( MyConnection * pConnection)

◆ ~MyQuery()

MyQuery::~MyQuery ( )
virtual

Definition at line 55 of file MyQuery.cpp.

56{
57#ifdef __DCL_DEBUG
58 if (!reset()) {
59 ByteString s;
60 size_t n = 512;
61 ByteBuffer* buf = ByteBuffer::create(n);
62 bool b = conn()->__getErrorMessage(buf->data(), &n);
63 if (b) {
64 buf->__dataLength = n;
65 s = buf;
66 }
67 buf->release();
68
69 if (b) {
70 __DCL_TRACE1_N(__T("Warning! %s\n"), s.data());
71 }
72 else {
73 __DCL_TRACE0_N(__T("Warning! Query reset error\n"));
74 }
75 }
76#else
77 (void)reset();
78#endif
79}
#define __DCL_TRACE1_N(fmt, arg)
#define __DCL_TRACE0_N(fmt)
Definition IFXField.cpp:37
#define __T(str)
Definition Object.h:44
ByteBuffer * buf
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
bool reset()
Definition MyQuery.cpp:86

Member Function Documentation

◆ __destroy()

void MyQuery::__destroy ( )
virtual

Implements SQL::Query.

Definition at line 81 of file MyQuery.cpp.

82{
83 delete this;
84}

◆ __execute()

bool MyQuery::__execute ( )
virtual

Implements SQL::Query.

Definition at line 381 of file MyQuery.cpp.

382{
383 __DCL_ASSERT(__stmt->param_count == Query::__paramCount);
384 // char*, byte_t*인 경우 데이터의 복사본을 유지하지 않는다.
385 // execute 전 매번 bind 한다.
386 if (Query::__paramCount) {
388 if (mysql_stmt_bind_param(__stmt, __inBINDs)) {
389 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
390 mysql_stmt_errno(__stmt),
391 mysql_stmt_error(__stmt)));
392 return false;
393 }
394 }
395
396 // 파라미터 값이 InputStream인 경우 mysql_stmt_send_long_data
397 for (size_t i = 0; i < Query::__paramCount; i++) {
398 if (!__params[i].onBeforeExecute()) {
399 return false;
400 }
401 }
402
403 if (mysql_stmt_execute(__stmt)) {
404 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
405 mysql_stmt_errno(__stmt),
406 mysql_stmt_error(__stmt)));
407 return false;
408 }
409
410 // UPDATE, INSERT, DELETE, etc, ...
411 Query::__affectedRows = mysql_stmt_affected_rows(__stmt);
412 __DCL_TRACE1_N(L"affectedRows[%lld]\n", Query::__affectedRows);
413
414 // execute 후 파라미터 값을 nil로 설정한다.
415 for (size_t i = 0; i < Query::__paramCount; i++) {
416 __params[i].onAfterExecute();
417 }
418
419#if __TRACE_THIS && 1
420 __DCL_TRACE2_N(L"state[%d] result.data[%p]\n",
421 __stmt->state, __stmt->result.data);
422 __DCL_TRACE2_N(L"fields[%u][%p]\n",
423 __stmt->field_count, __stmt->fields);
424 for (unsigned int i = 0; i < __stmt->field_count; i++) {
425 MYSQL_FIELD* e = &(__stmt->fields[i]);
426 __DCL_TRACE4_N(L"field %02u [%14hs][%10u][%16ls]\n",
427 i, e->name, e->length, __dataTypeName(e->type, e->flags));
428 }
429 if (conn()->connHandle()->server_status & SERVER_PS_OUT_PARAMS) {
430 __DCL_TRACE1_N(L"OUT/INOUT parameter [%u]\n", __stmt->field_count);
431 }
432#endif
433
434 // UPDATE, INSERT, DELETE만 eof 이어야 한다.
435 // 필드가 있는 경우, fetch에서 eof를 판별한다.
436 Query::__eof = __stmt->field_count == 0;
437
438 if (__stmt->field_count) {
439 if (!initFields()) {
440 return false;
441 }
442 if (conn()->storeResult()) {
443 __DCL_TRACE0_N(L"mysql_stmt_store_result\n");
444 if (mysql_stmt_store_result(__stmt)) {
445 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
446 mysql_stmt_errno(__stmt),
447 mysql_stmt_error(__stmt)));
448 return false;
449 }
450 }
451 }
452
453 return true;
454}
#define __DCL_TRACE2_N(fmt, arg1, arg2)
#define __SET_ERROR_MSG(_message)
#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
Definition IFXField.cpp:41
const wchar_t * __dataTypeName(const ifx_sqlvar_t *_sqlvar)
Definition IFXField.cpp:290
#define __DCL_ASSERT(expr)
Definition Object.h:371
MYSQL_BIND * __inBINDs
Definition MyQuery.h:23
MyParam * __params
Definition MyQuery.h:27
MYSQL_STMT * __stmt
Definition MyQuery.h:22
bool initFields()
Definition MyQuery.cpp:222

◆ __fetch()

bool MyQuery::__fetch ( )
virtual

Implements SQL::Query.

Definition at line 456 of file MyQuery.cpp.

457{
458 __DCL_ASSERT(!Query::__eof);
459 int r = mysql_stmt_fetch(__stmt);
460 switch (r) {
461 case MYSQL_NO_DATA: {
462 // Success, no more data exists.
463 Query::__eof = true;
464 return true;
465 }
466 case MYSQL_DATA_TRUNCATED: {
467 // BLOB, MEDIUM_BLOB, LONG_BLOB은 mysql_stmt_fetch_column을 사용한다.
468 // 이 셋의 MYSQL_FIELD.length의 값은 0이다.
469 // Data truncation occurred.
470 // Check the error members of the MYSQL_BIND
471 __DCL_TRACE0_N(L"Warning!! MYSQL_DATA_TRUNCATED\n");
472
473#if __TRACE_THIS && 1
474 for (unsigned int i = 0; i < __stmt->field_count; i++) {
475 MYSQL_BIND& b = __stmt->bind[i];
476 __DCL_TRACE2(L"field[%u] [%u]\n", i, b.error ? *b.error : 0);
477 }
478#endif
479 }
480 case 0: {
481 // Success, the dta has been fetched to application data buffers.
482 return true;
483 }
484 case 1 :
485 // Error occurred. Error code and message can be obtained by calling
486 // mysql_stmt_errno() and mysql_stmt_error().
487 default:
488 ;
489 }
490
491 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
492 mysql_stmt_errno(__stmt),
493 mysql_stmt_error(__stmt)));
494 return false;
495}
#define __DCL_TRACE2(fmt, arg1, arg2)
Definition Object.h:377
ByteString r

◆ __getField()

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

Implements SQL::Query.

Definition at line 570 of file MyQuery.cpp.

571{
572 __DCL_ASSERT(Query::__fieldCount > 0);
573 __DCL_ASSERT((0 <= _index) && (_index < Query::__fieldCount));
574 *_fieldHandleOut = &__fields[_index];
575 return true;
576}
MyField * __fields
Definition MyQuery.h:28

◆ __getParam()

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

Implements SQL::Query.

Definition at line 578 of file MyQuery.cpp.

579{
580 __DCL_ASSERT(Query::__paramCount > 0);
581 __DCL_ASSERT((0 <= _index) && (_index < Query::__paramCount));
582 *_paramHandleOut = &__params[_index];
583 return true;
584}

◆ __nextResult()

bool MyQuery::__nextResult ( )
virtual

Reimplemented from SQL::Query.

Definition at line 497 of file MyQuery.cpp.

498{
499 if (__fields) {
500 __DCL_ASSERT(Query::__fieldCount > 0);
501 delete[] __fields;
502 __fields = NULL;
503 Query::__fieldCount = 0;
504 }
505
506 if (__outBuffer) {
507 free(__outBuffer);
509 }
510
511 if (__outBINDs) {
512 free(__outBINDs);
514 }
515
516 __DCL_TRACE2_N(L"state[%d] result.data[%p]\n",
517 __stmt->state, __stmt->result.data);
518 if (__stmt->state >= MYSQL_STMT_USE_OR_STORE_CALLED) {
519 if (mysql_stmt_free_result(__stmt)) {
520 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
521 mysql_stmt_errno(__stmt),
522 mysql_stmt_error(__stmt)));
523 return false;
524 }
525 }
526
527 int r = mysql_stmt_next_result(__stmt);
528 if (r > 0) {
529 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
530 mysql_stmt_errno(__stmt),
531 mysql_stmt_error(__stmt)));
532 return false;
533 }
534#if __TRACE_THIS && 1
535 __DCL_TRACE2_N(L"state[%d] result.data[%p]\n",
536 __stmt->state, __stmt->result.data);
537 __DCL_TRACE3_N(L"next_[%d] fields[%u][%p]\n",
538 r, __stmt->field_count, __stmt->fields);
539 for (unsigned int i = 0; i < __stmt->field_count; i++) {
540 MYSQL_FIELD* e = &(__stmt->fields[i]);
541 __DCL_TRACE4_N(L"field %02u [%14hs][%10u][%16ls]\n",
542 i, e->name, e->length, __dataTypeName(e->type, e->flags));
543 }
544 if (conn()->connHandle()->server_status & SERVER_PS_OUT_PARAMS) {
545 __DCL_TRACE1_N(L"OUT/INOUT parameter [%u]\n", __stmt->field_count);
546 }
547#endif
548
549 // 필드가 있는 경우, fetch에서 eof를 판별한다.
550 Query::__eof = __stmt->field_count == 0;
551
552 if (__stmt->field_count) {
553 if (!initFields()) {
554 return false;
555 }
556 if (conn()->storeResult()) {
557 __DCL_TRACE0_N(L"mysql_stmt_store_result\n");
558 if (mysql_stmt_store_result(__stmt)) {
559 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
560 mysql_stmt_errno(__stmt),
561 mysql_stmt_error(__stmt)));
562 return false;
563 }
564 }
565 }
566
567 return true;
568}
#define NULL
Definition Config.h:340
#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
void * __outBuffer
Definition MyQuery.h:25
MYSQL_BIND * __outBINDs
Definition MyQuery.h:24

◆ __prepare()

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

Implements SQL::Query.

Definition at line 336 of file MyQuery.cpp.

338{
339 if(!reset())
340 return false;
341
342 if ((__stmt = mysql_stmt_init(conn()->connHandle())) == NULL) {
344 return false;
345 }
346
347 int r = mysql_stmt_prepare(__stmt, _sql, (unsigned long)_sqllen);
348 if (r) {
349 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
350 mysql_stmt_errno(__stmt),
351 mysql_stmt_error(__stmt)));
352 return false;
353 }
354
355#if __TRACE_THIS && 1
356 __DCL_TRACE2_N(L"state[%d] result.data[%p]\n",
357 __stmt->state, __stmt->result.data);
358 __DCL_TRACE4_N(L"params[%u][%p] fields[%u][%p]\n",
359 __stmt->param_count, __stmt->params,
360 __stmt->field_count, __stmt->fields);
361 for (unsigned int i = 0; i < __stmt->param_count; i++) {
362 MYSQL_BIND* e = &(__stmt->params[i]);
363 __DCL_TRACE4_N(L"param %02u buf[%p][%5u][%16ls]\n",
364 i, e->buffer, e->buffer_length, __dataTypeName(e->buffer_type, e->flags));
365 }
366 for (unsigned int i = 0; i < __stmt->field_count; i++) {
367 MYSQL_FIELD* e = &(__stmt->fields[i]);
368 __DCL_TRACE4_N(L"field %02u [%14hs][%10u][%16ls]\n",
369 i, e->name, e->length, __dataTypeName(e->type, e->flags));
370 }
371#endif
372
373 if (_paramCount > 0) {
374 if (!initParams(_paramCount))
375 return false;
376 }
377
378 return true;
379}
#define __SET_ERROR(_errorCode)
Definition SQLCore.cpp:150
bool initParams(size_t _paramCount)
Definition MyQuery.cpp:303
@ eOutOfMemory
Definition SQLCore.h:24

◆ initFields()

bool MyQuery::initFields ( )
protected

Definition at line 222 of file MyQuery.cpp.

223{
224 __DCL_ASSERT((Query::__fieldCount == 0)
225 && (__fields == NULL)
226 && (__outBINDs == NULL)
227 && (__outBuffer == NULL)
228 && (__stmt != NULL)
229 && (__stmt->field_count > 0)
230 );
231
232 Query::__fieldCount = __stmt->field_count;
233 size_t alloc = sizeof(MYSQL_BIND) * Query::__fieldCount;
234 __outBINDs = (MYSQL_BIND*)malloc(alloc);
235 if (!__outBINDs) {
237 return false;
238 }
239 memset(__outBINDs, 0, alloc);
240
241 // __fields를 위한 버퍼를 할당한다.
242 size_t offset = 0;
243 for (size_t i = 0; i < Query::__fieldCount; i++) {
244 MYSQL_FIELD& field = __stmt->fields[i];
245 offset = __TYPE_ALIGN(offset, field);
246 __DCL_TRACE3_N(L"offset [%4zd][%4zd] [%hs]\n",
247 offset, __TYPE_SIZE(field), field.name);
248 offset += __TYPE_SIZE(field);
249 }
250
251 __DCL_TRACE1_N(L"alloc [%zd]\n", offset);
252 // 모든 필드의 __TYPE_SIZE(field) == 0인 경우가 있을 수 있다.
253 // 모든 필드가 3000바이트 이상인 VARCHAR, VARBINARY, TEXT, BLOB이면
254 // offset의 값이 0이다.
255 if (offset > 0) {
256 __outBuffer = malloc(offset);
257 __DCL_ASSERT((size_t)__outBuffer % sizeof(void*) == 0);
258 if (__outBuffer == NULL) {
260 return false;
261 }
262 }
263
264 offset = 0;
265 for (size_t i = 0; i < Query::__fieldCount; i++) {
266 MYSQL_FIELD& field = __stmt->fields[i];
267 MYSQL_BIND& bind = __outBINDs[i];
268
269 offset = __TYPE_ALIGN(offset, field);
270 bind.buffer_length = __TYPE_SIZE(field);
271 bind.buffer_type = field.type;
272 bind.buffer = (char*)__outBuffer + offset;
273 offset += bind.buffer_length;
274
275 bind.length = &bind.length_value;
276 bind.is_null = &bind.is_null_value;
277 bind.error = &bind.error_value;
278 }
279
280 if (mysql_stmt_bind_result(__stmt, __outBINDs)) {
281 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
282 mysql_stmt_errno(__stmt),
283 mysql_stmt_error(__stmt)));
284 return false;
285 }
286
287 __fields = new MyField[Query::__fieldCount];
288 if (!__fields) {
290 return false;
291 }
292
293 for(unsigned int i = 0; i < Query::__fieldCount; i++) {
294 MYSQL_FIELD* field = __stmt->fields + i;
295 MYSQL_BIND* bind = __outBINDs + i;
296 if (!__fields[i].init(this, i, field, bind))
297 return false;
298 }
299
300 return true;
301}

◆ initParams()

bool MyQuery::initParams ( size_t _paramCount)
protected

Definition at line 303 of file MyQuery.cpp.

304{
305 __DCL_ASSERT((Query::__paramCount == 0)
306 && (__params == NULL)
307 && (__stmt != NULL)
308 && (__stmt->param_count > 0));
309 __DCL_ASSERT(__stmt->param_count == _paramCount);
310
311 Query::__paramCount = __stmt->param_count;
312 size_t alloc = sizeof(MYSQL_BIND) * Query::__paramCount;
313 __inBINDs = (MYSQL_BIND*)malloc(alloc);
314 if (!__inBINDs) {
316 return false;
317 }
318 memset(__inBINDs, 0, alloc);
319
320 __params = new MyParam[Query::__paramCount];
321 if (__params == NULL) {
323 return false;
324 }
325
326 for(unsigned int i = 0; i < Query::__paramCount; i++) {
327 MYSQL_BIND* bind = &__inBINDs[i];
328 bind->is_null = &bind->is_null_value;
329 if (!__params[i].init(this, i, bind))
330 return false;
331 }
332
333 return true;
334}

◆ reset()

bool MyQuery::reset ( )
protected

Definition at line 86 of file MyQuery.cpp.

87{
88 Query::__eof = true;
89 Query::__affectedRows = -1;
90
91 if (__fields) {
92 __DCL_ASSERT(Query::__fieldCount > 0);
93 delete[] __fields;
94 __fields = NULL;
95 Query::__fieldCount = 0;
96 }
97
98 if (__params) {
99 __DCL_ASSERT(Query::__paramCount > 0);
100 delete[] __params;
101 __params = NULL;
102 Query::__paramCount = 0;
103 }
104
105 if (__outBuffer) {
106 free(__outBuffer);
108 }
109
110 if (__outBINDs) {
111 free(__outBINDs);
113 }
114
115 if (__inBINDs) {
116 free(__inBINDs);
117 __inBINDs = NULL;
118 }
119
120 bool r = true;
121 if (__stmt) {
122 __DCL_TRACE2_N(L"state[%d] result.data[%p]\n",
123 __stmt->state, __stmt->result.data);
124 if (__stmt->state >= MYSQL_STMT_USE_OR_STORE_CALLED) {
125 if (mysql_stmt_free_result(__stmt)) {
126 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
127 mysql_stmt_errno(__stmt),
128 mysql_stmt_error(__stmt)));
129 return false;
130 }
131 }
132 if (mysql_stmt_close(__stmt)) {
133 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
134 mysql_errno(conn()->connHandle()),
135 mysql_error(conn()->connHandle())));
136 r = false;
137 }
138 __stmt = NULL;
139 }
140
141 return r;
142}

Member Data Documentation

◆ __fields

MyField* MyQuery::__fields
protected

Definition at line 28 of file MyQuery.h.

◆ __inBINDs

MYSQL_BIND* MyQuery::__inBINDs
protected

Definition at line 23 of file MyQuery.h.

◆ __outBINDs

MYSQL_BIND* MyQuery::__outBINDs
protected

Definition at line 24 of file MyQuery.h.

◆ __outBuffer

void* MyQuery::__outBuffer
protected

Definition at line 25 of file MyQuery.h.

◆ __params

MyParam* MyQuery::__params
protected

Definition at line 27 of file MyQuery.h.

◆ __stmt

MYSQL_STMT* MyQuery::__stmt
protected

Definition at line 22 of file MyQuery.h.


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