mysql2 0.5.3 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8be4e0f4afbea38c5460544e39c9e0d987dd040c9de5ebdbc4c1e200102ca8e4
4
- data.tar.gz: 996e05358297b03bf8f06abffd37d83a590912246ec607d2c3ee53b325c43022
3
+ metadata.gz: f387f841adc885eb4000a960ee34f475c7edab79e276d17ce8889f370bdcf387
4
+ data.tar.gz: 0c8732c2a45ed8ac68aea92765daba5969f860f1fe5a95d44e89b76deae7108b
5
5
  SHA512:
6
- metadata.gz: daf37441bcb29366453963529b5a144df0d599b79b7a0b9d90b2ae5ed3dee97c1945a58111d6fe6bc2f1c20f75c9960c3cc1cd988a0e5d1be5ce44b7dcdf3633
7
- data.tar.gz: 421df08c45f4257c2f04f3dc0a0e1c1557c695598c4e1a80236d618d1a79510459b8919b753ad9af2d46d21fa19ba060d5b53da2f54a00ff90ca45a4534c9108
6
+ metadata.gz: 8d6afb1b661525183075d14046630195bc79a5f945b92489d3daa0aeea8582e8d17a0fa9d1781fadeaaefaaeac567ead5ad7d0266e1fb9aa96076d26f1c03ad1
7
+ data.tar.gz: 9b2202a06e36ca910a9648f71d8646e67a6e665153b3ac04dcd535cd768bb78942dd799893e205df841b0461aeb5810985704e18e4a045b540f2d272b11776cd
data/README.md CHANGED
@@ -1,7 +1,12 @@
1
1
  # Mysql2 - A modern, simple and very fast MySQL library for Ruby - binding to libmysql
2
2
 
