mysql2 0.5.4 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +75 -16
- data/ext/mysql2/client.c +119 -39
- data/ext/mysql2/client.h +9 -2
- data/ext/mysql2/extconf.rb +45 -7
- data/ext/mysql2/mysql2_ext.h +13 -0
- data/ext/mysql2/mysql_enc_name_to_ruby.h +4 -3
- data/ext/mysql2/mysql_enc_to_ruby.h +15 -0
- data/ext/mysql2/result.c +58 -8
- data/ext/mysql2/statement.c +49 -10
- data/lib/mysql2/client.rb +4 -0
- data/lib/mysql2/version.rb +1 -1
- data/lib/mysql2.rb +1 -0
- data/support/C74CD1D8.asc +104 -0
- data/support/mysql_enc_to_ruby.rb +2 -1
- data/support/ruby_enc_to_mysql.rb +1 -0
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8e25b1a25080490b1bf04829d8f6616609391a094baa783d7da242342a4ff3b
|
4
|
+
data.tar.gz: 7dfab0d03b289b665807d21b29326b96711e5c1d3ae697e81f0e4ab7a5dd6280
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3709403d316832055596c96af2e260e3de9d181ba558f551f0d5fe0d89abfec0ea242f6c30228eac02284e1e7287cbd315933fadc517fab88a10d588c4f0d8b6
|
7
|
+
data.tar.gz: 63c17fa1c273cefa454ea7f6cc0860014514e4c899ceb1bd856271cd238938a4d0fb263118eb64dde0a9568905d6410110fbe3b8359bff3fab8314607de6dd50
|
data/README.md
CHANGED
@@ -65,6 +65,11 @@ This may be needed if you deploy to a system where these libraries
|
|
65
65
|
are located somewhere different than on your build system.
|
66
66
|
This overrides any rpath calculated by default or by the options above.
|
67
67
|
|
68
|
+
* `--with-openssl-dir[=/path/to/openssl]` - Specify the directory where OpenSSL
|
69
|
+
is installed. In most cases, the Ruby runtime and MySQL client libraries will
|
70
|
+
link against a system-installed OpenSSL library and this option is not needed.
|
71
|
+
Use this option when non-default library paths are needed.
|
72
|
+
|
68
73
|
* `--with-sanitize[=address,cfi,integer,memory,thread,undefined]` -
|
69
74
|
Enable sanitizers for Clang / GCC. If no argument is given, try to enable
|
70
75
|
all sanitizers or fail if none are available. If a command-separated list of
|
@@ -89,13 +94,48 @@ the library file `libmysqlclient.so` but is missing the header file `mysql.h`
|
|
89
94
|
|
90
95
|
### Mac OS X
|
91
96
|
|
92
|
-
You may use
|
97
|
+
You may use Homebrew, MacPorts, or a native MySQL installer package. The most
|
93
98
|
common paths will be automatically searched. If you want to select a specific
|
94
99
|
MySQL directory, use the `--with-mysql-dir` or `--with-mysql-config` options above.
|
95
100
|
|
96
101
|
If you have not done so already, you will need to install the XCode select tools by running
|
97
102
|
`xcode-select --install`.
|
98
103
|
|
104
|
+
Later versions of MacOS no longer distribute a linkable OpenSSL library. It is
|
105
|
+
common to use Homebrew or MacPorts to install OpenSSL. Make sure that both the
|
106
|
+
Ruby runtime and MySQL client libraries are compiled with the same OpenSSL
|
107
|
+
family, 1.0 or 1.1 or 3.0, since only one can be loaded at runtime.
|
108
|
+
|
109
|
+
``` sh
|
110
|
+
$ brew install openssl@1.1
|
111
|
+
$ gem install mysql2 -- --with-openssl-dir=$(brew --prefix openssl@1.1)
|
112
|
+
|
113
|
+
or
|
114
|
+
|
115
|
+
$ sudo port install openssl11
|
116
|
+
```
|
117
|
+
|
118
|
+
Since most Ruby projects use Bundler, you can set build options in the Bundler
|
119
|
+
config rather than manually installing a global mysql2 gem. This example shows
|
120
|
+
how to set build arguments with [Bundler config](https://bundler.io/man/bundle-config.1.html):
|
121
|
+
|
122
|
+
``` sh
|
123
|
+
$ bundle config --local build.mysql2 -- --with-openssl-dir=$(brew --prefix openssl@1.1)
|
124
|
+
```
|
125
|
+
|
126
|
+
Another helpful trick is to use the same OpenSSL library that your Ruby was
|
127
|
+
built with, if it was built with an alternate OpenSSL path. This example finds
|
128
|
+
the argument `--with-openssl-dir=/some/path` from the Ruby build and adds that
|
129
|
+
to the [Bundler config](https://bundler.io/man/bundle-config.1.html):
|
130
|
+
|
131
|
+
``` sh
|
132
|
+
$ bundle config --local build.mysql2 -- $(ruby -r rbconfig -e 'puts RbConfig::CONFIG["configure_args"]' | xargs -n1 | grep with-openssl-dir)
|
133
|
+
```
|
134
|
+
|
135
|
+
Note the additional double dashes (`--`) these separate command-line arguments
|
136
|
+
that `gem` or `bundler` interpret from the addiitonal arguments that are passed
|
137
|
+
to the mysql2 build process.
|
138
|
+
|
99
139
|
### Windows
|
100
140
|
|
101
141
|
Make sure that you have Ruby and the DevKit compilers installed. We recommend
|
@@ -205,7 +245,7 @@ result = statement.execute(1, "CA", :as => :array)
|
|
205
245
|
|
206
246
|
Session Tracking information can be accessed with
|
207
247
|
|
208
|
-
```ruby
|
248
|
+
``` ruby
|
209
249
|
c = Mysql2::Client.new(
|
210
250
|
host: "127.0.0.1",
|
211
251
|
username: "root",
|
@@ -241,7 +281,6 @@ Mysql2::Client.new(
|
|
241
281
|
:reconnect = true/false,
|
242
282
|
:local_infile = true/false,
|
243
283
|
:secure_auth = true/false,
|
244
|
-
:ssl_mode = :disabled / :preferred / :required / :verify_ca / :verify_identity,
|
245
284
|
:default_file = '/path/to/my.cfg',
|
246
285
|
:default_group = 'my.cfg section',
|
247
286
|
:default_auth = 'authentication_windows_client'
|
@@ -262,14 +301,13 @@ type of connection to make, with special interpretation you should be aware of:
|
|
262
301
|
* An IPv4 or IPv6 address will result in a TCP connection.
|
263
302
|
* Any other value will be looked up as a hostname for a TCP connection.
|
264
303
|
|
265
|
-
### SSL options
|
304
|
+
### SSL/TLS options
|
266
305
|
|
267
|
-
Setting any of the following options will enable an SSL connection, but
|
268
|
-
your MySQL client library and server have been compiled with SSL
|
269
|
-
MySQL client library defaults will be used for any parameters that are
|
270
|
-
or set to nil. Relative paths are allowed, and may be required by
|
271
|
-
hosting providers such as Heroku.
|
272
|
-
server presents a valid certificate.
|
306
|
+
Setting any of the following options will enable an SSL/TLS connection, but
|
307
|
+
only if your MySQL client library and server have been compiled with SSL
|
308
|
+
support. MySQL client library defaults will be used for any parameters that are
|
309
|
+
left out or set to nil. Relative paths are allowed, and may be required by
|
310
|
+
managed hosting providers such as Heroku.
|
273
311
|
|
274
312
|
``` ruby
|
275
313
|
Mysql2::Client.new(
|
@@ -279,10 +317,29 @@ Mysql2::Client.new(
|
|
279
317
|
:sslca => '/path/to/ca-cert.pem',
|
280
318
|
:sslcapath => '/path/to/cacerts',
|
281
319
|
:sslcipher => 'DHE-RSA-AES256-SHA',
|
282
|
-
:sslverify => true,
|
320
|
+
:sslverify => true, # Removed in MySQL 8.0
|
321
|
+
:ssl_mode => :disabled / :preferred / :required / :verify_ca / :verify_identity,
|
283
322
|
)
|
284
323
|
```
|
285
324
|
|
325
|
+
For MySQL versions 5.7.11 and higher, use `:ssl_mode` to prefer or require an
|
326
|
+
SSL connection and certificate validation. For earlier versions of MySQL, use
|
327
|
+
the `:sslverify` boolean. For details on each of the `:ssl_mode` options, see
|
328
|
+
[https://dev.mysql.com/doc/refman/8.0/en/connection-options.html](https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-mode).
|
329
|
+
|
330
|
+
The `:ssl_mode` option will also set the appropriate MariaDB connection flags:
|
331
|
+
|
332
|
+
| `:ssl_mode` | MariaDB option value |
|
333
|
+
| --- | --- |
|
334
|
+
| `:disabled` | MYSQL_OPT_SSL_ENFORCE = 0 |
|
335
|
+
| `:required` | MYSQL_OPT_SSL_ENFORCE = 1 |
|
336
|
+
| `:verify_identity` | MYSQL_OPT_SSL_VERIFY_SERVER_CERT = 1 |
|
337
|
+
|
338
|
+
MariaDB does not support the `:preferred` or `:verify_ca` options. For more
|
339
|
+
information about SSL/TLS in MariaDB, see
|
340
|
+
[https://mariadb.com/kb/en/securing-connections-for-client-and-server/](https://mariadb.com/kb/en/securing-connections-for-client-and-server/)
|
341
|
+
and [https://mariadb.com/kb/en/mysql_optionsv/#tls-options](https://mariadb.com/kb/en/mysql_optionsv/#tls-options)
|
342
|
+
|
286
343
|
### Secure auth
|
287
344
|
|
288
345
|
Starting with MySQL 5.6.5, secure_auth is enabled by default on servers (it was disabled by default prior to this).
|
@@ -329,7 +386,7 @@ In this example, the compression flag is negated with `-COMPRESS`.
|
|
329
386
|
Active Record typically reads its configuration from a file named `database.yml` or an environment variable `DATABASE_URL`.
|
330
387
|
Use the value `mysql2` as the protocol name. For example:
|
331
388
|
|
332
|
-
```
|
389
|
+
``` sh
|
333
390
|
DATABASE_URL=mysql2://sql_user:sql_pass@sql_host_name:port/sql_db_name?option1=value1&option2=value2
|
334
391
|
```
|
335
392
|
|
@@ -388,7 +445,7 @@ end
|
|
388
445
|
|
389
446
|
Yields:
|
390
447
|
|
391
|
-
```ruby
|
448
|
+
``` ruby
|
392
449
|
{"1"=>1}
|
393
450
|
{"2"=>2}
|
394
451
|
next_result: Unknown column 'A' in 'field list' (Mysql2::Error)
|
@@ -568,14 +625,16 @@ As for field values themselves, I'm workin on it - but expect that soon.
|
|
568
625
|
|
569
626
|
This gem is tested with the following Ruby versions on Linux and Mac OS X:
|
570
627
|
|
571
|
-
* Ruby MRI 2.0
|
628
|
+
* Ruby MRI 2.0 through 2.7 (all versions to date)
|
629
|
+
* Ruby MRI 3.0, 3.1, 3.2 (all versions to date)
|
572
630
|
* Rubinius 2.x and 3.x do work but may fail under some workloads
|
573
631
|
|
574
632
|
This gem is tested with the following MySQL and MariaDB versions:
|
575
633
|
|
576
634
|
* MySQL 5.5, 5.6, 5.7, 8.0
|
577
|
-
* MySQL Connector/C 6.0
|
578
|
-
* MariaDB 5.5, 10.
|
635
|
+
* MySQL Connector/C 6.0, 6.1, 8.0 (primarily on Windows)
|
636
|
+
* MariaDB 5.5, 10.x, with a focus on 10.6 LTS and 10.11 LTS
|
637
|
+
* MariaDB Connector/C 2.x, 3.x
|
579
638
|
|
580
639
|
### Ruby on Rails / Active Record
|
581
640
|
|
data/ext/mysql2/client.c
CHANGED
@@ -120,53 +120,80 @@ struct nogvl_select_db_args {
|
|
120
120
|
|
121
121
|
static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) {
|
122
122
|
unsigned long version = mysql_get_client_version();
|
123
|
+
const char *version_str = mysql_get_client_info();
|
123
124
|
|
124
|
-
|
125
|
-
|
125
|
+
/* Warn about versions that are known to be incomplete; these are pretty
|
126
|
+
* ancient, we want people to upgrade if they need SSL/TLS to work
|
127
|
+
*
|
128
|
+
* MySQL 5.x before 5.6.30 -- ssl_mode introduced but not fully working until 5.6.36)
|
129
|
+
* MySQL 5.7 before 5.7.3 -- ssl_mode introduced but not fully working until 5.7.11)
|
130
|
+
*/
|
131
|
+
if ((version >= 50000 && version < 50630) || (version >= 50700 && version < 50703)) {
|
132
|
+
rb_warn("Your mysql client library version %s does not support setting ssl_mode; full support comes with 5.6.36+, 5.7.11+, 8.0+", version_str);
|
126
133
|
return Qnil;
|
127
134
|
}
|
135
|
+
|
136
|
+
/* For these versions, map from the options we're exposing to Ruby to the constant available:
|
137
|
+
* ssl_mode: :verify_identity to MYSQL_OPT_SSL_VERIFY_SERVER_CERT = 1
|
138
|
+
* ssl_mode: :required to MYSQL_OPT_SSL_ENFORCE = 1
|
139
|
+
* ssl_mode: :disabled to MYSQL_OPT_SSL_ENFORCE = 0
|
140
|
+
*/
|
128
141
|
#if defined(HAVE_CONST_MYSQL_OPT_SSL_VERIFY_SERVER_CERT) || defined(HAVE_CONST_MYSQL_OPT_SSL_ENFORCE)
|
129
142
|
GET_CLIENT(self);
|
130
|
-
int val = NUM2INT(
|
131
|
-
|
132
|
-
|
143
|
+
int val = NUM2INT(setting);
|
144
|
+
|
145
|
+
/* Expected code path for MariaDB 10.x and MariaDB Connector/C 3.x
|
146
|
+
* Workaround code path for MySQL 5.7.3 - 5.7.10 and MySQL Connector/C 6.1.3 - 6.1.x
|
147
|
+
*/
|
148
|
+
if (version >= 100000 // MariaDB (all versions numbered 10.x)
|
149
|
+
|| (version >= 30000 && version < 40000) // MariaDB Connector/C (all versions numbered 3.x)
|
150
|
+
|| (version >= 50703 && version < 50711) // Workaround for MySQL 5.7.3 - 5.7.10
|
151
|
+
|| (version >= 60103 && version < 60200)) { // Workaround for MySQL Connector/C 6.1.3 - 6.1.x
|
133
152
|
#ifdef HAVE_CONST_MYSQL_OPT_SSL_VERIFY_SERVER_CERT
|
134
153
|
if (val == SSL_MODE_VERIFY_IDENTITY) {
|
135
154
|
my_bool b = 1;
|
136
|
-
int result = mysql_options(
|
155
|
+
int result = mysql_options(wrapper->client, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &b);
|
137
156
|
return INT2NUM(result);
|
138
157
|
}
|
139
158
|
#endif
|
140
159
|
#ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE
|
141
160
|
if (val == SSL_MODE_DISABLED || val == SSL_MODE_REQUIRED) {
|
142
|
-
my_bool b = (
|
143
|
-
int result = mysql_options(
|
161
|
+
my_bool b = (val == SSL_MODE_REQUIRED);
|
162
|
+
int result = mysql_options(wrapper->client, MYSQL_OPT_SSL_ENFORCE, &b);
|
144
163
|
return INT2NUM(result);
|
145
164
|
}
|
146
165
|
#endif
|
147
|
-
rb_warn(
|
166
|
+
rb_warn("Your mysql client library version %s does not support ssl_mode %d", version_str, val);
|
148
167
|
return Qnil;
|
149
168
|
} else {
|
150
|
-
rb_warn(
|
169
|
+
rb_warn("Your mysql client library version %s does not support ssl_mode as expected", version_str);
|
151
170
|
return Qnil;
|
152
171
|
}
|
153
172
|
#endif
|
173
|
+
|
174
|
+
/* For other versions -- known to be MySQL 5.6.36+, 5.7.11+, 8.0+
|
175
|
+
* pass the value of the argument to MYSQL_OPT_SSL_MODE -- note the code
|
176
|
+
* mapping from atoms / constants is in the MySQL::Client Ruby class
|
177
|
+
*/
|
154
178
|
#ifdef FULL_SSL_MODE_SUPPORT
|
155
179
|
GET_CLIENT(self);
|
156
|
-
int val = NUM2INT(
|
180
|
+
int val = NUM2INT(setting);
|
157
181
|
|
158
182
|
if (val != SSL_MODE_DISABLED && val != SSL_MODE_PREFERRED && val != SSL_MODE_REQUIRED && val != SSL_MODE_VERIFY_CA && val != SSL_MODE_VERIFY_IDENTITY) {
|
159
183
|
rb_raise(cMysql2Error, "ssl_mode= takes DISABLED, PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY, you passed: %d", val );
|
160
184
|
}
|
161
|
-
int result = mysql_options(
|
185
|
+
int result = mysql_options(wrapper->client, MYSQL_OPT_SSL_MODE, &val);
|
162
186
|
|
163
187
|
return INT2NUM(result);
|
164
188
|
#endif
|
189
|
+
|
190
|
+
// Warn if we get this far
|
165
191
|
#ifdef NO_SSL_MODE_SUPPORT
|
166
|
-
rb_warn(
|
192
|
+
rb_warn("Your mysql client library does not support setting ssl_mode");
|
167
193
|
return Qnil;
|
168
194
|
#endif
|
169
195
|
}
|
196
|
+
|
170
197
|
/*
|
171
198
|
* non-blocking mysql_*() functions that we won't be wrapping since
|
172
199
|
* they do not appear to hit the network nor issue any interruptible
|
@@ -192,11 +219,47 @@ static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) {
|
|
192
219
|
static void rb_mysql_client_mark(void * wrapper) {
|
193
220
|
mysql_client_wrapper * w = wrapper;
|
194
221
|
if (w) {
|
195
|
-
|
196
|
-
|
222
|
+
rb_gc_mark_movable(w->encoding);
|
223
|
+
rb_gc_mark_movable(w->active_fiber);
|
197
224
|
}
|
198
225
|
}
|
199
226
|
|
227
|
+
/* this is called during GC */
|
228
|
+
static void rb_mysql_client_free(void *ptr) {
|
229
|
+
mysql_client_wrapper *wrapper = ptr;
|
230
|
+
decr_mysql2_client(wrapper);
|
231
|
+
}
|
232
|
+
|
233
|
+
static size_t rb_mysql_client_memsize(const void * wrapper) {
|
234
|
+
const mysql_client_wrapper * w = wrapper;
|
235
|
+
return sizeof(*w);
|
236
|
+
}
|
237
|
+
|
238
|
+
static void rb_mysql_client_compact(void * wrapper) {
|
239
|
+
mysql_client_wrapper * w = wrapper;
|
240
|
+
if (w) {
|
241
|
+
rb_mysql2_gc_location(w->encoding);
|
242
|
+
rb_mysql2_gc_location(w->active_fiber);
|
243
|
+
}
|
244
|
+
}
|
245
|
+
|
246
|
+
const rb_data_type_t rb_mysql_client_type = {
|
247
|
+
"rb_mysql_client",
|
248
|
+
{
|
249
|
+
rb_mysql_client_mark,
|
250
|
+
rb_mysql_client_free,
|
251
|
+
rb_mysql_client_memsize,
|
252
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
253
|
+
rb_mysql_client_compact,
|
254
|
+
#endif
|
255
|
+
},
|
256
|
+
0,
|
257
|
+
0,
|
258
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
259
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
260
|
+
#endif
|
261
|
+
};
|
262
|
+
|
200
263
|
static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) {
|
201
264
|
VALUE rb_error_msg = rb_str_new2(mysql_error(wrapper->client));
|
202
265
|
VALUE rb_sql_state = rb_str_new2(mysql_sqlstate(wrapper->client));
|
@@ -297,18 +360,12 @@ static void *nogvl_close(void *ptr) {
|
|
297
360
|
mysql_close(wrapper->client);
|
298
361
|
wrapper->closed = 1;
|
299
362
|
wrapper->reconnect_enabled = 0;
|
300
|
-
wrapper->
|
363
|
+
wrapper->active_fiber = Qnil;
|
301
364
|
}
|
302
365
|
|
303
366
|
return NULL;
|
304
367
|
}
|
305
368
|
|
306
|
-
/* this is called during GC */
|
307
|
-
static void rb_mysql_client_free(void *ptr) {
|
308
|
-
mysql_client_wrapper *wrapper = ptr;
|
309
|
-
decr_mysql2_client(wrapper);
|
310
|
-
}
|
311
|
-
|
312
369
|
void decr_mysql2_client(mysql_client_wrapper *wrapper)
|
313
370
|
{
|
314
371
|
wrapper->refcount--;
|
@@ -340,9 +397,13 @@ void decr_mysql2_client(mysql_client_wrapper *wrapper)
|
|
340
397
|
static VALUE allocate(VALUE klass) {
|
341
398
|
VALUE obj;
|
342
399
|
mysql_client_wrapper * wrapper;
|
400
|
+
#ifdef NEW_TYPEDDATA_WRAPPER
|
401
|
+
obj = TypedData_Make_Struct(klass, mysql_client_wrapper, &rb_mysql_client_type, wrapper);
|
402
|
+
#else
|
343
403
|
obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
|
404
|
+
#endif
|
344
405
|
wrapper->encoding = Qnil;
|
345
|
-
wrapper->
|
406
|
+
wrapper->active_fiber = Qnil;
|
346
407
|
wrapper->automatic_close = 1;
|
347
408
|
wrapper->server_version = 0;
|
348
409
|
wrapper->reconnect_enabled = 0;
|
@@ -543,7 +604,7 @@ static VALUE do_send_query(VALUE args) {
|
|
543
604
|
mysql_client_wrapper *wrapper = query_args->wrapper;
|
544
605
|
if ((VALUE)rb_thread_call_without_gvl(nogvl_send_query, query_args, RUBY_UBF_IO, 0) == Qfalse) {
|
545
606
|
/* an error occurred, we're not active anymore */
|
546
|
-
wrapper->
|
607
|
+
wrapper->active_fiber = Qnil;
|
547
608
|
rb_raise_mysql2_error(wrapper);
|
548
609
|
}
|
549
610
|
return Qnil;
|
@@ -573,7 +634,7 @@ static void *nogvl_do_result(void *ptr, char use_result) {
|
|
573
634
|
|
574
635
|
/* once our result is stored off, this connection is
|
575
636
|
ready for another command to be issued */
|
576
|
-
wrapper->
|
637
|
+
wrapper->active_fiber = Qnil;
|
577
638
|
|
578
639
|
return result;
|
579
640
|
}
|
@@ -599,13 +660,13 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
|
|
599
660
|
GET_CLIENT(self);
|
600
661
|
|
601
662
|
/* if we're not waiting on a result, do nothing */
|
602
|
-
if (NIL_P(wrapper->
|
663
|
+
if (NIL_P(wrapper->active_fiber))
|
603
664
|
return Qnil;
|
604
665
|
|
605
666
|
REQUIRE_CONNECTED(wrapper);
|
606
667
|
if ((VALUE)rb_thread_call_without_gvl(nogvl_read_query_result, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
|
607
668
|
/* an error occurred, mark this connection inactive */
|
608
|
-
wrapper->
|
669
|
+
wrapper->active_fiber = Qnil;
|
609
670
|
rb_raise_mysql2_error(wrapper);
|
610
671
|
}
|
611
672
|
|
@@ -618,7 +679,7 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
|
|
618
679
|
|
619
680
|
if (result == NULL) {
|
620
681
|
if (mysql_errno(wrapper->client) != 0) {
|
621
|
-
wrapper->
|
682
|
+
wrapper->active_fiber = Qnil;
|
622
683
|
rb_raise_mysql2_error(wrapper);
|
623
684
|
}
|
624
685
|
/* no data and no error, so query was not a SELECT */
|
@@ -645,7 +706,7 @@ struct async_query_args {
|
|
645
706
|
static VALUE disconnect_and_raise(VALUE self, VALUE error) {
|
646
707
|
GET_CLIENT(self);
|
647
708
|
|
648
|
-
wrapper->
|
709
|
+
wrapper->active_fiber = Qnil;
|
649
710
|
|
650
711
|
/* Invalidate the MySQL socket to prevent further communication.
|
651
712
|
* The GC will come along later and call mysql_close to free it.
|
@@ -710,7 +771,7 @@ static VALUE disconnect_and_mark_inactive(VALUE self) {
|
|
710
771
|
GET_CLIENT(self);
|
711
772
|
|
712
773
|
/* Check if execution terminated while result was still being read. */
|
713
|
-
if (!NIL_P(wrapper->
|
774
|
+
if (!NIL_P(wrapper->active_fiber)) {
|
714
775
|
if (CONNECTED(wrapper)) {
|
715
776
|
/* Invalidate the MySQL socket to prevent further communication. */
|
716
777
|
#ifndef _WIN32
|
@@ -725,24 +786,24 @@ static VALUE disconnect_and_mark_inactive(VALUE self) {
|
|
725
786
|
}
|
726
787
|
/* Skip mysql client check performed before command execution. */
|
727
788
|
wrapper->client->status = MYSQL_STATUS_READY;
|
728
|
-
wrapper->
|
789
|
+
wrapper->active_fiber = Qnil;
|
729
790
|
}
|
730
791
|
|
731
792
|
return Qnil;
|
732
793
|
}
|
733
794
|
|
734
|
-
void
|
735
|
-
VALUE
|
795
|
+
static void rb_mysql_client_set_active_fiber(VALUE self) {
|
796
|
+
VALUE fiber_current = rb_fiber_current();
|
736
797
|
GET_CLIENT(self);
|
737
798
|
|
738
799
|
// see if this connection is still waiting on a result from a previous query
|
739
|
-
if (NIL_P(wrapper->
|
800
|
+
if (NIL_P(wrapper->active_fiber)) {
|
740
801
|
// mark this connection active
|
741
|
-
wrapper->
|
742
|
-
} else if (wrapper->
|
802
|
+
wrapper->active_fiber = fiber_current;
|
803
|
+
} else if (wrapper->active_fiber == fiber_current) {
|
743
804
|
rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
|
744
805
|
} else {
|
745
|
-
VALUE inspect = rb_inspect(wrapper->
|
806
|
+
VALUE inspect = rb_inspect(wrapper->active_fiber);
|
746
807
|
const char *thr = StringValueCStr(inspect);
|
747
808
|
|
748
809
|
rb_raise(cMysql2Error, "This connection is in use by: %s", thr);
|
@@ -806,7 +867,7 @@ static VALUE rb_mysql_query(VALUE self, VALUE sql, VALUE current) {
|
|
806
867
|
args.sql_len = RSTRING_LEN(args.sql);
|
807
868
|
args.wrapper = wrapper;
|
808
869
|
|
809
|
-
|
870
|
+
rb_mysql_client_set_active_fiber(self);
|
810
871
|
|
811
872
|
#ifndef _WIN32
|
812
873
|
rb_rescue2(do_send_query, (VALUE)&args, disconnect_and_raise, self, rb_eException, (VALUE)0);
|
@@ -1374,12 +1435,31 @@ static VALUE set_charset_name(VALUE self, VALUE value) {
|
|
1374
1435
|
static VALUE set_ssl_options(VALUE self, VALUE key, VALUE cert, VALUE ca, VALUE capath, VALUE cipher) {
|
1375
1436
|
GET_CLIENT(self);
|
1376
1437
|
|
1438
|
+
#ifdef HAVE_MYSQL_SSL_SET
|
1377
1439
|
mysql_ssl_set(wrapper->client,
|
1378
1440
|
NIL_P(key) ? NULL : StringValueCStr(key),
|
1379
1441
|
NIL_P(cert) ? NULL : StringValueCStr(cert),
|
1380
1442
|
NIL_P(ca) ? NULL : StringValueCStr(ca),
|
1381
1443
|
NIL_P(capath) ? NULL : StringValueCStr(capath),
|
1382
1444
|
NIL_P(cipher) ? NULL : StringValueCStr(cipher));
|
1445
|
+
#else
|
1446
|
+
/* mysql 8.3 does not provide mysql_ssl_set */
|
1447
|
+
if (!NIL_P(key)) {
|
1448
|
+
mysql_options(wrapper->client, MYSQL_OPT_SSL_KEY, StringValueCStr(key));
|
1449
|
+
}
|
1450
|
+
if (!NIL_P(cert)) {
|
1451
|
+
mysql_options(wrapper->client, MYSQL_OPT_SSL_CERT, StringValueCStr(cert));
|
1452
|
+
}
|
1453
|
+
if (!NIL_P(ca)) {
|
1454
|
+
mysql_options(wrapper->client, MYSQL_OPT_SSL_CA, StringValueCStr(ca));
|
1455
|
+
}
|
1456
|
+
if (!NIL_P(capath)) {
|
1457
|
+
mysql_options(wrapper->client, MYSQL_OPT_SSL_CAPATH, StringValueCStr(capath));
|
1458
|
+
}
|
1459
|
+
if (!NIL_P(cipher)) {
|
1460
|
+
mysql_options(wrapper->client, MYSQL_OPT_SSL_CIPHER, StringValueCStr(cipher));
|
1461
|
+
}
|
1462
|
+
#endif
|
1383
1463
|
|
1384
1464
|
return self;
|
1385
1465
|
}
|
@@ -1689,7 +1769,7 @@ void init_mysql2_client() {
|
|
1689
1769
|
rb_const_set(cMysql2Client, rb_intern("SESSION_TRACK_TRANSACTION_STATE"), INT2NUM(SESSION_TRACK_TRANSACTION_STATE));
|
1690
1770
|
#endif
|
1691
1771
|
|
1692
|
-
#if defined(FULL_SSL_MODE_SUPPORT) // MySQL 5.7.11 and above
|
1772
|
+
#if defined(FULL_SSL_MODE_SUPPORT) // MySQL 5.6.36 and MySQL 5.7.11 and above
|
1693
1773
|
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED));
|
1694
1774
|
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_PREFERRED"), INT2NUM(SSL_MODE_PREFERRED));
|
1695
1775
|
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(SSL_MODE_REQUIRED));
|
data/ext/mysql2/client.h
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
typedef struct {
|
5
5
|
VALUE encoding;
|
6
|
-
VALUE
|
6
|
+
VALUE active_fiber; /* rb_fiber_current() or Qnil */
|
7
7
|
long server_version;
|
8
8
|
int reconnect_enabled;
|
9
9
|
unsigned int connect_timeout;
|
@@ -15,12 +15,19 @@ typedef struct {
|
|
15
15
|
MYSQL *client;
|
16
16
|
} mysql_client_wrapper;
|
17
17
|
|
18
|
-
void rb_mysql_client_set_active_thread(VALUE self);
|
19
18
|
void rb_mysql_set_server_query_flags(MYSQL *client, VALUE result);
|
20
19
|
|
20
|
+
extern const rb_data_type_t rb_mysql_client_type;
|
21
|
+
|
22
|
+
#ifdef NEW_TYPEDDATA_WRAPPER
|
23
|
+
#define GET_CLIENT(self) \
|
24
|
+
mysql_client_wrapper *wrapper; \
|
25
|
+
TypedData_Get_Struct(self, mysql_client_wrapper, &rb_mysql_client_type, wrapper);
|
26
|
+
#else
|
21
27
|
#define GET_CLIENT(self) \
|
22
28
|
mysql_client_wrapper *wrapper; \
|
23
29
|
Data_Get_Struct(self, mysql_client_wrapper, wrapper);
|
30
|
+
#endif
|
24
31
|
|
25
32
|
void init_mysql2_client(void);
|
26
33
|
void decr_mysql2_client(mysql_client_wrapper *wrapper);
|
data/ext/mysql2/extconf.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
require 'English'
|
3
3
|
|
4
|
+
### Some helper functions
|
5
|
+
|
4
6
|
def asplode(lib)
|
5
7
|
if RUBY_PLATFORM =~ /mingw|mswin/
|
6
8
|
abort "-----\n#{lib} is missing. Check your installation of MySQL or Connector/C, and try again.\n-----"
|
@@ -26,20 +28,45 @@ def add_ssl_defines(header)
|
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
29
|
-
|
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
|
33
|
-
end
|
31
|
+
### Check for Ruby C extention interfaces
|
34
32
|
|
35
33
|
# 2.1+
|
36
34
|
have_func('rb_absint_size')
|
37
35
|
have_func('rb_absint_singlebit_p')
|
38
36
|
|
37
|
+
# 2.7+
|
38
|
+
have_func('rb_gc_mark_movable')
|
39
|
+
|
39
40
|
# Missing in RBX (https://github.com/rubinius/rubinius/issues/3771)
|
40
41
|
have_func('rb_wait_for_single_fd')
|
41
42
|
|
42
|
-
|
43
|
+
# 3.0+
|
44
|
+
have_func('rb_enc_interned_str', 'ruby.h')
|
45
|
+
|
46
|
+
### Find OpenSSL library
|
47
|
+
|
48
|
+
# User-specified OpenSSL if explicitly specified
|
49
|
+
if with_config('openssl-dir')
|
50
|
+
_, lib = dir_config('openssl')
|
51
|
+
if lib
|
52
|
+
# Ruby versions below 2.0 on Unix and below 2.1 on Windows
|
53
|
+
# do not properly search for lib directories, and must be corrected:
|
54
|
+
# https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/39717
|
55
|
+
unless lib && lib[-3, 3] == 'lib'
|
56
|
+
@libdir_basename = 'lib'
|
57
|
+
_, lib = dir_config('openssl')
|
58
|
+
end
|
59
|
+
abort "-----\nCannot find library dir(s) #{lib}\n-----" unless lib && lib.split(File::PATH_SEPARATOR).any? { |dir| File.directory?(dir) }
|
60
|
+
warn "-----\nUsing --with-openssl-dir=#{File.dirname lib}\n-----"
|
61
|
+
$LDFLAGS << " -L#{lib}"
|
62
|
+
end
|
63
|
+
# Homebrew OpenSSL on MacOS
|
64
|
+
elsif RUBY_PLATFORM =~ /darwin/ && system('command -v brew')
|
65
|
+
openssl_location = `brew --prefix openssl`.strip
|
66
|
+
$LDFLAGS << " -L#{openssl_location}/lib" if openssl_location
|
67
|
+
end
|
68
|
+
|
69
|
+
### Find MySQL client library
|
43
70
|
|
44
71
|
# borrowed from mysqlplus
|
45
72
|
# http://github.com/oldmoe/mysqlplus/blob/master/ext/extconf.rb
|
@@ -48,6 +75,7 @@ dirs = ENV.fetch('PATH').split(File::PATH_SEPARATOR) + %w[
|
|
48
75
|
/opt/local
|
49
76
|
/opt/local/mysql
|
50
77
|
/opt/local/lib/mysql5*
|
78
|
+
/opt/homebrew/opt/mysql*
|
51
79
|
/usr
|
52
80
|
/usr/mysql
|
53
81
|
/usr/local
|
@@ -136,10 +164,16 @@ have_const('MYSQL_OPTION_MULTI_STATEMENTS_OFF', mysql_h)
|
|
136
164
|
# to retain compatibility with the typedef in earlier MySQLs.
|
137
165
|
have_type('my_bool', mysql_h)
|
138
166
|
|
167
|
+
# detect mysql functions
|
168
|
+
have_func('mysql_ssl_set', mysql_h)
|
169
|
+
|
170
|
+
### Compiler flags to help catch errors
|
171
|
+
|
139
172
|
# This is our wishlist. We use whichever flags work on the host.
|
140
173
|
# -Wall and -Wextra are included by default.
|
141
174
|
wishlist = [
|
142
175
|
'-Weverything',
|
176
|
+
'-Wno-compound-token-split-by-macro', # Fixed in Ruby 2.7+ at https://bugs.ruby-lang.org/issues/17865
|
143
177
|
'-Wno-bad-function-cast', # rb_thread_call_without_gvl returns void * that we cast to VALUE
|
144
178
|
'-Wno-conditional-uninitialized', # false positive in client.c
|
145
179
|
'-Wno-covered-switch-default', # result.c -- enum_field_types (when fully covered, e.g. mysql 5.5)
|
@@ -164,6 +198,8 @@ end
|
|
164
198
|
|
165
199
|
$CFLAGS << ' ' << usable_flags.join(' ')
|
166
200
|
|
201
|
+
### Sanitizers to help with debugging -- many are available on both Clang/LLVM and GCC
|
202
|
+
|
167
203
|
enabled_sanitizers = disabled_sanitizers = []
|
168
204
|
# Specify a comma-separated list of sanitizers, or try them all by default
|
169
205
|
sanitizers = with_config('sanitize')
|
@@ -181,7 +217,7 @@ when String
|
|
181
217
|
end
|
182
218
|
end
|
183
219
|
|
184
|
-
unless disabled_sanitizers.empty?
|
220
|
+
unless disabled_sanitizers.empty? # rubocop:disable Style/IfUnlessModifier
|
185
221
|
abort "-----\nCould not enable requested sanitizers: #{disabled_sanitizers.join(',')}\n-----"
|
186
222
|
end
|
187
223
|
|
@@ -198,6 +234,8 @@ unless enabled_sanitizers.empty?
|
|
198
234
|
$CFLAGS << ' -g -fno-omit-frame-pointer'
|
199
235
|
end
|
200
236
|
|
237
|
+
### Find MySQL Client on Windows, set RPATH to find the library at runtime
|
238
|
+
|
201
239
|
if RUBY_PLATFORM =~ /mswin|mingw/ && !defined?(RubyInstaller)
|
202
240
|
# Build libmysql.a interface link library
|
203
241
|
require 'rake'
|
data/ext/mysql2/mysql2_ext.h
CHANGED
@@ -36,6 +36,19 @@ void Init_mysql2(void);
|
|
36
36
|
typedef bool my_bool;
|
37
37
|
#endif
|
38
38
|
|
39
|
+
// ruby 2.7+
|
40
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
41
|
+
#define rb_mysql2_gc_location(ptr) ptr = rb_gc_location(ptr)
|
42
|
+
#else
|
43
|
+
#define rb_gc_mark_movable(ptr) rb_gc_mark(ptr)
|
44
|
+
#define rb_mysql2_gc_location(ptr)
|
45
|
+
#endif
|
46
|
+
|
47
|
+
// ruby 2.2+
|
48
|
+
#ifdef TypedData_Make_Struct
|
49
|
+
#define NEW_TYPEDDATA_WRAPPER 1
|
50
|
+
#endif
|
51
|
+
|
39
52
|
#include <client.h>
|
40
53
|
#include <statement.h>
|
41
54
|
#include <result.h>
|
@@ -51,7 +51,7 @@ mysql2_mysql_enc_name_to_rb_hash (str, len)
|
|
51
51
|
74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
|
52
52
|
74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
|
53
53
|
74, 74, 74, 74, 74, 74, 74, 74, 15, 5,
|
54
|
-
0,
|
54
|
+
0, 30, 5, 25, 40, 10, 20, 50, 74, 74,
|
55
55
|
74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
|
56
56
|
74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
|
57
57
|
74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
|
@@ -89,7 +89,7 @@ mysql2_mysql_enc_name_to_rb (str, len)
|
|
89
89
|
{
|
90
90
|
enum
|
91
91
|
{
|
92
|
-
TOTAL_KEYWORDS =
|
92
|
+
TOTAL_KEYWORDS = 42,
|
93
93
|
MIN_WORD_LENGTH = 3,
|
94
94
|
MAX_WORD_LENGTH = 8,
|
95
95
|
MIN_HASH_VALUE = 3,
|
@@ -133,7 +133,8 @@ mysql2_mysql_enc_name_to_rb (str, len)
|
|
133
133
|
{"big5", "Big5"},
|
134
134
|
{"euckr", "EUC-KR"},
|
135
135
|
{"latin2", "ISO-8859-2"},
|
136
|
-
{""
|
136
|
+
{"utf8mb3", "UTF-8"},
|
137
|
+
{""},
|
137
138
|
{"dec8", NULL},
|
138
139
|
{"cp850", "CP850"},
|
139
140
|
{"latin1", "ISO-8859-1"},
|
@@ -306,5 +306,20 @@ static const char *mysql2_mysql_enc_to_rb[] = {
|
|
306
306
|
"UTF-8",
|
307
307
|
"UTF-8",
|
308
308
|
"UTF-8",
|
309
|
+
"UTF-8",
|
310
|
+
"UTF-8",
|
311
|
+
"UTF-8",
|
312
|
+
"UTF-8",
|
313
|
+
"UTF-8",
|
314
|
+
"UTF-8",
|
315
|
+
"UTF-8",
|
316
|
+
"UTF-8",
|
317
|
+
"UTF-8",
|
318
|
+
"UTF-8",
|
319
|
+
"UTF-8",
|
320
|
+
"UTF-8",
|
321
|
+
"UTF-8",
|
322
|
+
"UTF-8",
|
323
|
+
"UTF-8",
|
309
324
|
"UTF-8"
|
310
325
|
};
|
data/ext/mysql2/result.c
CHANGED
@@ -31,9 +31,13 @@ static rb_encoding *binaryEncoding;
|
|
31
31
|
#define MYSQL_TYPE_JSON 245
|
32
32
|
#endif
|
33
33
|
|
34
|
+
#ifndef NEW_TYPEDDATA_WRAPPER
|
35
|
+
#define TypedData_Get_Struct(obj, type, ignore, sval) Data_Get_Struct(obj, type, sval)
|
36
|
+
#endif
|
37
|
+
|
34
38
|
#define GET_RESULT(self) \
|
35
39
|
mysql2_result_wrapper *wrapper; \
|
36
|
-
|
40
|
+
TypedData_Get_Struct(self, mysql2_result_wrapper, &rb_mysql_result_type, wrapper);
|
37
41
|
|
38
42
|
typedef struct {
|
39
43
|
int symbolizeKeys;
|
@@ -61,11 +65,11 @@ static VALUE sym_symbolize_keys, sym_as, sym_array, sym_database_timezone,
|
|
61
65
|
static void rb_mysql_result_mark(void * wrapper) {
|
62
66
|
mysql2_result_wrapper * w = wrapper;
|
63
67
|
if (w) {
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
68
|
+
rb_gc_mark_movable(w->fields);
|
69
|
+
rb_gc_mark_movable(w->rows);
|
70
|
+
rb_gc_mark_movable(w->encoding);
|
71
|
+
rb_gc_mark_movable(w->client);
|
72
|
+
rb_gc_mark_movable(w->statement);
|
69
73
|
}
|
70
74
|
}
|
71
75
|
|
@@ -127,6 +131,48 @@ static void rb_mysql_result_free(void *ptr) {
|
|
127
131
|
xfree(wrapper);
|
128
132
|
}
|
129
133
|
|
134
|
+
static size_t rb_mysql_result_memsize(const void * wrapper) {
|
135
|
+
const mysql2_result_wrapper * w = wrapper;
|
136
|
+
size_t memsize = sizeof(*w);
|
137
|
+
if (w->stmt_wrapper) {
|
138
|
+
memsize += sizeof(*w->stmt_wrapper);
|
139
|
+
}
|
140
|
+
if (w->client_wrapper) {
|
141
|
+
memsize += sizeof(*w->client_wrapper);
|
142
|
+
}
|
143
|
+
return memsize;
|
144
|
+
}
|
145
|
+
|
146
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
147
|
+
static void rb_mysql_result_compact(void * wrapper) {
|
148
|
+
mysql2_result_wrapper * w = wrapper;
|
149
|
+
if (w) {
|
150
|
+
rb_mysql2_gc_location(w->fields);
|
151
|
+
rb_mysql2_gc_location(w->rows);
|
152
|
+
rb_mysql2_gc_location(w->encoding);
|
153
|
+
rb_mysql2_gc_location(w->client);
|
154
|
+
rb_mysql2_gc_location(w->statement);
|
155
|
+
}
|
156
|
+
}
|
157
|
+
#endif
|
158
|
+
|
159
|
+
static const rb_data_type_t rb_mysql_result_type = {
|
160
|
+
"rb_mysql_result",
|
161
|
+
{
|
162
|
+
rb_mysql_result_mark,
|
163
|
+
rb_mysql_result_free,
|
164
|
+
rb_mysql_result_memsize,
|
165
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
166
|
+
rb_mysql_result_compact,
|
167
|
+
#endif
|
168
|
+
},
|
169
|
+
0,
|
170
|
+
0,
|
171
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
172
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
173
|
+
#endif
|
174
|
+
};
|
175
|
+
|
130
176
|
static VALUE rb_mysql_result_free_(VALUE self) {
|
131
177
|
GET_RESULT(self);
|
132
178
|
rb_mysql_result_free_result(wrapper);
|
@@ -365,7 +411,7 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
|
|
365
411
|
int enc_index;
|
366
412
|
|
367
413
|
enc_name = (field.charsetnr-1 < MYSQL2_CHARSETNR_SIZE) ? mysql2_mysql_enc_to_rb[field.charsetnr-1] : NULL;
|
368
|
-
|
414
|
+
|
369
415
|
if (enc_name != NULL) {
|
370
416
|
/* use the field encoding we were able to match */
|
371
417
|
enc_index = rb_enc_find_index(enc_name);
|
@@ -1129,7 +1175,11 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
|
|
1129
1175
|
VALUE obj;
|
1130
1176
|
mysql2_result_wrapper * wrapper;
|
1131
1177
|
|
1178
|
+
#ifdef NEW_TYPEDDATA_WRAPPER
|
1179
|
+
obj = TypedData_Make_Struct(cMysql2Result, mysql2_result_wrapper, &rb_mysql_result_type, wrapper);
|
1180
|
+
#else
|
1132
1181
|
obj = Data_Make_Struct(cMysql2Result, mysql2_result_wrapper, rb_mysql_result_mark, rb_mysql_result_free, wrapper);
|
1182
|
+
#endif
|
1133
1183
|
wrapper->numberOfFields = 0;
|
1134
1184
|
wrapper->numberOfRows = 0;
|
1135
1185
|
wrapper->lastRowProcessed = 0;
|
@@ -1176,7 +1226,7 @@ void init_mysql2_result() {
|
|
1176
1226
|
cMysql2Result = rb_define_class_under(mMysql2, "Result", rb_cObject);
|
1177
1227
|
rb_undef_alloc_func(cMysql2Result);
|
1178
1228
|
rb_global_variable(&cMysql2Result);
|
1179
|
-
|
1229
|
+
|
1180
1230
|
rb_define_method(cMysql2Result, "each", rb_mysql_result_each, -1);
|
1181
1231
|
rb_define_method(cMysql2Result, "fields", rb_mysql_result_fetch_fields, 0);
|
1182
1232
|
rb_define_method(cMysql2Result, "field_types", rb_mysql_result_fetch_field_types, 0);
|
data/ext/mysql2/statement.c
CHANGED
@@ -6,9 +6,13 @@ static VALUE sym_stream, intern_new_with_args, intern_each, intern_to_s, intern_
|
|
6
6
|
static VALUE intern_sec_fraction, intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year,
|
7
7
|
intern_query_options;
|
8
8
|
|
9
|
+
#ifndef NEW_TYPEDDATA_WRAPPER
|
10
|
+
#define TypedData_Get_Struct(obj, type, ignore, sval) Data_Get_Struct(obj, type, sval)
|
11
|
+
#endif
|
12
|
+
|
9
13
|
#define GET_STATEMENT(self) \
|
10
14
|
mysql_stmt_wrapper *stmt_wrapper; \
|
11
|
-
|
15
|
+
TypedData_Get_Struct(self, mysql_stmt_wrapper, &rb_mysql_statement_type, stmt_wrapper); \
|
12
16
|
if (!stmt_wrapper->stmt) { rb_raise(cMysql2Error, "Invalid statement handle"); } \
|
13
17
|
if (stmt_wrapper->closed) { rb_raise(cMysql2Error, "Statement handle already closed"); }
|
14
18
|
|
@@ -16,9 +20,45 @@ static void rb_mysql_stmt_mark(void * ptr) {
|
|
16
20
|
mysql_stmt_wrapper *stmt_wrapper = ptr;
|
17
21
|
if (!stmt_wrapper) return;
|
18
22
|
|
19
|
-
|
23
|
+
rb_gc_mark_movable(stmt_wrapper->client);
|
24
|
+
}
|
25
|
+
|
26
|
+
static void rb_mysql_stmt_free(void *ptr) {
|
27
|
+
mysql_stmt_wrapper *stmt_wrapper = ptr;
|
28
|
+
decr_mysql2_stmt(stmt_wrapper);
|
29
|
+
}
|
30
|
+
|
31
|
+
static size_t rb_mysql_stmt_memsize(const void * ptr) {
|
32
|
+
const mysql_stmt_wrapper *stmt_wrapper = ptr;
|
33
|
+
return sizeof(*stmt_wrapper);
|
20
34
|
}
|
21
35
|
|
36
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
37
|
+
static void rb_mysql_stmt_compact(void * ptr) {
|
38
|
+
mysql_stmt_wrapper *stmt_wrapper = ptr;
|
39
|
+
if (!stmt_wrapper) return;
|
40
|
+
|
41
|
+
rb_mysql2_gc_location(stmt_wrapper->client);
|
42
|
+
}
|
43
|
+
#endif
|
44
|
+
|
45
|
+
static const rb_data_type_t rb_mysql_statement_type = {
|
46
|
+
"rb_mysql_statement",
|
47
|
+
{
|
48
|
+
rb_mysql_stmt_mark,
|
49
|
+
rb_mysql_stmt_free,
|
50
|
+
rb_mysql_stmt_memsize,
|
51
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
52
|
+
rb_mysql_stmt_compact,
|
53
|
+
#endif
|
54
|
+
},
|
55
|
+
0,
|
56
|
+
0,
|
57
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
58
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
59
|
+
#endif
|
60
|
+
};
|
61
|
+
|
22
62
|
static void *nogvl_stmt_close(void *ptr) {
|
23
63
|
mysql_stmt_wrapper *stmt_wrapper = ptr;
|
24
64
|
if (stmt_wrapper->stmt) {
|
@@ -28,11 +68,6 @@ static void *nogvl_stmt_close(void *ptr) {
|
|
28
68
|
return NULL;
|
29
69
|
}
|
30
70
|
|
31
|
-
static void rb_mysql_stmt_free(void *ptr) {
|
32
|
-
mysql_stmt_wrapper *stmt_wrapper = ptr;
|
33
|
-
decr_mysql2_stmt(stmt_wrapper);
|
34
|
-
}
|
35
|
-
|
36
71
|
void decr_mysql2_stmt(mysql_stmt_wrapper *stmt_wrapper) {
|
37
72
|
stmt_wrapper->refcount--;
|
38
73
|
|
@@ -96,7 +131,11 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
|
|
96
131
|
|
97
132
|
Check_Type(sql, T_STRING);
|
98
133
|
|
134
|
+
#ifdef NEW_TYPEDDATA_WRAPPER
|
135
|
+
rb_stmt = TypedData_Make_Struct(cMysql2Statement, mysql_stmt_wrapper, &rb_mysql_statement_type, stmt_wrapper);
|
136
|
+
#else
|
99
137
|
rb_stmt = Data_Make_Struct(cMysql2Statement, mysql_stmt_wrapper, rb_mysql_stmt_mark, rb_mysql_stmt_free, stmt_wrapper);
|
138
|
+
#endif
|
100
139
|
{
|
101
140
|
stmt_wrapper->client = rb_client;
|
102
141
|
stmt_wrapper->refcount = 1;
|
@@ -448,7 +487,7 @@ static VALUE rb_mysql_stmt_execute(int argc, VALUE *argv, VALUE self) {
|
|
448
487
|
if (metadata == NULL) {
|
449
488
|
if (mysql_stmt_errno(stmt) != 0) {
|
450
489
|
// either CR_OUT_OF_MEMORY or CR_UNKNOWN_ERROR. both fatal.
|
451
|
-
wrapper->
|
490
|
+
wrapper->active_fiber = Qnil;
|
452
491
|
rb_raise_mysql2_stmt_error(stmt_wrapper);
|
453
492
|
}
|
454
493
|
// no data and no error, so query was not a SELECT
|
@@ -461,7 +500,7 @@ static VALUE rb_mysql_stmt_execute(int argc, VALUE *argv, VALUE self) {
|
|
461
500
|
mysql_free_result(metadata);
|
462
501
|
rb_raise_mysql2_stmt_error(stmt_wrapper);
|
463
502
|
}
|
464
|
-
wrapper->
|
503
|
+
wrapper->active_fiber = Qnil;
|
465
504
|
}
|
466
505
|
|
467
506
|
resultObj = rb_mysql_result_to_obj(stmt_wrapper->client, wrapper->encoding, current, metadata, self);
|
@@ -502,7 +541,7 @@ static VALUE rb_mysql_stmt_fields(VALUE self) {
|
|
502
541
|
if (metadata == NULL) {
|
503
542
|
if (mysql_stmt_errno(stmt) != 0) {
|
504
543
|
// either CR_OUT_OF_MEMORY or CR_UNKNOWN_ERROR. both fatal.
|
505
|
-
wrapper->
|
544
|
+
wrapper->active_fiber = Qnil;
|
506
545
|
rb_raise_mysql2_stmt_error(stmt_wrapper);
|
507
546
|
}
|
508
547
|
// no data and no error, so query was not a SELECT
|
data/lib/mysql2/client.rb
CHANGED
@@ -20,6 +20,7 @@ module Mysql2
|
|
20
20
|
|
21
21
|
def initialize(opts = {})
|
22
22
|
raise Mysql2::Error, "Options parameter must be a Hash" unless opts.is_a? Hash
|
23
|
+
|
23
24
|
opts = Mysql2::Util.key_hash_as_symbols(opts)
|
24
25
|
@read_timeout = nil
|
25
26
|
@query_options = self.class.default_query_options.dup
|
@@ -33,6 +34,7 @@ module Mysql2
|
|
33
34
|
# TODO: stricter validation rather than silent massaging
|
34
35
|
%i[reconnect connect_timeout local_infile read_timeout write_timeout default_file default_group secure_auth init_command automatic_close enable_cleartext_plugin default_auth].each do |key|
|
35
36
|
next unless opts.key?(key)
|
37
|
+
|
36
38
|
case key
|
37
39
|
when :reconnect, :local_infile, :secure_auth, :automatic_close, :enable_cleartext_plugin
|
38
40
|
send(:"#{key}=", !!opts[key]) # rubocop:disable Style/DoubleNegation
|
@@ -136,6 +138,7 @@ module Mysql2
|
|
136
138
|
# and performance_schema.session_account_connect_attrs
|
137
139
|
def parse_connect_attrs(conn_attrs)
|
138
140
|
return {} if Mysql2::Client::CONNECT_ATTRS.zero?
|
141
|
+
|
139
142
|
conn_attrs ||= {}
|
140
143
|
conn_attrs[:program_name] ||= $PROGRAM_NAME
|
141
144
|
conn_attrs.each_with_object({}) do |(key, value), hash|
|
@@ -152,6 +155,7 @@ module Mysql2
|
|
152
155
|
def query_info
|
153
156
|
info = query_info_string
|
154
157
|
return {} unless info
|
158
|
+
|
155
159
|
info_hash = {}
|
156
160
|
info.split.each_slice(2) { |s| info_hash[s[0].downcase.delete(':').to_sym] = s[1].to_i }
|
157
161
|
info_hash
|
data/lib/mysql2/version.rb
CHANGED
data/lib/mysql2.rb
CHANGED
@@ -0,0 +1,104 @@
|
|
1
|
+
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
2
|
+
|
3
|
+
xsFNBFb8EKsBEADwGmleOSVThrbCyCVUdCreMTKpmD5p5aPz/0jc66050MAb71Hv
|
4
|
+
TVcfuMqHYO8O66qXLpEdqZpuk4D+rw1oKyC+d8uPD2PSHRqBXnR0Qf+LVTZvtO92
|
5
|
+
3R7pYnC2x6V6iVGpKQYFP8cwh2B1qgIa+9y/N8cQIqfD+0ghyiUjjTYek3YFBnqa
|
6
|
+
L/2h2V0Mt0DkBrDK80LqEY10PAFDfJjINAW9XNHZzi2KqUx5w1z8rItokXV6fYE5
|
7
|
+
ItyGMR6WVajJg5D4VCiZd0ymuQP2bGkrRbl6FH5vofVSkahKMJeHs2lbvMvNyS3c
|
8
|
+
n8vxoBvbbcwSAV1gvB1uzXXxv0kdkFZjhU1Tss4+Dak8qeEmIrC5qYycLxIdVEhT
|
9
|
+
Z8N8+P7Dll+QGOZKu9+OzhQ+byzpLFhUHKys53eXo/HrfWtw3DdP21yyb5P3QcgF
|
10
|
+
scxfZHzZtFNUL6XaVnauZM2lqquUW+lMNdKKGCBJ6co4QxjocsxfISyarcFj6ZR0
|
11
|
+
5Hf6VU3Y7AyuFZdL0SQWPv9BSu/swBOimrSiiVHbtE49Nx1x/d1wn1peYl07WRUv
|
12
|
+
C10eF36ZoqEuSGmDz59mWlwB3daIYAsAAiBwgcmN7aSB8XD4ZPUVSEZvwSm/IwuS
|
13
|
+
Rkpde+kIhTLjyv5bRGqU2P/Mi56dB4VFmMJaF26CiRXatxhXOAIAF9dXCwARAQAB
|
14
|
+
zS1NYXJpYURCIFNpZ25pbmcgS2V5IDxzaWduaW5nLWtleUBtYXJpYWRiLm9yZz7C
|
15
|
+
wXgEEwEIACIFAlb8EKsCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPFl
|
16
|
+
byTHTNHYJZ0P/2Z2RURRkSTHLKZ/GqSvPReReeB7AI+ZrDapkpG/26xp1Yw1isCO
|
17
|
+
y99pvQ7hjTFhdZQ7xSRUiT/e27wJxR7s4G/ck5VOVjuJzGnByNLmwMjdN1ONIO9P
|
18
|
+
hQAs2iF3uoIbVTxzXof2F8C0WSbKgEWbtqlCWlaapDpN8jKAWdsQsNMdXcdpJ2os
|
19
|
+
WiacQRxLREBGjVRkAiqdjYkegQ4BZ0GtPULKjZWCUNkaat51b7O7V19nSy/T7MM7
|
20
|
+
n+kqYQLMIHCF8LGd3QQsNppRnolWVRzXMdtR2+9iI21qv6gtHcMiAg6QcKA7halL
|
21
|
+
kCdIS2nWR8g7nZeZjq5XhckeNGrGX/3w/m/lwczYjMUer+qs2ww5expZJ7qhtSta
|
22
|
+
lE3EtL/l7zE4RlknqwDZ0IXtxCNPu2UovCzZmdZm8UWfMSKk/3VgL8HgzYRr8fo0
|
23
|
+
yj0XkckJ7snXvuhoviW2tjm46PyHPWRKgW4iEzUrB+hiXpy3ikt4rLRg/iMqKjyf
|
24
|
+
mvcE/VdmFVtsfbfRVvlaWiIWCndRTVBkAaTu8DwrGyugQsbjEcK+4E25/SaKIJIw
|
25
|
+
qfxpyBVhru21ypgEMAw1Y8KC7KntB7jzpFotE4wpv1jZKUZuy71ofr7g3/2O+7nW
|
26
|
+
LrR1mncbuT6yXo316r56dfKzOxQJBnYFwTjXfa65yBArjQBUCPNYOKr0wkYEEhEI
|
27
|
+
AAYFAlb8JFYACgkQy8sIKhu5Q9snYACgh3id41CYTHELOQ/ymj4tiuFt1lcAn3JU
|
28
|
+
9wH3pihM9ISvoeuGnwwHhcKnwsFcBBIBCAAGBQJW/CSEAAoJEJFxGJmV5Fqe11cP
|
29
|
+
/A3QhvqleuRaXoS5apIY3lrDL79Wo0bkydM3u2Ft9EqVVG5zZvlmWaXbw5wkPhza
|
30
|
+
7YUjrD7ylaE754lHI48jJp3KY7RosClY/Kuk56GJI/SoMKx4v518pAboZ4hjY9MY
|
31
|
+
gmiAuZEYx5Ibv1pj0+hkzRI78+f6+d5QTQ6y/35ZjSSJcBgCMAr/JRsmOkHu6cY6
|
32
|
+
qOpq4g8mvRAX5ivRm4UxE2gnxZyd2LjY2/S2kCZvHWVaZuiTD0EU1jYPoOo6fhc8
|
33
|
+
zjs5FWS56C1vp7aFOGBvsH3lwYAYi1K2S+/B4nqpitYJz/T0zFzzyYe7ZG77DXKD
|
34
|
+
/XajD22IzRGKjoeVPFBx+2V0YCCpWZkqkfZ2Dt3QVW//QIpVsOJnmaqolDg1sxoa
|
35
|
+
BEYBtCtovU0wh1pXWwfn7IgjIkPNl0AU8mW8Ll91WF+Lss/oMrUJMKVDenTJ6/ZO
|
36
|
+
06c+JFlP7dS3YGMsifwgy5abA4Xy4GWpAsyEM68mqsJUc7ZANZcQAKr6+DryzSfI
|
37
|
+
Olsn3kJzOtb/c3JhVmblEO6XzdfZJK/axPOp3mF1oEBoJ56fGwO2usgVwQDyLt3J
|
38
|
+
iluJrCvMSBL9KtBZWrTZH5t3rTMN0NUALy4Etd6Y8V94i8c5NixMDyjRU7aKJAAw
|
39
|
+
tUvxLd12dqtaXsuvGyzLbR4EDT/Q5DfLC1DZWpgtUtCVwsFcBBIBCAAGBQJW/CS2
|
40
|
+
AAoJEEHdwLQNpW8iMUoP/AjFKyZ+inQTI2jJJBBtrLjxaxZSG5ggCovowWn8NWv6
|
41
|
+
bQBm2VurYVKhvY1xUyxoLY8KN+MvoeTdpB3u7z+M6x+CdfoTGqWQ2yapOC0eEJBF
|
42
|
+
O+GFho2WE0msiO0IaVJrzdFTPE0EYR2BHziLu0DDSZADe1WYEqkkrZsCNgi6EMng
|
43
|
+
mX2h+DK2GlC3W2tY9sc63DsgzjcMBO9uYmpHj6nizsIrETqouVNUCLT0t8iETa25
|
44
|
+
Mehq/I92I70Qfebv7R4eMrs+tWXKyPU0OjV+8b8saZsv1xn98UkeXwYx4JI04OTw
|
45
|
+
nBeJG8yPrGDBO5iucmtaCvwGQ3c76qBivrA8eFz3azRxQYWWiFrkElTg+C/E83JQ
|
46
|
+
WgqPvPZkI5UHvBwBqcoIXG15AJoXA/ZWIB8nPKWKaV5KDnY3DBuA4rh5Mhy3xwcC
|
47
|
+
/22E/CmZMXjUUvDnlPgXCYAYU0FBbGk7JpSYawtNfdAN2XBRPq5sDKLLxftx7D8u
|
48
|
+
ESJXXAlPxoRh7x1ArdGM+EowlJJ0xpINBaT0Z/Hk0jxNIFEak796/WeGqewdOIki
|
49
|
+
dAs4tppUfzosla5K+qXfWwmhcKmpwA4oynE8wIaoXptoi8+rxaw4N6wAXlSrVxeC
|
50
|
+
VTnb7+UY/BT2Wx6IQ10C9jrsj6XIffMvngIinCD9Czvadmr7BEIxKt1LP+gGA8Zg
|
51
|
+
wsFcBBIBCgAGBQJYE6oDAAoJEL7YRJ/O6NqIJ24P+QFNa2O+Q1rLKrQiuPw4Q73o
|
52
|
+
7/blUpFNudZfeCDpDbUgJ01u1RHnWOyLcyknartAosFDJIpgcXY5I8jsBIO5IZPR
|
53
|
+
C/UKxZB3RYOhj49bySD9RNapHyq+Y56j9JUoz6tkKFBd+6g85Ej8d924xM1UnRCS
|
54
|
+
9cfI9W0fSunbCi2CXLbXFF7V+m3Ou1SVYGIAxpMn4RXyYfuqeB5wROR2GA5Ef6T3
|
55
|
+
S5byh1dRSEgnrBToENtp5n7Jwsc9pDofjtaUkO854l45IqFarGjCHZwtNRKd2lcK
|
56
|
+
FMnd1jS0nfGkUbn3qNJam1qaGWx4gXaT845VsYYVTbxtkKi+qPUIoOyYx4NEm6fC
|
57
|
+
ZywH72oP+fmUT/fbfSHa5j137dRqokkR6RFjnEMBl6WHwgqqUqeIT6t9uV6WWzX9
|
58
|
+
lNroZFAFL/de7H31iIRuZcm38DUZOfjVf9glweu4yFvuJ7cQtyQydFQJV4LGDT/C
|
59
|
+
8e9TWrV1/gWMyMGQlZsRWa+h+FfFUccQtfSdXpvSxtXfop+fVQmJgUUl92jh4K9j
|
60
|
+
c9a6rIp5v1Q1yEgs2iS50/V/NMSmEcE1XMOxFt9fX9T+XmKAWZ8L25lpILsHT3mB
|
61
|
+
VWrpHdbawUaiBp9elxhn6tFiTFR7qA7dlUyWrI+MMlINwSZ2AAXvmA2IajH/UIlh
|
62
|
+
xotxmSNiZYIQ6UbD3fk4wsFzBBABCgAdFiEEmy/52H2krRdju+d2+GQcuhDvLUgF
|
63
|
+
Ally44wACgkQ+GQcuhDvLUgkjQ//c3mBxfJm6yLAJD4s4OgsPv4pcp/EKmPcdztm
|
64
|
+
W0/glwopUZmq9oNo3VMMCGtusrQgpACzfUlesu9NWlPCB3olZkeGugygo0zuQBKs
|
65
|
+
55eG7bPzMLyfSqLKyogYocaGc4lpf4lbvlvxy37YGVrGpwT9i8t2REtM6iPKDcMM
|
66
|
+
sgVtNlqFdq3Fs2Haqt0m1EksX6/GSIrjK4LZEcPklrGPvUS3S+qkwuaGE/jXxncE
|
67
|
+
4jFQR9SYH6AHr6Vkt1CG9Dgpr+Ph0I9n0JRknBYoUZ1q51WdF946NplXkCskdzWG
|
68
|
+
RHgMUCz3ZehF1FzpKgfO9Zd0YZsmivV/g6frUw/TayP9gxKPt7z2Lsxzyh8X7cg6
|
69
|
+
TAvdG9JbG0PyPJT1TZ8qpjP/PtqPclHsHQQIbGSDFWzRM5znhS+5sgyw8FWInjw8
|
70
|
+
JjxoOWMa50464EfGeb2jZfwtRimJAJLWEf/JnvO779nXf5YbvUZgfXaX7k/cvCVk
|
71
|
+
U8M7oC7x8o6F0P2Lh6FgonklKEeIRtZBUNZ0Lk9OShVqlU9/v16MHq/Eyu/Mbs0D
|
72
|
+
en3vYgiYxOBR8czD1Wh4vsKiGfOzQ6oWti/DCURV+iTYhJc7mSWM6STzUFr0nCnF
|
73
|
+
x6W0j/zH6ZgiFAGOyIXW2DwfjFvYRcBL1RWAEKsiFwYrNV+MDonjKXjpVB1Ra90o
|
74
|
+
lLrZXAXCwHMEEgEKAB0WIQRMRw//78TT3Fl3hlXOGj3V48lPSQUCXAAgOgAKCRDO
|
75
|
+
Gj3V48lPSQxAB/43qoWteVZEiN3JW4FnHg+S60TnHSP69FKV+363XYKDa23pNpv4
|
76
|
+
tiJumo9Kvb4UoDft766/URHm5RKyPtrxy+wqotamrkGJUTtP2a68h7C31VX+pf6i
|
77
|
+
iQKmxRQz4zmW0pA5X01+AgpvcDH++Fv5NLBpnjqPdTh5b0gvr89E0zMNldNYOZu1
|
78
|
+
0H/mukrnGlFDu/osBuy+XJtP2MeasazVMLvjKs+hr//E+iLI9DZOwFBK6AX5gkkI
|
79
|
+
UEHkSeb4//AHwvanUMin9un9+F9iR+qDuDEKxuevYzM0owuoVcK5pAsRnRQJlnHW
|
80
|
+
/0BQ6FtNGpmljhvUk8a/l3xFf3z/uJG5vVKVzsFNBFb8EKsBEADDfCMsu2U1CdJh
|
81
|
+
r4xp6z4J89/tMnpCQASC8DQhtZ6bWG/ksyKt2DnDQ050XBEng+7epzHWA2UgT0li
|
82
|
+
Y05zZmFs1X7QeZr16B7JANq6fnHOdZB0ThS7JEYbProkMxcqAFLAZJCpZT534Gpz
|
83
|
+
W7qHwzjV+d13IziCHdi6+DD5eavYzBqY8QzjlOXbmIlY7dJUCwXTECUfirc6kH86
|
84
|
+
CS8fXZTke4QYZ55VnrOomB4QGqP371kwBETnhlhi74+pvi3jW05Z5x1tVMwuugyz
|
85
|
+
zkseZp1VYmJq5SHNFZ/pnAQLE9gUDTb6UWcPBwQh9Sw+7ahSK74lJKYm3wktyvZh
|
86
|
+
zAxbNyzs1M56yeFP6uFwJTBfNByyMAa6TGUhNkxlLcYjxKbVmoAnKCVM8t41TlLv
|
87
|
+
/a0ki8iQxqvphVLufksR9IpN6d3F15j6GeyVtxBEv04iv4vbuKthWytb+gjX4bI8
|
88
|
+
CAo9jGHevmtdiw/SbeKx2YBM1MF6eua37rFMooOBj4X7VfQCyS+crNsOQn8nJGah
|
89
|
+
YbzUDCCgnX+pqN9iZvXisMS79wVyD5DyISFDvT/5jY7IXxPibxr10P/8lfW1d72u
|
90
|
+
xyI2UiZKZpyHCt4k47yMq4KQGLGuhxJ6q6O3bi2aXRuz8bLqTBLca9dmx9wZFvRh
|
91
|
+
6jS/SKEg7eFcY0xbb6RVIv1UwGDYfQARAQABwsFfBBgBCAAJBQJW/BCrAhsMAAoJ
|
92
|
+
EPFlbyTHTNHYEBIQAJhFTh1u34Q+5bnfiM2dAdCr6T6w4Y1v9ePiIYdSImeseJS2
|
93
|
+
yRglpLcMjW0uEA9KXiRtC/Nm/ClnqYJzCKeIaweHqH6dIgJKaXZFt1Uaia7X9tDD
|
94
|
+
wqALGu97irUrrV1Kh9IkM0J29Vid5amakrdS4mwt2uEISSnCi7pfVoEro+S7tYQ9
|
95
|
+
iH6APVIwqWvcaty3cANdwKWfUQZ6a9IQ08xqzaMhMp2VzhVrWkq3B0j2aRoZR7BN
|
96
|
+
LH2I7Z0giIM8ARjZs99aTRL+SfMEQ3sUxNLb3KWP/n1lSFbrk4HGzqUBBfczESlN
|
97
|
+
c0970C6znK0H0HD11/3BTkMuPqww+Tzex4dpMQllMEKZ3wEyd9v6ba+nj/P1FHSE
|
98
|
+
y/VN6IXzd82s1lYOonKTdmXAIROcHnb0QUzwsd/mhB3jKhEDOV2ZcBTD3yHv8m7C
|
99
|
+
9G9y4hV+7yQlnPlSg3DjBp3SS5r+sOObCIy2Ad32upoXkilWa9g7GZSuhY9kyKqe
|
100
|
+
Eba1lgXXaQykEeqx0pexkWavNnb9JaPrAZHDjUGcXrREmjEyXyElRoD4CrWXySe4
|
101
|
+
6jCuNhVVlkLGo7osefynXa/+PNjQjURtx8en7M9A1FkQuRAxE8KIZgZzYxkGl5o5
|
102
|
+
POSFCA4JUoRPDcrl/sI3fuq2dIOE/BJ2r8dV+LddiR+iukhXRwJXH8RVVEUS
|
103
|
+
=mCOI
|
104
|
+
-----END PGP PUBLIC KEY BLOCK-----
|
@@ -33,6 +33,7 @@ mysql_to_rb = {
|
|
33
33
|
"macroman" => "macRoman",
|
34
34
|
"cp852" => "CP852",
|
35
35
|
"latin7" => "ISO-8859-13",
|
36
|
+
"utf8mb3" => "UTF-8",
|
36
37
|
"utf8mb4" => "UTF-8",
|
37
38
|
"cp1251" => "Windows-1251",
|
38
39
|
"utf16" => "UTF-16",
|
@@ -55,7 +56,7 @@ encodings_with_nil = Array.new(encodings.size)
|
|
55
56
|
collations.each do |collation|
|
56
57
|
mysql_col_idx = collation[2].to_i
|
57
58
|
rb_enc = mysql_to_rb.fetch(collation[1]) do |mysql_enc|
|
58
|
-
|
59
|
+
warn "WARNING: Missing mapping for collation \"#{collation[0]}\" with encoding \"#{mysql_enc}\" and id #{mysql_col_idx}, assuming NULL"
|
59
60
|
"NULL"
|
60
61
|
end
|
61
62
|
encodings[mysql_col_idx - 1] = [mysql_col_idx, rb_enc]
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
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.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Lopez
|
8
8
|
- Aaron Stone
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-02-08 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description:
|
14
|
+
description:
|
15
15
|
email:
|
16
16
|
- seniorlopez@gmail.com
|
17
17
|
- aaron@serendipity.cx
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- lib/mysql2/version.rb
|
49
49
|
- support/3A79BD29.asc
|
50
50
|
- support/5072E1F5.asc
|
51
|
+
- support/C74CD1D8.asc
|
51
52
|
- support/libmysql.def
|
52
53
|
- support/mysql_enc_to_ruby.rb
|
53
54
|
- support/ruby_enc_to_mysql.rb
|
@@ -56,12 +57,12 @@ licenses:
|
|
56
57
|
- MIT
|
57
58
|
metadata:
|
58
59
|
bug_tracker_uri: https://github.com/brianmario/mysql2/issues
|
59
|
-
changelog_uri: https://github.com/brianmario/mysql2/releases/tag/0.5.
|
60
|
-
documentation_uri: https://www.rubydoc.info/gems/mysql2/0.5.
|
60
|
+
changelog_uri: https://github.com/brianmario/mysql2/releases/tag/0.5.6
|
61
|
+
documentation_uri: https://www.rubydoc.info/gems/mysql2/0.5.6
|
61
62
|
homepage_uri: https://github.com/brianmario/mysql2
|
62
|
-
source_code_uri: https://github.com/brianmario/mysql2/tree/0.5.
|
63
|
+
source_code_uri: https://github.com/brianmario/mysql2/tree/0.5.6
|
63
64
|
msys2_mingw_dependencies: libmariadbclient
|
64
|
-
post_install_message:
|
65
|
+
post_install_message:
|
65
66
|
rdoc_options:
|
66
67
|
- "--charset=UTF-8"
|
67
68
|
require_paths:
|
@@ -77,8 +78,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
78
|
- !ruby/object:Gem::Version
|
78
79
|
version: '0'
|
79
80
|
requirements: []
|
80
|
-
rubygems_version: 3.0.
|
81
|
-
signing_key:
|
81
|
+
rubygems_version: 3.6.0.dev
|
82
|
+
signing_key:
|
82
83
|
specification_version: 4
|
83
84
|
summary: A simple, fast Mysql library for Ruby, binding to libmysql
|
84
85
|
test_files: []
|