DCL 4.0
Loading...
Searching...
No Matches
IFXConnection.cpp
Go to the documentation of this file.
1#line 1 "ifxconnection.ec"
2#include <dcl/Config.h>
3
4#include <sqlhdr.h>
5#include <sqliapi.h>
6
7#include <sqlstype.h>
8
9#if __DCL_WINDOWS
10 #include <windows.h>
11 #if __DCL_PTHREAD
12 #include <pthread.h>
13 #endif
14#else
15 #include <pthread.h>
16#endif
17
18#include <ctype.h> // isspace
19#include <string.h> // strlen, strncpy
20
21#include <dcl/Object.h>
22#if __DCL_HAVE_ALLOC_DEBUG
23#undef __DCL_ALLOC_LEVEL
24#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
25#endif
26
27#include <dcl/Numeric.h>
28#include <dcl/Regex.h>
29#include <dcl/Thread.h>
30
31#include <dcl/SQLCore.h>
32
33#include "IFXConnection.h"
34#include "IFXQuery.h"
35#include "IFXField.h" // for _getServerInfo
36
37#undef __THIS_FILE__
38static const wchar_t __THIS_FILE__[] = __T("dcl/sql/IFXConnection.ec");
39
40__DCL_BEGIN_NAMESPACE
41
43
44static volatile long __connectionID__ = 0;
45
46IFXConnection::IFXConnection(const wchar_t* _serverTitle)
47 : Connection(_serverTitle)
48{
49 __connectionID = ByteString::format("con:%ld", Thread::incrementAndGet(__connectionID__));
50}
51
55
57{
58 delete this;
59}
60
61/*
62pszConnectionString에 가능한 프로퍼티
63 USER,
64 PASSWORD,
65 SERVER, -- host name
66 DATABASE
67*/
68
69void IFXConnection::reset()
70{
71/*
72 * EXEC SQL BEGIN DECLARE SECTION;
73 */
74#line 67 "ifxconnection.ec"
75#line 68 "ifxconnection.ec"
76 char *pszConnectionID = (_CONST char*) __connectionID.data();
77/*
78 * EXEC SQL END DECLARE SECTION;
79 */
80#line 69 "ifxconnection.ec"
81
82
83/*
84 * EXEC SQL SET CONNECTION :pszConnectionID;
85 */
86#line 71 "ifxconnection.ec"
87 {
88#line 71 "ifxconnection.ec"
89 sqli_connect_set(0, pszConnectionID, 0);
90#line 71 "ifxconnection.ec"
91 }
92
93/*
94 * EXEC SQL BEGIN WORK;
95 */
96#line 73 "ifxconnection.ec"
97 {
98#line 73 "ifxconnection.ec"
99 sqli_trans_begin2((mint)1);
100#line 73 "ifxconnection.ec"
101 }
102 if (SQLCODE == 0) {
103 Connection::__canTransact = true;
104/*
105 * EXEC SQL ROLLBACK WORK;
106 */
107#line 76 "ifxconnection.ec"
108 {
109#line 76 "ifxconnection.ec"
110 sqli_trans_rollback();
111#line 76 "ifxconnection.ec"
112 }
113 }
114 else
115 Connection::__canTransact = false;
116
118}
119
120bool IFXConnection::__open(const char* _connString, size_t _connlen)
121{
122 ListedByteStringToByteStringMap map;
123 Connection::splitConnectionString(_connString, _connlen, map);
124
125 ByteString strServer = map["SERVER"];
126 ByteString strUser = map["USER"];
127 ByteString strPassword = map["PASSWORD"];
128 ByteString strDatabase = map["DATABASE"];
129
130 ByteString strDatabaseEnv = strDatabase;
131 if (!strServer.isEmpty()) {
132 strDatabaseEnv = strDatabaseEnv + "@" + strServer;
133 }
134 //__DCL_TRACE1(L"[%hs]\n", strDatabaseEnv.data());
135
136/*
137 * EXEC SQL BEGIN DECLARE SECTION;
138 */
139#line 100 "ifxconnection.ec"
140#line 101 "ifxconnection.ec"
141 char *pszUserName = (_CONST char*) strUser.data();
142 char *pszPassword = (_CONST char*) strPassword.data();
143 char *pszDatabaseEnv = (_CONST char*) strDatabaseEnv.data();
144 char *pszConnectionID = NULL;
145/*
146 * EXEC SQL END DECLARE SECTION;
147 */
148#line 105 "ifxconnection.ec"
149
150
151 pszConnectionID = (_CONST char*) __connectionID.data();
152
153/*
154 * EXEC SQL CONNECT TO :pszDatabaseEnv AS :pszConnectionID
155 * USER :pszUserName USING :pszPassword
156 * WITH CONCURRENT TRANSACTION;
157 */
158#line 109 "ifxconnection.ec"
159 {
160#line 111 "ifxconnection.ec"
161 ifx_conn_t *_sqiconn;
162 _sqiconn = (ifx_conn_t *)ifx_alloc_conn_user(pszUserName, pszPassword);
163 sqli_connect_open(ESQLINTVERSION, 0, pszDatabaseEnv, pszConnectionID, _sqiconn, 1);
164 ifx_free_conn_user(&_sqiconn);
165#line 111 "ifxconnection.ec"
166 }
167 if (SQLCODE < 0) {
168 __SET_ERROR_SQLCODE(SQLCODE);
169 return false;
170 }
171
172 if (!strDatabase.isEmpty())
173 reset();
174
175 return true;
176}
177
179{
180/*
181 * EXEC SQL BEGIN DECLARE SECTION;
182 */
183#line 125 "ifxconnection.ec"
184#line 126 "ifxconnection.ec"
185 char *pszConnectionID = (_CONST char*) __connectionID.data();
186/*
187 * EXEC SQL END DECLARE SECTION;
188 */
189#line 127 "ifxconnection.ec"
190
191
192/*
193 * EXEC SQL DISCONNECT :pszConnectionID;
194 */
195#line 129 "ifxconnection.ec"
196 {
197#line 129 "ifxconnection.ec"
198 sqli_connect_close(0, pszConnectionID, 0, 0);
199#line 129 "ifxconnection.ec"
200 }
201 if (SQLCODE < 0) {
202 __SET_ERROR_SQLCODE(SQLCODE);
203 return false;
204 }
205
206 return true;
207}
208
215
216typedef struct {
218 const char* pattern;
220
221static STMT_PATTERN sp[] = {
222 { StmtTransBegin, "BEGIN" },
223 { StmtTransEnd, "COMMIT|ROLLBACK" },
224 { StmtDatabase, "DATABASE" },
225 { StmtOther, NULL }
226};
227
228static StmtType __GetStmtType(const char* _sql)
229{
230 for(size_t i = 0; sp[i].type != StmtOther; i++) {
231 try {
232 if (Regex::test(sp[i].pattern, _sql, true))
233 return sp[i].type;
234 }
235 catch(Exception* e) {
236 e->destroy();
237 }
238 }
239 return StmtOther;
240}
241
242bool IFXConnection::__execute(const char* _sql, size_t _sqllen)
243{
244/*
245 * EXEC SQL BEGIN DECLARE SECTION;
246 */
247#line 173 "ifxconnection.ec"
248#line 174 "ifxconnection.ec"
249 char *pszConnectionID = (_CONST char*) __connectionID.data();
250 char *pszSqlStatement = (_CONST char*) _sql;
251/*
252 * EXEC SQL END DECLARE SECTION;
253 */
254#line 176 "ifxconnection.ec"
255
256
257/*
258 * EXEC SQL SET CONNECTION :pszConnectionID;
259 */
260#line 178 "ifxconnection.ec"
261 {
262#line 178 "ifxconnection.ec"
263 sqli_connect_set(0, pszConnectionID, 0);
264#line 178 "ifxconnection.ec"
265 }
266 if (SQLCODE < 0) {
267 __SET_ERROR_SQLCODE(SQLCODE);
268 return false;
269 }
270
271/*
272 * EXEC SQL EXECUTE IMMEDIATE :pszSqlStatement;
273 */
274#line 184 "ifxconnection.ec"
275 {
276#line 184 "ifxconnection.ec"
277 sqli_exec_immed(pszSqlStatement);
278#line 184 "ifxconnection.ec"
279 }
280 if (SQLCODE < 0) {
281 __SET_ERROR_SQLCODE(SQLCODE);
282 return false;
283 }
284
285 switch(__GetStmtType(_sql)) {
286 case StmtTransBegin :
288 break;
289 case StmtTransEnd :
291 break;
292 case StmtDatabase :
293 reset();
294 break;
295 case StmtOther :
296 default :
297 ;
298 }
299
300 return true;
301}
302
304{
305/*
306 * EXEC SQL BEGIN DECLARE SECTION;
307 */
308#line 210 "ifxconnection.ec"
309#line 211 "ifxconnection.ec"
310 char *pszConnectionID = (_CONST char*) __connectionID.data();
311/*
312 * EXEC SQL END DECLARE SECTION;
313 */
314#line 212 "ifxconnection.ec"
315
316
317/*
318 * EXEC SQL SET CONNECTION :pszConnectionID;
319 */
320#line 214 "ifxconnection.ec"
321 {
322#line 214 "ifxconnection.ec"
323 sqli_connect_set(0, pszConnectionID, 0);
324#line 214 "ifxconnection.ec"
325 }
326 if (SQLCODE < 0) {
327 __SET_ERROR_SQLCODE(SQLCODE);
328 return false;
329 }
330
331/*
332 * EXEC SQL BEGIN WORK;
333 */
334#line 220 "ifxconnection.ec"
335 {
336#line 220 "ifxconnection.ec"
337 sqli_trans_begin2((mint)1);
338#line 220 "ifxconnection.ec"
339 }
340 if (SQLCODE < 0) {
341 __SET_ERROR_SQLCODE(SQLCODE);
342 return false;
343 }
344
346 return true;
347}
348
350{
351/*
352 * EXEC SQL BEGIN DECLARE SECTION;
353 */
354#line 232 "ifxconnection.ec"
355#line 233 "ifxconnection.ec"
356 char *pszConnectionID = (_CONST char*) __connectionID.data();
357/*
358 * EXEC SQL END DECLARE SECTION;
359 */
360#line 234 "ifxconnection.ec"
361
362
363/*
364 * EXEC SQL SET CONNECTION :pszConnectionID;
365 */
366#line 236 "ifxconnection.ec"
367 {
368#line 236 "ifxconnection.ec"
369 sqli_connect_set(0, pszConnectionID, 0);
370#line 236 "ifxconnection.ec"
371 }
372 if (SQLCODE < 0) {
373 __SET_ERROR_SQLCODE(SQLCODE);
374 return false;
375 }
376
377/*
378 * EXEC SQL COMMIT WORK;
379 */
380#line 242 "ifxconnection.ec"
381 {
382#line 242 "ifxconnection.ec"
383 sqli_trans_commit();
384#line 242 "ifxconnection.ec"
385 }
386 if (SQLCODE < 0) {
387 __SET_ERROR_SQLCODE(SQLCODE);
388 return false;
389 }
390
392 return true;
393}
394
396{
397/*
398 * EXEC SQL BEGIN DECLARE SECTION;
399 */
400#line 254 "ifxconnection.ec"
401#line 255 "ifxconnection.ec"
402 char *pszConnectionID = (_CONST char*) __connectionID.data();
403/*
404 * EXEC SQL END DECLARE SECTION;
405 */
406#line 256 "ifxconnection.ec"
407
408
409/*
410 * EXEC SQL SET CONNECTION :pszConnectionID;
411 */
412#line 258 "ifxconnection.ec"
413 {
414#line 258 "ifxconnection.ec"
415 sqli_connect_set(0, pszConnectionID, 0);
416#line 258 "ifxconnection.ec"
417 }
418 if (SQLCODE < 0) {
419 __SET_ERROR_SQLCODE(SQLCODE);
420 return false;
421 }
422
423/*
424 * EXEC SQL ROLLBACK WORK;
425 */
426#line 264 "ifxconnection.ec"
427 {
428#line 264 "ifxconnection.ec"
429 sqli_trans_rollback();
430#line 264 "ifxconnection.ec"
431 }
432 if (SQLCODE < 0) {
433 __SET_ERROR_SQLCODE(SQLCODE);
434 return false;
435 }
436
438 return true;
439}
440
442{
443 __DCL_ASSERT(_queryHandleOut != NULL);
444
445 SQL::Query* pNewQuery = new IFXQuery(this);
446 if (!pNewQuery) {
448 return false;
449 }
450
451 *_queryHandleOut = pNewQuery;
452 return true;
453}
454
455void IFXConnection::setErrorStatus(SQL::Error _error, long _SQLCODE,
456 const wchar_t* _filename, int _line)
457{
458 Connection::setErrorStatus(_error, _filename, _line);
459 if (_SQLCODE == 0) {
460 __lastErrorMessage.clear();
461 return;
462 }
463
464 __DCL_ASSERT(_SQLCODE == sqlca.sqlcode);
465
466 ByteStringBuilder sb;
467 sb.format("SQLCODE(%d) ", _SQLCODE);
468
469 char buf[600];
470 mint actual = 0;
471 mint r = rgetlmsg(_SQLCODE, buf, sizeof(buf), &actual);
472 if (!r) {
473 while (actual > 0) {
474 if (!isspace(buf[actual - 1]))
475 break;
476 actual--;
477 }
478 buf[actual] = '\0';
479 sb.format(buf, sqlca.sqlerrm);
480 }
481 else {
482 sb.format("(%d)", r);
483 switch (r) {
484 case -1227:
485 sb.append("Message file not found");
486 break;
487 case -1228:
488 sb.append("Message number not found in message file");
489 break;
490 case -1231:
491 sb.append("Cannot seek within messge file");
492 break;
493 case -1232:
494 sb.append("Message buffer too small");
495 break;
496 default:
497 sb.append("Unkndown");
498 }
499 }
500 __lastErrorMessage = sb.toByteString();
501}
502
503bool IFXConnection::__getErrorMessage(char* _buf, size_t* _buflen)
504{
505 __DCL_ASSERT(Connection::__errorCode == SQL::eServerError);
506 if (__lastErrorMessage.length() < *_buflen)
507 *_buflen = __lastErrorMessage.length();
508 strncpy(_buf, __lastErrorMessage.data(), *_buflen);
509 return true;
510}
511
512bool IFXConnection::__getServerInfo(char* _buf, size_t* _buflen)
513{
514 IFXQuery* pQuery = new IFXQuery(this);
515 if (pQuery == NULL) {
517 return false;
518 }
519
520 bool localTrans = false;
522 __startTrans();
523 localTrans = true;
524 }
525
526 const char* _sql =
527 "SELECT DBINFO('version', 'full')"
528 " FROM systables WHERE tabid = 1";
529 for (; ; ) {
530 if (!pQuery->prepare(_sql, ByteString::length(_sql), 0))
531 break;
532
533 if (!pQuery->execute())
534 break;
535
536 if (!pQuery->fetch())
537 break;
538
539 if (pQuery->eof()) {
541 break;
542 }
543
544 IFXField* pField = NULL;
545 if (!pQuery->__getField(0, (SQL::Field**)&pField))
546 break;
547
548 if (pField->isNull()) {
550 break;
551 }
552
553 if (!pField->__getData(_buf, _buflen, SQL::typeText))
554 break;
555
556 pQuery->__destroy();
557 pQuery = NULL;
558
559 if (localTrans) {
561 }
562 return true;
563 }
564
565 if (pQuery) {
566 pQuery->__destroy();
567 }
568
569 if (localTrans) {
571 }
572 return false;
573}
574
575__DCL_END_NAMESPACE
576
577#line 408 "ifxconnection.ec"
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
#define _CONST
Definition Config.h:353
@ StmtTransEnd
@ StmtOther
@ StmtTransBegin
@ StmtDatabase
#define __SET_ERROR_SQLCODE(SQLCODE)
#define __SET_ERROR(_error)
int mint
Definition IFXParam.cpp:11
#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
StmtType
ByteString r
ByteBuffer * buf
#define __UNSET_STATE(state)
Definition SQLCore.h:431
#define __SET_STATE(state)
Definition SQLCore.h:430
virtual void destroy()
Definition Exception.cpp:74
virtual ~IFXConnection()
void setErrorStatus(SQL::Error _error, long _SQLCODE, const wchar_t *_filename, int _line)
virtual bool __startTrans()
virtual bool __commitTrans()
virtual bool __rollbackTrans()
virtual bool __open(const char *_connString, size_t _connlen)
virtual bool __createQueryInstance(SQL::Query **_queryHandleOut)
virtual void destroy()
virtual bool __close()
virtual bool __execute(const char *_sql, size_t _sqllen)
virtual bool __getServerInfo(char *_buf, size_t *_buflen)
IFXConnection(const wchar_t *_serverTitle)
virtual bool __getErrorMessage(char *_buf, size_t *_buflen)
virtual bool isNull() const
Definition IFXField.cpp:337
virtual bool __getData(void *_pv, size_t *_size, SQL::DataType _dataType)
Definition IFXField.cpp:384
virtual bool __getField(size_t _index, SQL::Field **_fieldHandleOut)
Definition IFXQuery.cpp:696
virtual void __destroy()
Definition IFXQuery.cpp:116
static bool test(const wchar_t *_regex, const wchar_t *_string, bool _icase=false) __DCL_THROWS1(RegexException *)
Definition Regex.cpp:252
Connection(const wchar_t *_serverTitle)
Definition SQLCore.cpp:653
bool inState(unsigned int uState) const
Definition SQLCore.inl:99
__PROTECTED const wchar_t int _line
Definition SQLCore.h:390
__PROTECTED const wchar_t * _filename
Definition SQLCore.h:390
@ typeText
Definition SQLCore.h:75
Error
Definition SQLCore.h:19
@ eOutOfMemory
Definition SQLCore.h:24
@ eServerError
Definition SQLCore.h:21
@ eNotAvailable
Definition SQLCore.h:38
static long incrementAndGet(volatile long &_n)
const char * pattern