DCL 4.0
Loading...
Searching...
No Matches
IBQuery.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <stdlib.h> // malloc, free
4
5#include <ibase.h>
6
7#include <dcl/Object.h>
8#if __DCL_HAVE_ALLOC_DEBUG
9#undef __DCL_ALLOC_LEVEL
10#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
11#endif
12
13#include <dcl/SQLCore.h>
14#include <dcl/OutputStream.h>
15#include <dcl/Charset.h>
16
17#include "IBConnection.h"
18#include "IBQuery.h"
19#include "IBField.h"
20#include "IBParam.h"
21
22#ifndef SQLDA_CURRENT_VERSION
23 #define SQLDA_CURRENT_VERSION SQLDA_VERSION1
24#endif
25
26#undef __THIS_FILE__
27static const wchar_t __THIS_FILE__[] = __T("dcl/sql/IBQuery.cpp");
28
29__DCL_BEGIN_NAMESPACE
30
32
34 : Query(_connHandle)
35{
36 __stmtHandle = NULL;
37 __inSQLDA = NULL;
38 __outSQLDA = NULL;
39 __outBuffer = NULL;
40
41 __stmtType = _IB_STMT_TYPE_UNKNOWN; // unknown
42 __fields = NULL;
43 __params = NULL;
44}
45
47{
48#ifdef __DCL_DEBUG
49 if (!reset()) {
50 ByteString s;
51 size_t n = 512;
52 ByteBuffer* buf = ByteBuffer::create(n);
53 bool b = conn()->__getErrorMessage(buf->data(), &n);
54 if (b) {
55 buf->__dataLength = n;
56 s = buf;
57 }
58 buf->release();
59
60 if (b) {
61 __DCL_TRACE1(__T("Warning! %s\n"), s.data());
62 }
63 else {
64 __DCL_TRACE0(__T("Warning! Query reset error\n"));
65 }
66 }
67#else
68 (void)reset();
69#endif
70}
71
73{
74 delete this;
75}
76
78{
79 Query::__eof = true;
80 Query::__affectedRows = -1;
82
83 // clear fields
84 if (__fields) {
85 __DCL_ASSERT(Query::__fieldCount > 0);
86 delete[] __fields;
87 __fields = NULL;
88 Query::__fieldCount = 0;
89 }
90
91 // clear binds
92 if (__params) {
93 __DCL_ASSERT(Query::__paramCount > 0);
94 delete[] __params;
95 __params = NULL;
96 Query::__paramCount = 0;
97 }
98
99 if (__outBuffer) {
100 free(__outBuffer);
102 }
103
104 if (__outSQLDA) {
105 free(__outSQLDA);
107 }
108
109 if (__inSQLDA) {
110 free(__inSQLDA);
111 __inSQLDA = NULL;
112 }
113
114 ISC_STATUS* statusVector = conn()->statusVector();
115 bool r = true;
116 if (__stmtHandle) {
117 if (isc_dsql_free_statement(
118 statusVector,
119 &__stmtHandle,
120 DSQL_drop)
121 ) {
122// __DCL_ASSERT(STATUS_FAILED(statusVector));
124 r = false;
125 }
127 }
128 return r;
129}
130
131static size_t __TYPE_ALIGN(size_t _offset, int _sqltype)
132{
133 size_t size = 0;
134 switch(_sqltype & ~1) {
135 case SQL_SHORT :
136 size = sizeof(short);
137 break;
138 case SQL_LONG :
139 size = sizeof(long);
140 break;
141 case SQL_INT64 :
142 size = sizeof(ISC_INT64);
143 break;
144 case SQL_FLOAT :
145 size = sizeof(float);
146 break;
147 case SQL_DOUBLE :
148 size = sizeof(double);
149 break;
150 case SQL_TYPE_DATE :
151 size = sizeof(ISC_DATE);
152 break;
153 case SQL_TYPE_TIME :
154 size = sizeof(ISC_TIME);
155 break;
156 case SQL_TIMESTAMP :
157 size = sizeof(ISC_TIMESTAMP);
158 break;
159 case SQL_TEXT :
160 size = sizeof(char);
161 break;
162 case SQL_VARYING :
163 size = sizeof(short);
164 break;
165 case SQL_BLOB :
166 size = sizeof(ISC_QUAD);
167 break;
168 default :
169 __DCL_TRACE3(__T("_offset[%d] _sqltype[%d] [%d]\n"), _offset, _sqltype, _sqltype & ~1);
170 __DCL_ASSERT(false);
171 }
172
173 return (_offset + size - 1) & ~(size - 1);
174}
175
177{
179 && (__outBuffer == NULL)
180 && (Query::__fieldCount == 0)
181 );
182
183 ISC_STATUS* statusVector = conn()->statusVector();
184
185 __outSQLDA = (XSQLDA*)malloc(XSQLDA_LENGTH(1));
187 __outSQLDA->sqln = 1;
188
189 if(isc_dsql_describe(
190 statusVector,
191 &__stmtHandle,
194 ) {
195// __DCL_ASSERT(STATUS_FAILED(statusVector));
197 return false;
198 }
199
200 if (__outSQLDA->sqld == 0) {
201 // 필드가 없다.
202 return true;
203 }
204
205 if (__outSQLDA->sqln < __outSQLDA->sqld) {
206 __outSQLDA = (XSQLDA*)realloc(__outSQLDA, XSQLDA_LENGTH(__outSQLDA->sqld));
208 __outSQLDA->sqln = __outSQLDA->sqld;
209
210 if (isc_dsql_describe(
211 statusVector,
212 &__stmtHandle,
215 ) {
216// __DCL_ASSERT(STATUS_FAILED(statusVector));
218 return false;
219 }
220 }
221
222 Query::__fieldCount = __outSQLDA->sqld;
223 __fields = new IBField[Query::__fieldCount];
224 if (__fields == NULL) {
226 return false;
227 }
228
229 size_t offset = 0;
230 XSQLVAR* sqlvar = __outSQLDA->sqlvar;
231 for(size_t i = 0; i < Query::__fieldCount; i++, sqlvar++) {
232 offset = __TYPE_ALIGN(offset, sqlvar->sqltype);
233 switch(sqlvar->sqltype & ~1) {
234 case SQL_TEXT :
235 offset += sqlvar->sqllen + 1;
236 break;
237 case SQL_VARYING :
238 offset += sqlvar->sqllen + sizeof(short) + 1;
239 break;
240 default :
241 offset += sqlvar->sqllen;
242 }
243 }
244
245 if (offset > 0) {
246 __outBuffer = (char*)malloc(offset);
247 __DCL_ASSERT((size_t)__outBuffer % sizeof(void*) == 0);
248 if (!__outBuffer) {
250 return false;
251 }
252 }
253
254 sqlvar = __outSQLDA->sqlvar;
255 offset = 0;
256 for(size_t i = 0; i < Query::__fieldCount; i++, sqlvar++) {
257 offset = __TYPE_ALIGN(offset, sqlvar->sqltype);
258 sqlvar->sqldata = (char*)__outBuffer + offset;
259 switch(sqlvar->sqltype & ~1) {
260 case SQL_TEXT :
261 offset += sqlvar->sqllen + 1;
262 break;
263 case SQL_VARYING :
264 offset += sqlvar->sqllen + sizeof(short) + 1;
265 break;
266 default :
267 offset += sqlvar->sqllen;
268 }
269
270 if (!__fields[i].init(this, sqlvar))
271 return false;
272 }
273
274 return true;
275}
276
277bool IBQuery::initParams(size_t _paramCount)
278{
279 ISC_STATUS* statusVector = conn()->statusVector();
280
281 __inSQLDA = (XSQLDA*)malloc(XSQLDA_LENGTH(1));
283 __inSQLDA->sqln = 1;
284
285 if (isc_dsql_describe_bind(
286 statusVector,
287 &__stmtHandle,
289 __inSQLDA)
290 ) {
291// __DCL_ASSERT(STATUS_FAILED(statusVector));
293 return false;
294 }
295
296 if (__inSQLDA->sqld == 0) {
297 // 파라미터가 없다. bind 할 필요가 없다.
298 return true;
299 }
300
301 if (__inSQLDA->sqln < __inSQLDA->sqld) {
302 __inSQLDA = (XSQLDA*)realloc(__inSQLDA, XSQLDA_LENGTH(__inSQLDA->sqld));
304 __inSQLDA->sqln = __inSQLDA->sqld;
305
306 if (isc_dsql_describe_bind(
307 statusVector,
308 &__stmtHandle,
310 __inSQLDA)
311 ) {
312// __DCL_ASSERT(STATUS_FAILED(m_statusVector));
314 return false;
315 }
316 }
317 __DCL_ASSERT(__inSQLDA->sqld == _paramCount);
318
319 Query::__paramCount = _paramCount;
320 __params = new IBParam[Query::__paramCount];
321 if (__params == NULL) {
323 return false;
324 }
325
326 XSQLVAR* sqlvar = __inSQLDA->sqlvar;
327 for(size_t i = 0; i < Query::__paramCount; i++, sqlvar++) {
328 if (!__params[i].init(this, sqlvar)) {
329 return false;
330 }
331 }
332
333 return true;
334}
335
336static char stmt_info_item[] = { isc_info_sql_stmt_type };
337static char count_info_item[] = { isc_info_sql_records };
338
339bool IBQuery::__prepare(const char* _sql, size_t _sqllen,
340 size_t _paramCount)
341{
342 if(!reset())
343 return false;
344
345 IBConnection* connHandle = conn();
346 ISC_STATUS* statusVector = connHandle->statusVector();
347
348 if (isc_dsql_allocate_statement(
349 statusVector,
350 connHandle->dbHandlePtr(),
352 ) {
353// __DCL_ASSERT(STATUS_FAILED(m_statusVector));
355 return false;
356 }
357
358 ISC_STATUS rs = isc_dsql_prepare(
359 statusVector,
360 connHandle->trHandlePtr(),
361 &__stmtHandle,
362 0,
363 (_CONST char*)_sql,
364 connHandle->dialect(),
365 NULL
366 );
367 if (rs) {
368// __DCL_ASSERT(STATUS_FAILED(m_statusVector));
370 return false;
371 }
372
373
374 int nLength;
375 char res_buffer[8];
376
377 if (isc_dsql_sql_info(
378 statusVector,
380 sizeof(stmt_info_item),
381 stmt_info_item,
382 sizeof(res_buffer),
383 res_buffer)
384 ) {
385// __DCL_ASSERT(STATUS_FAILED(m_statusVector));
387 return false;
388 }
389
390 if (res_buffer[0] != isc_info_sql_stmt_type) {
392 return false;
393 }
394 nLength = isc_vax_integer(&res_buffer[1], 2);
395 __stmtType = isc_vax_integer(&res_buffer[3], nLength);
396
397 // SELECT, EXECUTE PROCEDURE 는 Row Sets을 반환한다.
398 if ((__stmtType == isc_info_sql_stmt_select)
399 || (__stmtType == isc_info_sql_stmt_exec_procedure)
400 || (__stmtType == isc_info_sql_stmt_select_for_upd)) {
401 if (!initFields())
402 return false;
403 }
404
405 if (_paramCount > 0) {
406 if (!initParams(_paramCount))
407 return false;
408 }
409
410 return true;
411// rs = isc_dsql_set_cursor_name(statusVector, &__stmtHandle, "CURSOR1", 0);
412}
413
415{
416 IBConnection* connHandle = conn();
417 ISC_STATUS* statusVector = connHandle->statusVector();
418
419 if (__stmtType == isc_info_sql_stmt_exec_procedure) {
420 if (isc_dsql_execute2(
421 statusVector,
422 connHandle->trHandlePtr(),
424 connHandle->dialect(),
425 __inSQLDA,
426 __outSQLDA)) {
428 return false;
429 }
430 return true;
431 }
432
433 if (isc_dsql_execute(
434 statusVector,
435 connHandle->trHandlePtr(),
436 &__stmtHandle,
437 connHandle->dialect(),
438 __inSQLDA)) {
439// __DCL_ASSERT(STATUS_FAILED(statusVector));
441 return false;
442 }
443
444 for(size_t i = 0; i < Query::__paramCount; i++)
445 __params[i].onAfterExecute();
446
447 // INSERT, DELETE, UPDATE statement의 실행 후
448 // affected records를 구한다.
449
450 unsigned char count_type = 0;
451 switch(__stmtType) {
452 case isc_info_sql_stmt_update: {
453 count_type = isc_info_req_update_count;
454 break;
455 }
456 case isc_info_sql_stmt_delete: {
457 count_type = isc_info_req_delete_count;
458 break;
459 }
460 case isc_info_sql_stmt_insert: {
461 count_type = isc_info_req_insert_count;
462 break;
463 }
464 case isc_info_sql_stmt_select:
465 case isc_info_sql_stmt_select_for_upd: {
466 Query::__eof = false;
467 break;
468 }
469 case isc_info_sql_stmt_exec_procedure: {
470 for (size_t i = 0; i < Query::__fieldCount; i++) {
471 if (!__fields[i].onAfterFetch())
472 return false;
473 }
474 break;
475 }
476 }
477
478 if (count_type) {
479 unsigned char count_is = 0;
480 char count_buffer[33];
481 unsigned short length;
482
483 if (isc_dsql_sql_info(
484 statusVector,
485 &__stmtHandle,
486 sizeof(count_info_item),
487 count_info_item,
488 sizeof(count_buffer),
489 count_buffer)) {
490// __DCL_ASSERT(STATUS_FAILED(statusVector));
492 return false;
493 }
494
495 for(char* pch = count_buffer + 3; *pch != isc_info_end; ) {
496 count_is = *pch++;
497 length = (unsigned short)isc_vax_integer(pch, 2);
498 pch += 2;
499 Query::__affectedRows = isc_vax_integer(pch, length);
500 pch += length;
501 if (count_is == count_type)
502 break;
503 }
504 }
505
506 return true;
507}
508
510{
511 __DCL_ASSERT(!eof());
512 __DCL_ASSERT(__stmtType == isc_info_sql_stmt_select);
513
514 ISC_STATUS rs = isc_dsql_fetch(conn()->statusVector(),
515 &__stmtHandle,
517 __outSQLDA);
518 if (rs == 0) {
519 for(size_t i = 0; i < Query::__fieldCount; i++) {
520 if (!__fields[i].onAfterFetch())
521 return false;
522 }
523 return true;
524 }
525 else if (rs == 100) {
526 Query::__eof = true;
527 return true;
528 }
529
530 __DCL_TRACE1(L"[%zd]\n", (int64_t)rs);
532 return false;
533}
534
535bool IBQuery::__getField(size_t _index, SQL::Field** _fieldHandleOut)
536{
537 __DCL_ASSERT(Query::__fieldCount > 0);
538 __DCL_ASSERT((0 <= _index) && (_index < Query::__fieldCount));
539 *_fieldHandleOut = &__fields[_index];
540 return true;
541}
542
543bool IBQuery::__getParam(size_t _index, SQL::Param** _paramHandleOut)
544{
545 __DCL_ASSERT(Query::__paramCount > 0);
546 __DCL_ASSERT((0 <= _index) && (_index < Query::__paramCount));
547 *_paramHandleOut = &__params[_index];
548 return true;
549}
550
551__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
#define _CONST
Definition Config.h:353
#define SQLDA_CURRENT_VERSION
Definition IBQuery.cpp:23
#define _IB_STMT_TYPE_UNKNOWN
Definition IBQuery.h:6
#define __DCL_TRACE0(psz)
Definition Object.h:375
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#define __DCL_TRACE3(fmt, arg1, arg2, arg3)
Definition Object.h:378
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:228
#define __T(str)
Definition Object.h:44
ByteString r
ByteBuffer * buf
#define __SET_ERROR(_errorCode)
Definition SQLCore.cpp:150
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
short dialect() const
isc_tr_handle * trHandlePtr()
ISC_STATUS * statusVector()
isc_db_handle * dbHandlePtr()
IBQuery(IBConnection *_connHandle)
IBParam * __params
Definition IBQuery.h:30
bool initParams(size_t _paramCount)
Definition IBQuery.cpp:277
virtual void __destroy()
Definition IBQuery.cpp:72
virtual bool __fetch()
Definition IBQuery.cpp:509
char * __outBuffer
Definition IBQuery.h:28
virtual bool __getField(size_t _index, SQL::Field **_fieldHandleOut)
Definition IBQuery.cpp:535
virtual bool __prepare(const char *_sql, size_t _sqllen, size_t _paramCount)
Definition IBQuery.cpp:339
int __stmtType
Definition IBQuery.h:25
IBField * __fields
Definition IBQuery.h:31
bool initFields()
Definition IBQuery.cpp:176
XSQLDA * __inSQLDA
Definition IBQuery.h:26
virtual ~IBQuery()
Definition IBQuery.cpp:46
bool reset()
Definition IBQuery.cpp:77
XSQLDA * __outSQLDA
Definition IBQuery.h:27
virtual bool __getParam(size_t _index, SQL::Param **_paramHandleOut)
Definition IBQuery.cpp:543
virtual bool __execute()
Definition IBQuery.cpp:414
isc_stmt_handle __stmtHandle
Definition IBQuery.h:24
@ eOutOfMemory
Definition SQLCore.h:24
@ eServerError
Definition SQLCore.h:21