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 "PgConnection.h"
27static const wchar_t __THIS_FILE__[] = __T("dcl/sql/PgQuery.ec");
31IMPLEMENT_CLASSINFO(PgQuery, SQL::Query)
33PgQuery::PgQuery(PgConnection* pConnection)
36 ByteString strID = ByteString::format("%p", this);
38 __statementID = "stmt_" + strID;
39 __cursorID = "cursor_" + strID;
44 __cursorOpened = false;
45 __cursorDeclared = false;
57 ByteBuffer* buf = ByteBuffer::create(n);
58 bool b = conn()->__getErrorMessage(buf->data(), &n);
60 buf->__dataLength = n;
66 __DCL_TRACE1(__T("Warning! %s\n"), s.data());
69 __DCL_TRACE0(__T("Warning! Query reset error\n"));
77void PgQuery::__destroy()
79// cerr << "PgQuery::destory\n";
85 EXEC SQL BEGIN DECLARE SECTION;
86 char* pszConnectionID = conn()->connectionID();
87 char* pszStatementID = (_CONST char*)__statementID.data();
88 char* pszCursorID = (_CONST char*)__cursorID.data();
89 EXEC SQL END DECLARE SECTION;
91 EXEC SQL SET CONNECTION :pszConnectionID;
93 __SET_ERROR_SQLCODE(SQLCODE);
96 __DCL_ASSERT(SQLCODE == 0);
99 EXEC SQL CLOSE :pszCursorID;
100 __cursorOpened = false;
103 if (__cursorDeclared) {
104 EXEC SQL FREE :pszCursorID;
105 __cursorDeclared = false;
109 EXEC SQL FREE :pszStatementID;
113 Query::__affectedRows = -1;
117 __DCL_ASSERT(Query::__fieldCount > 0);
120 Query::__fieldCount = 0;
125 __DCL_ASSERT(Query::__paramCount > 0);
128 Query::__paramCount = 0;
132 // __outSQLDA는 Informix API에서 할당됨.
133 // DCLPgFree(__outSQLDA);
145bool PgQuery::initFields()
147 __DCL_ASSERT((__fields == NULL)
148 && (Query::__fieldCount == 0)
149 && (__outSQLDA != NULL)
150 && (__outSQLDA->sqld > 0));
152 Query::__fieldCount = __outSQLDA->sqld;
153 __fields = new PgField[Query::__fieldCount];
154 if (__fields == NULL) {
155 __SET_ERROR(SQL::eOutOfMemory);
159 sqlvar_t* sqlvar = __outSQLDA->sqlvar;
160 for(size_t i = 0; i < Query::__fieldCount; i++, sqlvar++) {
161 if (!__fields[i].init(this, sqlvar))
168bool PgQuery::initParams(size_t _paramCount)
170 __DCL_ASSERT((__params == NULL)
171 && (Query::__paramCount == 0)
172 && (__outSQLDA != NULL));
174 size_t nAllocSize = sizeof(sqlda_t)
175 + (sizeof(sqlvar_t) * _paramCount);
176 __inSQLDA = (sqlda_t*)malloc(nAllocSize);
177 if (__inSQLDA == NULL) {
178 __SET_ERROR(SQL::eOutOfMemory);
181 memset(__inSQLDA, 0, nAllocSize);
182 __inSQLDA->sqln = (short)_paramCount;
184 Query::__paramCount = _paramCount;
185 __params = new PgParam[Query::__paramCount];
186 if (__params == NULL) {
187 __SET_ERROR(SQL::eOutOfMemory);
191 sqlvar_t* sqlvar = __inSQLDA->sqlvar;
192 for(size_t i = 0; i < Query::__paramCount; i++, sqlvar++) {
193 if (!__params[i].init(this, sqlvar))
200const wchar_t* __dataTypeName(const sqlvar_t* _sqlvar);
202bool PgQuery::__prepare(const char* _sql, size_t _sqllen,
208 EXEC SQL BEGIN DECLARE SECTION;
209 char* pszConnectionID = conn()->connectionID();
210 char* pszStatementID = (_CONST char*)__statementID.data();
211 char* pszSQL = (_CONST char*)_sql;
212 EXEC SQL END DECLARE SECTION;
214 EXEC SQL SET CONNECTION :pszConnectionID;
216 __SET_ERROR_SQLCODE(SQLCODE);
219 __DCL_ASSERT(SQLCODE == 0);
221 EXEC SQL PREPARE :pszStatementID FROM :pszSQL;
224 __SET_ERROR_SQLCODE(SQLCODE);
228 EXEC SQL DESCRIBE :pszStatementID INTO __outSQLDA;
231 __SET_ERROR_SQLCODE(SQLCODE);
237 __DCL_TRACE1(L"[%p]\n", __outSQLDA);
238 __DCL_TRACE4(L"[%hs] [%ld] sqln[%d] sqld[%d]\n",
239 __outSQLDA->sqldaid, __outSQLDA->sqldabc,
240 __outSQLDA->sqln, __outSQLDA->sqld
242 for (int i = 0; i < __outSQLDA->sqld; i++) {
243 sqlvar_t* p = &(__outSQLDA->sqlvar[i]);
244 __DCL_TRACE4(L"[%19ls] [%hd] [%p] [%p]\n",
245 __dataTypeName(p), p->sqllen, p->sqldata, p->sqlind
249 if (__outSQLDA->sqld > 0) {
255 if (_paramCount > 0) {
256 if (!initParams(_paramCount))
263bool PgQuery::__execute()
265 EXEC SQL BEGIN DECLARE SECTION;
266 char* pszConnectionID = conn()->connectionID();
267 char* pszStatementID = (_CONST char*)__statementID.data();
268 char* pszCursorID = (_CONST char*)__cursorID.data();
269 EXEC SQL END DECLARE SECTION;
271 EXEC SQL SET CONNECTION :pszConnectionID;
273 __SET_ERROR_SQLCODE(SQLCODE);
276 __DCL_ASSERT(SQLCODE == 0);
278 if (__outSQLDA && __outSQLDA->sqld > 0) {
279 if (!__cursorDeclared) {
280 EXEC SQL DECLARE :pszCursorID CURSOR FOR :pszStatementID;
282 __SET_ERROR_SQLCODE(SQLCODE);
285 __cursorDeclared = true;
288 if (__cursorOpened) {
289 EXEC SQL CLOSE :pszCursorID;
291 __SET_ERROR_SQLCODE(SQLCODE);
294 __cursorOpened = false;
298 EXEC SQL OPEN :pszCursorID USING DESCRIPTOR __inSQLDA;
300 EXEC SQL OPEN :pszCursorID;
303 __SET_ERROR_SQLCODE(SQLCODE);
307 __cursorOpened = true;
312 // 2025.05.06 __outSQLDA 조건은 CURSOR로 처리 하므로
313 // 다음 EXEC SQL EXECUTE는 의미가 없다.
314 if (__outSQLDA && __inSQLDA)
315 EXEC SQL EXECUTE :pszStatementID INTO DESCRIPTOR __outSQLDA
316 USING DESCRIPTOR __inSQLDA;
318 EXEC SQL EXECUTE :pszStatementID INTO DESCRIPTOR __outSQLDA;
322 EXEC SQL EXECUTE :pszStatementID USING DESCRIPTOR __inSQLDA;
324 EXEC SQL EXECUTE :pszStatementID;
327 __SET_ERROR_SQLCODE(SQLCODE);
328 Query::__affectedRows = -1;
332 // INSERT, UPDATE, DELETE
333 Query::__affectedRows = sqlca.sqlerrd[2];
336 for(size_t i = 0; i < Query::__paramCount; i++) {
337 if (!(__params[i].onAfterExecute()))
344bool PgQuery::__fetch()
347 __DCL_ASSERT(!eof());
348 __DCL_ASSERT(__outSQLDA && __outSQLDA->sqld > 0);
350 EXEC SQL BEGIN DECLARE SECTION;
351 char* pszCursorID = (_CONST char*)__cursorID.data();
352 EXEC SQL END DECLARE SECTION;
354 EXEC SQL FETCH :pszCursorID USING DESCRIPTOR __outSQLDA;
356 if (SQLCODE == ECPG_NO_ERROR) {
358 __DCL_TRACE1(L"[%p]\n", __outSQLDA);
359 __DCL_TRACE4(L"[%hs] [%ld] sqln[%d] sqld[%d]\n",
360 __outSQLDA->sqldaid, __outSQLDA->sqldabc,
361 __outSQLDA->sqln, __outSQLDA->sqld
363 for (int i = 0; i < __outSQLDA->sqld; i++) {
364 sqlvar_t* p = &(__outSQLDA->sqlvar[i]);
365 __DCL_TRACE4(L"[%19ls] [%hd] [%p] [%p]\n",
366 __dataTypeName(p), p->sqllen, p->sqldata, p->sqlind
370 sqlvar_t* sqlvar = __outSQLDA->sqlvar;
371 for (size_t i = 0; i < Query::__fieldCount; i++) {
372 if (!__fields[i].onAfterFetch(sqlvar++))
377 else if (SQLCODE == ECPG_NOT_FOUND) {
382 __SET_ERROR_SQLCODE(SQLCODE);
386bool PgQuery::__getField(size_t _index, SQL::Field** _fieldHandleOut)
388 __DCL_ASSERT(Query::__fieldCount > 0);
389 __DCL_ASSERT((0 <= _index) && (_index < Query::__fieldCount));
390 *_fieldHandleOut = &__fields[_index];
394bool PgQuery::__getParam(size_t _index, SQL::Param** _paramHandleOut)
396 __DCL_ASSERT(Query::__paramCount > 0);
397 __DCL_ASSERT((0 <= _index) && (_index < Query::__paramCount));
398 *_paramHandleOut = &__params[_index];