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.pgc");
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()
266 for (size_t i = 0; i < Query::__paramCount; i++) {
267 __params[i].onBeforeExecute();
271 EXEC SQL BEGIN DECLARE SECTION;
272 char* pszConnectionID = conn()->connectionID();
273 char* pszStatementID = (_CONST char*)__statementID.data();
274 char* pszCursorID = (_CONST char*)__cursorID.data();
275 EXEC SQL END DECLARE SECTION;
277 EXEC SQL SET CONNECTION :pszConnectionID;
279 __SET_ERROR_SQLCODE(SQLCODE);
282 __DCL_ASSERT(SQLCODE == 0);
284 if (__outSQLDA && __outSQLDA->sqld > 0) {
285 if (!__cursorDeclared) {
286 EXEC SQL DECLARE :pszCursorID CURSOR FOR :pszStatementID;
288 __SET_ERROR_SQLCODE(SQLCODE);
291 __cursorDeclared = true;
294 if (__cursorOpened) {
295 EXEC SQL CLOSE :pszCursorID;
297 __SET_ERROR_SQLCODE(SQLCODE);
300 __cursorOpened = false;
304 EXEC SQL OPEN :pszCursorID USING DESCRIPTOR __inSQLDA;
306 EXEC SQL OPEN :pszCursorID;
309 __SET_ERROR_SQLCODE(SQLCODE);
313 __cursorOpened = true;
318 // 2025.05.06 __outSQLDA 조건은 CURSOR로 처리 하므로
319 // 다음 EXEC SQL EXECUTE는 의미가 없다.
320 if (__outSQLDA && __inSQLDA)
321 EXEC SQL EXECUTE :pszStatementID INTO DESCRIPTOR __outSQLDA
322 USING DESCRIPTOR __inSQLDA;
324 EXEC SQL EXECUTE :pszStatementID INTO DESCRIPTOR __outSQLDA;
328 EXEC SQL EXECUTE :pszStatementID USING DESCRIPTOR __inSQLDA;
330 EXEC SQL EXECUTE :pszStatementID;
333 __SET_ERROR_SQLCODE(SQLCODE);
334 Query::__affectedRows = -1;
338 // INSERT, UPDATE, DELETE
339 Query::__affectedRows = sqlca.sqlerrd[2];
342 for(size_t i = 0; i < Query::__paramCount; i++) {
343 if (!(__params[i].onAfterExecute()))
350bool PgQuery::__fetch()
353 __DCL_ASSERT(!eof());
354 __DCL_ASSERT(__outSQLDA && __outSQLDA->sqld > 0);
356 EXEC SQL BEGIN DECLARE SECTION;
357 char* pszCursorID = (_CONST char*)__cursorID.data();
358 EXEC SQL END DECLARE SECTION;
360 EXEC SQL FETCH :pszCursorID USING DESCRIPTOR __outSQLDA;
362 if (SQLCODE == ECPG_NO_ERROR) {
364 __DCL_TRACE1(L"[%p]\n", __outSQLDA);
365 __DCL_TRACE4(L"[%hs] [%ld] sqln[%d] sqld[%d]\n",
366 __outSQLDA->sqldaid, __outSQLDA->sqldabc,
367 __outSQLDA->sqln, __outSQLDA->sqld
369 for (int i = 0; i < __outSQLDA->sqld; i++) {
370 sqlvar_t* p = &(__outSQLDA->sqlvar[i]);
371 __DCL_TRACE4(L"[%19ls] [%hd] [%p] [%p]\n",
372 __dataTypeName(p), p->sqllen, p->sqldata, p->sqlind
376 sqlvar_t* sqlvar = __outSQLDA->sqlvar;
377 for (size_t i = 0; i < Query::__fieldCount; i++) {
378 if (!__fields[i].onAfterFetch(sqlvar++))
383 else if (SQLCODE == ECPG_NOT_FOUND) {
388 __SET_ERROR_SQLCODE(SQLCODE);
392bool PgQuery::__getField(size_t _index, SQL::Field** _fieldHandleOut)
394 __DCL_ASSERT(Query::__fieldCount > 0);
395 __DCL_ASSERT((0 <= _index) && (_index < Query::__fieldCount));
396 *_fieldHandleOut = &__fields[_index];
400bool PgQuery::__getParam(size_t _index, SQL::Param** _paramHandleOut)
402 __DCL_ASSERT(Query::__paramCount > 0);
403 __DCL_ASSERT((0 <= _index) && (_index < Query::__paramCount));
404 *_paramHandleOut = &__params[_index];