3#include <stdlib.h> // malloc, free
7#include <pgtypes_numeric.h>
8#include <pgtypes_date.h>
9#include <pgtypes_interval.h>
10#include <pgtypes_timestamp.h>
12#include <dcl/Object.h>
13#if __DCL_HAVE_ALLOC_DEBUG
14#undef __DCL_ALLOC_LEVEL
15#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
18#include <dcl/Numeric.h>
19#include <dcl/SQLCore.h>
21#include "PeConnection.h"
27static const char_t __THIS_FILE__[] = __T("dcl/sql/PeQuery.pgc");
31#define __SET_ERROR(_error) \
32 conn()->setErrorHandle(_error, 0L, __THIS_FILE__, __LINE__)
33#define __SET_ERROR_HANDLE(_SQLCODE) \
34 conn()->setErrorHandle(SQL::eServerError, _SQLCODE, __THIS_FILE__, __LINE__)
35#define __SET_ERROR_MSG(_message) \
36 conn()->setErrorMessage(_message, __THIS_FILE__, __LINE__)
38IMPLEMENT_CLASSINFO(PeQuery, SQL::Query)
40PeQuery::PeQuery(PeConnection* pConnection)
44 strID = ByteString::format("%zx", (size_t)this);
45 __statementID = "stmt_" + strID;
46 __cursorID = "curs_" + strID;
51 __cursorOpened = false;
52 __cursorDeclared = false;
63 size_t buflen = sizeof(buf) - 1;
64 bool b = conn()->__getErrorMessage(buf, &buflen);
65 buf[b ? buflen : 0] = '\0';
66 __DCL_TRACE1(L"Warning! Query reset error! %hs\n", buf);
73void PeQuery::__destroy()
75// cerr << "PeQuery::destory\n";
83 EXEC SQL BEGIN DECLARE SECTION;
84 char* connID = conn()->connectionID();
85 char* stmtID = (_CONST char*)__statementID.data();
86 char* cursorID = (_CONST char*)__cursorID.data();
87 EXEC SQL END DECLARE SECTION;
89 EXEC SQL SET CONNECTION :connID;
90 if (r && SQLCODE < 0) {
91 __SET_ERROR_HANDLE(SQLCODE);
94 __DCL_ASSERT(SQLCODE == 0);
97 __cursorOpened = false;
98 EXEC SQL CLOSE :cursorID;
99 if (r && SQLCODE < 0) {
100 __SET_ERROR_HANDLE(SQLCODE);
105 if (__cursorDeclared) {
106 __cursorDeclared = false;
108 EXEC SQL FREE :cursorID;
109 if (r && SQLCODE < 0) {
110 __SET_ERROR_HANDLE(SQLCODE);
117 EXEC SQL FREE :stmtID;
118 if (r && SQLCODE < 0) {
119 __SET_ERROR_HANDLE(SQLCODE);
125 Query::__affectedRows = -1;
129 __DCL_ASSERT(Query::__fieldCount > 0);
132 Query::__fieldCount = 0;
137 __DCL_ASSERT(Query::__paramCount > 0);
140 Query::__paramCount = 0;
144 // __outSQLDA는 Informix API에서 할당됨.
156bool PeQuery::initFields()
160 && (Query::__fieldCount == 0)
161 && (__outSQLDA != NULL)
162 && (__outSQLDA->sqld > 0)
165 Query::__fieldCount = __outSQLDA->sqld;
166 __fields = new PeField[Query::__fieldCount];
167 if (__fields == NULL) {
168 __SET_ERROR(SQL::eOutOfMemory);
172 sqlvar_t* sqlvar = __outSQLDA->sqlvar;
173 for(size_t i = 0; i < Query::__fieldCount; i++, sqlvar++) {
174 if (!__fields[i].init(this, sqlvar))
181bool PeQuery::initParams(size_t _paramCount)
183 __DCL_ASSERT((__params == NULL)
184 && (Query::__paramCount == 0)
185 && (__outSQLDA != NULL)
188 size_t nAllocSize = sizeof(sqlda_t)
189 + (sizeof(sqlvar_t) * _paramCount);
190 __inSQLDA = (sqlda_t*)malloc(nAllocSize);
191 if (__inSQLDA == NULL) {
192 __SET_ERROR(SQL::eOutOfMemory);
195 memset(__inSQLDA, 0, nAllocSize);
196 __inSQLDA->sqln = (short)_paramCount;
198 Query::__paramCount = _paramCount;
199 __params = new PeParam[Query::__paramCount];
200 if (__params == NULL) {
201 __SET_ERROR(SQL::eOutOfMemory);
205 sqlvar_t* sqlvar = __inSQLDA->sqlvar;
206 for(size_t i = 0; i < Query::__paramCount; i++, sqlvar++) {
207 if (!__params[i].init(this, sqlvar))
214const wchar_t* __dataTypeName(const sqlvar_t* _sqlvar);
216bool PeQuery::__prepare(const char* _sql, size_t _sqllen,
222 EXEC SQL BEGIN DECLARE SECTION;
223 char* connID = conn()->connectionID();
224 char* stmtID = (_CONST char*)__statementID.data();
225 char* sql = (_CONST char*)_sql;
226 EXEC SQL END DECLARE SECTION;
228 EXEC SQL SET CONNECTION :connID;
230 __SET_ERROR_HANDLE(SQLCODE);
233 __DCL_ASSERT(SQLCODE == 0);
235 EXEC SQL PREPARE :stmtID FROM :sql;
238 __SET_ERROR_HANDLE(SQLCODE);
242 EXEC SQL DESCRIBE :stmtID INTO __outSQLDA;
245 __SET_ERROR_HANDLE(SQLCODE);
251 __DCL_TRACE1(L"[%p]\n", __outSQLDA);
252 __DCL_TRACE4(L"[%hs] [%ld] sqln[%d] sqld[%d]\n",
253 __outSQLDA->sqldaid, __outSQLDA->sqldabc,
254 __outSQLDA->sqln, __outSQLDA->sqld
256 for (int i = 0; i < __outSQLDA->sqld; i++) {
257 sqlvar_t* p = &(__outSQLDA->sqlvar[i]);
258 __DCL_TRACE4(L"[%19ls] [%hd] [%p] [%p]\n",
259 __dataTypeName(p), p->sqllen, p->sqldata, p->sqlind
263 if (__outSQLDA->sqld > 0) {
269 if (_paramCount > 0) {
270 if (!initParams(_paramCount))
277bool PeQuery::__execute()
280 for (size_t i = 0; i < Query::__paramCount; i++) {
281 __params[i].onBeforeExecute();
285 EXEC SQL BEGIN DECLARE SECTION;
286 char* connID = conn()->connectionID();
287 char* stmtID = (_CONST char*)__statementID.data();
288 char* cursorID = (_CONST char*)__cursorID.data();
289 EXEC SQL END DECLARE SECTION;
291 EXEC SQL SET CONNECTION :connID;
293 __SET_ERROR_HANDLE(SQLCODE);
296 __DCL_ASSERT(SQLCODE == 0);
298 if (__outSQLDA && __outSQLDA->sqld > 0) {
299 if (!__cursorDeclared) {
300 EXEC SQL DECLARE :cursorID CURSOR FOR :stmtID;
302 __SET_ERROR_HANDLE(SQLCODE);
305 __cursorDeclared = true;
309 EXEC SQL OPEN :cursorID USING DESCRIPTOR __inSQLDA;
311 EXEC SQL OPEN :cursorID;
314 __SET_ERROR_HANDLE(SQLCODE);
318 __cursorOpened = true;
323 // 2025.05.06 __outSQLDA 조건은 CURSOR로 처리 하므로
324 // 다음 EXEC SQL EXECUTE는 의미가 없다.
325 if (__outSQLDA && __inSQLDA)
326 EXEC SQL EXECUTE :stmtID INTO DESCRIPTOR __outSQLDA
327 USING DESCRIPTOR __inSQLDA;
329 EXEC SQL EXECUTE :stmtID INTO DESCRIPTOR __outSQLDA;
333 EXEC SQL EXECUTE :stmtID USING DESCRIPTOR __inSQLDA;
335 EXEC SQL EXECUTE :stmtID;
338 __SET_ERROR_HANDLE(SQLCODE);
339 Query::__affectedRows = -1;
343 // INSERT, UPDATE, DELETE
344 Query::__affectedRows = sqlca.sqlerrd[2];
347 for(size_t i = 0; i < Query::__paramCount; i++) {
348 if (!(__params[i].onAfterExecute()))
355bool PeQuery::__fetch()
358 __DCL_ASSERT(!eof());
359 __DCL_ASSERT(__outSQLDA && __outSQLDA->sqld > 0);
361 EXEC SQL BEGIN DECLARE SECTION;
362 char* connID = conn()->connectionID();
363 char* cursorID = (_CONST char*)__cursorID.data();
364 EXEC SQL END DECLARE SECTION;
366 EXEC SQL SET CONNECTION :connID;
368 __SET_ERROR_HANDLE(SQLCODE);
371 __DCL_ASSERT(SQLCODE == 0);
373 EXEC SQL FETCH :cursorID USING DESCRIPTOR __outSQLDA;
375 if (SQLCODE == ECPG_NO_ERROR) {
377 __DCL_TRACE1(L"[%p]\n", __outSQLDA);
378 __DCL_TRACE4(L"[%hs] [%ld] sqln[%d] sqld[%d]\n",
379 __outSQLDA->sqldaid, __outSQLDA->sqldabc,
380 __outSQLDA->sqln, __outSQLDA->sqld
382 for (int i = 0; i < __outSQLDA->sqld; i++) {
383 sqlvar_t* p = &(__outSQLDA->sqlvar[i]);
384 __DCL_TRACE4(L"[%19ls] [%hd] [%p] [%p]\n",
385 __dataTypeName(p), p->sqllen, p->sqldata, p->sqlind
389 sqlvar_t* sqlvar = __outSQLDA->sqlvar;
390 for (size_t i = 0; i < Query::__fieldCount; i++) {
391 if (!__fields[i].onAfterFetch(sqlvar++))
396 else if (SQLCODE == ECPG_NOT_FOUND) {
398 if (__cursorOpened) {
399 __cursorOpened = false;
400 EXEC SQL CLOSE :cursorID;
402 __SET_ERROR_HANDLE(SQLCODE);
409 __SET_ERROR_HANDLE(SQLCODE);
413bool PeQuery::__getField(size_t _index, SQL::Field** _fieldHandleOut)
415 __DCL_ASSERT(Query::__fieldCount > 0);
416 __DCL_ASSERT((0 <= _index) && (_index < Query::__fieldCount));
417 *_fieldHandleOut = &__fields[_index];
421bool PeQuery::__getParam(size_t _index, SQL::Param** _paramHandleOut)
423 __DCL_ASSERT(Query::__paramCount > 0);
424 __DCL_ASSERT((0 <= _index) && (_index < Query::__paramCount));
425 *_paramHandleOut = &__params[_index];