mysql2 0.5.3 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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