DCL 3.7.4
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 <mysql.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/Regex.h>
15#include <dcl/ListedHashMap.h>
16#include <dcl/SQLCore.h>
17
18#include "MyConnection.h"
19#include "MyQuery.h"
20
21#define __TRACE_THIS 0
22#if __TRACE_THIS
23#define __DCL_TRACE0_N __DCL_TRACE0
24#define __DCL_TRACE1_N __DCL_TRACE1
25#define __DCL_TRACE2_N __DCL_TRACE2
26#define __DCL_TRACE3_N __DCL_TRACE3
27#define __DCL_TRACE4_N __DCL_TRACE4
28#else
29#define __DCL_TRACE0_N(fmt)
30#define __DCL_TRACE1_N(fmt, arg)
31#define __DCL_TRACE2_N(fmt, arg1, arg2)
32#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
33#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
34#endif
35
36#undef __THIS_FILE__
37static const char_t __THIS_FILE__[] = __T("dcl/sql/MyConnection.cpp");
38
39__DCL_BEGIN_NAMESPACE
40
41#define __SET_ERROR_HANDLE(_error) \
42 setErrorHandle(_error, __THIS_FILE__, __LINE__)
43#define __SET_ERROR_MSG(_msg) \
44 setErrorMessage(_msg, __THIS_FILE__, __LINE__)
45
47
48MyConnection::MyConnection(const wchar_t* _serverTitle)
49 : Connection(_serverTitle)
50{
51 Connection::__canTransact = true;
52 __mysql = NULL;
53 __storeResult = false;
54}
55
57{
58 if (__mysql) {
59 __DCL_TRACE0_N(L"Warning!! The connection was not closed\n");
60 close();
61 }
62}
63
65{
66 delete this;
67}
68
69/*
70_conns에 가능한 property
71 for mysql_real_connect
72 USER,
73 PASSWORD,
74 SERVER, -- host name
75 DATABASE,
76 PORT, -- tcp port
77 UNIX_SOCKET,
78
79 for mysql_options
80 APPLICATION
81
82 driver options
83 STORE_RESULT
84
85*/
86
87bool MyConnection::__open(const char* _conns, size_t _connslen)
88{
89 if (__mysql == NULL && (__mysql = mysql_init(NULL)) == NULL) {
91 return false;
92 }
93
94 ListedByteStringToByteStringMap map;
95 Connection::splitConnStr(_conns, _connslen, map);
96
97 ByteString _APPLICATION = map["APPLICATION"];
98 if (!_APPLICATION.isEmpty()) {
99 mysql_options(connHandle(), MYSQL_READ_DEFAULT_GROUP, _APPLICATION.data());
100 }
101
102 ByteString _USER = map["USER"];
103 ByteString _PASSWORD = map["PASSWORD"];
104 ByteString _SERVER = map["SERVER"];
105 ByteString _DATABASE = map["DATABASE"];
106 ByteString _PORT = map["PORT"];
107 ByteString _UNIX_SOCKET = map["UNIX_SOCKET"];
108 __storeResult = map.find("STORE_RESULT") != map.end();
109
110 unsigned int port = 0;
111 if (!_PORT.isEmpty()) {
112 char* endptr;
113 unsigned long n = strtoul(_PORT.data(), &endptr, 10);
114 if (n == ULONG_MAX) {
115 __SET_ERROR_MSG("연결 문자열이 잘못되었습니다. PORT=" + _PORT);
116 return false;
117 }
118 port = (unsigned int) n;
119 }
120
121 if (mysql_real_connect(
122 connHandle(),
123 _SERVER.isEmpty()? NULL : _SERVER.data(),
124 _USER.isEmpty()? NULL : _USER.data(),
125 _PASSWORD.isEmpty()? NULL : _PASSWORD.data(),
126 _DATABASE.isEmpty() ? NULL : _DATABASE.data(),
127 port,
128 _UNIX_SOCKET.isEmpty() ? NULL : _UNIX_SOCKET.data(),
129 0
130 ) == NULL) {
132 return false;
133 }
134
135 if (mysql_set_character_set(connHandle(), "utf8")) {
136 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
137 mysql_errno(connHandle()),
138 mysql_error(connHandle()))
139 );
140 return false;
141 }
142
143 if (mysql_autocommit(connHandle(), 0)) {
144 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
145 mysql_errno(connHandle()),
146 mysql_error(connHandle()))
147 );
148 return false;
149 }
150
151 return true;
152}
153
155{
156 if (!__mysql) {
158 return false;
159 }
160
161 mysql_close(__mysql);
162 __mysql = NULL;
163
164 return true;
165}
166
172
173typedef struct {
174 StmtType type;
175 const char* pattern;
177
178static STMT_PATTERN sp[] = {
179 { StmtTransBegin, "START[[:space:]]+TRANSACTION|BEGIN" },
180 { StmtTransEnd, "COMMIT|ROLLBACK" },
181 { StmtOther, NULL }
182};
183
184static StmtType __GetStmtType(const char* _sql)
185{
186 for (size_t i = 0; sp[i].type != StmtOther; i++) {
187 try {
188 if (Regex::test(sp[i].pattern, _sql, true))
189 return sp[i].type;
190 }
191 catch (Exception* p) {
192 p->destroy();
193 }
194 }
195 return StmtOther;
196}
197
198bool MyConnection::__execute(const char* _sql, size_t _sqllen)
199{
200 if (mysql_real_query(connHandle(), _sql, (unsigned long) _sqllen)) {
201 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
202 mysql_errno(connHandle()),
203 mysql_error(connHandle()))
204 );
205 }
206
207 switch (__GetStmtType(_sql)) {
208 case StmtTransBegin:
210 break;
211 case StmtTransEnd:
213 break;
214 case StmtOther:
215 default:
216 ;
217 }
218
219 return true;
220}
221
223{
224 return __execute("START TRANSACTION", 17);
225}
226
228{
229 if (mysql_commit(connHandle())) {
230 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
231 mysql_errno(connHandle()),
232 mysql_error(connHandle()))
233 );
234 }
235
236 return true;
237}
238
240{
241 if (mysql_rollback(connHandle())) {
242 __SET_ERROR_MSG(ByteString::format("(%u) %hs",
243 mysql_errno(connHandle()),
244 mysql_error(connHandle()))
245 );
246 }
247
248 return true;
249}
250
252{
253 __DCL_ASSERT(_queryHandleOut != NULL);
254
255 MyQuery* pNewQuery = new MyQuery(this);
256 if (!pNewQuery) {
258 return false;
259 }
260
261 *_queryHandleOut = pNewQuery;
262 return true;
263}
264
265bool MyConnection::__getErrorMessage(char* _buf, size_t* _buflen)
266{
267 if (__lastErrorMessage.length() < *_buflen) {
268 *_buflen = __lastErrorMessage.length();
269 *(_buf + *_buflen) = '\0';
270 }
271 strncpy(_buf, __lastErrorMessage.data(), *_buflen);
272 return true;
273}
274
275bool MyConnection::__getServerInfo(char* _buf, size_t* _buflen)
276{
277 const char* psz = mysql_get_server_info(connHandle());
278 if (!psz) {
279 return false;
280 }
281
282 size_t length = strlen(psz);
283 if (length < *_buflen) {
284 *_buflen = length;
285 *(_buf + *_buflen) = '\0';
286 }
287 strncpy(_buf, psz, *_buflen);
288 return true;
289}
290
291__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:312
wchar_t char_t
Definition Config.h:247
#define __SET_ERROR_MSG(_message)
@ StmtTransEnd
@ StmtOther
@ StmtTransBegin
#define __DCL_TRACE0_N(fmt)
#define __SET_ERROR_HANDLE(_SQLCODE)
#define __DCL_ASSERT(expr)
Definition Object.h:394
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:245
#define __T(str)
Definition Object.h:60
#define __UNSET_STATE(state)
Definition SQLCore.h:483
#define __SET_STATE(state)
Definition SQLCore.h:482
virtual void destroy()
Definition Exception.cpp:74
virtual bool __createQueryInstance(SQL::Query **_queryHandleOut)
virtual bool __execute(const char *_sql, size_t _sqllen)
virtual bool __startTrans()
virtual bool __getErrorMessage(char *_buf, size_t *_buflen)
virtual bool __rollbackTrans()
virtual void destroy()
MyConnection(const wchar_t *_serverTitle)
virtual bool __close()
virtual bool __commitTrans()
MYSQL * connHandle() const
virtual bool __getServerInfo(char *_buf, size_t *_buflen)
virtual bool __open(const char *_conns, size_t _connslen)
virtual ~MyConnection()
static bool test(const wchar_t *_regex, const wchar_t *_string, bool _icase=false) __DCL_THROWS1(RegexException *)
Definition Regex.cpp:250
@ eOutOfMemory
Definition SQLCore.h:24
@ eServerError
Definition SQLCore.h:21
@ eNotConnected
Definition SQLCore.h:33