3
- Travis CI [![Travis CI Status](https://travis-ci.org/brianmario/mysql2.png)](https://travis-ci.org/brianmario/mysql2)
4
- Appveyor CI [![Appveyor CI Status](https://ci.appveyor.com/api/projects/status/github/sodabrew/mysql2)](https://ci.appveyor.com/project/sodabrew/mysql2)
3
+ GitHub Actions
4
+ [![GitHub Actions Status: Build](https://github.com/brianmario/mysql2/actions/workflows/build.yml/badge.svg)](https://github.com/brianmario/mysql2/actions/workflows/build.yml)
5
+ [![GitHub Actions Status: Container](https://github.com/brianmario/mysql2/actions/workflows/container.yml/badge.svg)](https://github.com/brianmario/mysql2/actions/workflows/container.yml)
6
+ Travis CI
7
+ [![Travis CI Status](https://travis-ci.org/brianmario/mysql2.png)](https://travis-ci.org/brianmario/mysql2)
8
+ Appveyor CI
9
+ [![Appveyor CI Status](https://ci.appveyor.com/api/projects/status/github/sodabrew/mysql2)](https://ci.appveyor.com/project/sodabrew/mysql2)
5
10
 
6
11
  The Mysql2 gem is meant to serve the extremely common use-case of connecting, querying and iterating on results.
7
12
  Some database libraries out there serve as direct 1:1 mappings of the already complex C APIs available.
@@ -143,7 +148,7 @@ results.each do |row|
143
148
  # the keys are the fields, as you'd expect
144
149
  # the values are pre-built ruby primitives mapped from their corresponding field types in MySQL
145
150
  puts row["id"] # row["id"].is_a? Integer
146
- if row["dne"] # non-existant hash entry is nil
151
+ if row["dne"] # non-existent hash entry is nil
147
152
  puts row["dne"]
148
153
  end
149
154
  end
@@ -165,11 +170,12 @@ client.query("SELECT * FROM users WHERE group='githubbers'", :symbolize_keys =>
165
170
  end
166
171
  ```
167
172
 
168
- You can get the headers and the columns in the order that they were returned
173
+ You can get the headers, columns, and the field types in the order that they were returned
169
174
  by the query like this:
170
175
 
171
176
  ``` ruby
172
177
  headers = results.fields # <= that's an array of field names, in order
178
+ types = results.field_types # <= that's an array of field types, in order
173
179
  results.each(:as => :array) do |row|
174
180
  # Each row is an array, ordered the same as the query results
175
181
  # An otter's den is called a "holt" or "couch"
@@ -197,6 +203,23 @@ statement = @client.prepare("SELECT * FROM users WHERE last_login >= ? AND locat
197
203
  result = statement.execute(1, "CA", :as => :array)
198
204
  ```
199
205
 
206
+ Session Tracking information can be accessed with
207
+
208
+ ```ruby
209
+ c = Mysql2::Client.new(
210
+ host: "127.0.0.1",
211
+ username: "root",
212
+ flags: "SESSION_TRACK",
213
+ init_command: "SET @@SESSION.session_track_schema=ON"
214
+ )
215
+ c.query("INSERT INTO test VALUES (1)")
216
+ session_track_type = Mysql2::Client::SESSION_TRACK_SCHEMA
217
+ session_track_data = c.session_track(session_track_type)
218
+ ```
219
+
220
+ The types of session track types can be found at
221
+ [https://dev.mysql.com/doc/refman/5.7/en/session-state-tracking.html](https://dev.mysql.com/doc/refman/5.7/en/session-state-tracking.html)
222
+
200
223
  ## Connection options
201
224
 
202
225
  You may set the following connection options in Mysql2::Client.new(...):
@@ -262,7 +285,7 @@ Mysql2::Client.new(
262
285
 
263
286
  ### Secure auth
264
287
 
265
- Starting wih MySQL 5.6.5, secure_auth is enabled by default on servers (it was disabled by default prior to this).
288
+ Starting with MySQL 5.6.5, secure_auth is enabled by default on servers (it was disabled by default prior to this).
266
289
  When secure_auth is enabled, the server will refuse a connection if the account password is stored in old pre-MySQL 4.1 format.
267
290
  The MySQL 5.6.5 client library may also refuse to attempt a connection if provided an older format password.
268
291
  To bypass this restriction in the client, pass the option `:secure_auth => false` to Mysql2::Client.new().
@@ -299,6 +322,8 @@ development:
299
322
  secure_auth: false
300
323
  ```
301
324
 
325
+ In this example, the compression flag is negated with `-COMPRESS`.
326
+
302
327
  ### Using Active Record's DATABASE_URL
303
328
 
304
329
  Active Record typically reads its configuration from a file named `database.yml` or an environment variable `DATABASE_URL`.
@@ -423,7 +448,7 @@ Pass the `:as => :array` option to any of the above methods of configuration
423
448
 
424
449
  ### Array of Hashes
425
450
 
426
- The default result type is set to :hash, but you can override a previous setting to something else with :as => :hash
451
+ The default result type is set to `:hash`, but you can override a previous setting to something else with `:as => :hash`
427
452
 
428
453
  ### Timezones
429
454
 
@@ -554,7 +579,7 @@ This gem is tested with the following MySQL and MariaDB versions:
554
579
 
555
580
  ### Ruby on Rails / Active Record
556
581
 
557
- * mysql2 0.5.x works with Rails / Active Record 5.0.7, 5.1.6, and higher.
582
+ * mysql2 0.5.x works with Rails / Active Record 4.2.11, 5.0.7, 5.1.6, and higher.
558
583
  * mysql2 0.4.x works with Rails / Active Record 4.2.5 - 5.0 and higher.
559
584
  * mysql2 0.3.x works with Rails / Active Record 3.1, 3.2, 4.x, 5.0.
560
585
  * mysql2 0.2.x works with Rails / Active Record 2.3 - 3.0.
@@ -648,3 +673,4 @@ though.
648
673
  * [John Cant](http://github.com/johncant) - polishing and updating Prepared Statements support
649
674
  * [Justin Case](http://github.com/justincase) - polishing and updating Prepared Statements support and getting it merged
650
675
  * [Tamir Duberstein](http://github.com/tamird) - for help with timeouts and all around updates and cleanups
676
+ * [Jun Aruga](http://github.com/junaruga) - for migrating CI tests to GitHub Actions and other improvements
data/ext/mysql2/client.c CHANGED
@@ -45,7 +45,7 @@ static ID intern_brackets, intern_merge, intern_merge_bang, intern_new_with_args
45
45
  }
46
46
 
47
47
  /*
48
- * compatability with mysql-connector-c, where LIBMYSQL_VERSION is the correct
48
+ * compatibility with mysql-connector-c, where LIBMYSQL_VERSION is the correct
49
49
  * variable to use, but MYSQL_SERVER_VERSION gives the correct numbers when
50
50
  * linking against the server itself
51
51
  */
@@ -58,8 +58,23 @@ static ID intern_brackets, intern_merge, intern_merge_bang, intern_new_with_args
58
58
  #endif
59
59
 
60
60
  /*
61
- * compatibility with mysql-connector-c 6.1.x, and with MySQL 5.7.3 - 5.7.10.
61
+ * mariadb-connector-c defines CLIENT_SESSION_TRACKING and SESSION_TRACK_TRANSACTION_TYPE
62
+ * while mysql-connector-c defines CLIENT_SESSION_TRACK and SESSION_TRACK_TRANSACTION_STATE
63
+ * This is a hack to take care of both clients.
62
64
  */
65
+ #if defined(CLIENT_SESSION_TRACK)
66
+ #elif defined(CLIENT_SESSION_TRACKING)
67
+ #define CLIENT_SESSION_TRACK CLIENT_SESSION_TRACKING
68
+ #define SESSION_TRACK_TRANSACTION_STATE SESSION_TRACK_TRANSACTION_TYPE
69
+ #endif
70
+
71
+ /*
72
+ * compatibility with mysql-connector-c 6.1.x, MySQL 5.7.3 - 5.7.10 & with MariaDB 10.x and later.
73
+ */
74
+ #ifdef HAVE_CONST_MYSQL_OPT_SSL_VERIFY_SERVER_CERT
75
+ #define SSL_MODE_VERIFY_IDENTITY 5
76
+ #define HAVE_CONST_SSL_MODE_VERIFY_IDENTITY
77
+ #endif
63
78
  #ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE
64
79
  #define SSL_MODE_DISABLED 1
65
80
  #define SSL_MODE_REQUIRED 3
@@ -110,19 +125,27 @@ static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) {
110
125
  rb_warn( "Your mysql client library does not support setting ssl_mode; full support comes with 5.7.11." );
111
126
  return Qnil;
112
127
  }
113
- #ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE
128
+ #if defined(HAVE_CONST_MYSQL_OPT_SSL_VERIFY_SERVER_CERT) || defined(HAVE_CONST_MYSQL_OPT_SSL_ENFORCE)
114
129
  GET_CLIENT(self);
115
130
  int val = NUM2INT( setting );
116
- // Either MySQL 5.7.3 - 5.7.10, or Connector/C 6.1.3 - 6.1.x
117
- if ((version >= 50703 && version < 50711) || (version >= 60103 && version < 60200)) {
131
+ // Either MySQL 5.7.3 - 5.7.10, or Connector/C 6.1.3 - 6.1.x, or MariaDB 10.x and later
132
+ if ((version >= 50703 && version < 50711) || (version >= 60103 && version < 60200) || version >= 100000) {
133
+ #ifdef HAVE_CONST_MYSQL_OPT_SSL_VERIFY_SERVER_CERT
134
+ if (val == SSL_MODE_VERIFY_IDENTITY) {
135
+ my_bool b = 1;
136
+ int result = mysql_options( wrapper->client, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &b );
137
+ return INT2NUM(result);
138
+ }
139
+ #endif
140
+ #ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE
118
141
  if (val == SSL_MODE_DISABLED || val == SSL_MODE_REQUIRED) {
119
142
  my_bool b = ( val == SSL_MODE_REQUIRED );
120
143
  int result = mysql_options( wrapper->client, MYSQL_OPT_SSL_ENFORCE, &b );
121
144
  return INT2NUM(result);
122
- } else {
123
- rb_warn( "MySQL client libraries between 5.7.3 and 5.7.10 only support SSL_MODE_DISABLED and SSL_MODE_REQUIRED" );
124
- return Qnil;
125
145
  }
146
+ #endif
147
+ rb_warn( "Your mysql client library does not support ssl_mode %d.", val );
148
+ return Qnil;
126
149
  } else {
127
150
  rb_warn( "Your mysql client library does not support ssl_mode as expected." );
128
151
  return Qnil;
@@ -140,6 +163,7 @@ static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) {
140
163
  return INT2NUM(result);
141
164
  #endif
142
165
  #ifdef NO_SSL_MODE_SUPPORT
166
+ rb_warn( "Your mysql client library does not support setting ssl_mode; full support comes with 5.7.11." );
143
167
  return Qnil;
144
168
  #endif
145
169
  }
@@ -175,7 +199,7 @@ static void rb_mysql_client_mark(void * wrapper) {
175
199
 
176
200
  static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) {
177
201
  VALUE rb_error_msg = rb_str_new2(mysql_error(wrapper->client));
178
- VALUE rb_sql_state = rb_tainted_str_new2(mysql_sqlstate(wrapper->client));
202
+ VALUE rb_sql_state = rb_str_new2(mysql_sqlstate(wrapper->client));
179
203
  VALUE e;
180
204
 
181
205
  rb_enc_associate(rb_error_msg, rb_utf8_encoding());
@@ -269,7 +293,7 @@ static VALUE invalidate_fd(int clientfd)
269
293
  static void *nogvl_close(void *ptr) {
270
294
  mysql_client_wrapper *wrapper = ptr;
271
295
 
272
- if (!wrapper->closed) {
296
+ if (wrapper->initialized && !wrapper->closed) {
273
297
  mysql_close(wrapper->client);
274
298
  wrapper->closed = 1;
275
299
  wrapper->reconnect_enabled = 0;
@@ -323,9 +347,9 @@ static VALUE allocate(VALUE klass) {
323
347
  wrapper->server_version = 0;
324
348
  wrapper->reconnect_enabled = 0;
325
349
  wrapper->connect_timeout = 0;
326
- wrapper->initialized = 0; /* means that that the wrapper is initialized */
350
+ wrapper->initialized = 0; /* will be set true after calling mysql_init */
351
+ wrapper->closed = 1; /* will be set false after calling mysql_real_connect */
327
352
  wrapper->refcount = 1;
328
- wrapper->closed = 0;
329
353
  wrapper->client = (MYSQL*)xmalloc(sizeof(MYSQL));
330
354
 
331
355
  return obj;
@@ -467,6 +491,7 @@ static VALUE rb_mysql_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VA
467
491
  rb_raise_mysql2_error(wrapper);
468
492
  }
469
493
 
494
+ wrapper->closed = 0;
470
495
  wrapper->server_version = mysql_get_server_version(wrapper->client);
471
496
  return self;
472
497
  }
@@ -513,10 +538,10 @@ static void *nogvl_send_query(void *ptr) {
513
538
  return (void*)(rv == 0 ? Qtrue : Qfalse);
514
539
  }
515
540
 
516
- static VALUE do_send_query(void *args) {
517
- struct nogvl_send_query_args *query_args = args;
541
+ static VALUE do_send_query(VALUE args) {
542
+ struct nogvl_send_query_args *query_args = (void *)args;
518
543
  mysql_client_wrapper *wrapper = query_args->wrapper;
519
- if ((VALUE)rb_thread_call_without_gvl(nogvl_send_query, args, RUBY_UBF_IO, 0) == Qfalse) {
544
+ if ((VALUE)rb_thread_call_without_gvl(nogvl_send_query, query_args, RUBY_UBF_IO, 0) == Qfalse) {
520
545
  /* an error occurred, we're not active anymore */
521
546
  wrapper->active_thread = Qnil;
522
547
  rb_raise_mysql2_error(wrapper);
@@ -636,8 +661,8 @@ static VALUE disconnect_and_raise(VALUE self, VALUE error) {
636
661
  rb_exc_raise(error);
637
662
  }
638
663
 
639
- static VALUE do_query(void *args) {
640
- struct async_query_args *async_args = args;
664
+ static VALUE do_query(VALUE args) {
665
+ struct async_query_args *async_args = (void *)args;
641
666
  struct timeval tv;
642
667
  struct timeval *tvp;
643
668
  long int sec;
@@ -785,6 +810,7 @@ static VALUE rb_mysql_query(VALUE self, VALUE sql, VALUE current) {
785
810
 
786
811
  #ifndef _WIN32
787
812
  rb_rescue2(do_send_query, (VALUE)&args, disconnect_and_raise, self, rb_eException, (VALUE)0);
813
+ (void)RB_GC_GUARD(sql);
788
814
 
789
815
  if (rb_hash_aref(current, sym_async) == Qtrue) {
790
816
  return Qnil;
@@ -797,7 +823,8 @@ static VALUE rb_mysql_query(VALUE self, VALUE sql, VALUE current) {
797
823
  return rb_ensure(rb_mysql_client_async_result, self, disconnect_and_mark_inactive, self);
798
824
  }
799
825
  #else
800
- do_send_query(&args);
826
+ do_send_query((VALUE)&args);
827
+ (void)RB_GC_GUARD(sql);
801
828
 
802
829
  /* this will just block until the result is ready */
803
830
  return rb_ensure(rb_mysql_client_async_result, self, disconnect_and_mark_inactive, self);
@@ -908,10 +935,12 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
908
935
  retval = charval;
909
936
  break;
910
937
 
938
+ #ifdef HAVE_MYSQL_DEFAULT_AUTH
911
939
  case MYSQL_DEFAULT_AUTH:
912
940
  charval = (const char *)StringValueCStr(value);
913
941
  retval = charval;
914
942
  break;
943
+ #endif
915
944
 
916
945
  #ifdef HAVE_CONST_MYSQL_ENABLE_CLEARTEXT_PLUGIN
917
946
  case MYSQL_ENABLE_CLEARTEXT_PLUGIN:
@@ -1021,6 +1050,36 @@ static VALUE rb_mysql_client_last_id(VALUE self) {
1021
1050
  return ULL2NUM(mysql_insert_id(wrapper->client));
1022
1051
  }
1023
1052
 
1053
+ /* call-seq:
1054
+ * client.session_track
1055
+ *
1056
+ * Returns information about changes to the session state on the server.
1057
+ */
1058
+ static VALUE rb_mysql_client_session_track(VALUE self, VALUE type) {
1059
+ #ifdef CLIENT_SESSION_TRACK
1060
+ const char *data;
1061
+ size_t length;
1062
+ my_ulonglong retVal;
1063
+ GET_CLIENT(self);
1064
+
1065
+ REQUIRE_CONNECTED(wrapper);
1066
+ retVal = mysql_session_track_get_first(wrapper->client, NUM2INT(type), &data, &length);
1067
+ if (retVal != 0) {
1068
+ return Qnil;
1069
+ }
1070
+ VALUE rbAry = rb_ary_new();
1071
+ VALUE rbFirst = rb_str_new(data, length);
1072
+ rb_ary_push(rbAry, rbFirst);
1073
+ while(mysql_session_track_get_next(wrapper->client, NUM2INT(type), &data, &length) == 0) {
1074
+ VALUE rbNext = rb_str_new(data, length);
1075
+ rb_ary_push(rbAry, rbNext);
1076
+ }
1077
+ return rbAry;
1078
+ #else
1079
+ return Qnil;
1080
+ #endif
1081
+ }
1082
+
1024
1083
  /* call-seq:
1025
1084
  * client.affected_rows
1026
1085
  *
@@ -1347,7 +1406,11 @@ static VALUE set_init_command(VALUE self, VALUE value) {
1347
1406
  }
1348
1407
 
1349
1408
  static VALUE set_default_auth(VALUE self, VALUE value) {
1409
+ #ifdef HAVE_MYSQL_DEFAULT_AUTH
1350
1410
  return _mysql_client_options(self, MYSQL_DEFAULT_AUTH, value);
1411
+ #else
1412
+ rb_raise(cMysql2Error, "pluggable authentication is not available, you may need a newer MySQL client library");
1413
+ #endif
1351
1414
  }
1352
1415
 
1353
1416
  static VALUE set_enable_cleartext_plugin(VALUE self, VALUE value) {
@@ -1411,6 +1474,7 @@ void init_mysql2_client() {
1411
1474
  mMysql2 = rb_define_module("Mysql2"); Teach RDoc about Mysql2 constant.
1412
1475
  #endif
1413
1476
  cMysql2Client = rb_define_class_under(mMysql2, "Client", rb_cObject);
1477
+ rb_global_variable(&cMysql2Client);
1414
1478
 
1415
1479
  rb_define_alloc_func(cMysql2Client, allocate);
1416
1480
 
@@ -1441,6 +1505,7 @@ void init_mysql2_client() {
1441
1505
  rb_define_method(cMysql2Client, "query_info_string", rb_mysql_info, 0);
1442
1506
  rb_define_method(cMysql2Client, "ssl_cipher", rb_mysql_get_ssl_cipher, 0);
1443
1507
  rb_define_method(cMysql2Client, "encoding", rb_mysql_client_encoding, 0);
1508
+ rb_define_method(cMysql2Client, "session_track", rb_mysql_client_session_track, 1);
1444
1509
 
1445
1510
  rb_define_private_method(cMysql2Client, "connect_timeout=", set_connect_timeout, 1);
1446
1511
  rb_define_private_method(cMysql2Client, "read_timeout=", set_read_timeout, 1);
@@ -1613,16 +1678,32 @@ void init_mysql2_client() {
1613
1678
  INT2NUM(0));
1614
1679
  #endif
1615
1680
 
1681
+ #ifdef CLIENT_SESSION_TRACK
1682
+ rb_const_set(cMysql2Client, rb_intern("SESSION_TRACK"), INT2NUM(CLIENT_SESSION_TRACK));
1683
+ /* From mysql_com.h -- but stable from at least 5.7.4 through 8.0.20 */
1684
+ rb_const_set(cMysql2Client, rb_intern("SESSION_TRACK_SYSTEM_VARIABLES"), INT2NUM(SESSION_TRACK_SYSTEM_VARIABLES));
1685
+ rb_const_set(cMysql2Client, rb_intern("SESSION_TRACK_SCHEMA"), INT2NUM(SESSION_TRACK_SCHEMA));
1686
+ rb_const_set(cMysql2Client, rb_intern("SESSION_TRACK_STATE_CHANGE"), INT2NUM(SESSION_TRACK_STATE_CHANGE));
1687
+ rb_const_set(cMysql2Client, rb_intern("SESSION_TRACK_GTIDS"), INT2NUM(SESSION_TRACK_GTIDS));
1688
+ rb_const_set(cMysql2Client, rb_intern("SESSION_TRACK_TRANSACTION_CHARACTERISTICS"), INT2NUM(SESSION_TRACK_TRANSACTION_CHARACTERISTICS));
1689
+ rb_const_set(cMysql2Client, rb_intern("SESSION_TRACK_TRANSACTION_STATE"), INT2NUM(SESSION_TRACK_TRANSACTION_STATE));
1690
+ #endif
1691
+
1616
1692
  #if defined(FULL_SSL_MODE_SUPPORT) // MySQL 5.7.11 and above
1617
1693
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED));
1618
1694
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_PREFERRED"), INT2NUM(SSL_MODE_PREFERRED));
1619
1695
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(SSL_MODE_REQUIRED));
1620
1696
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_CA"), INT2NUM(SSL_MODE_VERIFY_CA));
1621
1697
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_IDENTITY"), INT2NUM(SSL_MODE_VERIFY_IDENTITY));
1622
- #elif defined(HAVE_CONST_MYSQL_OPT_SSL_ENFORCE) // MySQL 5.7.3 - 5.7.10
1698
+ #else
1699
+ #ifdef HAVE_CONST_MYSQL_OPT_SSL_VERIFY_SERVER_CERT // MySQL 5.7.3 - 5.7.10 & MariaDB 10.x and later
1700
+ rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_IDENTITY"), INT2NUM(SSL_MODE_VERIFY_IDENTITY));
1701
+ #endif
1702
+ #ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE // MySQL 5.7.3 - 5.7.10 & MariaDB 10.x and later
1623
1703
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED));
1624
1704
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(SSL_MODE_REQUIRED));
1625
1705
  #endif
1706
+ #endif
1626
1707
 
1627
1708
  #ifndef HAVE_CONST_SSL_MODE_DISABLED
1628
1709
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(0));
@@ -15,10 +15,21 @@ def add_ssl_defines(header)
15
15
  all_modes_found = %w[SSL_MODE_DISABLED SSL_MODE_PREFERRED SSL_MODE_REQUIRED SSL_MODE_VERIFY_CA SSL_MODE_VERIFY_IDENTITY].inject(true) do |m, ssl_mode|
16
16
  m && have_const(ssl_mode, header)
17
17
  end
18
- $CFLAGS << ' -DFULL_SSL_MODE_SUPPORT' if all_modes_found
19
- # if we only have ssl toggle (--ssl,--disable-ssl) from 5.7.3 to 5.7.10
20
- has_no_support = all_modes_found ? false : !have_const('MYSQL_OPT_SSL_ENFORCE', header)
21
- $CFLAGS << ' -DNO_SSL_MODE_SUPPORT' if has_no_support
18
+ if all_modes_found
19
+ $CFLAGS << ' -DFULL_SSL_MODE_SUPPORT'
20
+ else
21
+ # if we only have ssl toggle (--ssl,--disable-ssl) from 5.7.3 to 5.7.10
22
+ # and the verify server cert option. This is also the case for MariaDB.
23
+ has_verify_support = have_const('MYSQL_OPT_SSL_VERIFY_SERVER_CERT', header)
24
+ has_enforce_support = have_const('MYSQL_OPT_SSL_ENFORCE', header)
25
+ $CFLAGS << ' -DNO_SSL_MODE_SUPPORT' if !has_verify_support && !has_enforce_support
26
+ end
27
+ end
28
+
29
+ # Homebrew openssl
30
+ if RUBY_PLATFORM =~ /darwin/ && system("command -v brew")
31
+ openssl_location = `brew --prefix openssl`.strip
32
+ $LDFLAGS << " -L#{openssl_location}/lib" if openssl_location
22
33
  end
23
34
 
24
35
  # 2.1+
@@ -28,6 +39,8 @@ have_func('rb_absint_singlebit_p')
28
39
  # Missing in RBX (https://github.com/rubinius/rubinius/issues/3771)
29
40
  have_func('rb_wait_for_single_fd')
30
41
 
42
+ have_func("rb_enc_interned_str", "ruby.h")
43
+
31
44
  # borrowed from mysqlplus
32
45
  # http://github.com/oldmoe/mysqlplus/blob/master/ext/extconf.rb
33
46
  dirs = ENV.fetch('PATH').split(File::PATH_SEPARATOR) + %w[
@@ -42,6 +55,9 @@ dirs = ENV.fetch('PATH').split(File::PATH_SEPARATOR) + %w[
42
55
  /usr/local/mysql-*
43
56
  /usr/local/lib/mysql5*
44
57
  /usr/local/opt/mysql5*
58
+ /usr/local/opt/mysql@*
59
+ /usr/local/opt/mysql-client
60
+ /usr/local/opt/mysql-client@*
45
61
  ].map { |dir| dir << '/bin' }
46
62
 
47
63
  # For those without HOMEBREW_ROOT in PATH
@@ -108,6 +124,7 @@ have_struct_member('MYSQL', 'net.vio', mysql_h)
108
124
  have_struct_member('MYSQL', 'net.pvio', mysql_h)
109
125
 
110
126
  # These constants are actually enums, so they cannot be detected by #ifdef in C code.
127
+ have_const('MYSQL_DEFAULT_AUTH', mysql_h)
111
128
  have_const('MYSQL_ENABLE_CLEARTEXT_PLUGIN', mysql_h)
112
129
  have_const('SERVER_QUERY_NO_GOOD_INDEX_USED', mysql_h)
113
130
  have_const('SERVER_QUERY_NO_INDEX_USED', mysql_h)
@@ -148,7 +165,7 @@ end
148
165
  $CFLAGS << ' ' << usable_flags.join(' ')
149
166
 
150
167
  enabled_sanitizers = disabled_sanitizers = []
151
- # Specify a commna-separated list of sanitizers, or try them all by default
168
+ # Specify a comma-separated list of sanitizers, or try them all by default
152
169
  sanitizers = with_config('sanitize')
153
170
  case sanitizers
154
171
  when true
@@ -4,9 +4,14 @@ VALUE mMysql2, cMysql2Error, cMysql2TimeoutError;
4
4
 
5
5
  /* Ruby Extension initializer */
6
6
  void Init_mysql2() {
7
- mMysql2 = rb_define_module("Mysql2");
7
+ mMysql2 = rb_define_module("Mysql2");
8
+ rb_global_variable(&mMysql2);
9
+
8
10
  cMysql2Error = rb_const_get(mMysql2, rb_intern("Error"));
11
+ rb_global_variable(&cMysql2Error);
12
+
9
13
  cMysql2TimeoutError = rb_const_get(cMysql2Error, rb_intern("TimeoutError"));
14
+ rb_global_variable(&cMysql2TimeoutError);
10
15
 
11
16
  init_mysql2_client();
12
17
  init_mysql2_result();
data/ext/mysql2/result.c CHANGED
@@ -17,6 +17,20 @@ static rb_encoding *binaryEncoding;
17
17
  */
18
18
  #define MYSQL2_MIN_TIME 2678400ULL
19
19
 
20
+ #define MYSQL2_MAX_BYTES_PER_CHAR 3
21
+
22
+ /* From Mysql documentations:
23
+ * To distinguish between binary and nonbinary data for string data types,
24
+ * check whether the charsetnr value is 63. If so, the character set is binary,
25
+ * which indicates binary rather than nonbinary data. This enables you to distinguish BINARY
26
+ * from CHAR, VARBINARY from VARCHAR, and the BLOB types from the TEXT types.
27
+ */
28
+ #define MYSQL2_BINARY_CHARSET 63
29
+
30
+ #ifndef MYSQL_TYPE_JSON
31
+ #define MYSQL_TYPE_JSON 245
32
+ #endif
33
+
20
34
  #define GET_RESULT(self) \
21
35
  mysql2_result_wrapper *wrapper; \
22
36
  Data_Get_Struct(self, mysql2_result_wrapper, wrapper);
@@ -157,11 +171,18 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo
157
171
  rb_field = rb_intern3(field->name, field->name_length, rb_utf8_encoding());
158
172
  rb_field = ID2SYM(rb_field);
159
173
  } else {
160
- rb_field = rb_str_new(field->name, field->name_length);
161
- rb_enc_associate(rb_field, conn_enc);
162
- if (default_internal_enc) {
174
+ #ifdef HAVE_RB_ENC_INTERNED_STR
175
+ rb_field = rb_enc_interned_str(field->name, field->name_length, conn_enc);
176
+ if (default_internal_enc && default_internal_enc != conn_enc) {
177
+ rb_field = rb_str_to_interned_str(rb_str_export_to_enc(rb_field, default_internal_enc));
178
+ }
179
+ #else
180
+ rb_field = rb_enc_str_new(field->name, field->name_length, conn_enc);
181
+ if (default_internal_enc && default_internal_enc != conn_enc) {
163
182
  rb_field = rb_str_export_to_enc(rb_field, default_internal_enc);
164
183
  }
184
+ rb_obj_freeze(rb_field);
185
+ #endif
165
186
  }
166
187
  rb_ary_store(wrapper->fields, idx, rb_field);
167
188
  }
@@ -169,9 +190,171 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo
169
190
  return rb_field;
170
191
  }
171
192
 
193
+ static VALUE rb_mysql_result_fetch_field_type(VALUE self, unsigned int idx) {
194
+ VALUE rb_field_type;
195
+ GET_RESULT(self);
196
+
197
+ if (wrapper->fieldTypes == Qnil) {
198
+ wrapper->numberOfFields = mysql_num_fields(wrapper->result);
199
+ wrapper->fieldTypes = rb_ary_new2(wrapper->numberOfFields);
200
+ }
201
+
202
+ rb_field_type = rb_ary_entry(wrapper->fieldTypes, idx);
203
+ if (rb_field_type == Qnil) {
204
+ MYSQL_FIELD *field = NULL;
205
+ rb_encoding *default_internal_enc = rb_default_internal_encoding();
206
+ rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
207
+ int precision;
208
+
209
+ field = mysql_fetch_field_direct(wrapper->result, idx);
210
+
211
+ switch(field->type) {
212
+ case MYSQL_TYPE_NULL: // NULL
213
+ rb_field_type = rb_str_new_cstr("null");
214
+ break;
215
+ case MYSQL_TYPE_TINY: // signed char
216
+ rb_field_type = rb_sprintf("tinyint(%ld)", field->length);
217
+ break;
218
+ case MYSQL_TYPE_SHORT: // short int
219
+ rb_field_type = rb_sprintf("smallint(%ld)", field->length);
220
+ break;
221
+ case MYSQL_TYPE_YEAR: // short int
222
+ rb_field_type = rb_sprintf("year(%ld)", field->length);
223
+ break;
224
+ case MYSQL_TYPE_INT24: // int
225
+ rb_field_type = rb_sprintf("mediumint(%ld)", field->length);
226
+ break;
227
+ case MYSQL_TYPE_LONG: // int
228
+ rb_field_type = rb_sprintf("int(%ld)", field->length);
229
+ break;
230
+ case MYSQL_TYPE_LONGLONG: // long long int
231
+ rb_field_type = rb_sprintf("bigint(%ld)", field->length);
232
+ break;
233
+ case MYSQL_TYPE_FLOAT: // float
234
+ rb_field_type = rb_sprintf("float(%ld,%d)", field->length, field->decimals);
235
+ break;
236
+ case MYSQL_TYPE_DOUBLE: // double
237
+ rb_field_type = rb_sprintf("double(%ld,%d)", field->length, field->decimals);
238
+ break;
239
+ case MYSQL_TYPE_TIME: // MYSQL_TIME
240
+ rb_field_type = rb_str_new_cstr("time");
241
+ break;
242
+ case MYSQL_TYPE_DATE: // MYSQL_TIME
243
+ case MYSQL_TYPE_NEWDATE: // MYSQL_TIME
244
+ rb_field_type = rb_str_new_cstr("date");
245
+ break;
246
+ case MYSQL_TYPE_DATETIME: // MYSQL_TIME
247
+ rb_field_type = rb_str_new_cstr("datetime");
248
+ break;
249
+ case MYSQL_TYPE_TIMESTAMP: // MYSQL_TIME
250
+ rb_field_type = rb_str_new_cstr("timestamp");
251
+ break;
252
+ case MYSQL_TYPE_DECIMAL: // char[]
253
+ case MYSQL_TYPE_NEWDECIMAL: // char[]
254
+ /*
255
+ Handle precision similar to this line from mysql's code:
256
+ https://github.com/mysql/mysql-server/blob/ea7d2e2d16ac03afdd9cb72a972a95981107bf51/sql/field.cc#L2246
257
+ */
258
+ precision = field->length - (field->decimals > 0 ? 2 : 1);
259
+ rb_field_type = rb_sprintf("decimal(%d,%d)", precision, field->decimals);
260
+ break;
261
+ case MYSQL_TYPE_STRING: // char[]
262
+ if (field->flags & ENUM_FLAG) {
263
+ rb_field_type = rb_str_new_cstr("enum");
264
+ } else if (field->flags & SET_FLAG) {
265
+ rb_field_type = rb_str_new_cstr("set");
266
+ } else {
267
+ if (field->charsetnr == MYSQL2_BINARY_CHARSET) {
268
+ rb_field_type = rb_sprintf("binary(%ld)", field->length);
269
+ } else {
270
+ rb_field_type = rb_sprintf("char(%ld)", field->length / MYSQL2_MAX_BYTES_PER_CHAR);
271
+ }
272
+ }
273
+ break;
274
+ case MYSQL_TYPE_VAR_STRING: // char[]
275
+ if (field->charsetnr == MYSQL2_BINARY_CHARSET) {
276
+ rb_field_type = rb_sprintf("varbinary(%ld)", field->length);
277
+ } else {
278
+ rb_field_type = rb_sprintf("varchar(%ld)", field->length / MYSQL2_MAX_BYTES_PER_CHAR);
279
+ }
280
+ break;
281
+ case MYSQL_TYPE_VARCHAR: // char[]
282
+ rb_field_type = rb_sprintf("varchar(%ld)", field->length / MYSQL2_MAX_BYTES_PER_CHAR);
283
+ break;
284
+ case MYSQL_TYPE_TINY_BLOB: // char[]
285
+ rb_field_type = rb_str_new_cstr("tinyblob");
286
+ break;
287
+ case MYSQL_TYPE_BLOB: // char[]
288
+ if (field->charsetnr == MYSQL2_BINARY_CHARSET) {
289
+ switch(field->length) {
290
+ case 255:
291
+ rb_field_type = rb_str_new_cstr("tinyblob");
292
+ break;
293
+ case 65535:
294
+ rb_field_type = rb_str_new_cstr("blob");
295
+ break;
296
+ case 16777215:
297
+ rb_field_type = rb_str_new_cstr("mediumblob");
298
+ break;
299
+ case 4294967295:
300
+ rb_field_type = rb_str_new_cstr("longblob");
301
+ default:
302
+ break;
303
+ }
304
+ } else {
305
+ if (field->length == (255 * MYSQL2_MAX_BYTES_PER_CHAR)) {
306
+ rb_field_type = rb_str_new_cstr("tinytext");
307
+ } else if (field->length == (65535 * MYSQL2_MAX_BYTES_PER_CHAR)) {
308
+ rb_field_type = rb_str_new_cstr("text");
309
+ } else if (field->length == (16777215 * MYSQL2_MAX_BYTES_PER_CHAR)) {
310
+ rb_field_type = rb_str_new_cstr("mediumtext");
311
+ } else if (field->length == 4294967295) {
312
+ rb_field_type = rb_str_new_cstr("longtext");
313
+ } else {
314
+ rb_field_type = rb_sprintf("text(%ld)", field->length);
315
+ }
316
+ }
317
+ break;
318
+ case MYSQL_TYPE_MEDIUM_BLOB: // char[]
319
+ rb_field_type = rb_str_new_cstr("mediumblob");
320
+ break;
321
+ case MYSQL_TYPE_LONG_BLOB: // char[]
322
+ rb_field_type = rb_str_new_cstr("longblob");
323
+ break;
324
+ case MYSQL_TYPE_BIT: // char[]
325
+ rb_field_type = rb_sprintf("bit(%ld)", field->length);
326
+ break;
327
+ case MYSQL_TYPE_SET: // char[]
328
+ rb_field_type = rb_str_new_cstr("set");
329
+ break;
330
+ case MYSQL_TYPE_ENUM: // char[]
331
+ rb_field_type = rb_str_new_cstr("enum");
332
+ break;
333
+ case MYSQL_TYPE_GEOMETRY: // char[]
334
+ rb_field_type = rb_str_new_cstr("geometry");
335
+ break;
336
+ case MYSQL_TYPE_JSON: // json
337
+ rb_field_type = rb_str_new_cstr("json");
338
+ break;
339
+ default:
340
+ rb_field_type = rb_str_new_cstr("unknown");
341
+ break;
342
+ }
343
+
344
+ rb_enc_associate(rb_field_type, conn_enc);
345
+ if (default_internal_enc) {
346
+ rb_field_type = rb_str_export_to_enc(rb_field_type, default_internal_enc);
347
+ }
348
+
349
+ rb_ary_store(wrapper->fieldTypes, idx, rb_field_type);
350
+ }
351
+
352
+ return rb_field_type;
353
+ }
354
+
172
355
  static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_encoding *default_internal_enc, rb_encoding *conn_enc) {
173
356
  /* if binary flag is set, respect its wishes */
174
- if (field.flags & BINARY_FLAG && field.charsetnr == 63) {
357
+ if (field.flags & BINARY_FLAG && field.charsetnr == MYSQL2_BINARY_CHARSET) {
175
358
  rb_enc_associate(val, binaryEncoding);
176
359
  } else if (!field.charsetnr) {
177
360
  /* MySQL 4.x may not provide an encoding, binary will get the bytes through */
@@ -716,6 +899,25 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
716
899
  return wrapper->fields;
717
900
  }
718
901
 
902
+ static VALUE rb_mysql_result_fetch_field_types(VALUE self) {
903
+ unsigned int i = 0;
904
+
905
+ GET_RESULT(self);
906
+
907
+ if (wrapper->fieldTypes == Qnil) {
908
+ wrapper->numberOfFields = mysql_num_fields(wrapper->result);
909
+ wrapper->fieldTypes = rb_ary_new2(wrapper->numberOfFields);
910
+ }
911
+
912
+ if ((my_ulonglong)RARRAY_LEN(wrapper->fieldTypes) != wrapper->numberOfFields) {
913
+ for (i=0; i<wrapper->numberOfFields; i++) {
914
+ rb_mysql_result_fetch_field_type(self, i);
915
+ }
916
+ }
917
+
918
+ return wrapper->fieldTypes;
919
+ }
920
+
719
921
  static VALUE rb_mysql_result_each_(VALUE self,
720
922
  VALUE(*fetch_row_func)(VALUE, MYSQL_FIELD *fields, const result_each_args *args),
721
923
  const result_each_args *args)
@@ -934,6 +1136,7 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
934
1136
  wrapper->resultFreed = 0;
935
1137
  wrapper->result = r;
936
1138
  wrapper->fields = Qnil;
1139
+ wrapper->fieldTypes = Qnil;
937
1140
  wrapper->rows = Qnil;
938
1141
  wrapper->encoding = encoding;
939
1142
  wrapper->streamingComplete = 0;
@@ -966,11 +1169,17 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
966
1169
 
967
1170
  void init_mysql2_result() {
968
1171
  cDate = rb_const_get(rb_cObject, rb_intern("Date"));
1172
+ rb_global_variable(&cDate);
969
1173
  cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
1174
+ rb_global_variable(&cDateTime);
970
1175
 
971
1176
  cMysql2Result = rb_define_class_under(mMysql2, "Result", rb_cObject);
1177
+ rb_undef_alloc_func(cMysql2Result);
1178
+ rb_global_variable(&cMysql2Result);
1179
+
972
1180
  rb_define_method(cMysql2Result, "each", rb_mysql_result_each, -1);
973
1181
  rb_define_method(cMysql2Result, "fields", rb_mysql_result_fetch_fields, 0);
1182
+ rb_define_method(cMysql2Result, "field_types", rb_mysql_result_fetch_field_types, 0);
974
1183
  rb_define_method(cMysql2Result, "free", rb_mysql_result_free_, 0);
975
1184
  rb_define_method(cMysql2Result, "count", rb_mysql_result_count, 0);
976
1185
  rb_define_alias(cMysql2Result, "size", "count");
data/ext/mysql2/result.h CHANGED
@@ -6,6 +6,7 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
6
6
 
7
7
  typedef struct {
8
8
  VALUE fields;
9
+ VALUE fieldTypes;
9
10
  VALUE rows;
10
11
  VALUE client;
11
12
  VALUE encoding;
@@ -46,7 +46,7 @@ void rb_raise_mysql2_stmt_error(mysql_stmt_wrapper *stmt_wrapper) {
46
46
  VALUE e;
47
47
  GET_CLIENT(stmt_wrapper->client);
48
48
  VALUE rb_error_msg = rb_str_new2(mysql_stmt_error(stmt_wrapper->stmt));
49
- VALUE rb_sql_state = rb_tainted_str_new2(mysql_stmt_sqlstate(stmt_wrapper->stmt));
49
+ VALUE rb_sql_state = rb_str_new2(mysql_stmt_sqlstate(stmt_wrapper->stmt));
50
50
 
51
51
  rb_encoding *conn_enc;
52
52
  conn_enc = rb_to_encoding(wrapper->encoding);
@@ -456,7 +456,7 @@ static VALUE rb_mysql_stmt_execute(int argc, VALUE *argv, VALUE self) {
456
456
  }
457
457
 
458
458
  if (!is_streaming) {
459
- // recieve the whole result set from the server
459
+ // receive the whole result set from the server
460
460
  if (mysql_stmt_store_result(stmt)) {
461
461
  mysql_free_result(metadata);
462
462
  rb_raise_mysql2_stmt_error(stmt_wrapper);
@@ -572,10 +572,18 @@ static VALUE rb_mysql_stmt_close(VALUE self) {
572
572
 
573
573
  void init_mysql2_statement() {
574
574
  cDate = rb_const_get(rb_cObject, rb_intern("Date"));
575
+ rb_global_variable(&cDate);
576
+
575
577
  cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
578
+ rb_global_variable(&cDateTime);
579
+
576
580
  cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
581
+ rb_global_variable(&cBigDecimal);
577
582
 
578
583
  cMysql2Statement = rb_define_class_under(mMysql2, "Statement", rb_cObject);
584
+ rb_undef_alloc_func(cMysql2Statement);
585
+ rb_global_variable(&cMysql2Statement);
586
+
579
587
  rb_define_method(cMysql2Statement, "param_count", rb_mysql_stmt_param_count, 0);
580
588
  rb_define_method(cMysql2Statement, "field_count", rb_mysql_stmt_field_count, 0);
581
589
  rb_define_method(cMysql2Statement, "_execute", rb_mysql_stmt_execute, -1);
data/lib/mysql2/client.rb CHANGED
@@ -46,9 +46,14 @@ module Mysql2
46
46
  # force the encoding to utf8
47
47
  self.charset_name = opts[:encoding] || 'utf8'
48
48
 
49
+ mode = parse_ssl_mode(opts[:ssl_mode]) if opts[:ssl_mode]
50
+ if (mode == SSL_MODE_VERIFY_CA || mode == SSL_MODE_VERIFY_IDENTITY) && !opts[:sslca]
51
+ opts[:sslca] = find_default_ca_path
52
+ end
53
+
49
54
  ssl_options = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher)
50
55
  ssl_set(*ssl_options) if ssl_options.any? || opts.key?(:sslverify)
51
- self.ssl_mode = parse_ssl_mode(opts[:ssl_mode]) if opts[:ssl_mode]
56
+ self.ssl_mode = mode if mode
52
57
 
53
58
  flags = case opts[:flags]
54
59
  when Array
@@ -115,6 +120,18 @@ module Mysql2
115
120
  end
116
121
  end
117
122
 
123
+ # Find any default system CA paths to handle system roots
124
+ # by default if stricter validation is requested and no
125
+ # path is provide.
126
+ def find_default_ca_path
127
+ [
128
+ "/etc/ssl/certs/ca-certificates.crt",
129
+ "/etc/pki/tls/certs/ca-bundle.crt",
130
+ "/etc/ssl/ca-bundle.pem",
131
+ "/etc/ssl/cert.pem",
132
+ ].find { |f| File.exist?(f) }
133
+ end
134
+
118
135
  # Set default program_name in performance_schema.session_connect_attrs
119
136
  # and performance_schema.session_account_connect_attrs
120
137
  def parse_connect_attrs(conn_attrs)
@@ -127,7 +144,7 @@ module Mysql2
127
144
  end
128
145
 
129
146
  def query(sql, options = {})
130
- Thread.handle_interrupt(::Mysql2::Util::TIMEOUT_ERROR_CLASS => :never) do
147
+ Thread.handle_interrupt(::Mysql2::Util::TIMEOUT_ERROR_NEVER) do
131
148
  _query(sql, @query_options.merge(options))
132
149
  end
133
150
  end
data/lib/mysql2/error.rb CHANGED
@@ -24,6 +24,7 @@ module Mysql2
24
24
  1159 => ConnectionError, # ER_NET_READ_INTERRUPTED
25
25
  1160 => ConnectionError, # ER_NET_ERROR_ON_WRITE
26
26
  1161 => ConnectionError, # ER_NET_WRITE_INTERRUPTED
27
+ 1927 => ConnectionError, # ER_CONNECTION_KILLED
27
28
 
28
29
  2001 => ConnectionError, # CR_SOCKET_CREATE_ERROR
29
30
  2002 => ConnectionError, # CR_CONNECTION_ERROR
@@ -1,9 +1,7 @@
1
1
  module Mysql2
2
2
  class Statement
3
- include Enumerable
4
-
5
3
  def execute(*args, **kwargs)
6
- Thread.handle_interrupt(::Mysql2::Util::TIMEOUT_ERROR_CLASS => :never) do
4
+ Thread.handle_interrupt(::Mysql2::Util::TIMEOUT_ERROR_NEVER) do
7
5
  _execute(*args, **kwargs)
8
6
  end
9
7
  end
@@ -1,3 +1,3 @@
1
1
  module Mysql2
2
- VERSION = "0.5.3".freeze
2
+ VERSION = "0.5.4".freeze
3
3
  end
data/lib/mysql2.rb CHANGED
@@ -82,5 +82,6 @@ module Mysql2
82
82
  else
83
83
  ::Timeout::Error
84
84
  end
85
+ TIMEOUT_ERROR_NEVER = { TIMEOUT_ERROR_CLASS => :never }.freeze
85
86
  end
86
87
  end
@@ -0,0 +1,49 @@
1
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
2
+ Version: SKS 1.1.6
3
+ Comment: Hostname: pgp.mit.edu
4
+
5
+ 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
47
+ sTSKHe+QnnnoFmu4gnmDU31i
48
+ =Xqbo
49
+ -----END PGP PUBLIC KEY BLOCK-----
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Lopez
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-11-27 00:00:00.000000000 Z
12
+ date: 2022-05-03 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description:
15
15
  email:
@@ -46,6 +46,7 @@ files:
46
46
  - lib/mysql2/result.rb
47
47
  - lib/mysql2/statement.rb
48
48
  - lib/mysql2/version.rb
49
+ - support/3A79BD29.asc
49
50
  - support/5072E1F5.asc
50
51
  - support/libmysql.def
51
52
  - support/mysql_enc_to_ruby.rb
@@ -54,6 +55,11 @@ homepage: https://github.com/brianmario/mysql2
54
55
  licenses:
55
56
  - MIT
56
57
  metadata:
58
+ bug_tracker_uri: https://github.com/brianmario/mysql2/issues
59
+ changelog_uri: https://github.com/brianmario/mysql2/releases/tag/0.5.4
60
+ documentation_uri: https://www.rubydoc.info/gems/mysql2/0.5.4
61
+ homepage_uri: https://github.com/brianmario/mysql2
62
+ source_code_uri: https://github.com/brianmario/mysql2/tree/0.5.4
57
63
  msys2_mingw_dependencies: libmariadbclient
58
64
  post_install_message:
59
65
  rdoc_options:
@@ -71,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
77
  - !ruby/object:Gem::Version
72
78
  version: '0'
73
79
  requirements: []
74
- rubygems_version: 3.0.3
80
+ rubygems_version: 3.0.3.1
75
81
  signing_key:
76
82
  specification_version: 4
77
83
  summary: A simple, fast Mysql library for Ruby, binding to libmysql