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 +4 -4
- data/README.md +33 -7
- data/ext/mysql2/client.c +100 -19
- data/ext/mysql2/extconf.rb +22 -5
- data/ext/mysql2/mysql2_ext.c +6 -1
- data/ext/mysql2/result.c +213 -4
- data/ext/mysql2/result.h +1 -0
- data/ext/mysql2/statement.c +10 -2
- data/lib/mysql2/client.rb +19 -2
- data/lib/mysql2/error.rb +1 -0
- data/lib/mysql2/statement.rb +1 -3
- data/lib/mysql2/version.rb +1 -1
- data/lib/mysql2.rb +1 -0
- data/support/3A79BD29.asc +49 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f387f841adc885eb4000a960ee34f475c7edab79e276d17ce8889f370bdcf387
|
4
|
+
data.tar.gz: 0c8732c2a45ed8ac68aea92765daba5969f860f1fe5a95d44e89b76deae7108b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
4
|
-
|
3
|
+
GitHub Actions
|
4
|
+
[](https://github.com/brianmario/mysql2/actions/workflows/build.yml)
|
5
|
+
[](https://github.com/brianmario/mysql2/actions/workflows/container.yml)
|
6
|
+
Travis CI
|
7
|
+
[](https://travis-ci.org/brianmario/mysql2)
|
8
|
+
Appveyor CI
|
9
|
+
[](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-
|
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
|
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
|
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
|
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
|
-
*
|
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
|
-
*
|
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
|
-
#
|
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 =
|
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; /*
|
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(
|
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,
|
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(
|
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
|
-
#
|
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));
|
data/ext/mysql2/extconf.rb
CHANGED
@@ -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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
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
|
data/ext/mysql2/mysql2_ext.c
CHANGED
@@ -4,9 +4,14 @@ VALUE mMysql2, cMysql2Error, cMysql2TimeoutError;
|
|
4
4
|
|
5
5
|
/* Ruby Extension initializer */
|
6
6
|
void Init_mysql2() {
|
7
|
-
mMysql2
|
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
|
-
|
161
|
-
|
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 ==
|
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
data/ext/mysql2/statement.c
CHANGED
@@ -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 =
|
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
|
-
//
|
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 =
|
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::
|
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
|
data/lib/mysql2/statement.rb
CHANGED
@@ -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::
|
4
|
+
Thread.handle_interrupt(::Mysql2::Util::TIMEOUT_ERROR_NEVER) do
|
7
5
|
_execute(*args, **kwargs)
|
8
6
|
end
|
9
7
|
end
|
data/lib/mysql2/version.rb
CHANGED
data/lib/mysql2.rb
CHANGED
@@ -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.
|
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:
|
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
|