mysql2 0.4.2 → 0.5.2
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 +103 -59
- data/examples/eventmachine.rb +0 -2
- data/examples/threaded.rb +2 -4
- data/ext/mysql2/client.c +334 -94
- data/ext/mysql2/client.h +3 -51
- data/ext/mysql2/extconf.rb +45 -18
- data/ext/mysql2/mysql2_ext.c +2 -1
- data/ext/mysql2/mysql2_ext.h +8 -8
- data/ext/mysql2/mysql_enc_to_ruby.h +10 -0
- data/ext/mysql2/result.c +53 -94
- data/ext/mysql2/statement.c +191 -83
- data/ext/mysql2/statement.h +0 -2
- data/ext/mysql2/wait_for_single_fd.h +2 -1
- data/lib/mysql2/client.rb +50 -31
- data/lib/mysql2/em.rb +2 -4
- data/lib/mysql2/error.rb +49 -20
- data/lib/mysql2/result.rb +2 -0
- data/lib/mysql2/statement.rb +3 -9
- data/lib/mysql2/version.rb +1 -1
- data/lib/mysql2.rb +14 -15
- data/spec/configuration.yml.example +0 -6
- data/spec/em/em_spec.rb +6 -6
- data/spec/mysql2/client_spec.rb +372 -239
- data/spec/mysql2/error_spec.rb +4 -10
- data/spec/mysql2/result_spec.rb +132 -157
- data/spec/mysql2/statement_spec.rb +205 -177
- data/spec/spec_helper.rb +79 -61
- data/spec/ssl/gen_certs.sh +1 -1
- data/support/5072E1F5.asc +432 -0
- data/support/mysql_enc_to_ruby.rb +2 -2
- data/support/ruby_enc_to_mysql.rb +5 -5
- metadata +16 -14
data/ext/mysql2/client.c
CHANGED
@@ -15,24 +15,31 @@
|
|
15
15
|
#include "mysql_enc_name_to_ruby.h"
|
16
16
|
|
17
17
|
VALUE cMysql2Client;
|
18
|
-
extern VALUE mMysql2, cMysql2Error;
|
18
|
+
extern VALUE mMysql2, cMysql2Error, cMysql2TimeoutError;
|
19
19
|
static VALUE sym_id, sym_version, sym_header_version, sym_async, sym_symbolize_keys, sym_as, sym_array, sym_stream;
|
20
|
+
static VALUE sym_no_good_index_used, sym_no_index_used, sym_query_was_slow;
|
20
21
|
static ID intern_brackets, intern_merge, intern_merge_bang, intern_new_with_args;
|
21
22
|
|
22
|
-
#ifndef HAVE_RB_HASH_DUP
|
23
|
-
VALUE rb_hash_dup(VALUE other) {
|
24
|
-
return rb_funcall(rb_cHash, intern_brackets, 1, other);
|
25
|
-
}
|
26
|
-
#endif
|
27
|
-
|
28
23
|
#define REQUIRE_INITIALIZED(wrapper) \
|
29
24
|
if (!wrapper->initialized) { \
|
30
25
|
rb_raise(cMysql2Error, "MySQL client is not initialized"); \
|
31
26
|
}
|
32
27
|
|
28
|
+
#if defined(HAVE_MYSQL_NET_VIO) || defined(HAVE_ST_NET_VIO)
|
29
|
+
#define CONNECTED(wrapper) (wrapper->client->net.vio != NULL && wrapper->client->net.fd != -1)
|
30
|
+
#elif defined(HAVE_MYSQL_NET_PVIO) || defined(HAVE_ST_NET_PVIO)
|
31
|
+
#define CONNECTED(wrapper) (wrapper->client->net.pvio != NULL && wrapper->client->net.fd != -1)
|
32
|
+
#endif
|
33
|
+
|
34
|
+
#define REQUIRE_CONNECTED(wrapper) \
|
35
|
+
REQUIRE_INITIALIZED(wrapper) \
|
36
|
+
if (!CONNECTED(wrapper) && !wrapper->reconnect_enabled) { \
|
37
|
+
rb_raise(cMysql2Error, "MySQL client is not connected"); \
|
38
|
+
}
|
39
|
+
|
33
40
|
#define REQUIRE_NOT_CONNECTED(wrapper) \
|
34
41
|
REQUIRE_INITIALIZED(wrapper) \
|
35
|
-
if (wrapper
|
42
|
+
if (CONNECTED(wrapper)) { \
|
36
43
|
rb_raise(cMysql2Error, "MySQL connection is already open"); \
|
37
44
|
}
|
38
45
|
|
@@ -41,12 +48,24 @@ VALUE rb_hash_dup(VALUE other) {
|
|
41
48
|
* variable to use, but MYSQL_SERVER_VERSION gives the correct numbers when
|
42
49
|
* linking against the server itself
|
43
50
|
*/
|
44
|
-
#
|
51
|
+
#if defined(MARIADB_CLIENT_VERSION_STR)
|
52
|
+
#define MYSQL_LINK_VERSION MARIADB_CLIENT_VERSION_STR
|
53
|
+
#elif defined(LIBMYSQL_VERSION)
|
45
54
|
#define MYSQL_LINK_VERSION LIBMYSQL_VERSION
|
46
55
|
#else
|
47
56
|
#define MYSQL_LINK_VERSION MYSQL_SERVER_VERSION
|
48
57
|
#endif
|
49
58
|
|
59
|
+
/*
|
60
|
+
* compatibility with mysql-connector-c 6.1.x, and with MySQL 5.7.3 - 5.7.10.
|
61
|
+
*/
|
62
|
+
#ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE
|
63
|
+
#define SSL_MODE_DISABLED 1
|
64
|
+
#define SSL_MODE_REQUIRED 3
|
65
|
+
#define HAVE_CONST_SSL_MODE_DISABLED
|
66
|
+
#define HAVE_CONST_SSL_MODE_REQUIRED
|
67
|
+
#endif
|
68
|
+
|
50
69
|
/*
|
51
70
|
* used to pass all arguments to mysql_real_connect while inside
|
52
71
|
* rb_thread_call_without_gvl
|
@@ -83,6 +102,42 @@ struct nogvl_select_db_args {
|
|
83
102
|
char *db;
|
84
103
|
};
|
85
104
|
|
105
|
+
static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) {
|
106
|
+
unsigned long version = mysql_get_client_version();
|
107
|
+
|
108
|
+
if (version < 50703) {
|
109
|
+
rb_warn( "Your mysql client library does not support setting ssl_mode; full support comes with 5.7.11." );
|
110
|
+
return Qnil;
|
111
|
+
}
|
112
|
+
#ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE
|
113
|
+
GET_CLIENT(self);
|
114
|
+
int val = NUM2INT( setting );
|
115
|
+
if (version >= 50703 && version < 50711) {
|
116
|
+
if (val == SSL_MODE_DISABLED || val == SSL_MODE_REQUIRED) {
|
117
|
+
my_bool b = ( val == SSL_MODE_REQUIRED );
|
118
|
+
int result = mysql_options( wrapper->client, MYSQL_OPT_SSL_ENFORCE, &b );
|
119
|
+
return INT2NUM(result);
|
120
|
+
} else {
|
121
|
+
rb_warn( "MySQL client libraries between 5.7.3 and 5.7.10 only support SSL_MODE_DISABLED and SSL_MODE_REQUIRED" );
|
122
|
+
return Qnil;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
#endif
|
126
|
+
#ifdef FULL_SSL_MODE_SUPPORT
|
127
|
+
GET_CLIENT(self);
|
128
|
+
int val = NUM2INT( setting );
|
129
|
+
|
130
|
+
if (val != SSL_MODE_DISABLED && val != SSL_MODE_PREFERRED && val != SSL_MODE_REQUIRED && val != SSL_MODE_VERIFY_CA && val != SSL_MODE_VERIFY_IDENTITY) {
|
131
|
+
rb_raise(cMysql2Error, "ssl_mode= takes DISABLED, PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY, you passed: %d", val );
|
132
|
+
}
|
133
|
+
int result = mysql_options( wrapper->client, MYSQL_OPT_SSL_MODE, &val );
|
134
|
+
|
135
|
+
return INT2NUM(result);
|
136
|
+
#endif
|
137
|
+
#ifdef NO_SSL_MODE_SUPPORT
|
138
|
+
return Qnil;
|
139
|
+
#endif
|
140
|
+
}
|
86
141
|
/*
|
87
142
|
* non-blocking mysql_*() functions that we won't be wrapping since
|
88
143
|
* they do not appear to hit the network nor issue any interruptible
|
@@ -118,10 +173,8 @@ static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) {
|
|
118
173
|
VALUE rb_sql_state = rb_tainted_str_new2(mysql_sqlstate(wrapper->client));
|
119
174
|
VALUE e;
|
120
175
|
|
121
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
122
176
|
rb_enc_associate(rb_error_msg, rb_utf8_encoding());
|
123
177
|
rb_enc_associate(rb_sql_state, rb_usascii_encoding());
|
124
|
-
#endif
|
125
178
|
|
126
179
|
e = rb_funcall(cMysql2Error, intern_new_with_args, 4,
|
127
180
|
rb_error_msg,
|
@@ -211,11 +264,10 @@ static VALUE invalidate_fd(int clientfd)
|
|
211
264
|
static void *nogvl_close(void *ptr) {
|
212
265
|
mysql_client_wrapper *wrapper = ptr;
|
213
266
|
|
214
|
-
if (wrapper->
|
267
|
+
if (!wrapper->closed) {
|
215
268
|
mysql_close(wrapper->client);
|
216
|
-
|
217
|
-
wrapper->
|
218
|
-
wrapper->connected = 0;
|
269
|
+
wrapper->closed = 1;
|
270
|
+
wrapper->reconnect_enabled = 0;
|
219
271
|
wrapper->active_thread = Qnil;
|
220
272
|
}
|
221
273
|
|
@@ -234,7 +286,7 @@ void decr_mysql2_client(mysql_client_wrapper *wrapper)
|
|
234
286
|
|
235
287
|
if (wrapper->refcount == 0) {
|
236
288
|
#ifndef _WIN32
|
237
|
-
if (wrapper->
|
289
|
+
if (CONNECTED(wrapper) && !wrapper->automatic_close) {
|
238
290
|
/* The client is being garbage collected while connected. Prevent
|
239
291
|
* mysql_close() from sending a mysql-QUIT or from calling shutdown() on
|
240
292
|
* the socket by invalidating it. invalidate_fd() will drop this
|
@@ -246,10 +298,12 @@ void decr_mysql2_client(mysql_client_wrapper *wrapper)
|
|
246
298
|
fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely\n");
|
247
299
|
close(wrapper->client->net.fd);
|
248
300
|
}
|
301
|
+
wrapper->client->net.fd = -1;
|
249
302
|
}
|
250
303
|
#endif
|
251
304
|
|
252
305
|
nogvl_close(wrapper);
|
306
|
+
xfree(wrapper->client);
|
253
307
|
xfree(wrapper);
|
254
308
|
}
|
255
309
|
}
|
@@ -259,13 +313,14 @@ static VALUE allocate(VALUE klass) {
|
|
259
313
|
mysql_client_wrapper * wrapper;
|
260
314
|
obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
|
261
315
|
wrapper->encoding = Qnil;
|
262
|
-
|
316
|
+
wrapper->active_thread = Qnil;
|
317
|
+
wrapper->automatic_close = 1;
|
263
318
|
wrapper->server_version = 0;
|
264
319
|
wrapper->reconnect_enabled = 0;
|
265
320
|
wrapper->connect_timeout = 0;
|
266
|
-
wrapper->connected = 0; /* means that a database connection is open */
|
267
321
|
wrapper->initialized = 0; /* means that that the wrapper is initialized */
|
268
322
|
wrapper->refcount = 1;
|
323
|
+
wrapper->closed = 0;
|
269
324
|
wrapper->client = (MYSQL*)xmalloc(sizeof(MYSQL));
|
270
325
|
|
271
326
|
return obj;
|
@@ -295,9 +350,7 @@ static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) {
|
|
295
350
|
return str;
|
296
351
|
} else {
|
297
352
|
rb_str = rb_str_new((const char*)newStr, newLen);
|
298
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
299
353
|
rb_enc_copy(rb_str, str);
|
300
|
-
#endif
|
301
354
|
xfree(newStr);
|
302
355
|
return rb_str;
|
303
356
|
}
|
@@ -324,14 +377,43 @@ static VALUE rb_mysql_info(VALUE self) {
|
|
324
377
|
}
|
325
378
|
|
326
379
|
rb_str = rb_str_new2(info);
|
327
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
328
380
|
rb_enc_associate(rb_str, rb_utf8_encoding());
|
329
|
-
#endif
|
330
381
|
|
331
382
|
return rb_str;
|
332
383
|
}
|
333
384
|
|
334
|
-
static VALUE
|
385
|
+
static VALUE rb_mysql_get_ssl_cipher(VALUE self)
|
386
|
+
{
|
387
|
+
const char *cipher;
|
388
|
+
VALUE rb_str;
|
389
|
+
GET_CLIENT(self);
|
390
|
+
|
391
|
+
cipher = mysql_get_ssl_cipher(wrapper->client);
|
392
|
+
|
393
|
+
if (cipher == NULL) {
|
394
|
+
return Qnil;
|
395
|
+
}
|
396
|
+
|
397
|
+
rb_str = rb_str_new2(cipher);
|
398
|
+
rb_enc_associate(rb_str, rb_utf8_encoding());
|
399
|
+
|
400
|
+
return rb_str;
|
401
|
+
}
|
402
|
+
|
403
|
+
#ifdef CLIENT_CONNECT_ATTRS
|
404
|
+
static int opt_connect_attr_add_i(VALUE key, VALUE value, VALUE arg)
|
405
|
+
{
|
406
|
+
mysql_client_wrapper *wrapper = (mysql_client_wrapper *)arg;
|
407
|
+
rb_encoding *enc = rb_to_encoding(wrapper->encoding);
|
408
|
+
key = rb_str_export_to_enc(key, enc);
|
409
|
+
value = rb_str_export_to_enc(value, enc);
|
410
|
+
|
411
|
+
mysql_options4(wrapper->client, MYSQL_OPT_CONNECT_ATTR_ADD, StringValueCStr(key), StringValueCStr(value));
|
412
|
+
return ST_CONTINUE;
|
413
|
+
}
|
414
|
+
#endif
|
415
|
+
|
416
|
+
static VALUE rb_mysql_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags, VALUE conn_attrs) {
|
335
417
|
struct nogvl_connect_args args;
|
336
418
|
time_t start_time, end_time, elapsed_time, connect_timeout;
|
337
419
|
VALUE rv;
|
@@ -346,6 +428,11 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
|
|
346
428
|
args.mysql = wrapper->client;
|
347
429
|
args.client_flag = NUM2ULONG(flags);
|
348
430
|
|
431
|
+
#ifdef CLIENT_CONNECT_ATTRS
|
432
|
+
mysql_options(wrapper->client, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
433
|
+
rb_hash_foreach(conn_attrs, opt_connect_attr_add_i, (VALUE)wrapper);
|
434
|
+
#endif
|
435
|
+
|
349
436
|
if (wrapper->connect_timeout)
|
350
437
|
time(&start_time);
|
351
438
|
rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0);
|
@@ -372,33 +459,41 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
|
|
372
459
|
if (wrapper->connect_timeout)
|
373
460
|
mysql_options(wrapper->client, MYSQL_OPT_CONNECT_TIMEOUT, &wrapper->connect_timeout);
|
374
461
|
if (rv == Qfalse)
|
375
|
-
|
462
|
+
rb_raise_mysql2_error(wrapper);
|
376
463
|
}
|
377
464
|
|
378
465
|
wrapper->server_version = mysql_get_server_version(wrapper->client);
|
379
|
-
wrapper->connected = 1;
|
380
466
|
return self;
|
381
467
|
}
|
382
468
|
|
383
469
|
/*
|
384
|
-
*
|
385
|
-
*
|
386
|
-
*
|
387
|
-
*
|
470
|
+
* Immediately disconnect from the server; normally the garbage collector
|
471
|
+
* will disconnect automatically when a connection is no longer needed.
|
472
|
+
* Explicitly closing this will free up server resources sooner than waiting
|
473
|
+
* for the garbage collector.
|
388
474
|
*
|
389
|
-
* @
|
390
|
-
* @return [void]
|
475
|
+
* @return [nil]
|
391
476
|
*/
|
392
477
|
static VALUE rb_mysql_client_close(VALUE self) {
|
393
478
|
GET_CLIENT(self);
|
394
479
|
|
395
|
-
if (wrapper->
|
480
|
+
if (wrapper->client) {
|
396
481
|
rb_thread_call_without_gvl(nogvl_close, wrapper, RUBY_UBF_IO, 0);
|
397
482
|
}
|
398
483
|
|
399
484
|
return Qnil;
|
400
485
|
}
|
401
486
|
|
487
|
+
/* call-seq:
|
488
|
+
* client.closed?
|
489
|
+
*
|
490
|
+
* @return [Boolean]
|
491
|
+
*/
|
492
|
+
static VALUE rb_mysql_client_closed(VALUE self) {
|
493
|
+
GET_CLIENT(self);
|
494
|
+
return CONNECTED(wrapper) ? Qfalse : Qtrue;
|
495
|
+
}
|
496
|
+
|
402
497
|
/*
|
403
498
|
* mysql_send_query is unlikely to block since most queries are small
|
404
499
|
* enough to fit in a socket buffer, but sometimes large UPDATE and
|
@@ -418,8 +513,8 @@ static VALUE do_send_query(void *args) {
|
|
418
513
|
mysql_client_wrapper *wrapper = query_args->wrapper;
|
419
514
|
if ((VALUE)rb_thread_call_without_gvl(nogvl_send_query, args, RUBY_UBF_IO, 0) == Qfalse) {
|
420
515
|
/* an error occurred, we're not active anymore */
|
421
|
-
|
422
|
-
|
516
|
+
wrapper->active_thread = Qnil;
|
517
|
+
rb_raise_mysql2_error(wrapper);
|
423
518
|
}
|
424
519
|
return Qnil;
|
425
520
|
}
|
@@ -448,7 +543,7 @@ static void *nogvl_do_result(void *ptr, char use_result) {
|
|
448
543
|
|
449
544
|
/* once our result is stored off, this connection is
|
450
545
|
ready for another command to be issued */
|
451
|
-
|
546
|
+
wrapper->active_thread = Qnil;
|
452
547
|
|
453
548
|
return result;
|
454
549
|
}
|
@@ -480,8 +575,8 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
|
|
480
575
|
REQUIRE_CONNECTED(wrapper);
|
481
576
|
if ((VALUE)rb_thread_call_without_gvl(nogvl_read_query_result, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
|
482
577
|
/* an error occurred, mark this connection inactive */
|
483
|
-
|
484
|
-
|
578
|
+
wrapper->active_thread = Qnil;
|
579
|
+
rb_raise_mysql2_error(wrapper);
|
485
580
|
}
|
486
581
|
|
487
582
|
is_streaming = rb_hash_aref(rb_iv_get(self, "@current_query_options"), sym_stream);
|
@@ -493,18 +588,21 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
|
|
493
588
|
|
494
589
|
if (result == NULL) {
|
495
590
|
if (mysql_errno(wrapper->client) != 0) {
|
496
|
-
|
591
|
+
wrapper->active_thread = Qnil;
|
497
592
|
rb_raise_mysql2_error(wrapper);
|
498
593
|
}
|
499
594
|
/* no data and no error, so query was not a SELECT */
|
500
595
|
return Qnil;
|
501
596
|
}
|
502
597
|
|
598
|
+
// Duplicate the options hash and put the copy in the Result object
|
503
599
|
current = rb_hash_dup(rb_iv_get(self, "@current_query_options"));
|
504
600
|
(void)RB_GC_GUARD(current);
|
505
601
|
Check_Type(current, T_HASH);
|
506
602
|
resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result, Qnil);
|
507
603
|
|
604
|
+
rb_mysql_set_server_query_flags(wrapper->client, resultObj);
|
605
|
+
|
508
606
|
return resultObj;
|
509
607
|
}
|
510
608
|
|
@@ -517,15 +615,17 @@ struct async_query_args {
|
|
517
615
|
static VALUE disconnect_and_raise(VALUE self, VALUE error) {
|
518
616
|
GET_CLIENT(self);
|
519
617
|
|
520
|
-
|
521
|
-
wrapper->connected = 0;
|
618
|
+
wrapper->active_thread = Qnil;
|
522
619
|
|
523
620
|
/* Invalidate the MySQL socket to prevent further communication.
|
524
621
|
* The GC will come along later and call mysql_close to free it.
|
525
622
|
*/
|
526
|
-
if (
|
527
|
-
|
528
|
-
|
623
|
+
if (CONNECTED(wrapper)) {
|
624
|
+
if (invalidate_fd(wrapper->client->net.fd) == Qfalse) {
|
625
|
+
fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely, closing unsafely\n");
|
626
|
+
close(wrapper->client->net.fd);
|
627
|
+
}
|
628
|
+
wrapper->client->net.fd = -1;
|
529
629
|
}
|
530
630
|
|
531
631
|
rb_exc_raise(error);
|
@@ -560,7 +660,7 @@ static VALUE do_query(void *args) {
|
|
560
660
|
retval = rb_wait_for_single_fd(async_args->fd, RB_WAITFD_IN, tvp);
|
561
661
|
|
562
662
|
if (retval == 0) {
|
563
|
-
rb_raise(
|
663
|
+
rb_raise(cMysql2TimeoutError, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
|
564
664
|
}
|
565
665
|
|
566
666
|
if (retval < 0) {
|
@@ -574,26 +674,32 @@ static VALUE do_query(void *args) {
|
|
574
674
|
|
575
675
|
return Qnil;
|
576
676
|
}
|
577
|
-
#
|
578
|
-
static VALUE finish_and_mark_inactive(void *args) {
|
579
|
-
VALUE self = args;
|
580
|
-
MYSQL_RES *result;
|
677
|
+
#endif
|
581
678
|
|
679
|
+
static VALUE disconnect_and_mark_inactive(VALUE self) {
|
582
680
|
GET_CLIENT(self);
|
583
681
|
|
682
|
+
/* Check if execution terminated while result was still being read. */
|
584
683
|
if (!NIL_P(wrapper->active_thread)) {
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
684
|
+
if (CONNECTED(wrapper)) {
|
685
|
+
/* Invalidate the MySQL socket to prevent further communication. */
|
686
|
+
#ifndef _WIN32
|
687
|
+
if (invalidate_fd(wrapper->client->net.fd) == Qfalse) {
|
688
|
+
rb_warn("mysql2 failed to invalidate FD safely, closing unsafely\n");
|
689
|
+
close(wrapper->client->net.fd);
|
690
|
+
}
|
691
|
+
#else
|
692
|
+
close(wrapper->client->net.fd);
|
693
|
+
#endif
|
694
|
+
wrapper->client->net.fd = -1;
|
695
|
+
}
|
696
|
+
/* Skip mysql client check performed before command execution. */
|
697
|
+
wrapper->client->status = MYSQL_STATUS_READY;
|
698
|
+
wrapper->active_thread = Qnil;
|
592
699
|
}
|
593
700
|
|
594
701
|
return Qnil;
|
595
702
|
}
|
596
|
-
#endif
|
597
703
|
|
598
704
|
void rb_mysql_client_set_active_thread(VALUE self) {
|
599
705
|
VALUE thread_current = rb_thread_current();
|
@@ -649,7 +755,7 @@ static VALUE rb_mysql_client_abandon_results(VALUE self) {
|
|
649
755
|
* Query the database with +sql+, with optional +options+. For the possible
|
650
756
|
* options, see default_query_options on the Mysql2::Client class.
|
651
757
|
*/
|
652
|
-
static VALUE
|
758
|
+
static VALUE rb_mysql_query(VALUE self, VALUE sql, VALUE current) {
|
653
759
|
#ifndef _WIN32
|
654
760
|
struct async_query_args async_args;
|
655
761
|
#endif
|
@@ -664,12 +770,8 @@ static VALUE rb_query(VALUE self, VALUE sql, VALUE current) {
|
|
664
770
|
rb_iv_set(self, "@current_query_options", current);
|
665
771
|
|
666
772
|
Check_Type(sql, T_STRING);
|
667
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
668
773
|
/* ensure the string is in the encoding the connection is expecting */
|
669
774
|
args.sql = rb_str_export_to_enc(sql, rb_to_encoding(wrapper->encoding));
|
670
|
-
#else
|
671
|
-
args.sql = sql;
|
672
|
-
#endif
|
673
775
|
args.sql_ptr = RSTRING_PTR(args.sql);
|
674
776
|
args.sql_len = RSTRING_LEN(args.sql);
|
675
777
|
args.wrapper = wrapper;
|
@@ -687,13 +789,13 @@ static VALUE rb_query(VALUE self, VALUE sql, VALUE current) {
|
|
687
789
|
|
688
790
|
rb_rescue2(do_query, (VALUE)&async_args, disconnect_and_raise, self, rb_eException, (VALUE)0);
|
689
791
|
|
690
|
-
return rb_mysql_client_async_result
|
792
|
+
return rb_ensure(rb_mysql_client_async_result, self, disconnect_and_mark_inactive, self);
|
691
793
|
}
|
692
794
|
#else
|
693
795
|
do_send_query(&args);
|
694
796
|
|
695
797
|
/* this will just block until the result is ready */
|
696
|
-
return rb_ensure(rb_mysql_client_async_result, self,
|
798
|
+
return rb_ensure(rb_mysql_client_async_result, self, disconnect_and_mark_inactive, self);
|
697
799
|
#endif
|
698
800
|
}
|
699
801
|
|
@@ -706,20 +808,16 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
|
|
706
808
|
unsigned char *newStr;
|
707
809
|
VALUE rb_str;
|
708
810
|
unsigned long newLen, oldLen;
|
709
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
710
811
|
rb_encoding *default_internal_enc;
|
711
812
|
rb_encoding *conn_enc;
|
712
|
-
#endif
|
713
813
|
GET_CLIENT(self);
|
714
814
|
|
715
815
|
REQUIRE_CONNECTED(wrapper);
|
716
816
|
Check_Type(str, T_STRING);
|
717
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
718
817
|
default_internal_enc = rb_default_internal_encoding();
|
719
818
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
720
819
|
/* ensure the string is in the encoding the connection is expecting */
|
721
820
|
str = rb_str_export_to_enc(str, conn_enc);
|
722
|
-
#endif
|
723
821
|
|
724
822
|
oldLen = RSTRING_LEN(str);
|
725
823
|
newStr = xmalloc(oldLen*2+1);
|
@@ -727,21 +825,17 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
|
|
727
825
|
newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, RSTRING_PTR(str), oldLen);
|
728
826
|
if (newLen == oldLen) {
|
729
827
|
/* no need to return a new ruby string if nothing changed */
|
730
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
731
828
|
if (default_internal_enc) {
|
732
829
|
str = rb_str_export_to_enc(str, default_internal_enc);
|
733
830
|
}
|
734
|
-
#endif
|
735
831
|
xfree(newStr);
|
736
832
|
return str;
|
737
833
|
} else {
|
738
834
|
rb_str = rb_str_new((const char*)newStr, newLen);
|
739
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
740
835
|
rb_enc_associate(rb_str, conn_enc);
|
741
836
|
if (default_internal_enc) {
|
742
837
|
rb_str = rb_str_export_to_enc(rb_str, default_internal_enc);
|
743
838
|
}
|
744
|
-
#endif
|
745
839
|
xfree(newStr);
|
746
840
|
return rb_str;
|
747
841
|
}
|
@@ -787,10 +881,12 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
|
|
787
881
|
retval = &boolval;
|
788
882
|
break;
|
789
883
|
|
884
|
+
#ifdef MYSQL_SECURE_AUTH
|
790
885
|
case MYSQL_SECURE_AUTH:
|
791
886
|
boolval = (value == Qfalse ? 0 : 1);
|
792
887
|
retval = &boolval;
|
793
888
|
break;
|
889
|
+
#endif
|
794
890
|
|
795
891
|
case MYSQL_READ_DEFAULT_FILE:
|
796
892
|
charval = (const char *)StringValueCStr(value);
|
@@ -807,6 +903,13 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
|
|
807
903
|
retval = charval;
|
808
904
|
break;
|
809
905
|
|
906
|
+
#ifdef HAVE_CONST_MYSQL_ENABLE_CLEARTEXT_PLUGIN
|
907
|
+
case MYSQL_ENABLE_CLEARTEXT_PLUGIN:
|
908
|
+
boolval = (value == Qfalse ? 0 : 1);
|
909
|
+
retval = &boolval;
|
910
|
+
break;
|
911
|
+
#endif
|
912
|
+
|
810
913
|
default:
|
811
914
|
return Qfalse;
|
812
915
|
}
|
@@ -843,10 +946,8 @@ static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE klass) {
|
|
843
946
|
version = rb_str_new2(mysql_get_client_info());
|
844
947
|
header_version = rb_str_new2(MYSQL_LINK_VERSION);
|
845
948
|
|
846
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
847
949
|
rb_enc_associate(version, rb_usascii_encoding());
|
848
950
|
rb_enc_associate(header_version, rb_usascii_encoding());
|
849
|
-
#endif
|
850
951
|
|
851
952
|
rb_hash_aset(version_info, sym_id, LONG2NUM(mysql_get_client_version()));
|
852
953
|
rb_hash_aset(version_info, sym_version, version);
|
@@ -862,27 +963,21 @@ static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE klass) {
|
|
862
963
|
*/
|
863
964
|
static VALUE rb_mysql_client_server_info(VALUE self) {
|
864
965
|
VALUE version, server_info;
|
865
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
866
966
|
rb_encoding *default_internal_enc;
|
867
967
|
rb_encoding *conn_enc;
|
868
|
-
#endif
|
869
968
|
GET_CLIENT(self);
|
870
969
|
|
871
970
|
REQUIRE_CONNECTED(wrapper);
|
872
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
873
971
|
default_internal_enc = rb_default_internal_encoding();
|
874
972
|
conn_enc = rb_to_encoding(wrapper->encoding);
|
875
|
-
#endif
|
876
973
|
|
877
974
|
version = rb_hash_new();
|
878
975
|
rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_server_version(wrapper->client)));
|
879
976
|
server_info = rb_str_new2(mysql_get_server_info(wrapper->client));
|
880
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
881
977
|
rb_enc_associate(server_info, conn_enc);
|
882
978
|
if (default_internal_enc) {
|
883
979
|
server_info = rb_str_export_to_enc(server_info, default_internal_enc);
|
884
980
|
}
|
885
|
-
#endif
|
886
981
|
rb_hash_aset(version, sym_version, server_info);
|
887
982
|
return version;
|
888
983
|
}
|
@@ -996,13 +1091,30 @@ static void *nogvl_ping(void *ptr) {
|
|
996
1091
|
static VALUE rb_mysql_client_ping(VALUE self) {
|
997
1092
|
GET_CLIENT(self);
|
998
1093
|
|
999
|
-
if (!wrapper
|
1094
|
+
if (!CONNECTED(wrapper)) {
|
1000
1095
|
return Qfalse;
|
1001
1096
|
} else {
|
1002
1097
|
return (VALUE)rb_thread_call_without_gvl(nogvl_ping, wrapper->client, RUBY_UBF_IO, 0);
|
1003
1098
|
}
|
1004
1099
|
}
|
1005
1100
|
|
1101
|
+
/* call-seq:
|
1102
|
+
* client.set_server_option(value)
|
1103
|
+
*
|
1104
|
+
* Enables or disables an option for the connection.
|
1105
|
+
* Read https://dev.mysql.com/doc/refman/5.7/en/mysql-set-server-option.html
|
1106
|
+
* for more information.
|
1107
|
+
*/
|
1108
|
+
static VALUE rb_mysql_client_set_server_option(VALUE self, VALUE value) {
|
1109
|
+
GET_CLIENT(self);
|
1110
|
+
|
1111
|
+
if (mysql_set_server_option(wrapper->client, NUM2INT(value)) == 0) {
|
1112
|
+
return Qtrue;
|
1113
|
+
} else {
|
1114
|
+
return Qfalse;
|
1115
|
+
}
|
1116
|
+
}
|
1117
|
+
|
1006
1118
|
/* call-seq:
|
1007
1119
|
* client.more_results?
|
1008
1120
|
*
|
@@ -1011,10 +1123,10 @@ static VALUE rb_mysql_client_ping(VALUE self) {
|
|
1011
1123
|
static VALUE rb_mysql_client_more_results(VALUE self)
|
1012
1124
|
{
|
1013
1125
|
GET_CLIENT(self);
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1126
|
+
if (mysql_more_results(wrapper->client) == 0)
|
1127
|
+
return Qfalse;
|
1128
|
+
else
|
1129
|
+
return Qtrue;
|
1018
1130
|
}
|
1019
1131
|
|
1020
1132
|
/* call-seq:
|
@@ -1061,6 +1173,7 @@ static VALUE rb_mysql_client_store_result(VALUE self)
|
|
1061
1173
|
return Qnil;
|
1062
1174
|
}
|
1063
1175
|
|
1176
|
+
// Duplicate the options hash and put the copy in the Result object
|
1064
1177
|
current = rb_hash_dup(rb_iv_get(self, "@current_query_options"));
|
1065
1178
|
(void)RB_GC_GUARD(current);
|
1066
1179
|
Check_Type(current, T_HASH);
|
@@ -1069,7 +1182,6 @@ static VALUE rb_mysql_client_store_result(VALUE self)
|
|
1069
1182
|
return resultObj;
|
1070
1183
|
}
|
1071
1184
|
|
1072
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
1073
1185
|
/* call-seq:
|
1074
1186
|
* client.encoding
|
1075
1187
|
*
|
@@ -1079,7 +1191,39 @@ static VALUE rb_mysql_client_encoding(VALUE self) {
|
|
1079
1191
|
GET_CLIENT(self);
|
1080
1192
|
return wrapper->encoding;
|
1081
1193
|
}
|
1194
|
+
|
1195
|
+
/* call-seq:
|
1196
|
+
* client.automatic_close?
|
1197
|
+
*
|
1198
|
+
* @return [Boolean]
|
1199
|
+
*/
|
1200
|
+
static VALUE get_automatic_close(VALUE self) {
|
1201
|
+
GET_CLIENT(self);
|
1202
|
+
return wrapper->automatic_close ? Qtrue : Qfalse;
|
1203
|
+
}
|
1204
|
+
|
1205
|
+
/* call-seq:
|
1206
|
+
* client.automatic_close = false
|
1207
|
+
*
|
1208
|
+
* Set this to +false+ to leave the connection open after it is garbage
|
1209
|
+
* collected. To avoid "Aborted connection" errors on the server, explicitly
|
1210
|
+
* call +close+ when the connection is no longer needed.
|
1211
|
+
*
|
1212
|
+
* @see http://dev.mysql.com/doc/en/communication-errors.html
|
1213
|
+
*/
|
1214
|
+
static VALUE set_automatic_close(VALUE self, VALUE value) {
|
1215
|
+
GET_CLIENT(self);
|
1216
|
+
if (RTEST(value)) {
|
1217
|
+
wrapper->automatic_close = 1;
|
1218
|
+
} else {
|
1219
|
+
#ifndef _WIN32
|
1220
|
+
wrapper->automatic_close = 0;
|
1221
|
+
#else
|
1222
|
+
rb_warn("Connections are always closed by garbage collector on Windows");
|
1082
1223
|
#endif
|
1224
|
+
}
|
1225
|
+
return value;
|
1226
|
+
}
|
1083
1227
|
|
1084
1228
|
/* call-seq:
|
1085
1229
|
* client.reconnect = true
|
@@ -1132,16 +1276,14 @@ static VALUE set_write_timeout(VALUE self, VALUE value) {
|
|
1132
1276
|
|
1133
1277
|
static VALUE set_charset_name(VALUE self, VALUE value) {
|
1134
1278
|
char *charset_name;
|
1135
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
1136
1279
|
const struct mysql2_mysql_enc_name_to_rb_map *mysql2rb;
|
1137
1280
|
rb_encoding *enc;
|
1138
1281
|
VALUE rb_enc;
|
1139
|
-
#endif
|
1140
1282
|
GET_CLIENT(self);
|
1141
1283
|
|
1284
|
+
Check_Type(value, T_STRING);
|
1142
1285
|
charset_name = RSTRING_PTR(value);
|
1143
1286
|
|
1144
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
1145
1287
|
mysql2rb = mysql2_mysql_enc_name_to_rb(charset_name, (unsigned int)RSTRING_LEN(value));
|
1146
1288
|
if (mysql2rb == NULL || mysql2rb->rb_name == NULL) {
|
1147
1289
|
VALUE inspect = rb_inspect(value);
|
@@ -1151,7 +1293,6 @@ static VALUE set_charset_name(VALUE self, VALUE value) {
|
|
1151
1293
|
rb_enc = rb_enc_from_encoding(enc);
|
1152
1294
|
wrapper->encoding = rb_enc;
|
1153
1295
|
}
|
1154
|
-
#endif
|
1155
1296
|
|
1156
1297
|
if (mysql_options(wrapper->client, MYSQL_SET_CHARSET_NAME, charset_name)) {
|
1157
1298
|
/* TODO: warning - unable to set charset */
|
@@ -1175,7 +1316,12 @@ static VALUE set_ssl_options(VALUE self, VALUE key, VALUE cert, VALUE ca, VALUE
|
|
1175
1316
|
}
|
1176
1317
|
|
1177
1318
|
static VALUE set_secure_auth(VALUE self, VALUE value) {
|
1319
|
+
/* This option was deprecated in MySQL 5.x and removed in MySQL 8.0 */
|
1320
|
+
#ifdef MYSQL_SECURE_AUTH
|
1178
1321
|
return _mysql_client_options(self, MYSQL_SECURE_AUTH, value);
|
1322
|
+
#else
|
1323
|
+
return Qfalse;
|
1324
|
+
#endif
|
1179
1325
|
}
|
1180
1326
|
|
1181
1327
|
static VALUE set_read_default_file(VALUE self, VALUE value) {
|
@@ -1190,12 +1336,20 @@ static VALUE set_init_command(VALUE self, VALUE value) {
|
|
1190
1336
|
return _mysql_client_options(self, MYSQL_INIT_COMMAND, value);
|
1191
1337
|
}
|
1192
1338
|
|
1339
|
+
static VALUE set_enable_cleartext_plugin(VALUE self, VALUE value) {
|
1340
|
+
#ifdef HAVE_CONST_MYSQL_ENABLE_CLEARTEXT_PLUGIN
|
1341
|
+
return _mysql_client_options(self, MYSQL_ENABLE_CLEARTEXT_PLUGIN, value);
|
1342
|
+
#else
|
1343
|
+
rb_raise(cMysql2Error, "enable-cleartext-plugin is not available, you may need a newer MySQL client library");
|
1344
|
+
#endif
|
1345
|
+
}
|
1346
|
+
|
1193
1347
|
static VALUE initialize_ext(VALUE self) {
|
1194
1348
|
GET_CLIENT(self);
|
1195
1349
|
|
1196
1350
|
if ((VALUE)rb_thread_call_without_gvl(nogvl_init, wrapper, RUBY_UBF_IO, 0) == Qfalse) {
|
1197
1351
|
/* TODO: warning - not enough memory? */
|
1198
|
-
|
1352
|
+
rb_raise_mysql2_error(wrapper);
|
1199
1353
|
}
|
1200
1354
|
|
1201
1355
|
wrapper->initialized = 1;
|
@@ -1250,6 +1404,7 @@ void init_mysql2_client() {
|
|
1250
1404
|
rb_define_singleton_method(cMysql2Client, "info", rb_mysql_client_info, 0);
|
1251
1405
|
|
1252
1406
|
rb_define_method(cMysql2Client, "close", rb_mysql_client_close, 0);
|
1407
|
+
rb_define_method(cMysql2Client, "closed?", rb_mysql_client_closed, 0);
|
1253
1408
|
rb_define_method(cMysql2Client, "abandon_results!", rb_mysql_client_abandon_results, 0);
|
1254
1409
|
rb_define_method(cMysql2Client, "escape", rb_mysql_client_real_escape, 1);
|
1255
1410
|
rb_define_method(cMysql2Client, "server_info", rb_mysql_client_server_info, 0);
|
@@ -1261,15 +1416,17 @@ void init_mysql2_client() {
|
|
1261
1416
|
rb_define_method(cMysql2Client, "thread_id", rb_mysql_client_thread_id, 0);
|
1262
1417
|
rb_define_method(cMysql2Client, "ping", rb_mysql_client_ping, 0);
|
1263
1418
|
rb_define_method(cMysql2Client, "select_db", rb_mysql_client_select_db, 1);
|
1419
|
+
rb_define_method(cMysql2Client, "set_server_option", rb_mysql_client_set_server_option, 1);
|
1264
1420
|
rb_define_method(cMysql2Client, "more_results?", rb_mysql_client_more_results, 0);
|
1265
1421
|
rb_define_method(cMysql2Client, "next_result", rb_mysql_client_next_result, 0);
|
1266
1422
|
rb_define_method(cMysql2Client, "store_result", rb_mysql_client_store_result, 0);
|
1423
|
+
rb_define_method(cMysql2Client, "automatic_close?", get_automatic_close, 0);
|
1424
|
+
rb_define_method(cMysql2Client, "automatic_close=", set_automatic_close, 1);
|
1267
1425
|
rb_define_method(cMysql2Client, "reconnect=", set_reconnect, 1);
|
1268
1426
|
rb_define_method(cMysql2Client, "warning_count", rb_mysql_client_warning_count, 0);
|
1269
1427
|
rb_define_method(cMysql2Client, "query_info_string", rb_mysql_info, 0);
|
1270
|
-
|
1428
|
+
rb_define_method(cMysql2Client, "ssl_cipher", rb_mysql_get_ssl_cipher, 0);
|
1271
1429
|
rb_define_method(cMysql2Client, "encoding", rb_mysql_client_encoding, 0);
|
1272
|
-
#endif
|
1273
1430
|
|
1274
1431
|
rb_define_private_method(cMysql2Client, "connect_timeout=", set_connect_timeout, 1);
|
1275
1432
|
rb_define_private_method(cMysql2Client, "read_timeout=", set_read_timeout, 1);
|
@@ -1281,9 +1438,11 @@ void init_mysql2_client() {
|
|
1281
1438
|
rb_define_private_method(cMysql2Client, "default_group=", set_read_default_group, 1);
|
1282
1439
|
rb_define_private_method(cMysql2Client, "init_command=", set_init_command, 1);
|
1283
1440
|
rb_define_private_method(cMysql2Client, "ssl_set", set_ssl_options, 5);
|
1441
|
+
rb_define_private_method(cMysql2Client, "ssl_mode=", rb_set_ssl_mode_option, 1);
|
1442
|
+
rb_define_private_method(cMysql2Client, "enable_cleartext_plugin=", set_enable_cleartext_plugin, 1);
|
1284
1443
|
rb_define_private_method(cMysql2Client, "initialize_ext", initialize_ext, 0);
|
1285
|
-
rb_define_private_method(cMysql2Client, "connect",
|
1286
|
-
rb_define_private_method(cMysql2Client, "_query",
|
1444
|
+
rb_define_private_method(cMysql2Client, "connect", rb_mysql_connect, 8);
|
1445
|
+
rb_define_private_method(cMysql2Client, "_query", rb_mysql_query, 2);
|
1287
1446
|
|
1288
1447
|
sym_id = ID2SYM(rb_intern("id"));
|
1289
1448
|
sym_version = ID2SYM(rb_intern("version"));
|
@@ -1294,6 +1453,10 @@ void init_mysql2_client() {
|
|
1294
1453
|
sym_array = ID2SYM(rb_intern("array"));
|
1295
1454
|
sym_stream = ID2SYM(rb_intern("stream"));
|
1296
1455
|
|
1456
|
+
sym_no_good_index_used = ID2SYM(rb_intern("no_good_index_used"));
|
1457
|
+
sym_no_index_used = ID2SYM(rb_intern("no_index_used"));
|
1458
|
+
sym_query_was_slow = ID2SYM(rb_intern("query_was_slow"));
|
1459
|
+
|
1297
1460
|
intern_brackets = rb_intern("[]");
|
1298
1461
|
intern_merge = rb_intern("merge");
|
1299
1462
|
intern_merge_bang = rb_intern("merge!");
|
@@ -1302,6 +1465,10 @@ void init_mysql2_client() {
|
|
1302
1465
|
#ifdef CLIENT_LONG_PASSWORD
|
1303
1466
|
rb_const_set(cMysql2Client, rb_intern("LONG_PASSWORD"),
|
1304
1467
|
LONG2NUM(CLIENT_LONG_PASSWORD));
|
1468
|
+
#else
|
1469
|
+
/* HACK because MariaDB 10.2 no longer defines this constant,
|
1470
|
+
* but we're using it in our default connection flags. */
|
1471
|
+
rb_const_set(cMysql2Client, rb_intern("LONG_PASSWORD"), INT2NUM(0));
|
1305
1472
|
#endif
|
1306
1473
|
|
1307
1474
|
#ifdef CLIENT_FOUND_ROWS
|
@@ -1379,6 +1546,16 @@ void init_mysql2_client() {
|
|
1379
1546
|
rb_const_set(cMysql2Client, rb_intern("SECURE_CONNECTION"), LONG2NUM(0));
|
1380
1547
|
#endif
|
1381
1548
|
|
1549
|
+
#ifdef HAVE_CONST_MYSQL_OPTION_MULTI_STATEMENTS_ON
|
1550
|
+
rb_const_set(cMysql2Client, rb_intern("OPTION_MULTI_STATEMENTS_ON"),
|
1551
|
+
LONG2NUM(MYSQL_OPTION_MULTI_STATEMENTS_ON));
|
1552
|
+
#endif
|
1553
|
+
|
1554
|
+
#ifdef HAVE_CONST_MYSQL_OPTION_MULTI_STATEMENTS_OFF
|
1555
|
+
rb_const_set(cMysql2Client, rb_intern("OPTION_MULTI_STATEMENTS_OFF"),
|
1556
|
+
LONG2NUM(MYSQL_OPTION_MULTI_STATEMENTS_OFF));
|
1557
|
+
#endif
|
1558
|
+
|
1382
1559
|
#ifdef CLIENT_MULTI_STATEMENTS
|
1383
1560
|
rb_const_set(cMysql2Client, rb_intern("MULTI_STATEMENTS"),
|
1384
1561
|
LONG2NUM(CLIENT_MULTI_STATEMENTS));
|
@@ -1408,4 +1585,67 @@ void init_mysql2_client() {
|
|
1408
1585
|
rb_const_set(cMysql2Client, rb_intern("BASIC_FLAGS"),
|
1409
1586
|
LONG2NUM(CLIENT_BASIC_FLAGS));
|
1410
1587
|
#endif
|
1588
|
+
|
1589
|
+
#ifdef CLIENT_CONNECT_ATTRS
|
1590
|
+
rb_const_set(cMysql2Client, rb_intern("CONNECT_ATTRS"),
|
1591
|
+
LONG2NUM(CLIENT_CONNECT_ATTRS));
|
1592
|
+
#else
|
1593
|
+
/* HACK because MySQL 5.5 and earlier don't define this constant,
|
1594
|
+
* but we're using it in our default connection flags. */
|
1595
|
+
rb_const_set(cMysql2Client, rb_intern("CONNECT_ATTRS"),
|
1596
|
+
INT2NUM(0));
|
1597
|
+
#endif
|
1598
|
+
|
1599
|
+
#if defined(FULL_SSL_MODE_SUPPORT) // MySQL 5.7.11 and above
|
1600
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED));
|
1601
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_PREFERRED"), INT2NUM(SSL_MODE_PREFERRED));
|
1602
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(SSL_MODE_REQUIRED));
|
1603
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_CA"), INT2NUM(SSL_MODE_VERIFY_CA));
|
1604
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_IDENTITY"), INT2NUM(SSL_MODE_VERIFY_IDENTITY));
|
1605
|
+
#elif defined(HAVE_CONST_MYSQL_OPT_SSL_ENFORCE) // MySQL 5.7.3 - 5.7.10
|
1606
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED));
|
1607
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(SSL_MODE_REQUIRED));
|
1608
|
+
#endif
|
1609
|
+
|
1610
|
+
#ifndef HAVE_CONST_SSL_MODE_DISABLED
|
1611
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(0));
|
1612
|
+
#endif
|
1613
|
+
#ifndef HAVE_CONST_SSL_MODE_PREFERRED
|
1614
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_PREFERRED"), INT2NUM(0));
|
1615
|
+
#endif
|
1616
|
+
#ifndef HAVE_CONST_SSL_MODE_REQUIRED
|
1617
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(0));
|
1618
|
+
#endif
|
1619
|
+
#ifndef HAVE_CONST_SSL_MODE_VERIFY_CA
|
1620
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_CA"), INT2NUM(0));
|
1621
|
+
#endif
|
1622
|
+
#ifndef HAVE_CONST_SSL_MODE_VERIFY_IDENTITY
|
1623
|
+
rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_IDENTITY"), INT2NUM(0));
|
1624
|
+
#endif
|
1625
|
+
}
|
1626
|
+
|
1627
|
+
#define flag_to_bool(f) ((client->server_status & f) ? Qtrue : Qfalse)
|
1628
|
+
|
1629
|
+
void rb_mysql_set_server_query_flags(MYSQL *client, VALUE result) {
|
1630
|
+
VALUE server_flags = rb_hash_new();
|
1631
|
+
|
1632
|
+
#ifdef HAVE_CONST_SERVER_QUERY_NO_GOOD_INDEX_USED
|
1633
|
+
rb_hash_aset(server_flags, sym_no_good_index_used, flag_to_bool(SERVER_QUERY_NO_GOOD_INDEX_USED));
|
1634
|
+
#else
|
1635
|
+
rb_hash_aset(server_flags, sym_no_good_index_used, Qnil);
|
1636
|
+
#endif
|
1637
|
+
|
1638
|
+
#ifdef HAVE_CONST_SERVER_QUERY_NO_INDEX_USED
|
1639
|
+
rb_hash_aset(server_flags, sym_no_index_used, flag_to_bool(SERVER_QUERY_NO_INDEX_USED));
|
1640
|
+
#else
|
1641
|
+
rb_hash_aset(server_flags, sym_no_index_used, Qnil);
|
1642
|
+
#endif
|
1643
|
+
|
1644
|
+
#ifdef HAVE_CONST_SERVER_QUERY_WAS_SLOW
|
1645
|
+
rb_hash_aset(server_flags, sym_query_was_slow, flag_to_bool(SERVER_QUERY_WAS_SLOW));
|
1646
|
+
#else
|
1647
|
+
rb_hash_aset(server_flags, sym_query_was_slow, Qnil);
|
1648
|
+
#endif
|
1649
|
+
|
1650
|
+
rb_iv_set(result, "@server_flags", server_flags);
|
1411
1651
|
}
|