mysql2 0.2.24 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/CHANGELOG.md +148 -0
  5. data/Gemfile +3 -0
  6. data/README.rdoc +257 -0
  7. data/Rakefile +5 -0
  8. data/benchmark/active_record.rb +51 -0
  9. data/benchmark/active_record_threaded.rb +42 -0
  10. data/benchmark/allocations.rb +33 -0
  11. data/benchmark/escape.rb +36 -0
  12. data/benchmark/query_with_mysql_casting.rb +80 -0
  13. data/benchmark/query_without_mysql_casting.rb +47 -0
  14. data/benchmark/sequel.rb +37 -0
  15. data/benchmark/setup_db.rb +119 -0
  16. data/benchmark/threaded.rb +44 -0
  17. data/ext/mysql2/client.c +272 -849
  18. data/ext/mysql2/client.h +12 -27
  19. data/ext/mysql2/extconf.rb +14 -72
  20. data/ext/mysql2/mysql2_ext.h +4 -7
  21. data/ext/mysql2/result.c +123 -319
  22. data/ext/mysql2/result.h +1 -4
  23. data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +64 -0
  24. data/lib/active_record/fiber_patches.rb +104 -0
  25. data/lib/mysql2.rb +5 -20
  26. data/lib/mysql2/client.rb +200 -50
  27. data/lib/mysql2/em.rb +3 -13
  28. data/lib/mysql2/em_fiber.rb +31 -0
  29. data/lib/mysql2/error.rb +6 -71
  30. data/lib/mysql2/version.rb +2 -2
  31. data/mysql2.gemspec +32 -0
  32. data/spec/em/em_fiber_spec.rb +22 -0
  33. data/spec/em/em_spec.rb +9 -74
  34. data/spec/mysql2/client_spec.rb +126 -593
  35. data/spec/mysql2/error_spec.rb +44 -58
  36. data/spec/mysql2/result_spec.rb +85 -257
  37. data/spec/spec_helper.rb +3 -24
  38. data/tasks/benchmarks.rake +20 -0
  39. data/tasks/compile.rake +71 -0
  40. data/tasks/rspec.rake +16 -0
  41. data/tasks/vendor_mysql.rake +40 -0
  42. metadata +179 -92
  43. checksums.yaml +0 -7
  44. data/README.md +0 -524
  45. data/ext/mysql2/infile.c +0 -122
  46. data/ext/mysql2/infile.h +0 -1
  47. data/ext/mysql2/mysql_enc_name_to_ruby.h +0 -168
  48. data/ext/mysql2/mysql_enc_to_ruby.h +0 -246
  49. data/ext/mysql2/wait_for_single_fd.h +0 -36
  50. data/lib/active_record/connection_adapters/mysql2_adapter.rb +0 -635
  51. data/lib/arel/engines/sql/compilers/mysql2_compiler.rb +0 -11
  52. data/lib/mysql2/console.rb +0 -5
  53. data/spec/configuration.yml.example +0 -17
  54. data/spec/my.cnf.example +0 -9
  55. data/spec/test_data +0 -1
  56. data/support/mysql_enc_to_ruby.rb +0 -82
  57. data/support/ruby_enc_to_mysql.rb +0 -61
data/ext/mysql2/client.c CHANGED
@@ -1,68 +1,28 @@
1
1
  #include <mysql2_ext.h>
2
-
3
- #include <time.h>
2
+ #include <client.h>
4
3
  #include <errno.h>
5
- #ifndef _WIN32
6
- #include <sys/types.h>
7
- #include <sys/socket.h>
8
- #endif
9
- #ifndef _MSC_VER
10
- #include <unistd.h>
11
- #endif
12
- #include <fcntl.h>
13
- #include "wait_for_single_fd.h"
14
-
15
- #include "mysql_enc_name_to_ruby.h"
16
4
 
17
5
  VALUE cMysql2Client;
18
6
  extern VALUE mMysql2, cMysql2Error;
19
- static VALUE sym_id, sym_version, sym_async, sym_symbolize_keys, sym_as, sym_array, sym_stream;
20
- static ID intern_merge, intern_merge_bang, intern_error_number_eql, intern_sql_state_eql;
7
+ static VALUE intern_encoding_from_charset;
8
+ static VALUE sym_id, sym_version, sym_async, sym_symbolize_keys, sym_as, sym_array;
9
+ static ID intern_merge, intern_error_number_eql, intern_sql_state_eql;
21
10
 
