mysql2 0.4.10 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 75b3d925930b92cf7b1a36fa196d334e245919ac
4
- data.tar.gz: 2bbe0a78b156f8c5b59643c4d57a7ce19b764bcc
3
+ metadata.gz: a6bf072c2ecc5ecb841ac10b4f0d7af76143e1a0
4
+ data.tar.gz: 3f92fd936bed501a93ebf7d32848b89059989310
5
5
  SHA512:
6
- metadata.gz: 602f336b5ed83421862b9dec36a9ddbd477dcbacc3ef16d58d5252072dba0bc7f7a955000482414eda1d104bda72ded87f3f4c795f8b4b4d36999bc6ee171e4b
7
- data.tar.gz: 20281fda66cf4595edc05ac6a933d5f641c2f9f87771e8ace1e9de00902ecea54ddbc2d1b743c3dbd97b48c795d0ad32f9ab785e5848a4f3de92c7ddebeef659
6
+ metadata.gz: 9efb2aa011d4e0f0fd5c6bb1a088164686cb515f78c97d20121a9810f6b4bef9f9be07f7deebf4100153a096b3e3a319f6d7ebabe1b53c1841970a0617729c0c
7
+ data.tar.gz: 3d15ed281a359a7fb8d5815769c2d6555066796cf9f3abf55ff39375a847d186ba32508820e850f09dfb34e3a3560521bc0c151355bcaa9295c3669b4c1e089f
data/README.md CHANGED
@@ -7,7 +7,7 @@ The Mysql2 gem is meant to serve the extremely common use-case of connecting, qu
7
7
  Some database libraries out there serve as direct 1:1 mappings of the already complex C APIs available.
8
8
  This one is not.
9
9
 
