@@ -57,6 +57,7 @@ constexpr int PATCH = 0;
57
57
class MySQLClientLibrary ;
58
58
class MySQLConnection ;
59
59
class MySQLPreparedStatement ;
60
+ class MySQLQuery ;
60
61
61
62
class MySQLClientLibrary {
62
63
private:
@@ -102,7 +103,8 @@ class MySQLConnection {
102
103
private:
103
104
MySQLConnection (const std::shared_ptr<MySQLClientLibrary>& library) :
104
105
m_library (library),
105
- m_mysql (mysql_init(nullptr ))
106
+ m_mysql (::mysql_init(nullptr )),
107
+ m_hasActiveQuery (false )
106
108
{
107
109
if (!m_mysql) {
108
110
throw std::runtime_error (" failed to initialize connection object" );
@@ -120,7 +122,7 @@ class MySQLConnection {
120
122
~MySQLConnection ()
121
123
{
122
124
if (m_mysql) {
123
- mysql_close (m_mysql);
125
+ :: mysql_close (m_mysql);
124
126
}
125
127
}
126
128
@@ -137,7 +139,7 @@ class MySQLConnection {
137
139
void connect (const std::string& host, const unsigned port, const std::string& database,
138
140
const std::string& user, const char * password, unsigned long clientFlags = 0 )
139
141
{
140
- if (!mysql_real_connect (m_mysql, host.c_str (), user.c_str (), password,
142
+ if (!:: mysql_real_connect (m_mysql, host.c_str (), user.c_str (), password,
141
143
database.c_str (), port, nullptr , clientFlags)) {
142
144
throw std::runtime_error (" could not connect to database server" );
143
145
}
@@ -154,12 +156,151 @@ class MySQLConnection {
154
156
155
157
unsigned long getServerVersion () const noexcept
156
158
{
157
- return mysql_get_server_version (m_mysql);
159
+ return ::mysql_get_server_version (m_mysql);
160
+ }
161
+
162
+ void setHasActiveQuery (bool hasActiveQuery) noexcept
163
+ {
164
+ m_hasActiveQuery = hasActiveQuery;
165
+ }
166
+
167
+ bool hasActiveQuery () const noexcept
168
+ {
169
+ return m_hasActiveQuery;
170
+ }
171
+
172
+ void commit ()
173
+ {
158
174
}
159
175
160
176
private:
161
177
std::shared_ptr<MySQLClientLibrary> m_library;
162
178
::MYSQL* m_mysql;
179
+ bool m_hasActiveQuery;
180
+ };
181
+
182
+ class MySQLQuery {
183
+ private:
184
+ MySQLQuery (const std::shared_ptr<MySQLConnection>& conn, const char * sql, std::size_t length) :
185
+ m_conn (conn),
186
+ m_errorCode (0 )
187
+ {
188
+ if (conn->hasActiveQuery ()) {
189
+ throw std::logic_error (" some query is already running" );
190
+ }
191
+
192
+ MYSQL* mysql = (MYSQL*)*conn;
193
+
194
+ m_errorCode = ::mysql_real_query (mysql, sql, static_cast <unsigned long >(length));
195
+ if (m_errorCode) {
196
+ throw std::runtime_error (" failed to execute MySQL query" );
197
+ }
198
+
199
+ conn->setHasActiveQuery (true );
200
+ }
201
+
202
+ public:
203
+ static std::shared_ptr<MySQLQuery> create (const std::shared_ptr<MySQLConnection>& conn,
204
+ const std::string& sql)
205
+ {
206
+ return std::shared_ptr<MySQLQuery>(new MySQLQuery (conn, sql.c_str (), sql.length ()));
207
+ }
208
+
209
+ static std::shared_ptr<MySQLQuery> create (const std::shared_ptr<MySQLConnection>& conn,
210
+ const char * sql, std::size_t length)
211
+ {
212
+ return std::shared_ptr<MySQLQuery>(new MySQLQuery (conn, sql, length));
213
+ }
214
+
215
+ ~MySQLQuery () noexcept
216
+ {
217
+ stop ();
218
+ }
219
+
220
+ MySQLQuery (const MySQLQuery&) = delete ;
221
+ MySQLQuery (MySQLQuery&&) = delete ;
222
+ MySQLQuery& operator =(const MySQLQuery&) = delete ;
223
+ MySQLQuery& operator =(MySQLQuery&&) = delete ;
224
+
225
+ unsigned int getFieldCount () const noexcept
226
+ {
227
+ return mysql_field_count ((MYSQL*)*m_conn);
228
+ }
229
+
230
+ bool hasResults () const noexcept
231
+ {
232
+ return getFieldCount () > 0 ;
233
+ }
234
+
235
+ unsigned long long getNumberOfAffectedRows () const noexcept
236
+ {
237
+ return ::mysql_affected_rows ((MYSQL*)*m_conn);
238
+ }
239
+
240
+ bool hasMoreResults () const noexcept
241
+ {
242
+ return ::mysql_more_results ((MYSQL*)*m_conn);
243
+ }
244
+
245
+ bool nextResult ()
246
+ {
247
+ const auto result = ::mysql_next_result ((MYSQL*)*m_conn);
248
+ if (result > 0 ) {
249
+ throw std::runtime_error (" failed to fetch next row" );
250
+ }
251
+ return result == 0 ;
252
+ }
253
+
254
+ bool useResult ()
255
+ {
256
+ m_result = ::mysql_use_result ((MYSQL*)*m_conn);
257
+ if (m_result == nullptr && ::mysql_errno ((MYSQL*)*m_conn) != 0 ) {
258
+ throw std::runtime_error (" failed to fetch first row of result" );
259
+ }
260
+ }
261
+
262
+ MYSQL_ROW fetchRow ()
263
+ {
264
+ checkHaveResult ();
265
+ MYSQL_ROW row = ::mysql_fetch_row (m_result);
266
+ if (::mysql_errno ((MYSQL*)*m_conn) != 0 ) {
267
+ throw std::runtime_error (" failed to fetch next row" );
268
+ }
269
+ return row;
270
+ }
271
+
272
+ void stopResult ()
273
+ {
274
+ checkHaveResult ();
275
+ doStopResult ();
276
+ }
277
+
278
+ void stop () noexcept
279
+ {
280
+ if (m_result) {
281
+ doStopResult ();
282
+ }
283
+ m_conn->setHasActiveQuery (false );
284
+ }
285
+
286
+ private:
287
+
288
+ void checkHaveResult () const
289
+ {
290
+ if (!m_result) {
291
+ throw std::logic_error (" there is no active result" );
292
+ }
293
+ }
294
+
295
+ void doStopResult ()
296
+ {
297
+ ::mysql_free_result (m_result);
298
+ m_result = nullptr ;
299
+ }
300
+
301
+ std::shared_ptr<MySQLConnection> m_conn;
302
+ int m_errorCode;
303
+ MYSQL_RES* m_result;
163
304
};
164
305
165
306
class MySQLPreparedStatement {
@@ -178,8 +319,7 @@ class MySQLPreparedStatement {
178
319
179
320
public:
180
321
181
- static std::shared_ptr<MySQLPreparedStatement> create (
182
- const std::shared_ptr<MySQLConnection>& conn)
322
+ static std::shared_ptr<MySQLPreparedStatement> create (const std::shared_ptr<MySQLConnection>& conn)
183
323
{
184
324
return std::shared_ptr<MySQLPreparedStatement>(new MySQLPreparedStatement (conn));
185
325
}
@@ -216,7 +356,7 @@ class MySQLPreparedStatement {
216
356
if (len == std::string::npos) {
217
357
len = strlen (sql);
218
358
}
219
- m_errorCode = mysql_stmt_prepare (m_stmt, sql, static_cast <unsigned long >(len));
359
+ m_errorCode = :: mysql_stmt_prepare (m_stmt, sql, static_cast <unsigned long >(len));
220
360
if (m_errorCode != 0 ) {
221
361
std::ostringstream err;
222
362
err << " failed to prepare prepared statement: "
@@ -286,7 +426,7 @@ class MySQLPreparedStatement {
286
426
if (m_parameters.empty ()) {
287
427
throw std::logic_error (" there are no parameters" );
288
428
}
289
- m_errorCode = mysql_stmt_bind_param (m_stmt, &m_parameters[0 ]);
429
+ m_errorCode = :: mysql_stmt_bind_param (m_stmt, &m_parameters[0 ]);
290
430
if (m_errorCode != 0 ) {
291
431
std::ostringstream err;
292
432
err << " failed to bind parameters prepared statement: "
@@ -351,7 +491,7 @@ class MySQLPreparedStatement {
351
491
if (m_results.empty ()) {
352
492
throw std::logic_error (" there are no results" );
353
493
}
354
- m_errorCode = mysql_stmt_bind_result (m_stmt, &m_results[0 ]);
494
+ m_errorCode = :: mysql_stmt_bind_result (m_stmt, &m_results[0 ]);
355
495
if (m_errorCode != 0 ) {
356
496
std::ostringstream err;
357
497
err << " failed to bind results prepared statement: "
@@ -362,7 +502,7 @@ class MySQLPreparedStatement {
362
502
363
503
void execute ()
364
504
{
365
- m_errorCode = mysql_stmt_execute (m_stmt);
505
+ m_errorCode = :: mysql_stmt_execute (m_stmt);
366
506
if (m_errorCode != 0 ) {
367
507
std::ostringstream err;
368
508
err << " failed to execute prepared statement: "
@@ -373,7 +513,7 @@ class MySQLPreparedStatement {
373
513
374
514
bool fetch ()
375
515
{
376
- const int res = mysql_stmt_fetch (m_stmt);
516
+ const int res = :: mysql_stmt_fetch (m_stmt);
377
517
switch (res) {
378
518
case 0 : return true ;
379
519
case MYSQL_NO_DATA: return false ;
@@ -383,7 +523,7 @@ class MySQLPreparedStatement {
383
523
384
524
void stop ()
385
525
{
386
- if (mysql_stmt_free_result (m_stmt)) {
526
+ if (:: mysql_stmt_free_result (m_stmt)) {
387
527
throw std::runtime_error (" failed to stop prepared statement" );
388
528
}
389
529
}
0 commit comments