22
- #ifndef HAVE_RB_HASH_DUP
23
- static VALUE rb_hash_dup(VALUE other) {
24
- return rb_funcall(rb_cHash, rb_intern("[]"), 1, other);
25
- }
26
- #endif
27
-
28
- #define REQUIRE_INITIALIZED(wrapper) \
29
- if (!wrapper->initialized) { \
30
- rb_raise(cMysql2Error, "MySQL client is not initialized"); \
31
- }
32
-
33
- #define REQUIRE_CONNECTED(wrapper) \
34
- REQUIRE_INITIALIZED(wrapper) \
35
- if (!wrapper->connected && !wrapper->reconnect_enabled) { \
11
+ #define REQUIRE_OPEN_DB(wrapper) \
12
+ if(wrapper->closed) { \
36
13
  rb_raise(cMysql2Error, "closed MySQL connection"); \
37
14
  }
38
15
 
39
- #define REQUIRE_NOT_CONNECTED(wrapper) \
40
- REQUIRE_INITIALIZED(wrapper) \
41
- if (wrapper->connected) { \
42
- rb_raise(cMysql2Error, "MySQL connection is already open"); \
43
- }
44
-
45
16
  #define MARK_CONN_INACTIVE(conn) \
46
- wrapper->active_thread = Qnil;
17
+ wrapper->active = 0
47
18
 
48
19
  #define GET_CLIENT(self) \
49
20
  mysql_client_wrapper *wrapper; \
50
21
  Data_Get_Struct(self, mysql_client_wrapper, wrapper)
51
22
 
52
- /*
53
- * compatability with mysql-connector-c, where LIBMYSQL_VERSION is the correct
54
- * variable to use, but MYSQL_SERVER_VERSION gives the correct numbers when
55
- * linking against the server itself
56
- */
57
- #ifdef LIBMYSQL_VERSION
58
- #define MYSQL_LINK_VERSION LIBMYSQL_VERSION
59
- #else
60
- #define MYSQL_LINK_VERSION MYSQL_SERVER_VERSION
61
- #endif
62
-
63
23
  /*
64
24
  * used to pass all arguments to mysql_real_connect while inside
65
- * rb_thread_call_without_gvl
25
+ * rb_thread_blocking_region
66
26
  */
67
27
  struct nogvl_connect_args {
68
28
  MYSQL *mysql;
@@ -77,23 +37,11 @@ struct nogvl_connect_args {
77
37
 
78
38
  /*
79
39
  * used to pass all arguments to mysql_send_query while inside
80
- * rb_thread_call_without_gvl
40
+ * rb_thread_blocking_region
81
41
  */
82
42
  struct nogvl_send_query_args {
83
43
  MYSQL *mysql;
84
44
  VALUE sql;
85
- const char *sql_ptr;
86
- long sql_len;
87
- mysql_client_wrapper *wrapper;
88
- };
89
-
90
- /*
91
- * used to pass all arguments to mysql_select_db while inside
92
- * rb_thread_call_without_gvl
93
- */
94
- struct nogvl_select_db_args {
95
- MYSQL *mysql;
96
- char *db;
97
45
  };
98
46
 
99
47
  /*
@@ -122,136 +70,94 @@ static void rb_mysql_client_mark(void * wrapper) {
122
70
  mysql_client_wrapper * w = wrapper;
123
71
  if (w) {
124
72
  rb_gc_mark(w->encoding);
125
- rb_gc_mark(w->active_thread);
126
73
  }
127
74
  }
128
75
 
129
76
  static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) {
130
77
  VALUE rb_error_msg = rb_str_new2(mysql_error(wrapper->client));
131
78
  VALUE rb_sql_state = rb_tainted_str_new2(mysql_sqlstate(wrapper->client));
132
- VALUE e;
133
-
134
79
  #ifdef HAVE_RUBY_ENCODING_H
135
- rb_enc_associate(rb_error_msg, rb_utf8_encoding());
136
- rb_enc_associate(rb_sql_state, rb_usascii_encoding());
80
+ rb_encoding *default_internal_enc = rb_default_internal_encoding();
81
+ rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
82
+
83
+ rb_enc_associate(rb_error_msg, conn_enc);
84
+ rb_enc_associate(rb_sql_state, conn_enc);
85
+ if (default_internal_enc) {
86
+ rb_error_msg = rb_str_export_to_enc(rb_error_msg, default_internal_enc);
87
+ rb_sql_state = rb_str_export_to_enc(rb_sql_state, default_internal_enc);
88
+ }
137
89
  #endif
138
90
 
139
- e = rb_funcall(cMysql2Error, rb_intern("new"), 2, rb_error_msg, LONG2FIX(wrapper->server_version));
91
+ VALUE e = rb_exc_new3(cMysql2Error, rb_error_msg);
140
92
  rb_funcall(e, intern_error_number_eql, 1, UINT2NUM(mysql_errno(wrapper->client)));
141
93
  rb_funcall(e, intern_sql_state_eql, 1, rb_sql_state);
142
94
  rb_exc_raise(e);
143
95
  return Qnil;
144
96
  }
145
97
 
146
- static void *nogvl_init(void *ptr) {
98
+ static VALUE nogvl_init(void *ptr) {
147
99
  MYSQL *client;
148
- mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;
149
100
 
150
101
  /* may initialize embedded server and read /etc/services off disk */
151
- client = mysql_init(wrapper->client);
152
-
153
- if (client) mysql2_set_local_infile(client, wrapper);
154
-
155
- return (void*)(client ? Qtrue : Qfalse);
102
+ client = mysql_init((MYSQL *)ptr);
103
+ return client ? Qtrue : Qfalse;
156
104
  }
157
105
 
158
- static void *nogvl_connect(void *ptr) {
106
+ static VALUE nogvl_connect(void *ptr) {
159
107
  struct nogvl_connect_args *args = ptr;
160
108
  MYSQL *client;
161
109
 
162
- client = mysql_real_connect(args->mysql, args->host,
163
- args->user, args->passwd,
164
- args->db, args->port, args->unix_socket,
165
- args->client_flag);
110
+ do {
111
+ client = mysql_real_connect(args->mysql, args->host,
112
+ args->user, args->passwd,
113
+ args->db, args->port, args->unix_socket,
114
+ args->client_flag);
115
+ } while (! client && errno == EINTR && (errno = 0) == 0);
166
116
 
167
- return (void *)(client ? Qtrue : Qfalse);
117
+ return client ? Qtrue : Qfalse;
168
118
  }
169
119
 
120
+ static VALUE nogvl_close(void *ptr) {
121
+ mysql_client_wrapper *wrapper;
170
122
  #ifndef _WIN32
171
- /*
172
- * Redirect clientfd to /dev/null for mysql_close and SSL_close to write,
173
- * shutdown, and close. The hack is needed to prevent shutdown() from breaking
174
- * a socket that may be in use by the parent or other processes after fork.
175
- *
176
- * /dev/null is used to absorb writes; previously a dummy socket was used, but
177
- * it could not abosrb writes and caused openssl to go into an infinite loop.
178
- *
179
- * Returns Qtrue or Qfalse (success or failure)
180
- *
181
- * Note: if this function is needed on Windows, use "nul" instead of "/dev/null"
182
- */
183
- static VALUE invalidate_fd(int clientfd)
184
- {
185
- #ifdef SOCK_CLOEXEC
186
- /* Atomically set CLOEXEC on the new FD in case another thread forks */
187
- int sockfd = open("/dev/null", O_RDWR | O_CLOEXEC);
188
- if (sockfd < 0) {
189
- /* Maybe SOCK_CLOEXEC is defined but not available on this kernel */
190
- int sockfd = open("/dev/null", O_RDWR);
191
- fcntl(sockfd, F_SETFD, FD_CLOEXEC);
192
- }
193
- #else
194
- /* Well we don't have SOCK_CLOEXEC, so just set FD_CLOEXEC quickly */
195
- int sockfd = open("/dev/null", O_RDWR);
196
- fcntl(sockfd, F_SETFD, FD_CLOEXEC);
123
+ int flags;
197
124
  #endif
125
+ wrapper = ptr;
126
+ if (!wrapper->closed) {
127
+ wrapper->closed = 1;
198
128
 
199
- if (sockfd < 0) {
200
129
  /*
201
- * Cannot raise here, because one or both of the following may be true:
202
- * a) we have no GVL (in C Ruby)
203
- * b) are running as a GC finalizer
130
+ * we'll send a QUIT message to the server, but that message is more of a
131
+ * formality than a hard requirement since the socket is getting shutdown
132
+ * anyways, so ensure the socket write does not block our interpreter
133
+ *
134
+ *
135
+ * if the socket is dead we have no chance of blocking,
136
+ * so ignore any potential fcntl errors since they don't matter
204
137
  */
205
- return Qfalse;
206
- }
207
-
208
- dup2(sockfd, clientfd);
209
- close(sockfd);
210
-
211
- return Qtrue;
212
- }
213
- #endif /* _WIN32 */
214
-
215
- static void *nogvl_close(void *ptr) {
216
- mysql_client_wrapper *wrapper;
217
- wrapper = ptr;
218
- if (wrapper->connected) {
219
- wrapper->active_thread = Qnil;
220
- wrapper->connected = 0;
221
138
  #ifndef _WIN32
222
- /* Invalidate the socket before calling mysql_close(). This prevents
223
- * mysql_close() from sending a mysql-QUIT or from calling shutdown() on
224
- * the socket. The difference is that invalidate_fd will drop this
225
- * process's reference to the socket only, while a QUIT or shutdown()
226
- * would render the underlying connection unusable, interrupting other
227
- * processes which share this object across a fork().
228
- */
229
- if (invalidate_fd(wrapper->client->net.fd) == Qfalse) {
230
- fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely, leaking some memory\n");
231
- close(wrapper->client->net.fd);
232
- return NULL;
233
- }
139
+ flags = fcntl(wrapper->client->net.fd, F_GETFL);
140
+ if (flags > 0 && !(flags & O_NONBLOCK))
141
+ fcntl(wrapper->client->net.fd, F_SETFL, flags | O_NONBLOCK);
142
+ #else
143
+ u_long iMode;
144
+ iMode = 1;
145
+ ioctlsocket(wrapper->client->net.fd, FIONBIO, &iMode);
234
146
  #endif
235
147
 
236
- mysql_close(wrapper->client); /* only used to free memory at this point */
148
+ mysql_close(wrapper->client);
149
+ xfree(wrapper->client);
237
150
  }
238
151
 
239
- return NULL;
152
+ return Qnil;
240
153
  }
241
154
 
242
- static void rb_mysql_client_free(void *ptr) {
155
+ static void rb_mysql_client_free(void * ptr) {
243
156
  mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;
244
- decr_mysql2_client(wrapper);
245
- }
246
157
 
247
- void decr_mysql2_client(mysql_client_wrapper *wrapper)
248
- {
249
- wrapper->refcount--;
250
- if (wrapper->refcount == 0) {
251
- nogvl_close(wrapper);
252
- xfree(wrapper->client);
253
- xfree(wrapper);
254
- }
158
+ nogvl_close(wrapper);
159
+
160
+ xfree(ptr);
255
161
  }
256
162
 
257
163
  static VALUE allocate(VALUE klass) {
@@ -259,25 +165,13 @@ static VALUE allocate(VALUE klass) {
259
165
  mysql_client_wrapper * wrapper;
260
166
  obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
261
167
  wrapper->encoding = Qnil;
262
- wrapper->active_thread = Qnil;
263
- wrapper->server_version = 0;
264
- wrapper->reconnect_enabled = 0;
265
- wrapper->connect_timeout = 0;
266
- wrapper->connected = 0; /* means that a database connection is open */
267
- wrapper->initialized = 0; /* means that that the wrapper is initialized */
268
- wrapper->refcount = 1;
168
+ wrapper->active = 0;
169
+ wrapper->closed = 1;
269
170
  wrapper->client = (MYSQL*)xmalloc(sizeof(MYSQL));
270
171
  return obj;
271
172
  }
272
173
 
273
- /* call-seq:
274
- * Mysql2::Client.escape(string)
275
- *
276
- * Escape +string+ so that it may be used in a SQL statement.
277
- * Note that this escape method is not connection encoding aware.
278
- * If you need encoding support use Mysql2::Client#escape instead.
279
- */
280
- static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) {
174
+ static VALUE rb_mysql_client_escape(VALUE klass, VALUE str) {
281
175
  unsigned char *newStr;
282
176
  VALUE rb_str;
283
177
  unsigned long newLen, oldLen;
@@ -289,7 +183,7 @@ static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) {
289
183
 
290
184
  newLen = mysql_escape_string((char *)newStr, StringValuePtr(str), oldLen);
291
185
  if (newLen == oldLen) {
292
- /* no need to return a new ruby string if nothing changed */
186
+ // no need to return a new ruby string if nothing changed
293
187
  xfree(newStr);
294
188
  return str;
295
189
  } else {
@@ -302,81 +196,24 @@ static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) {
302
196
  }
303
197
  }
304
198
 
305
- static VALUE rb_mysql_client_warning_count(VALUE self) {
306
- unsigned int warning_count;
307
- GET_CLIENT(self);
308
-
309
- warning_count = mysql_warning_count(wrapper->client);
310
-
311
- return UINT2NUM(warning_count);
312
- }
313
-
314
- static VALUE rb_mysql_info(VALUE self) {
315
- const char *info;
316
- VALUE rb_str;
317
- GET_CLIENT(self);
318
-
319
- info = mysql_info(wrapper->client);
320
-
321
- if (info == NULL) {
322
- return Qnil;
323
- }
324
-
325
- rb_str = rb_str_new2(info);
326
- #ifdef HAVE_RUBY_ENCODING_H
327
- rb_enc_associate(rb_str, rb_utf8_encoding());
328
- #endif
329
-
330
- return rb_str;
331
- }
332
-
333
199
  static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags) {
334
200
  struct nogvl_connect_args args;
335
- time_t start_time, end_time;
336
- unsigned int elapsed_time, connect_timeout;
337
- VALUE rv;
338
201
  GET_CLIENT(self);
339
202
 
340
- args.host = NIL_P(host) ? NULL : StringValuePtr(host);
203
+ args.host = NIL_P(host) ? "localhost" : StringValuePtr(host);
341
204
  args.unix_socket = NIL_P(socket) ? NULL : StringValuePtr(socket);
342
- args.port = NIL_P(port) ? 0 : NUM2INT(port);
205
+ args.port = NIL_P(port) ? 3306 : NUM2INT(port);
343
206
  args.user = NIL_P(user) ? NULL : StringValuePtr(user);
344
207
  args.passwd = NIL_P(pass) ? NULL : StringValuePtr(pass);
345
208
  args.db = NIL_P(database) ? NULL : StringValuePtr(database);
346
209
  args.mysql = wrapper->client;
347
210
  args.client_flag = NUM2ULONG(flags);
348
211
 
349
- if (wrapper->connect_timeout)
350
- time(&start_time);
351
- rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0);
352
- if (rv == Qfalse) {
353
- while (rv == Qfalse && errno == EINTR) {
354
- if (wrapper->connect_timeout) {
355
- time(&end_time);
356
- /* avoid long connect timeout from system time changes */
357
- if (end_time < start_time)
358
- start_time = end_time;
359
- elapsed_time = end_time - start_time;
360
- /* avoid an early timeout due to time truncating milliseconds off the start time */
361
- if (elapsed_time > 0)
362
- elapsed_time--;
363
- if (elapsed_time >= wrapper->connect_timeout)
364
- break;
365
- connect_timeout = wrapper->connect_timeout - elapsed_time;
366
- mysql_options(wrapper->client, MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout);
367
- }
368
- errno = 0;
369
- rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0);
370
- }
371
- /* restore the connect timeout for reconnecting */
372
- if (wrapper->connect_timeout)
373
- mysql_options(wrapper->client, MYSQL_OPT_CONNECT_TIMEOUT, &wrapper->connect_timeout);
374
- if (rv == Qfalse)
375
- return rb_raise_mysql2_error(wrapper);
212
+ if (rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0) == Qfalse) {
213
+ // unable to connect
214
+ return rb_raise_mysql2_error(wrapper);
376
215
  }
377
216
 
378
- wrapper->server_version = mysql_get_server_version(wrapper->client);
379
- wrapper->connected = 1;
380
217
  return self;
381
218
  }
382
219
 
@@ -389,8 +226,8 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
389
226
  static VALUE rb_mysql_client_close(VALUE self) {
390
227
  GET_CLIENT(self);
391
228
 
392
- if (wrapper->connected) {
393
- rb_thread_call_without_gvl(nogvl_close, wrapper, RUBY_UBF_IO, 0);
229
+ if (!wrapper->closed) {
230
+ rb_thread_blocking_region(nogvl_close, wrapper, RUBY_UBF_IO, 0);
394
231
  }
395
232
 
396
233
  return Qnil;
@@ -401,24 +238,15 @@ static VALUE rb_mysql_client_close(VALUE self) {
401
238
  * enough to fit in a socket buffer, but sometimes large UPDATE and
402
239
  * INSERTs will cause the process to block
403
240
  */
404
- static void *nogvl_send_query(void *ptr) {
241
+ static VALUE nogvl_send_query(void *ptr) {
405
242
  struct nogvl_send_query_args *args = ptr;
406
243
  int rv;
244
+ const char *sql = StringValuePtr(args->sql);
245
+ long sql_len = RSTRING_LEN(args->sql);
407
246
 
408
- rv = mysql_send_query(args->mysql, args->sql_ptr, args->sql_len);
247
+ rv = mysql_send_query(args->mysql, sql, sql_len);
409
248
 
410
- return (void*)(rv == 0 ? Qtrue : Qfalse);
411
- }
412
-
413
- static VALUE do_send_query(void *args) {
414
- struct nogvl_send_query_args *query_args = args;
415
- mysql_client_wrapper *wrapper = query_args->wrapper;
416
- if ((VALUE)rb_thread_call_without_gvl(nogvl_send_query, args, RUBY_UBF_IO, 0) == Qfalse) {
417
- /* an error occurred, we're not active anymore */
418
- MARK_CONN_INACTIVE(self);
419
- return rb_raise_mysql2_error(wrapper);
420
- }
421
- return Qnil;
249
+ return rv == 0 ? Qtrue : Qfalse;
422
250
  }
423
251
 
424
252
  /*
@@ -426,129 +254,117 @@ static VALUE do_send_query(void *args) {
426
254
  * response can overflow the socket buffers and cause us to eventually
427
255
  * block while calling mysql_read_query_result
428
256
  */
429
- static void *nogvl_read_query_result(void *ptr) {
257
+ static VALUE nogvl_read_query_result(void *ptr) {
430
258
  MYSQL * client = ptr;
431
259
  my_bool res = mysql_read_query_result(client);
432
260
 
433
- return (void *)(res == 0 ? Qtrue : Qfalse);
434
- }
435
-
436
- static void *nogvl_do_result(void *ptr, char use_result) {
437
- mysql_client_wrapper *wrapper;
438
- MYSQL_RES *result;
439
-
440
- wrapper = (mysql_client_wrapper *)ptr;
441
- if(use_result) {
442
- result = mysql_use_result(wrapper->client);
443
- } else {
444
- result = mysql_store_result(wrapper->client);
445
- }
446
-
447
- /* once our result is stored off, this connection is
448
- ready for another command to be issued */
449
- wrapper->active_thread = Qnil;
450
-
451
- return result;
261
+ return res == 0 ? Qtrue : Qfalse;
452
262
  }
453
263
 
454
264
  /* mysql_store_result may (unlikely) read rows off the socket */
455
- static void *nogvl_store_result(void *ptr) {
456
- return nogvl_do_result(ptr, 0);
457
- }
458
-
459
- static void *nogvl_use_result(void *ptr) {
460
- return nogvl_do_result(ptr, 1);
265
+ static VALUE nogvl_store_result(void *ptr) {
266
+ MYSQL * client = ptr;
267
+ return (VALUE)mysql_store_result(client);
461
268
  }
462
269
 
463
- /* call-seq:
464
- * client.async_result
465
- *
466
- * Returns the result for the last async issued query.
467
- */
468
270
  static VALUE rb_mysql_client_async_result(VALUE self) {
469
271
  MYSQL_RES * result;
470
272
  VALUE resultObj;
471
- VALUE current, is_streaming;
273
+ #ifdef HAVE_RUBY_ENCODING_H
274
+ mysql2_result_wrapper * result_wrapper;
275
+ #endif
472
276
  GET_CLIENT(self);
473
277
 
474
- /* if we're not waiting on a result, do nothing */
475
- if (NIL_P(wrapper->active_thread))
476
- return Qnil;
477
-
478
- REQUIRE_CONNECTED(wrapper);
479
- if ((VALUE)rb_thread_call_without_gvl(nogvl_read_query_result, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
480
- /* an error occurred, mark this connection inactive */
278
+ REQUIRE_OPEN_DB(wrapper);
279
+ if (rb_thread_blocking_region(nogvl_read_query_result, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
280
+ // an error occurred, mark this connection inactive
481
281
  MARK_CONN_INACTIVE(self);
482
282
  return rb_raise_mysql2_error(wrapper);
483
283
  }
484
284
 
485
- is_streaming = rb_hash_aref(rb_iv_get(self, "@current_query_options"), sym_stream);
486
- if(is_streaming == Qtrue) {
487
- result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_use_result, wrapper, RUBY_UBF_IO, 0);
488
- } else {
489
- result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
490
- }
285
+ result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, wrapper->client, RUBY_UBF_IO, 0);
286
+
287
+ // we have our result, mark this connection inactive
288
+ MARK_CONN_INACTIVE(self);
491
289
 
492
290
  if (result == NULL) {
493
- if (mysql_errno(wrapper->client) != 0) {
494
- MARK_CONN_INACTIVE(self);
291
+ if (mysql_field_count(wrapper->client) != 0) {
495
292
  rb_raise_mysql2_error(wrapper);
496
293
  }
497
- /* no data and no error, so query was not a SELECT */
498
294
  return Qnil;
499
295
  }
500
296
 
501
- current = rb_hash_dup(rb_iv_get(self, "@current_query_options"));
502
- RB_GC_GUARD(current);
503
- Check_Type(current, T_HASH);
504
- resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result);
297
+ resultObj = rb_mysql_result_to_obj(result);
298
+ // pass-through query options for result construction later
299
+ rb_iv_set(resultObj, "@query_options", rb_funcall(rb_iv_get(self, "@query_options"), rb_intern("dup"), 0));
505
300
 
301
+ #ifdef HAVE_RUBY_ENCODING_H
302
+ GetMysql2Result(resultObj, result_wrapper);
303
+ result_wrapper->encoding = wrapper->encoding;
304
+ #endif
506
305
  return resultObj;
507
306
  }
508
307
 
509
- #ifndef _WIN32
510
- struct async_query_args {
511
- int fd;
512
- VALUE self;
513
- };
514
-
515
- static VALUE disconnect_and_raise(VALUE self, VALUE error) {
308
+ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
309
+ struct nogvl_send_query_args args;
310
+ fd_set fdset;
311
+ int fd, retval;
312
+ int async = 0;
313
+ VALUE opts, defaults, read_timeout;
314
+ #ifdef HAVE_RUBY_ENCODING_H
315
+ rb_encoding *conn_enc;
316
+ #endif
317
+ struct timeval tv;
318
+ struct timeval* tvp;
319
+ long int sec;
320
+ VALUE result;
516
321
  GET_CLIENT(self);
517
322
 
518
- wrapper->active_thread = Qnil;
519
- wrapper->connected = 0;
323
+ REQUIRE_OPEN_DB(wrapper);
324
+ args.mysql = wrapper->client;
520
325
 
521
- /* Invalidate the MySQL socket to prevent further communication.
522
- * The GC will come along later and call mysql_close to free it.
523
- */
524
- if (invalidate_fd(wrapper->client->net.fd) == Qfalse) {
525
- fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely, closing unsafely\n");
526
- close(wrapper->client->net.fd);
326
+ // see if this connection is still waiting on a result from a previous query
327
+ if (wrapper->active == 0) {
328
+ // mark this connection active
329
+ wrapper->active = 1;
330
+ } else {
331
+ rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
527
332
  }
528
333
 
529
- rb_exc_raise(error);
334
+ defaults = rb_iv_get(self, "@query_options");
335
+ if (rb_scan_args(argc, argv, "11", &args.sql, &opts) == 2) {
336
+ opts = rb_funcall(defaults, intern_merge, 1, opts);
337
+ rb_iv_set(self, "@query_options", opts);
530
338
 
531
- return Qnil;
532
- }
339
+ if (rb_hash_aref(opts, sym_async) == Qtrue) {
340
+ async = 1;
341
+ }
342
+ } else {
343
+ opts = defaults;
344
+ }
533
345
 
534
- static VALUE do_query(void *args) {
535
- struct async_query_args *async_args;
536
- struct timeval tv;
537
- struct timeval* tvp;
538
- long int sec;
539
- int retval;
540
- VALUE read_timeout;
346
+ Check_Type(args.sql, T_STRING);
347
+ #ifdef HAVE_RUBY_ENCODING_H
348
+ conn_enc = rb_to_encoding(wrapper->encoding);
349
+ // ensure the string is in the encoding the connection is expecting
350
+ args.sql = rb_str_export_to_enc(args.sql, conn_enc);
351
+ #endif
352
+
353
+ if (rb_thread_blocking_region(nogvl_send_query, &args, RUBY_UBF_IO, 0) == Qfalse) {
354
+ // an error occurred, we're not active anymore
355
+ MARK_CONN_INACTIVE(self);
356
+ return rb_raise_mysql2_error(wrapper);
357
+ }
541
358
 
542
- async_args = (struct async_query_args *)args;
543
- read_timeout = rb_iv_get(async_args->self, "@read_timeout");
359
+ read_timeout = rb_iv_get(self, "@read_timeout");
544
360
 
545
361
  tvp = NULL;
546
362
  if (!NIL_P(read_timeout)) {
547
363
  Check_Type(read_timeout, T_FIXNUM);
548
364
  tvp = &tv;
549
365
  sec = FIX2INT(read_timeout);
550
- /* TODO: support partial seconds?
551
- also, this check is here for sanity, we also check up in Ruby */
366
+ // TODO: support partial seconds?
367
+ // also, this check is here for sanity, we also check up in Ruby
552
368
  if (sec >= 0) {
553
369
  tvp->tv_sec = sec;
554
370
  } else {
@@ -557,163 +373,55 @@ static VALUE do_query(void *args) {
557
373
  tvp->tv_usec = 0;
558
374
  }
559
375
 
560
- for(;;) {
561
- retval = rb_wait_for_single_fd(async_args->fd, RB_WAITFD_IN, tvp);
562
-
563
- if (retval == 0) {
564
- rb_raise(cMysql2Error, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
565
- }
566
-
567
- if (retval < 0) {
568
- rb_sys_fail(0);
569
- }
570
-
571
- if (retval > 0) {
572
- break;
573
- }
574
- }
575
-
576
- return Qnil;
577
- }
578
- #else
579
- static VALUE finish_and_mark_inactive(void *args) {
580
- VALUE self;
581
- MYSQL_RES *result;
582
-
583
- self = (VALUE)args;
584
-
585
- GET_CLIENT(self);
586
-
587
- if (!NIL_P(wrapper->active_thread)) {
588
- /* if we got here, the result hasn't been read off the wire yet
589
- so lets do that and then throw it away because we have no way
590
- of getting it back up to the caller from here */
591
- result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
592
- mysql_free_result(result);
593
-
594
- wrapper->active_thread = Qnil;
595
- }
376
+ if (!async) {
377
+ // the below code is largely from do_mysql
378
+ // http://github.com/datamapper/do
379
+ fd = wrapper->client->net.fd;
380
+ for(;;) {
381
+ int fd_set_fd = fd;
596
382
 
597
- return Qnil;
598
- }
383
+ #ifdef _WIN32
384
+ WSAPROTOCOL_INFO wsa_pi;
385
+ // dupicate the SOCKET from libmysql
386
+ int r = WSADuplicateSocket(fd, GetCurrentProcessId(), &wsa_pi);
387
+ SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
388
+ // create the CRT fd so ruby can get back to the SOCKET
389
+ fd_set_fd = _open_osfhandle(s, O_RDWR|O_BINARY);
599
390
  #endif
600
391
 
601
- /* call-seq:
602
- * client.abandon_results!
603
- *
604
- * When using MULTI_STATEMENTS support, calling this will throw
605
- * away any unprocessed results as fast as it can in order to
606
- * put the connection back into a state where queries can be issued
607
- * again.
608
- */
609
- static VALUE rb_mysql_client_abandon_results(VALUE self) {
610
- MYSQL_RES *result;
611
- int ret;
392
+ FD_ZERO(&fdset);
393
+ FD_SET(fd_set_fd, &fdset);
612
394
 
613
- GET_CLIENT(self);
395
+ retval = rb_thread_select(fd_set_fd + 1, &fdset, NULL, NULL, tvp);
614
396
 
615
- while (mysql_more_results(wrapper->client) == 1) {
616
- ret = mysql_next_result(wrapper->client);
617
- if (ret > 0) {
618
- rb_raise_mysql2_error(wrapper);
619
- }
620
-
621
- result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
622
-
623
- if (result != NULL) {
624
- mysql_free_result(result);
625
- }
626
- }
627
-
628
- return Qnil;
629
- }
630
-
631
- /* call-seq:
632
- * client.query(sql, options = {})
633
- *
634
- * Query the database with +sql+, with optional +options+. For the possible
635
- * options, see @@default_query_options on the Mysql2::Client class.
636
- */
637
- static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
638
- #ifndef _WIN32
639
- struct async_query_args async_args;
640
- #endif
641
- struct nogvl_send_query_args args;
642
- int async = 0;
643
- VALUE opts, current;
644
- VALUE thread_current = rb_thread_current();
645
- #ifdef HAVE_RUBY_ENCODING_H
646
- rb_encoding *conn_enc;
397
+ #ifdef _WIN32
398
+ // cleanup the CRT fd
399
+ _close(fd_set_fd);
400
+ // cleanup the duplicated SOCKET
401
+ closesocket(s);
647
402
  #endif
648
- GET_CLIENT(self);
649
-
650
- REQUIRE_CONNECTED(wrapper);
651
- args.mysql = wrapper->client;
652
403
 
653
- current = rb_hash_dup(rb_iv_get(self, "@query_options"));
654
- RB_GC_GUARD(current);
655
- Check_Type(current, T_HASH);
656
- rb_iv_set(self, "@current_query_options", current);
404
+ if (retval == 0) {
405
+ rb_raise(cMysql2Error, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
406
+ }
657
407
 
658
- if (rb_scan_args(argc, argv, "11", &args.sql, &opts) == 2) {
659
- rb_funcall(current, intern_merge_bang, 1, opts);
408
+ if (retval < 0) {
409
+ rb_sys_fail(0);
410
+ }
660
411
 
661
- if (rb_hash_aref(current, sym_async) == Qtrue) {
662
- async = 1;
412
+ if (retval > 0) {
413
+ break;
414
+ }
663
415
  }
664
- }
665
416
 
666
- Check_Type(args.sql, T_STRING);
667
- #ifdef HAVE_RUBY_ENCODING_H
668
- conn_enc = rb_to_encoding(wrapper->encoding);
669
- /* ensure the string is in the encoding the connection is expecting */
670
- args.sql = rb_str_export_to_enc(args.sql, conn_enc);
671
- #endif
672
- args.sql_ptr = StringValuePtr(args.sql);
673
- args.sql_len = RSTRING_LEN(args.sql);
674
-
675
- /* see if this connection is still waiting on a result from a previous query */
676
- if (NIL_P(wrapper->active_thread)) {
677
- /* mark this connection active */
678
- wrapper->active_thread = thread_current;
679
- } else if (wrapper->active_thread == thread_current) {
680
- rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
681
- } else {
682
- VALUE inspect = rb_inspect(wrapper->active_thread);
683
- const char *thr = StringValueCStr(inspect);
684
-
685
- rb_raise(cMysql2Error, "This connection is in use by: %s", thr);
686
- RB_GC_GUARD(inspect);
687
- }
688
-
689
- args.wrapper = wrapper;
690
-
691
- #ifndef _WIN32
692
- rb_rescue2(do_send_query, (VALUE)&args, disconnect_and_raise, self, rb_eException, (VALUE)0);
693
-
694
- if (!async) {
695
- async_args.fd = wrapper->client->net.fd;
696
- async_args.self = self;
417
+ result = rb_mysql_client_async_result(self);
697
418
 
698
- rb_rescue2(do_query, (VALUE)&async_args, disconnect_and_raise, self, rb_eException, (VALUE)0);
699
-
700
- return rb_mysql_client_async_result(self);
419
+ return result;
701
420
  } else {
702
421
  return Qnil;
703
422
  }
704
- #else
705
- do_send_query(&args);
706
-
707
- /* this will just block until the result is ready */
708
- return rb_ensure(rb_mysql_client_async_result, self, finish_and_mark_inactive, self);
709
- #endif
710
423
  }
711
424
 
712
- /* call-seq:
713
- * client.escape(string)
714
- *
715
- * Escape +string+ so that it may be used in a SQL statement.
716
- */
717
425
  static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
718
426
  unsigned char *newStr;
719
427
  VALUE rb_str;
@@ -724,12 +432,12 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
724
432
  #endif
725
433
  GET_CLIENT(self);
726
434
 
727
- REQUIRE_CONNECTED(wrapper);
435
+ REQUIRE_OPEN_DB(wrapper);
728
436
  Check_Type(str, T_STRING);
729
437
  #ifdef HAVE_RUBY_ENCODING_H
730
438
  default_internal_enc = rb_default_internal_encoding();
731
439
  conn_enc = rb_to_encoding(wrapper->encoding);
732
- /* ensure the string is in the encoding the connection is expecting */
440
+ // ensure the string is in the encoding the connection is expecting
733
441
  str = rb_str_export_to_enc(str, conn_enc);
734
442
  #endif
735
443
 
@@ -738,7 +446,7 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
738
446
 
739
447
  newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, StringValuePtr(str), oldLen);
740
448
  if (newLen == oldLen) {
741
- /* no need to return a new ruby string if nothing changed */
449
+ // no need to return a new ruby string if nothing changed
742
450
  xfree(newStr);
743
451
  return str;
744
452
  } else {
@@ -754,102 +462,13 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
754
462
  }
755
463
  }
756
464
 
757
- static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
758
- int result;
759
- const void *retval = NULL;
760
- unsigned int intval = 0;
761
- const char * charval = NULL;
762
- my_bool boolval;
763
-
764
- GET_CLIENT(self);
765
-
766
- REQUIRE_NOT_CONNECTED(wrapper);
767
-
768
- if (NIL_P(value))
769
- return Qfalse;
770
-
771
- switch(opt) {
772
- case MYSQL_OPT_CONNECT_TIMEOUT:
773
- intval = NUM2UINT(value);
774
- retval = &intval;
775
- break;
776
-
777
- case MYSQL_OPT_READ_TIMEOUT:
778
- intval = NUM2UINT(value);
779
- retval = &intval;
780
- break;
781
-
782
- case MYSQL_OPT_WRITE_TIMEOUT:
783
- intval = NUM2UINT(value);
784
- retval = &intval;
785
- break;
786
-
787
- case MYSQL_OPT_LOCAL_INFILE:
788
- intval = (value == Qfalse ? 0 : 1);
789
- retval = &intval;
790
- break;
791
-
792
- case MYSQL_OPT_RECONNECT:
793
- boolval = (value == Qfalse ? 0 : 1);
794
- retval = &boolval;
795
- break;
796
-
797
- case MYSQL_SECURE_AUTH:
798
- boolval = (value == Qfalse ? 0 : 1);
799
- retval = &boolval;
800
- break;
801
-
802
- case MYSQL_READ_DEFAULT_FILE:
803
- charval = (const char *)StringValuePtr(value);
804
- retval = charval;
805
- break;
806
-
807
- case MYSQL_READ_DEFAULT_GROUP:
808
- charval = (const char *)StringValuePtr(value);
809
- retval = charval;
810
- break;
811
-
812
- case MYSQL_INIT_COMMAND:
813
- charval = (const char *)StringValuePtr(value);
814
- retval = charval;
815
- break;
816
-
817
- default:
818
- return Qfalse;
819
- }
820
-
821
- result = mysql_options(wrapper->client, opt, retval);
822
-
823
- /* Zero means success */
824
- if (result != 0) {
825
- rb_warn("%s\n", mysql_error(wrapper->client));
826
- } else {
827
- /* Special case for options that are stored in the wrapper struct */
828
- switch (opt) {
829
- case MYSQL_OPT_RECONNECT:
830
- wrapper->reconnect_enabled = boolval;
831
- break;
832
- case MYSQL_OPT_CONNECT_TIMEOUT:
833
- wrapper->connect_timeout = intval;
834
- break;
835
- }
836
- }
837
-
838
- return (result == 0) ? Qtrue : Qfalse;
839
- }
840
-
841
- /* call-seq:
842
- * client.info
843
- *
844
- * Returns a string that represents the client library version.
845
- */
846
465
  static VALUE rb_mysql_client_info(VALUE self) {
847
466
  VALUE version, client_info;
848
467
  #ifdef HAVE_RUBY_ENCODING_H
849
468
  rb_encoding *default_internal_enc;
850
469
  rb_encoding *conn_enc;
851
- GET_CLIENT(self);
852
470
  #endif
471
+ GET_CLIENT(self);
853
472
  version = rb_hash_new();
854
473
 
855
474
  #ifdef HAVE_RUBY_ENCODING_H
@@ -869,11 +488,6 @@ static VALUE rb_mysql_client_info(VALUE self) {
869
488
  return version;
870
489
  }
871
490
 
872
- /* call-seq:
873
- * client.server_info
874
- *
875
- * Returns a string that represents the server version number
876
- */
877
491
  static VALUE rb_mysql_client_server_info(VALUE self) {
878
492
  VALUE version, server_info;
879
493
  #ifdef HAVE_RUBY_ENCODING_H
@@ -882,7 +496,7 @@ static VALUE rb_mysql_client_server_info(VALUE self) {
882
496
  #endif
883
497
  GET_CLIENT(self);
884
498
 
885
- REQUIRE_CONNECTED(wrapper);
499
+ REQUIRE_OPEN_DB(wrapper);
886
500
  #ifdef HAVE_RUBY_ENCODING_H
887
501
  default_internal_enc = rb_default_internal_encoding();
888
502
  conn_enc = rb_to_encoding(wrapper->encoding);
@@ -901,48 +515,34 @@ static VALUE rb_mysql_client_server_info(VALUE self) {
901
515
  return version;
902
516
  }
903
517
 
904
- /* call-seq:
905
- * client.socket
906
- *
907
- * Return the file descriptor number for this client.
908
- */
909
518
  static VALUE rb_mysql_client_socket(VALUE self) {
910
519
  GET_CLIENT(self);
911
- #ifndef _WIN32
912
- {
913
- int fd_set_fd;
914
- REQUIRE_CONNECTED(wrapper);
915
- fd_set_fd = wrapper->client->net.fd;
916
- return INT2NUM(fd_set_fd);
917
- }
520
+ REQUIRE_OPEN_DB(wrapper);
521
+ int fd_set_fd = wrapper->client->net.fd;
522
+ #ifdef _WIN32
523
+ WSAPROTOCOL_INFO wsa_pi;
524
+ // dupicate the SOCKET from libmysql
525
+ int r = WSADuplicateSocket(wrapper->client->net.fd, GetCurrentProcessId(), &wsa_pi);
526
+ SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
527
+ // create the CRT fd so ruby can get back to the SOCKET
528
+ fd_set_fd = _open_osfhandle(s, O_RDWR|O_BINARY);
529
+ return INT2NUM(fd_set_fd);
918
530
  #else
919
- rb_raise(cMysql2Error, "Raw access to the mysql file descriptor isn't supported on Windows");
531
+ return INT2NUM(fd_set_fd);
920
532
  #endif
921
533
  }
922
534
 
923
- /* call-seq:
924
- * client.last_id
925
- *
926
- * Returns the value generated for an AUTO_INCREMENT column by the previous INSERT or UPDATE
927
- * statement.
928
- */
929
535
  static VALUE rb_mysql_client_last_id(VALUE self) {
930
536
  GET_CLIENT(self);
931
- REQUIRE_CONNECTED(wrapper);
537
+ REQUIRE_OPEN_DB(wrapper);
932
538
  return ULL2NUM(mysql_insert_id(wrapper->client));
933
539
  }
934
540
 
935
- /* call-seq:
936
- * client.affected_rows
937
- *
938
- * returns the number of rows changed, deleted, or inserted by the last statement
939
- * if it was an UPDATE, DELETE, or INSERT.
940
- */
941
541
  static VALUE rb_mysql_client_affected_rows(VALUE self) {
942
542
  my_ulonglong retVal;
943
543
  GET_CLIENT(self);
944
544
 
945
- REQUIRE_CONNECTED(wrapper);
545
+ REQUIRE_OPEN_DB(wrapper);
946
546
  retVal = mysql_affected_rows(wrapper->client);
947
547
  if (retVal == (my_ulonglong)-1) {
948
548
  rb_raise_mysql2_error(wrapper);
@@ -950,227 +550,93 @@ static VALUE rb_mysql_client_affected_rows(VALUE self) {
950
550
  return ULL2NUM(retVal);
951
551
  }
952
552
 
953
- /* call-seq:
954
- * client.thread_id
955
- *
956
- * Returns the thread ID of the current connection.
957
- */
958
553
  static VALUE rb_mysql_client_thread_id(VALUE self) {
959
554
  unsigned long retVal;
960
555
  GET_CLIENT(self);
961
556
 
962
- REQUIRE_CONNECTED(wrapper);
557
+ REQUIRE_OPEN_DB(wrapper);
963
558
  retVal = mysql_thread_id(wrapper->client);
964
559
  return ULL2NUM(retVal);
965
560
  }
966
561
 
967
- static void *nogvl_select_db(void *ptr) {
968
- struct nogvl_select_db_args *args = ptr;
969
-
970
- if (mysql_select_db(args->mysql, args->db) == 0)
971
- return (void *)Qtrue;
972
- else
973
- return (void *)Qfalse;
974
- }
975
-
976
- /* call-seq:
977
- * client.select_db(name)
978
- *
979
- * Causes the database specified by +name+ to become the default (current)
980
- * database on the connection specified by mysql.
981
- */
982
- static VALUE rb_mysql_client_select_db(VALUE self, VALUE db)
562
+ static VALUE nogvl_ping(void *ptr)
983
563
  {
984
- struct nogvl_select_db_args args;
985
-
986
- GET_CLIENT(self);
987
- REQUIRE_CONNECTED(wrapper);
988
-
989
- args.mysql = wrapper->client;
990
- args.db = StringValuePtr(db);
991
-
992
- if (rb_thread_call_without_gvl(nogvl_select_db, &args, RUBY_UBF_IO, 0) == Qfalse)
993
- rb_raise_mysql2_error(wrapper);
994
-
995
- return db;
996
- }
997
-
998
- static void *nogvl_ping(void *ptr) {
999
564
  MYSQL *client = ptr;
1000
565
 
1001
- return (void *)(mysql_ping(client) == 0 ? Qtrue : Qfalse);
566
+ return mysql_ping(client) == 0 ? Qtrue : Qfalse;
1002
567
  }
1003
568
 
1004
- /* call-seq:
1005
- * client.ping
1006
- *
1007
- * Checks whether the connection to the server is working. If the connection
1008
- * has gone down and auto-reconnect is enabled an attempt to reconnect is made.
1009
- * If the connection is down and auto-reconnect is disabled, ping returns an
1010
- * error.
1011
- */
1012
569
  static VALUE rb_mysql_client_ping(VALUE self) {
1013
570
  GET_CLIENT(self);
1014
571
 
1015
- if (!wrapper->connected) {
572
+ if (wrapper->closed) {
1016
573
  return Qfalse;
1017
574
  } else {
1018
- return (VALUE)rb_thread_call_without_gvl(nogvl_ping, wrapper->client, RUBY_UBF_IO, 0);
1019
- }
1020
- }
1021
-
1022
- /* call-seq:
1023
- * client.more_results?
1024
- *
1025
- * Returns true or false if there are more results to process.
1026
- */
1027
- static VALUE rb_mysql_client_more_results(VALUE self)
1028
- {
1029
- GET_CLIENT(self);
1030
- if (mysql_more_results(wrapper->client) == 0)
1031
- return Qfalse;
1032
- else
1033
- return Qtrue;
1034
- }
1035
-
1036
- /* call-seq:
1037
- * client.next_result
1038
- *
1039
- * Fetch the next result set from the server.
1040
- * Returns nothing.
1041
- */
1042
- static VALUE rb_mysql_client_next_result(VALUE self)
1043
- {
1044
- int ret;
1045
- GET_CLIENT(self);
1046
- ret = mysql_next_result(wrapper->client);
1047
- if (ret > 0) {
1048
- rb_raise_mysql2_error(wrapper);
1049
- return Qfalse;
1050
- } else if (ret == 0) {
1051
- return Qtrue;
1052
- } else {
1053
- return Qfalse;
1054
- }
1055
- }
1056
-
1057
- /* call-seq:
1058
- * client.store_result
1059
- *
1060
- * Return the next result object from a query which
1061
- * yielded multiple result sets.
1062
- */
1063
- static VALUE rb_mysql_client_store_result(VALUE self)
1064
- {
1065
- MYSQL_RES * result;
1066
- VALUE resultObj;
1067
- VALUE current;
1068
- GET_CLIENT(self);
1069
-
1070
- result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
1071
-
1072
- if (result == NULL) {
1073
- if (mysql_errno(wrapper->client) != 0) {
1074
- rb_raise_mysql2_error(wrapper);
1075
- }
1076
- /* no data and no error, so query was not a SELECT */
1077
- return Qnil;
575
+ return rb_thread_blocking_region(nogvl_ping, wrapper->client, RUBY_UBF_IO, 0);
1078
576
  }
1079
-
1080
- current = rb_hash_dup(rb_iv_get(self, "@current_query_options"));
1081
- RB_GC_GUARD(current);
1082
- Check_Type(current, T_HASH);
1083
- resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result);
1084
-
1085
- return resultObj;
1086
577
  }
1087
578
 
1088
579
  #ifdef HAVE_RUBY_ENCODING_H
1089
- /* call-seq:
1090
- * client.encoding
1091
- *
1092
- * Returns the encoding set on the client.
1093
- */
1094
580
  static VALUE rb_mysql_client_encoding(VALUE self) {
1095
581
  GET_CLIENT(self);
1096
582
  return wrapper->encoding;
1097
583
  }
1098
584
  #endif
1099
585
 
1100
- /* call-seq:
1101
- * client.reconnect = true
1102
- *
1103
- * Enable or disable the automatic reconnect behavior of libmysql.
1104
- * Read http://dev.mysql.com/doc/refman/5.5/en/auto-reconnect.html
1105
- * for more information.
1106
- */
1107
586
  static VALUE set_reconnect(VALUE self, VALUE value) {
1108
- return _mysql_client_options(self, MYSQL_OPT_RECONNECT, value);
1109
- }
587
+ my_bool reconnect;
588
+ GET_CLIENT(self);
1110
589
 
1111
- static VALUE set_local_infile(VALUE self, VALUE value) {
1112
- return _mysql_client_options(self, MYSQL_OPT_LOCAL_INFILE, value);
1113
- }
590
+ if(!NIL_P(value)) {
591
+ reconnect = value == Qfalse ? 0 : 1;
1114
592
 
1115
- static VALUE set_connect_timeout(VALUE self, VALUE value) {
1116
- long int sec;
1117
- Check_Type(value, T_FIXNUM);
1118
- sec = FIX2INT(value);
1119
- if (sec < 0) {
1120
- rb_raise(cMysql2Error, "connect_timeout must be a positive integer, you passed %ld", sec);
593
+ /* set default reconnect behavior */
594
+ if (mysql_options(wrapper->client, MYSQL_OPT_RECONNECT, &reconnect)) {
595
+ /* TODO: warning - unable to set reconnect behavior */
596
+ rb_warn("%s\n", mysql_error(wrapper->client));
597
+ }
1121
598
  }
1122
- return _mysql_client_options(self, MYSQL_OPT_CONNECT_TIMEOUT, value);
599
+ return value;
1123
600
  }
1124
601
 
1125
- static VALUE set_read_timeout(VALUE self, VALUE value) {
1126
- long int sec;
1127
- Check_Type(value, T_FIXNUM);
1128
- sec = FIX2INT(value);
1129
- if (sec < 0) {
1130
- rb_raise(cMysql2Error, "read_timeout must be a positive integer, you passed %ld", sec);
1131
- }
1132
- /* Set the instance variable here even though _mysql_client_options
1133
- might not succeed, because the timeout is used in other ways
1134
- elsewhere */
1135
- rb_iv_set(self, "@read_timeout", value);
1136
- return _mysql_client_options(self, MYSQL_OPT_READ_TIMEOUT, value);
1137
- }
602
+ static VALUE set_connect_timeout(VALUE self, VALUE value) {
603
+ unsigned int connect_timeout = 0;
604
+ GET_CLIENT(self);
1138
605
 
1139
- static VALUE set_write_timeout(VALUE self, VALUE value) {
1140
- long int sec;
1141
- Check_Type(value, T_FIXNUM);
1142
- sec = FIX2INT(value);
1143
- if (sec < 0) {
1144
- rb_raise(cMysql2Error, "write_timeout must be a positive integer, you passed %ld", sec);
606
+ if(!NIL_P(value)) {
607
+ connect_timeout = NUM2INT(value);
608
+ if(0 == connect_timeout) return value;
609
+
610
+ /* set default connection timeout behavior */
611
+ if (mysql_options(wrapper->client, MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout)) {
612
+ /* TODO: warning - unable to set connection timeout */
613
+ rb_warn("%s\n", mysql_error(wrapper->client));
614
+ }
1145
615
  }
1146
- return _mysql_client_options(self, MYSQL_OPT_WRITE_TIMEOUT, value);
616
+ return value;
1147
617
  }
1148
618
 
1149
619
  static VALUE set_charset_name(VALUE self, VALUE value) {
1150
- char *charset_name;
620
+ char * charset_name;
1151
621
  #ifdef HAVE_RUBY_ENCODING_H
1152
- size_t charset_name_len;
1153
- const struct mysql2_mysql_enc_name_to_rb_map *mysql2rb;
1154
- rb_encoding *enc;
1155
- VALUE rb_enc;
622
+ VALUE new_encoding;
1156
623
  #endif
1157
624
  GET_CLIENT(self);
1158
625
 
1159
- charset_name = RSTRING_PTR(value);
1160
-
1161
626
  #ifdef HAVE_RUBY_ENCODING_H
1162
- charset_name_len = RSTRING_LEN(value);
1163
- mysql2rb = mysql2_mysql_enc_name_to_rb(charset_name, charset_name_len);
1164
- if (mysql2rb == NULL || mysql2rb->rb_name == NULL) {
627
+ new_encoding = rb_funcall(cMysql2Client, intern_encoding_from_charset, 1, value);
628
+ if (new_encoding == Qnil) {
1165
629
  VALUE inspect = rb_inspect(value);
1166
630
  rb_raise(cMysql2Error, "Unsupported charset: '%s'", RSTRING_PTR(inspect));
1167
631
  } else {
1168
- enc = rb_enc_find(mysql2rb->rb_name);
1169
- rb_enc = rb_enc_from_encoding(enc);
1170
- wrapper->encoding = rb_enc;
632
+ if (wrapper->encoding == Qnil) {
633
+ wrapper->encoding = new_encoding;
634
+ }
1171
635
  }
1172
636
  #endif
1173
637
 
638
+ charset_name = StringValuePtr(value);
639
+
1174
640
  if (mysql_options(wrapper->client, MYSQL_SET_CHARSET_NAME, charset_name)) {
1175
641
  /* TODO: warning - unable to set charset */
1176
642
  rb_warn("%s\n", mysql_error(wrapper->client));
@@ -1182,73 +648,48 @@ static VALUE set_charset_name(VALUE self, VALUE value) {
1182
648
  static VALUE set_ssl_options(VALUE self, VALUE key, VALUE cert, VALUE ca, VALUE capath, VALUE cipher) {
1183
649
  GET_CLIENT(self);
1184
650
 
1185
- mysql_ssl_set(wrapper->client,
1186
- NIL_P(key) ? NULL : StringValuePtr(key),
1187
- NIL_P(cert) ? NULL : StringValuePtr(cert),
1188
- NIL_P(ca) ? NULL : StringValuePtr(ca),
1189
- NIL_P(capath) ? NULL : StringValuePtr(capath),
1190
- NIL_P(cipher) ? NULL : StringValuePtr(cipher));
651
+ if(!NIL_P(ca) || !NIL_P(key)) {
652
+ mysql_ssl_set(wrapper->client,
653
+ NIL_P(key) ? NULL : StringValuePtr(key),
654
+ NIL_P(cert) ? NULL : StringValuePtr(cert),
655
+ NIL_P(ca) ? NULL : StringValuePtr(ca),
656
+ NIL_P(capath) ? NULL : StringValuePtr(capath),
657
+ NIL_P(cipher) ? NULL : StringValuePtr(cipher));
658
+ }
1191
659
 
1192
660
  return self;
1193
661
  }
1194
662
 
1195
- static VALUE set_secure_auth(VALUE self, VALUE value) {
1196
- return _mysql_client_options(self, MYSQL_SECURE_AUTH, value);
1197
- }
1198
-
1199
- static VALUE set_read_default_file(VALUE self, VALUE value) {
1200
- return _mysql_client_options(self, MYSQL_READ_DEFAULT_FILE, value);
1201
- }
1202
-
1203
- static VALUE set_read_default_group(VALUE self, VALUE value) {
1204
- return _mysql_client_options(self, MYSQL_READ_DEFAULT_GROUP, value);
1205
- }
1206
-
1207
- static VALUE set_init_command(VALUE self, VALUE value) {
1208
- return _mysql_client_options(self, MYSQL_INIT_COMMAND, value);
1209
- }
1210
-
1211
- static VALUE initialize_ext(VALUE self) {
663
+ static VALUE init_connection(VALUE self) {
1212
664
  GET_CLIENT(self);
1213
665
 
1214
- if ((VALUE)rb_thread_call_without_gvl(nogvl_init, wrapper, RUBY_UBF_IO, 0) == Qfalse) {
666
+ if (rb_thread_blocking_region(nogvl_init, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
1215
667
  /* TODO: warning - not enough memory? */
1216
668
  return rb_raise_mysql2_error(wrapper);
1217
669
  }
1218
670
 
1219
- wrapper->initialized = 1;
671
+ wrapper->closed = 0;
1220
672
  return self;
1221
673
  }
1222
674
 
1223
675
  void init_mysql2_client() {
1224
- /* verify the libmysql we're about to use was the version we were built against
1225
- https://github.com/luislavena/mysql-gem/commit/a600a9c459597da0712f70f43736e24b484f8a99 */
676
+ // verify the libmysql we're about to use was the version we were built against
677
+ // https://github.com/luislavena/mysql-gem/commit/a600a9c459597da0712f70f43736e24b484f8a99
1226
678
  int i;
1227
679
  int dots = 0;
1228
680
  const char *lib = mysql_get_client_info();
1229
-
1230
- for (i = 0; lib[i] != 0 && MYSQL_LINK_VERSION[i] != 0; i++) {
681
+ for (i = 0; lib[i] != 0 && MYSQL_SERVER_VERSION[i] != 0; i++) {
1231
682
  if (lib[i] == '.') {
1232
683
  dots++;
1233
- /* we only compare MAJOR and MINOR */
684
+ // we only compare MAJOR and MINOR
1234
685
  if (dots == 2) break;
1235
686
  }
1236
- if (lib[i] != MYSQL_LINK_VERSION[i]) {
1237
- rb_raise(rb_eRuntimeError, "Incorrect MySQL client library version! This gem was compiled for %s but the client library is %s.", MYSQL_LINK_VERSION, lib);
687
+ if (lib[i] != MYSQL_SERVER_VERSION[i]) {
688
+ rb_raise(rb_eRuntimeError, "Incorrect MySQL client library version! This gem was compiled for %s but the client library is %s.", MYSQL_SERVER_VERSION, lib);
1238
689
  return;
1239
690
  }
1240
691
  }
1241
692
 
1242
- /* Initializing mysql library, so different threads could call Client.new */
1243
- /* without race condition in the library */
1244
- if (mysql_library_init(0, NULL, NULL) != 0) {
1245
- rb_raise(rb_eRuntimeError, "Could not initialize MySQL client library");
1246
- return;
1247
- }
1248
-
1249
- #if 0
1250
- mMysql2 = rb_define_module("Mysql2"); Teach RDoc about Mysql2 constant.
1251
- #endif
1252
693
  cMysql2Client = rb_define_class_under(mMysql2, "Client", rb_cObject);
1253
694
 
1254
695
  rb_define_alloc_func(cMysql2Client, allocate);
@@ -1257,7 +698,6 @@ void init_mysql2_client() {
1257
698
 
1258
699
  rb_define_method(cMysql2Client, "close", rb_mysql_client_close, 0);
1259
700
  rb_define_method(cMysql2Client, "query", rb_mysql_client_query, -1);
1260
- rb_define_method(cMysql2Client, "abandon_results!", rb_mysql_client_abandon_results, 0);
1261
701
  rb_define_method(cMysql2Client, "escape", rb_mysql_client_real_escape, 1);
1262
702
  rb_define_method(cMysql2Client, "info", rb_mysql_client_info, 0);
1263
703
  rb_define_method(cMysql2Client, "server_info", rb_mysql_client_server_info, 0);
@@ -1267,150 +707,133 @@ void init_mysql2_client() {
1267
707
  rb_define_method(cMysql2Client, "affected_rows", rb_mysql_client_affected_rows, 0);
1268
708
  rb_define_method(cMysql2Client, "thread_id", rb_mysql_client_thread_id, 0);
1269
709
  rb_define_method(cMysql2Client, "ping", rb_mysql_client_ping, 0);
1270
- rb_define_method(cMysql2Client, "select_db", rb_mysql_client_select_db, 1);
1271
- rb_define_method(cMysql2Client, "more_results?", rb_mysql_client_more_results, 0);
1272
- rb_define_method(cMysql2Client, "next_result", rb_mysql_client_next_result, 0);
1273
- rb_define_method(cMysql2Client, "store_result", rb_mysql_client_store_result, 0);
1274
- rb_define_method(cMysql2Client, "reconnect=", set_reconnect, 1);
1275
- rb_define_method(cMysql2Client, "warning_count", rb_mysql_client_warning_count, 0);
1276
- rb_define_method(cMysql2Client, "query_info_string", rb_mysql_info, 0);
1277
710
  #ifdef HAVE_RUBY_ENCODING_H
1278
711
  rb_define_method(cMysql2Client, "encoding", rb_mysql_client_encoding, 0);
1279
712
  #endif
1280
713
 
714
+ rb_define_private_method(cMysql2Client, "reconnect=", set_reconnect, 1);
1281
715
  rb_define_private_method(cMysql2Client, "connect_timeout=", set_connect_timeout, 1);
1282
- rb_define_private_method(cMysql2Client, "read_timeout=", set_read_timeout, 1);
1283
- rb_define_private_method(cMysql2Client, "write_timeout=", set_write_timeout, 1);
1284
- rb_define_private_method(cMysql2Client, "local_infile=", set_local_infile, 1);
1285
716
  rb_define_private_method(cMysql2Client, "charset_name=", set_charset_name, 1);
1286
- rb_define_private_method(cMysql2Client, "secure_auth=", set_secure_auth, 1);
1287
- rb_define_private_method(cMysql2Client, "default_file=", set_read_default_file, 1);
1288
- rb_define_private_method(cMysql2Client, "default_group=", set_read_default_group, 1);
1289
- rb_define_private_method(cMysql2Client, "init_command=", set_init_command, 1);
1290
717
  rb_define_private_method(cMysql2Client, "ssl_set", set_ssl_options, 5);
1291
- rb_define_private_method(cMysql2Client, "initialize_ext", initialize_ext, 0);
718
+ rb_define_private_method(cMysql2Client, "init_connection", init_connection, 0);
1292
719
  rb_define_private_method(cMysql2Client, "connect", rb_connect, 7);
1293
720
 
721
+ intern_encoding_from_charset = rb_intern("encoding_from_charset");
722
+
1294
723
  sym_id = ID2SYM(rb_intern("id"));
1295
724
  sym_version = ID2SYM(rb_intern("version"));
1296
725
  sym_async = ID2SYM(rb_intern("async"));
1297
726
  sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
1298
727
  sym_as = ID2SYM(rb_intern("as"));
1299
728
  sym_array = ID2SYM(rb_intern("array"));
1300
- sym_stream = ID2SYM(rb_intern("stream"));
1301
729
 
1302
730
  intern_merge = rb_intern("merge");
1303
- intern_merge_bang = rb_intern("merge!");
1304
731
  intern_error_number_eql = rb_intern("error_number=");
1305
732
  intern_sql_state_eql = rb_intern("sql_state=");
1306
733
 
1307
734
  #ifdef CLIENT_LONG_PASSWORD
1308
735
  rb_const_set(cMysql2Client, rb_intern("LONG_PASSWORD"),
1309
- LONG2NUM(CLIENT_LONG_PASSWORD));
736
+ INT2NUM(CLIENT_LONG_PASSWORD));
1310
737
  #endif
1311
738
 
1312
739
  #ifdef CLIENT_FOUND_ROWS
1313
740
  rb_const_set(cMysql2Client, rb_intern("FOUND_ROWS"),
1314
- LONG2NUM(CLIENT_FOUND_ROWS));
741
+ INT2NUM(CLIENT_FOUND_ROWS));
1315
742
  #endif
1316
743
 
1317
744
  #ifdef CLIENT_LONG_FLAG
1318
745
  rb_const_set(cMysql2Client, rb_intern("LONG_FLAG"),
1319
- LONG2NUM(CLIENT_LONG_FLAG));
746
+ INT2NUM(CLIENT_LONG_FLAG));
1320
747
  #endif
1321
748
 
1322
749
  #ifdef CLIENT_CONNECT_WITH_DB
1323
750
  rb_const_set(cMysql2Client, rb_intern("CONNECT_WITH_DB"),
1324
- LONG2NUM(CLIENT_CONNECT_WITH_DB));
751
+ INT2NUM(CLIENT_CONNECT_WITH_DB));
1325
752
  #endif
1326
753
 
1327
754
  #ifdef CLIENT_NO_SCHEMA
1328
755
  rb_const_set(cMysql2Client, rb_intern("NO_SCHEMA"),
1329
- LONG2NUM(CLIENT_NO_SCHEMA));
756
+ INT2NUM(CLIENT_NO_SCHEMA));
1330
757
  #endif
1331
758
 
1332
759
  #ifdef CLIENT_COMPRESS
1333
- rb_const_set(cMysql2Client, rb_intern("COMPRESS"), LONG2NUM(CLIENT_COMPRESS));
760
+ rb_const_set(cMysql2Client, rb_intern("COMPRESS"), INT2NUM(CLIENT_COMPRESS));
1334
761
  #endif
1335
762
 
1336
763
  #ifdef CLIENT_ODBC
1337
- rb_const_set(cMysql2Client, rb_intern("ODBC"), LONG2NUM(CLIENT_ODBC));
764
+ rb_const_set(cMysql2Client, rb_intern("ODBC"), INT2NUM(CLIENT_ODBC));
1338
765
  #endif
1339
766
 
1340
767
  #ifdef CLIENT_LOCAL_FILES
1341
768
  rb_const_set(cMysql2Client, rb_intern("LOCAL_FILES"),
1342
- LONG2NUM(CLIENT_LOCAL_FILES));
769
+ INT2NUM(CLIENT_LOCAL_FILES));
1343
770
  #endif
1344
771
 
1345
772
  #ifdef CLIENT_IGNORE_SPACE
1346
773
  rb_const_set(cMysql2Client, rb_intern("IGNORE_SPACE"),
1347
- LONG2NUM(CLIENT_IGNORE_SPACE));
774
+ INT2NUM(CLIENT_IGNORE_SPACE));
1348
775
  #endif
1349
776
 
1350
777
  #ifdef CLIENT_PROTOCOL_41
1351
778
  rb_const_set(cMysql2Client, rb_intern("PROTOCOL_41"),
1352
- LONG2NUM(CLIENT_PROTOCOL_41));
779
+ INT2NUM(CLIENT_PROTOCOL_41));
1353
780
  #endif
1354
781
 
1355
782
  #ifdef CLIENT_INTERACTIVE
1356
783
  rb_const_set(cMysql2Client, rb_intern("INTERACTIVE"),
1357
- LONG2NUM(CLIENT_INTERACTIVE));
784
+ INT2NUM(CLIENT_INTERACTIVE));
1358
785
  #endif
1359
786
 
1360
787
  #ifdef CLIENT_SSL
1361
- rb_const_set(cMysql2Client, rb_intern("SSL"), LONG2NUM(CLIENT_SSL));
788
+ rb_const_set(cMysql2Client, rb_intern("SSL"), INT2NUM(CLIENT_SSL));
1362
789
  #endif
1363
790
 
1364
791
  #ifdef CLIENT_IGNORE_SIGPIPE
1365
792
  rb_const_set(cMysql2Client, rb_intern("IGNORE_SIGPIPE"),
1366
- LONG2NUM(CLIENT_IGNORE_SIGPIPE));
793
+ INT2NUM(CLIENT_IGNORE_SIGPIPE));
1367
794
  #endif
1368
795
 
1369
796
  #ifdef CLIENT_TRANSACTIONS
1370
797
  rb_const_set(cMysql2Client, rb_intern("TRANSACTIONS"),
1371
- LONG2NUM(CLIENT_TRANSACTIONS));
798
+ INT2NUM(CLIENT_TRANSACTIONS));
1372
799
  #endif
1373
800
 
1374
801
  #ifdef CLIENT_RESERVED
1375
- rb_const_set(cMysql2Client, rb_intern("RESERVED"), LONG2NUM(CLIENT_RESERVED));
802
+ rb_const_set(cMysql2Client, rb_intern("RESERVED"), INT2NUM(CLIENT_RESERVED));
1376
803
  #endif
1377
804
 
1378
805
  #ifdef CLIENT_SECURE_CONNECTION
1379
806
  rb_const_set(cMysql2Client, rb_intern("SECURE_CONNECTION"),
1380
- LONG2NUM(CLIENT_SECURE_CONNECTION));
1381
- #else
1382
- /* HACK because MySQL5.7 no longer defines this constant,
1383
- * but we're using it in our default connection flags. */
1384
- rb_const_set(cMysql2Client, rb_intern("SECURE_CONNECTION"), LONG2NUM(0));
807
+ INT2NUM(CLIENT_SECURE_CONNECTION));
1385
808
  #endif
1386
809
 
1387
810
  #ifdef CLIENT_MULTI_STATEMENTS
1388
811
  rb_const_set(cMysql2Client, rb_intern("MULTI_STATEMENTS"),
1389
- LONG2NUM(CLIENT_MULTI_STATEMENTS));
812
+ INT2NUM(CLIENT_MULTI_STATEMENTS));
1390
813
  #endif
1391
814
 
1392
815
  #ifdef CLIENT_PS_MULTI_RESULTS
1393
816
  rb_const_set(cMysql2Client, rb_intern("PS_MULTI_RESULTS"),
1394
- LONG2NUM(CLIENT_PS_MULTI_RESULTS));
817
+ INT2NUM(CLIENT_PS_MULTI_RESULTS));
1395
818
  #endif
1396
819
 
1397
820
  #ifdef CLIENT_SSL_VERIFY_SERVER_CERT
1398
821
  rb_const_set(cMysql2Client, rb_intern("SSL_VERIFY_SERVER_CERT"),
1399
- LONG2NUM(CLIENT_SSL_VERIFY_SERVER_CERT));
822
+ INT2NUM(CLIENT_SSL_VERIFY_SERVER_CERT));
1400
823
  #endif
1401
824
 
1402
825
  #ifdef CLIENT_REMEMBER_OPTIONS
1403
826
  rb_const_set(cMysql2Client, rb_intern("REMEMBER_OPTIONS"),
1404
- LONG2NUM(CLIENT_REMEMBER_OPTIONS));
827
+ INT2NUM(CLIENT_REMEMBER_OPTIONS));
1405
828
  #endif
1406
829
 
1407
830
  #ifdef CLIENT_ALL_FLAGS
1408
831
  rb_const_set(cMysql2Client, rb_intern("ALL_FLAGS"),
1409
- LONG2NUM(CLIENT_ALL_FLAGS));
832
+ INT2NUM(CLIENT_ALL_FLAGS));
1410
833
  #endif
1411
834
 
1412
835
  #ifdef CLIENT_BASIC_FLAGS
1413
836
  rb_const_set(cMysql2Client, rb_intern("BASIC_FLAGS"),
1414
- LONG2NUM(CLIENT_BASIC_FLAGS));
837
+ INT2NUM(CLIENT_BASIC_FLAGS));
1415
838
  #endif
1416
839
  }