DCL 4.0
Loading...
Searching...
No Matches
OciQuery.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <oci.h>
4
5#include <stdlib.h> // abs
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
15#include "OciConnection.h"
16#include "OciQuery.h"
17#include "OciField.h"
18#include "OciParam.h"
19
20#define __TRACE_THIS 0
21#if __TRACE_THIS
22#define __DCL_TRACE0_N __DCL_TRACE0
23#define __DCL_TRACE1_N __DCL_TRACE1
24#define __DCL_TRACE2_N __DCL_TRACE2
25#define __DCL_TRACE3_N __DCL_TRACE3
26#define __DCL_TRACE4_N __DCL_TRACE4
27#else
28#define __DCL_TRACE0_N(fmt)
29#define __DCL_TRACE1_N(fmt, arg)
30#define __DCL_TRACE2_N(fmt, arg1, arg2)
31#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
32#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
33#endif
34
35#undef __THIS_FILE__
36static const wchar_t __THIS_FILE__[] = __T("dcl/sql/OciQuery.cpp");
37
38__DCL_BEGIN_NAMESPACE
39
40#undef __SET_ERROR
41#define __SET_ERROR(_error, status, pError) \
42 conn()->setErrorStatus(_error, status, pError, \
43 true, __THIS_FILE__, __LINE__)
44
45#define __SET_ERROR_NORESET(_error, status, pError) \
46 conn()->setErrorStatus(_error, status, pError, \
47 false, __THIS_FILE__, __LINE__)
48
50
52 : Query(_connHandle)
53{
54 __stmt = NULL;
55 __stmtType = _OCI_STMT_TYPE_UNKNOWN;
56
57 __fields = NULL;
58 __params = NULL;
59 Query::__placeholder = L':';
60}
61
63{
64#ifdef __DCL_DEBUG
65 if (!reset()) {
66 ByteString s;
67 size_t n = 512;
68 ByteBuffer* buf = ByteBuffer::create(n);
69 bool b = conn()->__getErrorMessage(buf->data(), &n);
70 if (b) {
71 buf->__dataLength = n;
72 s = buf;
73 }
74 buf->release();
75
76 if (b) {
77 __DCL_TRACE1(__T("Warning! %s\n"), s.data());
78 }
79 else {
80 __DCL_TRACE0(__T("Warning! Query reset error\n"));
81 }
82 }
83#else
84 (void)reset();
85#endif
86}
87
89{
90 delete this;
91}
92
94{
95 Query::__eof = true;
96 Query::__affectedRows = -1;
98
99 // clear fields
100 if (__fields) {
101 __DCL_ASSERT(Query::__fieldCount > 0);
102 delete[] __fields;
103 __fields = NULL;
104 Query::__fieldCount = 0;
105 }
106
107 // clear binds
108 if (__params) {
109 __DCL_ASSERT(Query::__paramCount > 0);
110 delete[] __params;
111 __params = NULL;
112 Query::__paramCount = 0;
113 }
114
115 if (__stmt) {
116 sword status = ::OCIStmtRelease(
117 __stmt,
118 conn()->errorHandle(),
119 NULL, 0,
120 OCI_DEFAULT
121 );
122 if (status != OCI_SUCCESS) {
124 return false;
125 }
126 __stmt = NULL;
127 }
128
129 return true;
130}
131
132bool OciQuery::initParams(size_t _paramCount)
133{
134#if defined(__DCL_DEBUG) && 1
135 ub4 size = 0;
136 ub4 startloc = 1;
137 sb4 found = 0;
138 text* bvnp; ub1 bvnl;
139 text* invp; ub1 inpl;
140 ub1 dupl; OCIBind* hndl;
141
142 sword status = ::OCIStmtGetBindInfo(
143 __stmt,
144 conn()->errorHandle(),
145 size, startloc, &found,
146 &bvnp, &bvnl, &invp, &inpl,
147 &dupl, &hndl);
148 __DCL_TRACE2_N(L"[%d][%d]\n", status, found);
149 if (status != OCI_SUCCESS) {
150 if (status == OCI_NO_DATA) {
151 return true;
152 }
153 // 그렇다면 에러다.
154 __SET_ERROR(SQL::eServerError, status, conn()->errorHandle());
155 return false;
156 }
157 __DCL_ASSERT(abs(found) == _paramCount);
158#endif
159
160 Query::__paramCount = _paramCount;
161 __params = new OciParam[Query::__paramCount];
162 if (__params == NULL) {
164 return false;
165 }
166
167 for(size_t i = 0; i < Query::__paramCount; i++) {
168 if (!__params[i].init(this, i + 1))
169 return false;
170 }
171
172 return true;
173}
174
175bool OciQuery::__prepare(const char* _sql, size_t _sqllen,
176 size_t _paramCount)
177{
178 OciConnection* pConnection = conn();
179 OCIError* pError = pConnection->errorHandle();
180
181 if (!reset())
182 return false;
183
184 sword status = OCI_SUCCESS;
185
186 status = ::OCIStmtPrepare2(
187 pConnection->svcctxHandle(),
188 &__stmt,
189 pError,
190 (const text* )_sql,
191 _sqllen,
192 NULL, 0,
193 OCI_NTV_SYNTAX,
194 OCI_DEFAULT);
195 if (status != OCI_SUCCESS) {
196 __SET_ERROR(SQL::eServerError, status, pError);
197 return false;
198 }
199
200 status = ::OCIAttrGet(__stmt,
201 OCI_HTYPE_STMT,
202 &__stmtType,
203 NULL,
204 OCI_ATTR_STMT_TYPE,
205 pError);
206 if (status != OCI_SUCCESS) {
207 __SET_ERROR(SQL::eServerError, status, pError);
208 return false;
209 }
210
211 if (_paramCount > 0) {
212 if (!initParams(_paramCount))
213 return false;
214 }
215
216 return true;
217}
218
220{
221 OciConnection* pConnection = conn();
222 OCIError* pError = pConnection->errorHandle();
223 sword status = OCI_SUCCESS;
224
225 ub4 nFieldCount = 0;
226 status = ::OCIAttrGet(__stmt,
227 OCI_HTYPE_STMT,
228 &nFieldCount,
229 NULL,
230 OCI_ATTR_PARAM_COUNT,
231 pError);
232 if (status != OCI_SUCCESS) {
233 __SET_ERROR(SQL::eServerError, status, pError);
234 return false;
235 }
236
237 Query::__fieldCount = nFieldCount;
238 __fields = new OciField[Query::__fieldCount];
239 if (__fields == NULL) {
241 return false;
242 }
243
244 for(size_t i = 0; i < Query::__fieldCount; i++) {
245 if (!__fields[i].init(this, i + 1))
246 return false;
247 }
248
249 return true;
250}
251
253{
254 for(size_t i = 0; i < Query::__paramCount; i++) {
255 if (!__params[i].doBind())
256 return false;
257 }
258
259 OciConnection* pConnection = conn();
260 OCIError* pError = pConnection->errorHandle();
261
262 sword status = OCI_SUCCESS;
263 status = ::OCIStmtExecute(
264 pConnection->svcctxHandle(),
265 __stmt,
266 pError,
267 (__stmtType == OCI_STMT_SELECT) ? 0 : 1,
268 0,
269 NULL,
270 NULL,
271 OCI_DEFAULT);
272 if (status != OCI_SUCCESS) {
273 __SET_ERROR_NORESET(SQL::eServerError, status, pError);
274 return false;
275 }
276
277 // OCI의 경우 stmt execute 후 fields를 결정할 수 있다.
278 if (__stmtType == OCI_STMT_SELECT) {
279 if (!__fields) {
280 if (!initFields())
281 return false;
282 }
283
284 Query::__eof = false;
285 }
286
287 for(size_t i = 0; i < Query::__paramCount; i++) {
288 if (!__params[i].onAfterExecute())
289 return false;
290 }
291
292/*
293 for(size_t i = 0; i < Query::__paramCount; i++)
294 {
295 if (__params[i]._dataType() == SQLT_BLOB)
296 if(!__params[i].writeBlob())
297 return false;
298 }
299*/
300 if (__stmtType == OCI_STMT_UPDATE
301 || __stmtType == OCI_STMT_INSERT
302 || __stmtType == OCI_STMT_DELETE) {
303
304 ub8 nAffectedRows = 0;
305 status = ::OCIAttrGet(__stmt,
306 OCI_HTYPE_STMT,
307 &nAffectedRows,
308 NULL,
309 OCI_ATTR_UB8_ROW_COUNT,
310 pError);
311 if (status != OCI_SUCCESS) {
312 __SET_ERROR(SQL::eServerError, status, pError);
313 return false;
314 }
315 Query::__affectedRows = nAffectedRows;
316 }
317 return true;
318}
320{
321 __DCL_ASSERT(!eof());
322 OCIError* pError = conn()->errorHandle();
323 sword status = ::OCIStmtFetch2(
324 __stmt,
325 pError,
326 1,
327 OCI_FETCH_NEXT, 0,
328 OCI_DEFAULT);
329 if (status == OCI_SUCCESS) {
330 for(size_t i = 0; i < Query::__fieldCount; i++) {
331 if (!__fields[i].onAfterFetch())
332 return false;
333 }
334 return true;
335 }
336 else if (status == OCI_NO_DATA) {
337 Query::__eof = true;
338 return true;
339 }
340
341 __SET_ERROR_NORESET(SQL::eServerError, status, pError);
342 return false;
343}
344
345bool OciQuery::__getField(size_t _index, SQL::Field** _fieldHandleOut)
346{
347 __DCL_ASSERT(Query::__fieldCount > 0);
348 __DCL_ASSERT((0 <= _index) && (_index < Query::__fieldCount));
349 *_fieldHandleOut = &__fields[_index];
350 return true;
351}
352
353bool OciQuery::__getParam(size_t _index, SQL::Param** _paramHandleOut)
354{
355 __DCL_ASSERT(Query::__paramCount > 0);
356 __DCL_ASSERT((0 <= _index) && (_index < Query::__paramCount));
357 *_paramHandleOut = &__params[_index];
358 return true;
359}
360
361__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
#define __DCL_TRACE2_N(fmt, arg1, arg2)
#define __DCL_TRACE0(psz)
Definition Object.h:375
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#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
#define __SET_ERROR_NORESET(_error, status, pError)
Definition OciQuery.cpp:45
#define _OCI_STMT_TYPE_UNKNOWN
Definition OciQuery.h:6
ByteBuffer * buf
#define __SET_ERROR(_errorCode)
Definition SQLCore.cpp:150
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
OCISvcCtx * svcctxHandle() const
OCIError * errorHandle() const
virtual bool __fetch()
Definition OciQuery.cpp:319
bool initFields()
Definition OciQuery.cpp:219
virtual void __destroy()
Definition OciQuery.cpp:88
virtual bool __getParam(size_t _index, SQL::Param **_paramHandleOut)
Definition OciQuery.cpp:353
OciQuery(OciConnection *_connHandle)
virtual bool __getField(size_t _index, SQL::Field **_fieldHandleOut)
Definition OciQuery.cpp:345
ub2 __stmtType
Definition OciQuery.h:21
OciField * __fields
Definition OciQuery.h:23
OCIStmt * __stmt
Definition OciQuery.h:20
virtual bool __execute()
Definition OciQuery.cpp:252
OciParam * __params
Definition OciQuery.h:24
virtual bool __prepare(const char *_sql, size_t _sqllen, size_t _paramCount)
Definition OciQuery.cpp:175
bool initParams(size_t _paramCount)
Definition OciQuery.cpp:132
bool reset()
Definition OciQuery.cpp:93
virtual ~OciQuery()
Definition OciQuery.cpp:62
@ eOutOfMemory
Definition SQLCore.h:24
@ eServerError
Definition SQLCore.h:21