DCL 4.0
Loading...
Searching...
No Matches
IBConnection.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <stdlib.h> // strtol
4#include <string.h> // strncpy
5
6#include <ibase.h>
7
8#include <dcl/Object.h>
9#if __DCL_HAVE_ALLOC_DEBUG
10#undef __DCL_ALLOC_LEVEL
11#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
12#endif
13
14#include <dcl/Numeric.h>
15#include <dcl/Regex.h>
16#include <dcl/SQLCore.h>
17
18#include "IBConnection.h"
19#include "IBQuery.h"
20
21#undef __THIS_FILE__
22static const wchar_t __THIS_FILE__[] = __T("dcl/sql/IBConnection.cpp");
23
24__DCL_BEGIN_NAMESPACE
25
27
28IBConnection::IBConnection(const wchar_t* _serverTitle)
29 : Connection(_serverTitle)
30{
31 Connection::__canTransact = true;
32
33 __dialect = SQL_DIALECT_CURRENT;
34 __dbHandle = NULL;
35 __trHandle = NULL;
36// memset(__status, 0, sizeof(ISC_STATUS) * ISC_STATUS_VECTOR_LENGTH);
37}
38
42
44{
45// cerr << "IBConnection::destory\n";
46 delete this;
47}
48
49/*
50 pszConnectionString에 가능한 property
51 USER,
52 PASSWORD,
53 SERVER, -- host name
54 DATABASE
55 SQL_DIALECT
56
57 or CREATE DATABASE statement
58*/
59
60static const char* __createDatabasePattern__ = "CREATE[[:space:]]+DATABASE";
61
62bool IBConnection::__open(const char* _connString, size_t _connlen)
63{
64 try {
65 if (Regex::test(__createDatabasePattern__, _connString, true)) {
66 // CREATE DATABASE
67 if(isc_dsql_execute_immediate(
68 __status,
69 &__dbHandle,
70 &__trHandle,
71 0,
72 (_CONST char*)_connString,
73 __dialect,
74 NULL)) {
76 return false;
77 }
78 return true;
79 }
80 }
81 catch(RegexException* e) {
82 e->destroy();
83 }
84
85 ListedByteStringToByteStringMap map;
86 Connection::splitConnectionString(_connString, _connlen, map);
87
88 ByteString strServer = map["SERVER"];
89 ByteString strDatabase = map["DATABASE"];
90 ByteString strUser = map["USER"];
91 ByteString strPassword = map["PASSWORD"];
92 ByteString strSqlDialect = map["SQL_DIALECT"];
93
94 if (!strSqlDialect.isEmpty()) {
95 int nDialect = SQL_DIALECT_CURRENT;
96 char* endptr;
97 long n = strtol(strSqlDialect, &endptr, 10);
98 if (n == LONG_MAX || n == LONG_MIN
99 || n < INT_MIN || INT_MAX < n
100 ) {
101 __SET_ERROR_MSG("연결 문자열이 잘못되었습니다. SQL_DIALECT="
102 + strSqlDialect);
103 return false;
104 }
105
106 nDialect = (int)n;
107
108 if (!(nDialect == SQL_DIALECT_V5
109 || nDialect == SQL_DIALECT_V6_TRANSITION
110 || nDialect == SQL_DIALECT_V6)) {
111 __SET_ERROR_MSG("\"SQL_DIALECT\"- invalid value");
112 return false;
113 }
114
115 __dialect = nDialect;
116 }
117
118 if ((strUser.length() > 127) || (strPassword.length() > 127)) {
119 // USER NAME 과 PASSWORD 의 길이는 127을 넘을 수 없다.
121 return false;
122 }
123
124 ByteString strDatabaseEnv;
125 if (!strServer.isEmpty())
126 strDatabaseEnv = strServer + ":";
127
128 if (!strDatabase.isEmpty())
129 strDatabaseEnv = strDatabaseEnv + strDatabase;
130
131 if (strDatabaseEnv.isEmpty()) {
133 return false;
134 }
135
136 // database parameter block
137 ByteStringBuilder dpb;
138 dpb = (char)isc_dpb_version1;
139 dpb += (char)isc_dpb_user_name;
140 dpb += (char)strUser.length();
141 dpb += strUser;
142 dpb += (char)isc_dpb_password;
143 dpb += (char)strPassword.length();
144 dpb += strPassword;
145
146 dpb += (char)isc_dpb_lc_ctype;
147 dpb += (char)4;
148 dpb += "UTF8";
149
150 if (isc_attach_database(
151 __status,
152 strDatabaseEnv.length(),
153 (_CONST char*)strDatabaseEnv.data(),
154 &__dbHandle,
155 dpb.length(),
156 (_CONST char*)dpb.data())
157 ) {
158// __DCL_ASSERT(STATUS_FAILED(__status));
160 __dbHandle = NULL;
161 return false;
162 }
163 return true;
164}
165
167{
168 __DCL_ASSERT(__dbHandle != NULL);
169 __DCL_ASSERT(__trHandle == NULL);
170
171 if (isc_detach_database(
172 __status,
173 &__dbHandle)
174 ) {
175// __DCL_ASSERT(STATUS_FAILED(__status));
177 return false;
178 }
179 __dbHandle = NULL;
180 return true;
181}
182
189
190typedef struct {
191 StmtType type;
192 const char* pattern;
194
195static STMT_PATTERN sp[] = {
196 { StmtTransBegin, "SET[[:space:]]+TRANSACTION" },
197 { StmtTransEnd, "COMMIT|ROLLBACK" },
198 { StmtCreateDatabase, __createDatabasePattern__ },
199 { StmtOther, NULL }
200};
201
202static StmtType __GetStmtType(const char* _sql)
203{
204 for(size_t i = 0; sp[i].type != StmtOther; i++) {
205 if (Regex::test(sp[i].pattern, _sql, true))
206 return sp[i].type;
207 }
208 return StmtOther;
209}
210
211bool IBConnection::__execute(const char* _sql, size_t n)
212{
214 __DCL_ASSERT(__dbHandle != NULL);
215 if(isc_dsql_execute_immediate(
216 __status,
217 &__dbHandle,
218 &__trHandle,
219 (unsigned short int)n,
220 (_CONST char*)_sql,
221 __dialect,
222 NULL)
223 ) {
224// __DCL_ASSERT(STATUS_FAILED(__status));
226 return false;
227 }
228
229 switch (__GetStmtType(_sql)) {
230 case StmtTransBegin :
232 __DCL_ASSERT(__trHandle != NULL);
233 break;
234 case StmtTransEnd :
236 __trHandle = NULL;
237 break;
238 default :
239 ;
240 }
241
242 return true;
243}
244
246{
247 __DCL_ASSERT(__trHandle == NULL);
248 if (isc_start_transaction(
249 __status,
250 &__trHandle,
251 1,
252 &__dbHandle,
253 0,
254 NULL)
255 ) {
256// __DCL_ASSERT(STATUS_FAILED(__status));
258 return false;
259 }
260
261 return true;
262}
263
265{
266 __DCL_ASSERT(__trHandle != NULL);
267 if(isc_commit_transaction(
268 __status,
269 &__trHandle)
270 ) {
271// __DCL_ASSERT(STATUS_FAILED(__status));
273 return false;
274 }
275 __trHandle = NULL;
276
277 return true;
278}
279
281{
282 __DCL_ASSERT(__trHandle != NULL);
283 if(isc_rollback_transaction(
284 __status,
285 &__trHandle)
286 ) {
287// __DCL_ASSERT(STATUS_FAILED(__status));
289 return false;
290 }
291 __trHandle = NULL;
292
293 return true;
294}
295
297{
298 __DCL_ASSERT(_queryHandleOut != NULL);
299
300 SQL::Query* pNewQuery = new IBQuery(this);
301 if (!pNewQuery) {
303 return false;
304 }
305
306 *_queryHandleOut = pNewQuery;
307 return true;
308}
309
310bool IBConnection::__getErrorMessage(char* _buf, size_t* _buflen)
311{
312 ByteStringBuilder sb;
313 if (!__lastErrorMessage.isEmpty())
314 sb = __lastErrorMessage;
315 else {
316 char sz[512];
317 ISC_STATUS* pStatus = __status;
318 long nLen = 0;
319 for(size_t i = 0; (nLen = isc_interprete(sz, &pStatus))
320 && (i < ISC_STATUS_VECTOR_LENGTH); i++) {
321 if (i > 0)
322 sb += ", ";
323 sb.append(sz, 0, nLen);
324 }
325 }
326
327 if (sb.length() < *_buflen)
328 *_buflen = sb.length();
329
330 strncpy(_buf, sb.data(), *_buflen);
331
332 return true;
333}
334
335static char database_info_items[] = {
336 isc_info_version,
337 isc_info_db_id,
338 isc_info_end
339};
340
341bool IBConnection::__getServerInfo(char* _buf, size_t* _buflen)
342{
343 char buffer[512];
344 if (isc_database_info (
345 __status,
346 &__dbHandle,
347 sizeof(database_info_items),
348 database_info_items,
349 sizeof(buffer),
350 buffer)) {
352 return false;
353 }
354
355 ByteString strVersion;
356 ByteString strDb;
357 ByteString strSite;
358
359 char* p = buffer;
360 char item;
361 unsigned short length;
362 __DCL_ASSERT(sizeof(unsigned short) == 2);
363 while(*p != isc_info_end) {
364 item = *p++;
365 length = (unsigned short)isc_vax_integer(p, 2);
366 p += 2;
367 if (item == isc_info_version) {
368 // __DCL_ASSERT(p[0] == 1);
369 //__DCL_TRACE1(L"[%d]\n", p[0]);
370 strVersion.assign(p, 2, p[1]);
371 }
372 else if (item == isc_info_db_id) {
373 char* t = p;
374 //__DCL_TRACE1(L"[%d]\n", *t);
375 //__DCL_ASSERT(*t == 2);
376 t++;
377 unsigned short nStrLen = *t++;
378 strDb.assign(t, nStrLen);
379 t += nStrLen;
380 nStrLen = *t++;
381 strSite.assign(t, nStrLen);
382 }
383 else {
385 return false;
386 }
387 p += length;
388 }
389
390 ByteString strInfo = "InterBase " + strVersion + " \"" + strSite + ':' + strDb + "\"";
391 if (strInfo.length() < *_buflen)
392 *_buflen = strInfo.length();
393
394 strncpy(_buf, strInfo.data(), *_buflen);
395 return true;
396}
397
398__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
#define UINT16_MAX
Definition Config.h:322
#define _CONST
Definition Config.h:353
@ StmtCreateDatabase
#define __SET_ERROR(_error)
#define ISC_STATUS_VECTOR_LENGTH
Definition IBConnection.h:6
#define __SET_ERROR_MSG(str)
@ StmtTransEnd
@ StmtOther
@ StmtTransBegin
#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 __UNSET_STATE(state)
Definition SQLCore.h:431
#define __SET_STATE(state)
Definition SQLCore.h:430
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
virtual void destroy()
Definition Exception.cpp:74
virtual bool __createQueryInstance(SQL::Query **_queryHandleOut)
virtual ~IBConnection()
virtual bool __execute(const char *_sql, size_t _sqllen)
virtual void destroy()
virtual bool __commitTrans()
virtual bool __getServerInfo(char *_buf, size_t *_buflen)
virtual bool __startTrans()
virtual bool __close()
virtual bool __rollbackTrans()
virtual bool __open(const char *_connString, size_t _connlen)
virtual bool __getErrorMessage(char *_buf, size_t *_buflen)
IBConnection(const wchar_t *_serverTitle)
static bool test(const wchar_t *_regex, const wchar_t *_string, bool _icase=false) __DCL_THROWS1(RegexException *)
Definition Regex.cpp:252
@ eOutOfMemory
Definition SQLCore.h:24
@ eInvalidConnectionString
Definition SQLCore.h:31
@ eServerError
Definition SQLCore.h:21
@ eNotAvailable
Definition SQLCore.h:38