DCL 4.0
Loading...
Searching...
No Matches
MyConnection.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <string.h> // strlen, strncpy
4#include <stdlib.h> // strtol, strtoul, strtoll, strtoull
5
6#include <dcl/Object.h>
7#if __DCL_HAVE_ALLOC_DEBUG
8#undef __DCL_ALLOC_LEVEL
9#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
10#endif
11
12#include <dcl/Regex.h>
13#include <dcl/ListedHashMap.h>
14#include <dcl/SQLCore.h>
15
16#include "MyConnection.h"
17#include "MyQuery.h"
18
19#define __TRACE_THIS 0
20#if __TRACE_THIS
21#define __DCL_TRACE0_N __DCL_TRACE0
22#define __DCL_TRACE1_N __DCL_TRACE1
23#define __DCL_TRACE2_N __DCL_TRACE2
24#define __DCL_TRACE3_N __DCL_TRACE3
25#define __DCL_TRACE4_N __DCL_TRACE4
26#else
27#define __DCL_TRACE0_N(fmt)
28#define __DCL_TRACE1_N(fmt, arg)
29#define __DCL_TRACE2_N(fmt, arg1, arg2)
30#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
31#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
32#endif
33
34#if __DCL_HAVE_THIS_FILE__
35#undef __THIS_FILE__
36static const wchar_t __THIS_FILE__[] = __T("dcl/sql/MyConnection.cpp");
37#endif
38
39__DCL_BEGIN_NAMESPACE
40
42
43MyConnection::MyConnection(const wchar_t* _serverTitle)
44 : Connection(_serverTitle)
45{
46 Connection::__canTransact = true;
47 __mysql = NULL;
48 __storeResult = false;
49}
50
52{
53 if (__mysql) {
54 __DCL_TRACE0_N(L"Warning!! The connection was not closed\n");
55 close();
56 }
57}
58
60{
61 delete this;
62}
63
64/*
65pszConnectionByteString에 가능한 property
66 for mysql_real_connect
67 USER,
68 PASSWORD,
69 SERVER, -- host name
70 DATABASE,
71 PORT, -- tcp port
72 UNIX_SOCKET,
73
74 for mysql_options
75 APPLICATION
76
77 driver options
78 STORE_RESULT
79
80*/
81
82bool MyConnection::__open(const char* _pszConnString, size_t _n)
83{
84 if ((__mysql = mysql_init(NULL)) == NULL) {
86 return false;
87 }
88
89 ListedByteStringToByteStringMap map;
90 Connection::splitConnectionString(_pszConnString, _n, map);
91
92 ByteString strAppName = map["APPLICATION"];
93
94 if (!strAppName.isEmpty()) {
95 mysql_options(connHandle(), MYSQL_READ_DEFAULT_GROUP, strAppName.data());
96 }
97
98 ByteString strUser = map["USER"];
99 ByteString strPassword = map["PASSWORD"];
100 ByteString strHost = map["SERVER"];
101 ByteString strDb = map["DATABASE"];
102 ByteString strPort = map["PORT"];
103 ByteString strUnixSocket = map["UNIX_SOCKET"];
104 __storeResult = map.find("STORE_RESULT") != map.end();
105
106 unsigned int port = 0;
107 if (!strPort.isEmpty()) {
108 char* endptr;
109 unsigned long n = strtoul(strPort.data(), &endptr, 10);
110 if (n == ULONG_MAX) {
111 __SET_ERROR_MSG("연결 문자열이 잘못되었습니다. PORT=" + strPort);
112 return false;
113 }
114 port = (unsigned int) n;
115 }
116
117 if (mysql_real_connect(
118 connHandle(),
119 strHost.isEmpty()? NULL : strHost.data(),
120 strUser.isEmpty()? NULL : strUser.data(),
121 strPassword.isEmpty()? NULL : strPassword.data(),
122 strDb.isEmpty() ? NULL : strDb.data(),
123 port,
124 strUnixSocket.isEmpty() ? NULL : strUnixSocket.data(),
125 0
126 ) == NULL) {
128 return false;
129 }
130
131 if (mysql_set_character_set(connHandle(), "utf8")) {
132 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
133 mysql_errno(connHandle()),
134 mysql_error(connHandle())));
135 return false;
136 }
137
138 if (mysql_autocommit(connHandle(), 0)) {
139 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
140 mysql_errno(connHandle()),
141 mysql_error(connHandle())));
142 return false;
143 }
144
145 return true;
146}
147
149{
150 if (!__mysql) {
152 return false;
153 }
154
155 mysql_close(__mysql);
156 __mysql = NULL;
157
158 return true;
159}
160
166
167typedef struct {
168 StmtType type;
169 const char* pattern;
171
172static STMT_PATTERN sp[] = {
173 { StmtTransBegin, "START[[:space:]]+TRANSACTION|BEGIN" },
174 { StmtTransEnd, "COMMIT|ROLLBACK" },
175 { StmtOther, NULL }
176};
177
178static StmtType __GetStmtType(const char* _sql)
179{
180 for (size_t i = 0; sp[i].type != StmtOther; i++) {
181 try {
182 if (Regex::test(sp[i].pattern, _sql, true))
183 return sp[i].type;
184 }
185 catch (Exception* p) {
186 p->destroy();
187 }
188 }
189 return StmtOther;
190}
191
192bool MyConnection::__execute(const char* _sql, size_t _n)
193{
194 if (mysql_real_query(connHandle(), _sql, (unsigned long) _n)) {
195 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
196 mysql_errno(connHandle()),
197 mysql_error(connHandle())));
198 }
199
200 switch (__GetStmtType(_sql)) {
201 case StmtTransBegin:
203 break;
204 case StmtTransEnd:
206 break;
207 case StmtOther:
208 default:
209 ;
210 }
211
212 return true;
213}
214
216{
217 return __execute("START TRANSACTION", 17);
218}
219
221{
222 if (mysql_commit(connHandle())) {
223 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
224 mysql_errno(connHandle()),
225 mysql_error(connHandle())));
226 }
227
228 return true;
229}
230
232{
233 if (mysql_rollback(connHandle())) {
234 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
235 mysql_errno(connHandle()),
236 mysql_error(connHandle())));
237 }
238
239 return true;
240}
241
243{
244 __DCL_ASSERT(_ppQuery != NULL);
245
246 MyQuery* pNewQuery = new MyQuery(this);
247 if (!pNewQuery) {
249 return false;
250 }
251
252 *_ppQuery = pNewQuery;
253 return true;
254}
255
256bool MyConnection::__getErrorMessage(char* _buffer, size_t* _size)
257{
258 if (__lastErrorMessage.length() < *_size)
259 *_size = __lastErrorMessage.length();
260
261 strncpy(_buffer, __lastErrorMessage.data(), *_size);
262
263 return true;
264}
265
266bool MyConnection::__getServerInfo(char* _buffer, size_t* _size)
267{
268 const char* psz = mysql_get_server_info(connHandle());
269 if (!psz)
270 return false;
271
272 size_t nLength = strlen(psz);
273
274 if (nLength < *_size)
275 *_size = nLength;
276
277 strncpy(_buffer, psz, *_size);
278
279 return true;
280}
281
282__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
@ StmtTransEnd
@ StmtOther
@ StmtTransBegin
#define __DCL_TRACE0_N(fmt)
Definition IFXField.cpp:37
#define __SET_ERROR(_error)
#define __SET_ERROR_MSG(_msg)
#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 __startTrans()
virtual bool __rollbackTrans()
virtual void destroy()
MyConnection(const wchar_t *_serverTitle)
virtual bool __close()
virtual bool __commitTrans()
virtual bool __createQueryInstance(SQL::Query **_ppQuery)
virtual bool __execute(const char *pszSQL, size_t _n)
virtual bool __getServerInfo(char *_buffer, size_t *_size)
MYSQL * connHandle() const
virtual bool __open(const char *_pszConnString, size_t _n)
virtual bool __getErrorMessage(char *_buffer, size_t *_size)
virtual ~MyConnection()
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
@ eServerError
Definition SQLCore.h:21
@ eNotConnected
Definition SQLCore.h:33