10
- It also forces the use of UTF-8 [or binary] for the connection [and all strings in 1.9, unless Encoding.default_internal is set then it'll convert from UTF-8 to that encoding] and uses encoding-aware MySQL API calls where it can.
10
+ It also forces the use of UTF-8 [or binary] for the connection and uses encoding-aware MySQL API calls where it can.
11
11
 
12
12
  The API consists of three classes:
13
13
 
@@ -138,7 +138,7 @@ results.each do |row|
138
138
  # conveniently, row is a hash
139
139
  # the keys are the fields, as you'd expect
140
140
  # the values are pre-built ruby primitives mapped from their corresponding field types in MySQL
141
- puts row["id"] # row["id"].class == Fixnum
141
+ puts row["id"] # row["id"].is_a? Integer
142
142
  if row["dne"] # non-existant hash entry is nil
143
143
  puts row["dne"]
144
144
  end
@@ -175,7 +175,11 @@ end
175
175
  Prepared statements are supported, as well. In a prepared statement, use a `?`
176
176
  in place of each value and then execute the statement to retrieve a result set.
177
177
  Pass your arguments to the execute method in the same number and order as the
178
- question marks in the statement.
178
+ question marks in the statement. Query options can be passed as keyword arguments
179
+ to the execute method.
180
+
181
+ Be sure to read about the known limitations of prepared statements at
182
+ https://dev.mysql.com/doc/refman/5.6/en/c-api-prepared-statement-problems.html
179
183
 
180
184
  ``` ruby
181
185
  statement = @client.prepare("SELECT * FROM users WHERE login_count = ?")
@@ -184,6 +188,9 @@ result2 = statement.execute(2)
184
188
 
185
189
  statement = @client.prepare("SELECT * FROM users WHERE last_login >= ? AND location LIKE ?")
186
190
  result = statement.execute(1, "CA")
191
+
192
+ statement = @client.prepare("SELECT * FROM users WHERE last_login >= ? AND location LIKE ?")
193
+ result = statement.execute(1, "CA", :as => :array)
187
194
  ```
188
195
 
189
196
  ## Connection options
@@ -203,6 +210,7 @@ Mysql2::Client.new(
203
210
  :read_timeout = seconds,
204
211
  :write_timeout = seconds,
205
212
  :connect_timeout = seconds,
213
+ :connect_attrs = {:program_name => $PROGRAM_NAME, ...},
206
214
  :reconnect = true/false,
207
215
  :local_infile = true/false,
208
216
  :secure_auth = true/false,
@@ -381,6 +389,15 @@ c = Mysql2::Client.new
381
389
  c.query(sql, :symbolize_keys => true)
382
390
  ```
383
391
 
392
+ or
393
+
394
+ ``` ruby
395
+ # this will set the options for the Mysql2::Result instance returned from the #execute method
396
+ c = Mysql2::Client.new
397
+ s = c.prepare(sql)
398
+ s.execute(arg1, args2, :symbolize_keys => true)
399
+ ```
400
+
384
401
  ## Result types
385
402
 
386
403
  ### Array of Arrays
@@ -509,18 +526,18 @@ As for field values themselves, I'm workin on it - but expect that soon.
509
526
 
510
527
  This gem is tested with the following Ruby versions on Linux and Mac OS X:
511
528
 
512
- * Ruby MRI 1.8.7, 1.9.3, 2.0.0, 2.1.x, 2.2.x, 2.3.x, 2.4.x
513
- * Ruby Enterprise Edition (based on MRI 1.8.7)
529
+ * Ruby MRI 2.0.0, 2.1.x, 2.2.x, 2.3.x, 2.4.x, 2.5.x, 2.6.x
514
530
  * Rubinius 2.x and 3.x do work but may fail under some workloads
515
531
 
516
532
  This gem is tested with the following MySQL and MariaDB versions:
517
533
 
518
534
  * MySQL 5.5, 5.6, 5.7, 8.0
519
535
  * MySQL Connector/C 6.0 and 6.1 (primarily on Windows)
520
- * MariaDB 5.5, 10.0, 10.1
536
+ * MariaDB 5.5, 10.0, 10.1, 10.2, 10.3
521
537
 
522
538
  ### Ruby on Rails / Active Record
523
539
 
540
+ * mysql2 0.5.x works with Rails / Active Record 5.0.7, 5.1.6, and higher.
524
541
  * mysql2 0.4.x works with Rails / Active Record 4.2.5 - 5.0 and higher.
525
542
  * mysql2 0.3.x works with Rails / Active Record 3.1, 3.2, 4.x, 5.0.
526
543
  * mysql2 0.2.x works with Rails / Active Record 2.3 - 3.0.
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  $LOAD_PATH.unshift 'lib'
4
2
 
5
3
  require 'rubygems'
@@ -1,17 +1,15 @@
1
- # encoding: utf-8
2
-
3
1
  $LOAD_PATH.unshift 'lib'
4
2
  require 'mysql2'
5
3
  require 'timeout'
6
4
 
7
5
  # Should never exceed worst case 3.5 secs across all 20 threads
8
6
  Timeout.timeout(3.5) do
9
- 20.times.map do
7
+ Array.new(20) do
10
8
  Thread.new do
11
9
  overhead = rand(3)
12
10
  puts ">> thread #{Thread.current.object_id} query, #{overhead} sec overhead"
13
11
  # 3 second overhead per query
14
- Mysql2::Client.new(:host => "localhost", :username => "root").query("SELECT sleep(#{overhead}) as result")
12
+ Mysql2::Client.new(host: "localhost", username: "root").query("SELECT sleep(#{overhead}) as result")
15
13
  puts "<< thread #{Thread.current.object_id} result, #{overhead} sec overhead"
16
14
  end
17
15
  end.each(&:join)
@@ -15,16 +15,11 @@
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"); \
@@ -119,7 +114,7 @@ static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) {
119
114
  int val = NUM2INT( setting );
120
115
  if (version >= 50703 && version < 50711) {
121
116
  if (val == SSL_MODE_DISABLED || val == SSL_MODE_REQUIRED) {
122
- bool b = ( val == SSL_MODE_REQUIRED );
117
+ my_bool b = ( val == SSL_MODE_REQUIRED );
123
118
  int result = mysql_options( wrapper->client, MYSQL_OPT_SSL_ENFORCE, &b );
124
119
  return INT2NUM(result);
125
120
  } else {
@@ -178,10 +173,8 @@ static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) {
178
173
  VALUE rb_sql_state = rb_tainted_str_new2(mysql_sqlstate(wrapper->client));
179
174
  VALUE e;
180
175
 
181
- #ifdef HAVE_RUBY_ENCODING_H
182
176
  rb_enc_associate(rb_error_msg, rb_utf8_encoding());
183
177
  rb_enc_associate(rb_sql_state, rb_usascii_encoding());
184
- #endif
185
178
 
186
179
  e = rb_funcall(cMysql2Error, intern_new_with_args, 4,
187
180
  rb_error_msg,
@@ -357,9 +350,7 @@ static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) {
357
350
  return str;
358
351
  } else {
359
352
  rb_str = rb_str_new((const char*)newStr, newLen);
360
- #ifdef HAVE_RUBY_ENCODING_H
361
353
  rb_enc_copy(rb_str, str);
362
- #endif
363
354
  xfree(newStr);
364
355
  return rb_str;
365
356
  }
@@ -386,9 +377,7 @@ static VALUE rb_mysql_info(VALUE self) {
386
377
  }
387
378
 
388
379
  rb_str = rb_str_new2(info);
389
- #ifdef HAVE_RUBY_ENCODING_H
390
380
  rb_enc_associate(rb_str, rb_utf8_encoding());
391
- #endif
392
381
 
393
382
  return rb_str;
394
383
  }
@@ -406,14 +395,25 @@ static VALUE rb_mysql_get_ssl_cipher(VALUE self)
406
395
  }
407
396
 
408
397
  rb_str = rb_str_new2(cipher);
409
- #ifdef HAVE_RUBY_ENCODING_H
410
398
  rb_enc_associate(rb_str, rb_utf8_encoding());
411
- #endif
412
399
 
413
400
  return rb_str;
414
401
  }
415
402
 
416
- static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags) {
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) {
417
417
  struct nogvl_connect_args args;
418
418
  time_t start_time, end_time, elapsed_time, connect_timeout;
419
419
  VALUE rv;
@@ -428,6 +428,11 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
428
428
  args.mysql = wrapper->client;
429
429
  args.client_flag = NUM2ULONG(flags);
430
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
+
431
436
  if (wrapper->connect_timeout)
432
437
  time(&start_time);
433
438
  rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0);
@@ -521,7 +526,7 @@ static VALUE do_send_query(void *args) {
521
526
  */
522
527
  static void *nogvl_read_query_result(void *ptr) {
523
528
  MYSQL * client = ptr;
524
- bool res = mysql_read_query_result(client);
529
+ my_bool res = mysql_read_query_result(client);
525
530
 
526
531
  return (void *)(res == 0 ? Qtrue : Qfalse);
527
532
  }
@@ -590,11 +595,14 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
590
595
  return Qnil;
591
596
  }
592
597
 
598
+ // Duplicate the options hash and put the copy in the Result object
593
599
  current = rb_hash_dup(rb_iv_get(self, "@current_query_options"));
594
600
  (void)RB_GC_GUARD(current);
595
601
  Check_Type(current, T_HASH);
596
602
  resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result, Qnil);
597
603
 
604
+ rb_mysql_set_server_query_flags(wrapper->client, resultObj);
605
+
598
606
  return resultObj;
599
607
  }
600
608
 
@@ -652,7 +660,7 @@ static VALUE do_query(void *args) {
652
660
  retval = rb_wait_for_single_fd(async_args->fd, RB_WAITFD_IN, tvp);
653
661
 
654
662
  if (retval == 0) {
655
- rb_raise(cMysql2Error, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
663
+ rb_raise(cMysql2TimeoutError, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
656
664
  }
657
665
 
658
666
  if (retval < 0) {
@@ -747,7 +755,7 @@ static VALUE rb_mysql_client_abandon_results(VALUE self) {
747
755
  * Query the database with +sql+, with optional +options+. For the possible
748
756
  * options, see default_query_options on the Mysql2::Client class.
749
757
  */
750
- static VALUE rb_query(VALUE self, VALUE sql, VALUE current) {
758
+ static VALUE rb_mysql_query(VALUE self, VALUE sql, VALUE current) {
751
759
  #ifndef _WIN32
752
760
  struct async_query_args async_args;
753
761
  #endif
@@ -762,12 +770,8 @@ static VALUE rb_query(VALUE self, VALUE sql, VALUE current) {
762
770
  rb_iv_set(self, "@current_query_options", current);
763
771
 
764
772
  Check_Type(sql, T_STRING);
765
- #ifdef HAVE_RUBY_ENCODING_H
766
773
  /* ensure the string is in the encoding the connection is expecting */
767
774
  args.sql = rb_str_export_to_enc(sql, rb_to_encoding(wrapper->encoding));
768
- #else
769
- args.sql = sql;
770
- #endif
771
775
  args.sql_ptr = RSTRING_PTR(args.sql);
772
776
  args.sql_len = RSTRING_LEN(args.sql);
773
777
  args.wrapper = wrapper;
@@ -804,20 +808,16 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
804
808
  unsigned char *newStr;
805
809
  VALUE rb_str;
806
810
  unsigned long newLen, oldLen;
807
- #ifdef HAVE_RUBY_ENCODING_H
808
811
  rb_encoding *default_internal_enc;
809
812
  rb_encoding *conn_enc;
810
- #endif
811
813
  GET_CLIENT(self);
812
814
 
813
815
  REQUIRE_CONNECTED(wrapper);
814
816
  Check_Type(str, T_STRING);
815
- #ifdef HAVE_RUBY_ENCODING_H
816
817
  default_internal_enc = rb_default_internal_encoding();
817
818
  conn_enc = rb_to_encoding(wrapper->encoding);
818
819
  /* ensure the string is in the encoding the connection is expecting */
819
820
  str = rb_str_export_to_enc(str, conn_enc);
820
- #endif
821
821
 
822
822
  oldLen = RSTRING_LEN(str);
823
823
  newStr = xmalloc(oldLen*2+1);
@@ -825,21 +825,17 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
825
825
  newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, RSTRING_PTR(str), oldLen);
826
826
  if (newLen == oldLen) {
827
827
  /* no need to return a new ruby string if nothing changed */
828
- #ifdef HAVE_RUBY_ENCODING_H
829
828
  if (default_internal_enc) {
830
829
  str = rb_str_export_to_enc(str, default_internal_enc);
831
830
  }
832
- #endif
833
831
  xfree(newStr);
834
832
  return str;
835
833
  } else {
836
834
  rb_str = rb_str_new((const char*)newStr, newLen);
837
- #ifdef HAVE_RUBY_ENCODING_H
838
835
  rb_enc_associate(rb_str, conn_enc);
839
836
  if (default_internal_enc) {
840
837
  rb_str = rb_str_export_to_enc(rb_str, default_internal_enc);
841
838
  }
842
- #endif
843
839
  xfree(newStr);
844
840
  return rb_str;
845
841
  }
@@ -850,7 +846,7 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
850
846
  const void *retval = NULL;
851
847
  unsigned int intval = 0;
852
848
  const char * charval = NULL;
853
- bool boolval;
849
+ my_bool boolval;
854
850
 
855
851
  GET_CLIENT(self);
856
852
 
@@ -950,10 +946,8 @@ static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE klass) {
950
946
  version = rb_str_new2(mysql_get_client_info());
951
947
  header_version = rb_str_new2(MYSQL_LINK_VERSION);
952
948
 
953
- #ifdef HAVE_RUBY_ENCODING_H
954
949
  rb_enc_associate(version, rb_usascii_encoding());
955
950
  rb_enc_associate(header_version, rb_usascii_encoding());
956
- #endif
957
951
 
958
952
  rb_hash_aset(version_info, sym_id, LONG2NUM(mysql_get_client_version()));
959
953
  rb_hash_aset(version_info, sym_version, version);
@@ -969,27 +963,21 @@ static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE klass) {
969
963
  */
970
964
  static VALUE rb_mysql_client_server_info(VALUE self) {
971
965
  VALUE version, server_info;
972
- #ifdef HAVE_RUBY_ENCODING_H
973
966
  rb_encoding *default_internal_enc;
974
967
  rb_encoding *conn_enc;
975
- #endif
976
968
  GET_CLIENT(self);
977
969
 
978
970
  REQUIRE_CONNECTED(wrapper);
979
- #ifdef HAVE_RUBY_ENCODING_H
980
971
  default_internal_enc = rb_default_internal_encoding();
981
972
  conn_enc = rb_to_encoding(wrapper->encoding);
982
- #endif
983
973
 
984
974
  version = rb_hash_new();
985
975
  rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_server_version(wrapper->client)));
986
976
  server_info = rb_str_new2(mysql_get_server_info(wrapper->client));
987
- #ifdef HAVE_RUBY_ENCODING_H
988
977
  rb_enc_associate(server_info, conn_enc);
989
978
  if (default_internal_enc) {
990
979
  server_info = rb_str_export_to_enc(server_info, default_internal_enc);
991
980
  }
992
- #endif
993
981
  rb_hash_aset(version, sym_version, server_info);
994
982
  return version;
995
983
  }
@@ -1110,6 +1098,23 @@ static VALUE rb_mysql_client_ping(VALUE self) {
1110
1098
  }
1111
1099
  }
1112
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
+
1113
1118
  /* call-seq:
1114
1119
  * client.more_results?
1115
1120
  *
@@ -1168,6 +1173,7 @@ static VALUE rb_mysql_client_store_result(VALUE self)
1168
1173
  return Qnil;
1169
1174
  }
1170
1175
 
1176
+ // Duplicate the options hash and put the copy in the Result object
1171
1177
  current = rb_hash_dup(rb_iv_get(self, "@current_query_options"));
1172
1178
  (void)RB_GC_GUARD(current);
1173
1179
  Check_Type(current, T_HASH);
@@ -1176,7 +1182,6 @@ static VALUE rb_mysql_client_store_result(VALUE self)
1176
1182
  return resultObj;
1177
1183
  }
1178
1184
 
1179
- #ifdef HAVE_RUBY_ENCODING_H
1180
1185
  /* call-seq:
1181
1186
  * client.encoding
1182
1187
  *
@@ -1186,7 +1191,6 @@ static VALUE rb_mysql_client_encoding(VALUE self) {
1186
1191
  GET_CLIENT(self);
1187
1192
  return wrapper->encoding;
1188
1193
  }
1189
- #endif
1190
1194
 
1191
1195
  /* call-seq:
1192
1196
  * client.automatic_close?
@@ -1272,17 +1276,14 @@ static VALUE set_write_timeout(VALUE self, VALUE value) {
1272
1276
 
1273
1277
  static VALUE set_charset_name(VALUE self, VALUE value) {
1274
1278
  char *charset_name;
1275
- #ifdef HAVE_RUBY_ENCODING_H
1276
1279
  const struct mysql2_mysql_enc_name_to_rb_map *mysql2rb;
1277
1280
  rb_encoding *enc;
1278
1281
  VALUE rb_enc;
1279
- #endif
1280
1282
  GET_CLIENT(self);
1281
1283
 
1282
1284
  Check_Type(value, T_STRING);
1283
1285
  charset_name = RSTRING_PTR(value);
1284
1286
 
1285
- #ifdef HAVE_RUBY_ENCODING_H
1286
1287
  mysql2rb = mysql2_mysql_enc_name_to_rb(charset_name, (unsigned int)RSTRING_LEN(value));
1287
1288
  if (mysql2rb == NULL || mysql2rb->rb_name == NULL) {
1288
1289
  VALUE inspect = rb_inspect(value);
@@ -1292,7 +1293,6 @@ static VALUE set_charset_name(VALUE self, VALUE value) {
1292
1293
  rb_enc = rb_enc_from_encoding(enc);
1293
1294
  wrapper->encoding = rb_enc;
1294
1295
  }
1295
- #endif
1296
1296
 
1297
1297
  if (mysql_options(wrapper->client, MYSQL_SET_CHARSET_NAME, charset_name)) {
1298
1298
  /* TODO: warning - unable to set charset */
@@ -1416,6 +1416,7 @@ void init_mysql2_client() {
1416
1416
  rb_define_method(cMysql2Client, "thread_id", rb_mysql_client_thread_id, 0);
1417
1417
  rb_define_method(cMysql2Client, "ping", rb_mysql_client_ping, 0);
1418
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);
1419
1420
  rb_define_method(cMysql2Client, "more_results?", rb_mysql_client_more_results, 0);
1420
1421
  rb_define_method(cMysql2Client, "next_result", rb_mysql_client_next_result, 0);
1421
1422
  rb_define_method(cMysql2Client, "store_result", rb_mysql_client_store_result, 0);
@@ -1425,9 +1426,7 @@ void init_mysql2_client() {
1425
1426
  rb_define_method(cMysql2Client, "warning_count", rb_mysql_client_warning_count, 0);
1426
1427
  rb_define_method(cMysql2Client, "query_info_string", rb_mysql_info, 0);
1427
1428
  rb_define_method(cMysql2Client, "ssl_cipher", rb_mysql_get_ssl_cipher, 0);
1428
- #ifdef HAVE_RUBY_ENCODING_H
1429
1429
  rb_define_method(cMysql2Client, "encoding", rb_mysql_client_encoding, 0);
1430
- #endif
1431
1430
 
1432
1431
  rb_define_private_method(cMysql2Client, "connect_timeout=", set_connect_timeout, 1);
1433
1432
  rb_define_private_method(cMysql2Client, "read_timeout=", set_read_timeout, 1);
@@ -1442,8 +1441,8 @@ void init_mysql2_client() {
1442
1441
  rb_define_private_method(cMysql2Client, "ssl_mode=", rb_set_ssl_mode_option, 1);
1443
1442
  rb_define_private_method(cMysql2Client, "enable_cleartext_plugin=", set_enable_cleartext_plugin, 1);
1444
1443
  rb_define_private_method(cMysql2Client, "initialize_ext", initialize_ext, 0);
1445
- rb_define_private_method(cMysql2Client, "connect", rb_connect, 7);
1446
- rb_define_private_method(cMysql2Client, "_query", rb_query, 2);
1444
+ rb_define_private_method(cMysql2Client, "connect", rb_mysql_connect, 8);
1445
+ rb_define_private_method(cMysql2Client, "_query", rb_mysql_query, 2);
1447
1446
 
1448
1447
  sym_id = ID2SYM(rb_intern("id"));
1449
1448
  sym_version = ID2SYM(rb_intern("version"));
@@ -1454,6 +1453,10 @@ void init_mysql2_client() {
1454
1453
  sym_array = ID2SYM(rb_intern("array"));
1455
1454
  sym_stream = ID2SYM(rb_intern("stream"));
1456
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
+
1457
1460
  intern_brackets = rb_intern("[]");
1458
1461
  intern_merge = rb_intern("merge");
1459
1462
  intern_merge_bang = rb_intern("merge!");
@@ -1543,6 +1546,16 @@ void init_mysql2_client() {
1543
1546
  rb_const_set(cMysql2Client, rb_intern("SECURE_CONNECTION"), LONG2NUM(0));
1544
1547
  #endif
1545
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
+
1546
1559
  #ifdef CLIENT_MULTI_STATEMENTS
1547
1560
  rb_const_set(cMysql2Client, rb_intern("MULTI_STATEMENTS"),
1548
1561
  LONG2NUM(CLIENT_MULTI_STATEMENTS));
@@ -1573,6 +1586,16 @@ void init_mysql2_client() {
1573
1586
  LONG2NUM(CLIENT_BASIC_FLAGS));
1574
1587
  #endif
1575
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
+
1576
1599
  #if defined(FULL_SSL_MODE_SUPPORT) // MySQL 5.7.11 and above
1577
1600
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED));
1578
1601
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_PREFERRED"), INT2NUM(SSL_MODE_PREFERRED));
@@ -1600,3 +1623,29 @@ void init_mysql2_client() {
1600
1623
  rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_IDENTITY"), INT2NUM(0));
1601
1624
  #endif
1602
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);
1651
+ }