mysql2 0.3.20 → 0.5.3
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 +5 -5
 - data/CHANGELOG.md +1 -0
 - data/README.md +183 -72
 - data/ext/mysql2/client.c +432 -183
 - data/ext/mysql2/client.h +10 -38
 - data/ext/mysql2/extconf.rb +126 -56
 - data/ext/mysql2/infile.c +2 -2
 - data/ext/mysql2/mysql2_ext.c +3 -1
 - data/ext/mysql2/mysql2_ext.h +13 -14
 - data/ext/mysql2/mysql_enc_name_to_ruby.h +62 -58
 - data/ext/mysql2/mysql_enc_to_ruby.h +82 -18
 - data/ext/mysql2/result.c +505 -164
 - data/ext/mysql2/result.h +11 -4
 - data/ext/mysql2/statement.c +604 -0
 - data/ext/mysql2/statement.h +17 -0
 - data/ext/mysql2/wait_for_single_fd.h +2 -1
 - data/lib/mysql2/client.rb +89 -28
 - data/lib/mysql2/console.rb +1 -1
 - data/lib/mysql2/em.rb +6 -9
 - data/lib/mysql2/error.rb +55 -35
 - data/lib/mysql2/field.rb +3 -0
 - data/lib/mysql2/result.rb +2 -0
 - data/lib/mysql2/statement.rb +11 -0
 - data/lib/mysql2/version.rb +1 -1
 - data/lib/mysql2.rb +46 -24
 - data/support/5072E1F5.asc +432 -0
 - data/support/mysql_enc_to_ruby.rb +15 -11
 - data/support/ruby_enc_to_mysql.rb +8 -6
 - metadata +22 -77
 - data/examples/eventmachine.rb +0 -21
 - data/examples/threaded.rb +0 -20
 - data/spec/configuration.yml.example +0 -17
 - data/spec/em/em_spec.rb +0 -135
 - data/spec/my.cnf.example +0 -9
 - data/spec/mysql2/client_spec.rb +0 -921
 - data/spec/mysql2/error_spec.rb +0 -83
 - data/spec/mysql2/result_spec.rb +0 -514
 - data/spec/rcov.opts +0 -3
 - data/spec/spec_helper.rb +0 -87
 - data/spec/test_data +0 -1
 
    
        data/ext/mysql2/client.c
    CHANGED
    
    | 
         @@ -15,51 +15,58 @@ 
     | 
|
| 
       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  
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
            static VALUE rb_hash_dup(VALUE other) {
         
     | 
| 
       24 
     | 
    
         
            -
              return rb_funcall(rb_cHash, rb_intern("[]"), 1, other);
         
     | 
| 
       25 
     | 
    
         
            -
            }
         
     | 
| 
       26 
     | 
    
         
            -
            #endif
         
     | 
| 
      
 20 
     | 
    
         
            +
            static VALUE sym_no_good_index_used, sym_no_index_used, sym_query_was_slow;
         
     | 
| 
      
 21 
     | 
    
         
            +
            static ID intern_brackets, intern_merge, intern_merge_bang, intern_new_with_args,
         
     | 
| 
      
 22 
     | 
    
         
            +
              intern_current_query_options, intern_read_timeout;
         
     | 
| 
       27 
23 
     | 
    
         | 
| 
       28 
24 
     | 
    
         
             
            #define REQUIRE_INITIALIZED(wrapper) \
         
     | 
| 
       29 
25 
     | 
    
         
             
              if (!wrapper->initialized) { \
         
     | 
| 
       30 
26 
     | 
    
         
             
                rb_raise(cMysql2Error, "MySQL client is not initialized"); \
         
     | 
| 
       31 
27 
     | 
    
         
             
              }
         
     | 
| 
       32 
28 
     | 
    
         | 
| 
      
 29 
     | 
    
         
            +
            #if defined(HAVE_MYSQL_NET_VIO) || defined(HAVE_ST_NET_VIO)
         
     | 
| 
      
 30 
     | 
    
         
            +
              #define CONNECTED(wrapper) (wrapper->client->net.vio != NULL && wrapper->client->net.fd != -1)
         
     | 
| 
      
 31 
     | 
    
         
            +
            #elif defined(HAVE_MYSQL_NET_PVIO) || defined(HAVE_ST_NET_PVIO)
         
     | 
| 
      
 32 
     | 
    
         
            +
              #define CONNECTED(wrapper) (wrapper->client->net.pvio != NULL && wrapper->client->net.fd != -1)
         
     | 
| 
      
 33 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
       33 
35 
     | 
    
         
             
            #define REQUIRE_CONNECTED(wrapper) \
         
     | 
| 
       34 
36 
     | 
    
         
             
              REQUIRE_INITIALIZED(wrapper) \
         
     | 
| 
       35 
     | 
    
         
            -
              if (!wrapper 
     | 
| 
       36 
     | 
    
         
            -
                rb_raise(cMysql2Error, " 
     | 
| 
      
 37 
     | 
    
         
            +
              if (!CONNECTED(wrapper) && !wrapper->reconnect_enabled) { \
         
     | 
| 
      
 38 
     | 
    
         
            +
                rb_raise(cMysql2Error, "MySQL client is not connected"); \
         
     | 
| 
       37 
39 
     | 
    
         
             
              }
         
     | 
| 
       38 
40 
     | 
    
         | 
| 
       39 
41 
     | 
    
         
             
            #define REQUIRE_NOT_CONNECTED(wrapper) \
         
     | 
| 
       40 
42 
     | 
    
         
             
              REQUIRE_INITIALIZED(wrapper) \
         
     | 
| 
       41 
     | 
    
         
            -
              if (wrapper 
     | 
| 
      
 43 
     | 
    
         
            +
              if (CONNECTED(wrapper)) { \
         
     | 
| 
       42 
44 
     | 
    
         
             
                rb_raise(cMysql2Error, "MySQL connection is already open"); \
         
     | 
| 
       43 
45 
     | 
    
         
             
              }
         
     | 
| 
       44 
46 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
            #define MARK_CONN_INACTIVE(conn) \
         
     | 
| 
       46 
     | 
    
         
            -
              wrapper->active_thread = Qnil;
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
            #define GET_CLIENT(self) \
         
     | 
| 
       49 
     | 
    
         
            -
              mysql_client_wrapper *wrapper; \
         
     | 
| 
       50 
     | 
    
         
            -
              Data_Get_Struct(self, mysql_client_wrapper, wrapper)
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
47 
     | 
    
         
             
            /*
         
     | 
| 
       53 
48 
     | 
    
         
             
             * compatability with mysql-connector-c, where LIBMYSQL_VERSION is the correct
         
     | 
| 
       54 
49 
     | 
    
         
             
             * variable to use, but MYSQL_SERVER_VERSION gives the correct numbers when
         
     | 
| 
       55 
50 
     | 
    
         
             
             * linking against the server itself
         
     | 
| 
       56 
51 
     | 
    
         
             
             */
         
     | 
| 
       57 
     | 
    
         
            -
            # 
     | 
| 
      
 52 
     | 
    
         
            +
            #if defined(MARIADB_CLIENT_VERSION_STR)
         
     | 
| 
      
 53 
     | 
    
         
            +
              #define MYSQL_LINK_VERSION MARIADB_CLIENT_VERSION_STR
         
     | 
| 
      
 54 
     | 
    
         
            +
            #elif defined(LIBMYSQL_VERSION)
         
     | 
| 
       58 
55 
     | 
    
         
             
              #define MYSQL_LINK_VERSION LIBMYSQL_VERSION
         
     | 
| 
       59 
56 
     | 
    
         
             
            #else
         
     | 
| 
       60 
57 
     | 
    
         
             
              #define MYSQL_LINK_VERSION MYSQL_SERVER_VERSION
         
     | 
| 
       61 
58 
     | 
    
         
             
            #endif
         
     | 
| 
       62 
59 
     | 
    
         | 
| 
      
 60 
     | 
    
         
            +
            /*
         
     | 
| 
      
 61 
     | 
    
         
            +
             * compatibility with mysql-connector-c 6.1.x, and with MySQL 5.7.3 - 5.7.10.
         
     | 
| 
      
 62 
     | 
    
         
            +
             */
         
     | 
| 
      
 63 
     | 
    
         
            +
            #ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE
         
     | 
| 
      
 64 
     | 
    
         
            +
              #define SSL_MODE_DISABLED 1
         
     | 
| 
      
 65 
     | 
    
         
            +
              #define SSL_MODE_REQUIRED 3
         
     | 
| 
      
 66 
     | 
    
         
            +
              #define HAVE_CONST_SSL_MODE_DISABLED
         
     | 
| 
      
 67 
     | 
    
         
            +
              #define HAVE_CONST_SSL_MODE_REQUIRED
         
     | 
| 
      
 68 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
       63 
70 
     | 
    
         
             
            /*
         
     | 
| 
       64 
71 
     | 
    
         
             
             * used to pass all arguments to mysql_real_connect while inside
         
     | 
| 
       65 
72 
     | 
    
         
             
             * rb_thread_call_without_gvl
         
     | 
| 
         @@ -96,6 +103,46 @@ struct nogvl_select_db_args { 
     | 
|
| 
       96 
103 
     | 
    
         
             
              char *db;
         
     | 
| 
       97 
104 
     | 
    
         
             
            };
         
     | 
| 
       98 
105 
     | 
    
         | 
| 
      
 106 
     | 
    
         
            +
            static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) {
         
     | 
| 
      
 107 
     | 
    
         
            +
              unsigned long version = mysql_get_client_version();
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
              if (version < 50703) {
         
     | 
| 
      
 110 
     | 
    
         
            +
                rb_warn( "Your mysql client library does not support setting ssl_mode; full support comes with 5.7.11." );
         
     | 
| 
      
 111 
     | 
    
         
            +
                return Qnil;
         
     | 
| 
      
 112 
     | 
    
         
            +
              }
         
     | 
| 
      
 113 
     | 
    
         
            +
            #ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE
         
     | 
| 
      
 114 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 115 
     | 
    
         
            +
              int val = NUM2INT( setting );
         
     | 
| 
      
 116 
     | 
    
         
            +
              // Either MySQL 5.7.3 - 5.7.10, or Connector/C 6.1.3 - 6.1.x
         
     | 
| 
      
 117 
     | 
    
         
            +
              if ((version >= 50703 && version < 50711) || (version >= 60103 && version < 60200)) {
         
     | 
| 
      
 118 
     | 
    
         
            +
                if (val == SSL_MODE_DISABLED || val == SSL_MODE_REQUIRED) {
         
     | 
| 
      
 119 
     | 
    
         
            +
                  my_bool b = ( val == SSL_MODE_REQUIRED );
         
     | 
| 
      
 120 
     | 
    
         
            +
                  int result = mysql_options( wrapper->client, MYSQL_OPT_SSL_ENFORCE, &b );
         
     | 
| 
      
 121 
     | 
    
         
            +
                  return INT2NUM(result);
         
     | 
| 
      
 122 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 123 
     | 
    
         
            +
                  rb_warn( "MySQL client libraries between 5.7.3 and 5.7.10 only support SSL_MODE_DISABLED and SSL_MODE_REQUIRED" );
         
     | 
| 
      
 124 
     | 
    
         
            +
                  return Qnil;
         
     | 
| 
      
 125 
     | 
    
         
            +
                }
         
     | 
| 
      
 126 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 127 
     | 
    
         
            +
                rb_warn( "Your mysql client library does not support ssl_mode as expected." );
         
     | 
| 
      
 128 
     | 
    
         
            +
                return Qnil;
         
     | 
| 
      
 129 
     | 
    
         
            +
              }
         
     | 
| 
      
 130 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 131 
     | 
    
         
            +
            #ifdef FULL_SSL_MODE_SUPPORT
         
     | 
| 
      
 132 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 133 
     | 
    
         
            +
              int val = NUM2INT( setting );
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
              if (val != SSL_MODE_DISABLED && val != SSL_MODE_PREFERRED && val != SSL_MODE_REQUIRED && val != SSL_MODE_VERIFY_CA && val != SSL_MODE_VERIFY_IDENTITY) {
         
     | 
| 
      
 136 
     | 
    
         
            +
                rb_raise(cMysql2Error, "ssl_mode= takes DISABLED, PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY, you passed: %d", val );
         
     | 
| 
      
 137 
     | 
    
         
            +
              }
         
     | 
| 
      
 138 
     | 
    
         
            +
              int result = mysql_options( wrapper->client, MYSQL_OPT_SSL_MODE, &val );
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
              return INT2NUM(result);
         
     | 
| 
      
 141 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 142 
     | 
    
         
            +
            #ifdef NO_SSL_MODE_SUPPORT
         
     | 
| 
      
 143 
     | 
    
         
            +
              return Qnil;
         
     | 
| 
      
 144 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 145 
     | 
    
         
            +
            }
         
     | 
| 
       99 
146 
     | 
    
         
             
            /*
         
     | 
| 
       100 
147 
     | 
    
         
             
             * non-blocking mysql_*() functions that we won't be wrapping since
         
     | 
| 
       101 
148 
     | 
    
         
             
             * they do not appear to hit the network nor issue any interruptible
         
     | 
| 
         @@ -131,21 +178,20 @@ static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) { 
     | 
|
| 
       131 
178 
     | 
    
         
             
              VALUE rb_sql_state = rb_tainted_str_new2(mysql_sqlstate(wrapper->client));
         
     | 
| 
       132 
179 
     | 
    
         
             
              VALUE e;
         
     | 
| 
       133 
180 
     | 
    
         | 
| 
       134 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       135 
181 
     | 
    
         
             
              rb_enc_associate(rb_error_msg, rb_utf8_encoding());
         
     | 
| 
       136 
182 
     | 
    
         
             
              rb_enc_associate(rb_sql_state, rb_usascii_encoding());
         
     | 
| 
       137 
     | 
    
         
            -
            #endif
         
     | 
| 
       138 
183 
     | 
    
         | 
| 
       139 
     | 
    
         
            -
              e = rb_funcall(cMysql2Error,  
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
      
 184 
     | 
    
         
            +
              e = rb_funcall(cMysql2Error, intern_new_with_args, 4,
         
     | 
| 
      
 185 
     | 
    
         
            +
                             rb_error_msg,
         
     | 
| 
      
 186 
     | 
    
         
            +
                             LONG2FIX(wrapper->server_version),
         
     | 
| 
      
 187 
     | 
    
         
            +
                             UINT2NUM(mysql_errno(wrapper->client)),
         
     | 
| 
      
 188 
     | 
    
         
            +
                             rb_sql_state);
         
     | 
| 
       142 
189 
     | 
    
         
             
              rb_exc_raise(e);
         
     | 
| 
       143 
     | 
    
         
            -
              return Qnil;
         
     | 
| 
       144 
190 
     | 
    
         
             
            }
         
     | 
| 
       145 
191 
     | 
    
         | 
| 
       146 
192 
     | 
    
         
             
            static void *nogvl_init(void *ptr) {
         
     | 
| 
       147 
193 
     | 
    
         
             
              MYSQL *client;
         
     | 
| 
       148 
     | 
    
         
            -
              mysql_client_wrapper *wrapper =  
     | 
| 
      
 194 
     | 
    
         
            +
              mysql_client_wrapper *wrapper = ptr;
         
     | 
| 
       149 
195 
     | 
    
         | 
| 
       150 
196 
     | 
    
         
             
              /* may initialize embedded server and read /etc/services off disk */
         
     | 
| 
       151 
197 
     | 
    
         
             
              client = mysql_init(wrapper->client);
         
     | 
| 
         @@ -221,41 +267,46 @@ static VALUE invalidate_fd(int clientfd) 
     | 
|
| 
       221 
267 
     | 
    
         
             
            #endif /* _WIN32 */
         
     | 
| 
       222 
268 
     | 
    
         | 
| 
       223 
269 
     | 
    
         
             
            static void *nogvl_close(void *ptr) {
         
     | 
| 
       224 
     | 
    
         
            -
              mysql_client_wrapper *wrapper;
         
     | 
| 
       225 
     | 
    
         
            -
              wrapper = ptr;
         
     | 
| 
       226 
     | 
    
         
            -
              if (wrapper->connected) {
         
     | 
| 
       227 
     | 
    
         
            -
                wrapper->active_thread = Qnil;
         
     | 
| 
       228 
     | 
    
         
            -
                wrapper->connected = 0;
         
     | 
| 
       229 
     | 
    
         
            -
            #ifndef _WIN32
         
     | 
| 
       230 
     | 
    
         
            -
                /* Invalidate the socket before calling mysql_close(). This prevents
         
     | 
| 
       231 
     | 
    
         
            -
                 * mysql_close() from sending a mysql-QUIT or from calling shutdown() on
         
     | 
| 
       232 
     | 
    
         
            -
                 * the socket. The difference is that invalidate_fd will drop this
         
     | 
| 
       233 
     | 
    
         
            -
                 * process's reference to the socket only, while a QUIT or shutdown()
         
     | 
| 
       234 
     | 
    
         
            -
                 * would render the underlying connection unusable, interrupting other
         
     | 
| 
       235 
     | 
    
         
            -
                 * processes which share this object across a fork().
         
     | 
| 
       236 
     | 
    
         
            -
                 */
         
     | 
| 
       237 
     | 
    
         
            -
                if (invalidate_fd(wrapper->client->net.fd) == Qfalse) {
         
     | 
| 
       238 
     | 
    
         
            -
                  fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely, leaking some memory\n");
         
     | 
| 
       239 
     | 
    
         
            -
                  close(wrapper->client->net.fd);
         
     | 
| 
       240 
     | 
    
         
            -
                  return NULL;
         
     | 
| 
       241 
     | 
    
         
            -
                }
         
     | 
| 
       242 
     | 
    
         
            -
            #endif
         
     | 
| 
      
 270 
     | 
    
         
            +
              mysql_client_wrapper *wrapper = ptr;
         
     | 
| 
       243 
271 
     | 
    
         | 
| 
       244 
     | 
    
         
            -
             
     | 
| 
      
 272 
     | 
    
         
            +
              if (!wrapper->closed) {
         
     | 
| 
      
 273 
     | 
    
         
            +
                mysql_close(wrapper->client);
         
     | 
| 
      
 274 
     | 
    
         
            +
                wrapper->closed = 1;
         
     | 
| 
      
 275 
     | 
    
         
            +
                wrapper->reconnect_enabled = 0;
         
     | 
| 
      
 276 
     | 
    
         
            +
                wrapper->active_thread = Qnil;
         
     | 
| 
       245 
277 
     | 
    
         
             
              }
         
     | 
| 
       246 
278 
     | 
    
         | 
| 
       247 
279 
     | 
    
         
             
              return NULL;
         
     | 
| 
       248 
280 
     | 
    
         
             
            }
         
     | 
| 
       249 
281 
     | 
    
         | 
| 
      
 282 
     | 
    
         
            +
            /* this is called during GC */
         
     | 
| 
       250 
283 
     | 
    
         
             
            static void rb_mysql_client_free(void *ptr) {
         
     | 
| 
       251 
     | 
    
         
            -
              mysql_client_wrapper *wrapper =  
     | 
| 
      
 284 
     | 
    
         
            +
              mysql_client_wrapper *wrapper = ptr;
         
     | 
| 
       252 
285 
     | 
    
         
             
              decr_mysql2_client(wrapper);
         
     | 
| 
       253 
286 
     | 
    
         
             
            }
         
     | 
| 
       254 
287 
     | 
    
         | 
| 
       255 
288 
     | 
    
         
             
            void decr_mysql2_client(mysql_client_wrapper *wrapper)
         
     | 
| 
       256 
289 
     | 
    
         
             
            {
         
     | 
| 
       257 
290 
     | 
    
         
             
              wrapper->refcount--;
         
     | 
| 
      
 291 
     | 
    
         
            +
             
     | 
| 
       258 
292 
     | 
    
         
             
              if (wrapper->refcount == 0) {
         
     | 
| 
      
 293 
     | 
    
         
            +
            #ifndef _WIN32
         
     | 
| 
      
 294 
     | 
    
         
            +
                if (CONNECTED(wrapper) && !wrapper->automatic_close) {
         
     | 
| 
      
 295 
     | 
    
         
            +
                  /* The client is being garbage collected while connected. Prevent
         
     | 
| 
      
 296 
     | 
    
         
            +
                   * mysql_close() from sending a mysql-QUIT or from calling shutdown() on
         
     | 
| 
      
 297 
     | 
    
         
            +
                   * the socket by invalidating it. invalidate_fd() will drop this
         
     | 
| 
      
 298 
     | 
    
         
            +
                   * process's reference to the socket only, while a QUIT or shutdown()
         
     | 
| 
      
 299 
     | 
    
         
            +
                   * would render the underlying connection unusable, interrupting other
         
     | 
| 
      
 300 
     | 
    
         
            +
                   * processes which share this object across a fork().
         
     | 
| 
      
 301 
     | 
    
         
            +
                   */
         
     | 
| 
      
 302 
     | 
    
         
            +
                  if (invalidate_fd(wrapper->client->net.fd) == Qfalse) {
         
     | 
| 
      
 303 
     | 
    
         
            +
                    fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely\n");
         
     | 
| 
      
 304 
     | 
    
         
            +
                    close(wrapper->client->net.fd);
         
     | 
| 
      
 305 
     | 
    
         
            +
                  }
         
     | 
| 
      
 306 
     | 
    
         
            +
                  wrapper->client->net.fd = -1;
         
     | 
| 
      
 307 
     | 
    
         
            +
                }
         
     | 
| 
      
 308 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 309 
     | 
    
         
            +
             
     | 
| 
       259 
310 
     | 
    
         
             
                nogvl_close(wrapper);
         
     | 
| 
       260 
311 
     | 
    
         
             
                xfree(wrapper->client);
         
     | 
| 
       261 
312 
     | 
    
         
             
                xfree(wrapper);
         
     | 
| 
         @@ -268,13 +319,15 @@ static VALUE allocate(VALUE klass) { 
     | 
|
| 
       268 
319 
     | 
    
         
             
              obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
         
     | 
| 
       269 
320 
     | 
    
         
             
              wrapper->encoding = Qnil;
         
     | 
| 
       270 
321 
     | 
    
         
             
              wrapper->active_thread = Qnil;
         
     | 
| 
      
 322 
     | 
    
         
            +
              wrapper->automatic_close = 1;
         
     | 
| 
       271 
323 
     | 
    
         
             
              wrapper->server_version = 0;
         
     | 
| 
       272 
324 
     | 
    
         
             
              wrapper->reconnect_enabled = 0;
         
     | 
| 
       273 
325 
     | 
    
         
             
              wrapper->connect_timeout = 0;
         
     | 
| 
       274 
     | 
    
         
            -
              wrapper->connected = 0; /* means that a database connection is open */
         
     | 
| 
       275 
326 
     | 
    
         
             
              wrapper->initialized = 0; /* means that that the wrapper is initialized */
         
     | 
| 
       276 
327 
     | 
    
         
             
              wrapper->refcount = 1;
         
     | 
| 
      
 328 
     | 
    
         
            +
              wrapper->closed = 0;
         
     | 
| 
       277 
329 
     | 
    
         
             
              wrapper->client = (MYSQL*)xmalloc(sizeof(MYSQL));
         
     | 
| 
      
 330 
     | 
    
         
            +
             
     | 
| 
       278 
331 
     | 
    
         
             
              return obj;
         
     | 
| 
       279 
332 
     | 
    
         
             
            }
         
     | 
| 
       280 
333 
     | 
    
         | 
| 
         @@ -302,9 +355,7 @@ static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) { 
     | 
|
| 
       302 
355 
     | 
    
         
             
                return str;
         
     | 
| 
       303 
356 
     | 
    
         
             
              } else {
         
     | 
| 
       304 
357 
     | 
    
         
             
                rb_str = rb_str_new((const char*)newStr, newLen);
         
     | 
| 
       305 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       306 
358 
     | 
    
         
             
                rb_enc_copy(rb_str, str);
         
     | 
| 
       307 
     | 
    
         
            -
            #endif
         
     | 
| 
       308 
359 
     | 
    
         
             
                xfree(newStr);
         
     | 
| 
       309 
360 
     | 
    
         
             
                return rb_str;
         
     | 
| 
       310 
361 
     | 
    
         
             
              }
         
     | 
| 
         @@ -331,17 +382,45 @@ static VALUE rb_mysql_info(VALUE self) { 
     | 
|
| 
       331 
382 
     | 
    
         
             
              }
         
     | 
| 
       332 
383 
     | 
    
         | 
| 
       333 
384 
     | 
    
         
             
              rb_str = rb_str_new2(info);
         
     | 
| 
       334 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       335 
385 
     | 
    
         
             
              rb_enc_associate(rb_str, rb_utf8_encoding());
         
     | 
| 
       336 
     | 
    
         
            -
            #endif
         
     | 
| 
       337 
386 
     | 
    
         | 
| 
       338 
387 
     | 
    
         
             
              return rb_str;
         
     | 
| 
       339 
388 
     | 
    
         
             
            }
         
     | 
| 
       340 
389 
     | 
    
         | 
| 
       341 
     | 
    
         
            -
            static VALUE  
     | 
| 
      
 390 
     | 
    
         
            +
            static VALUE rb_mysql_get_ssl_cipher(VALUE self)
         
     | 
| 
      
 391 
     | 
    
         
            +
            {
         
     | 
| 
      
 392 
     | 
    
         
            +
              const char *cipher;
         
     | 
| 
      
 393 
     | 
    
         
            +
              VALUE rb_str;
         
     | 
| 
      
 394 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 395 
     | 
    
         
            +
             
     | 
| 
      
 396 
     | 
    
         
            +
              cipher = mysql_get_ssl_cipher(wrapper->client);
         
     | 
| 
      
 397 
     | 
    
         
            +
             
     | 
| 
      
 398 
     | 
    
         
            +
              if (cipher == NULL) {
         
     | 
| 
      
 399 
     | 
    
         
            +
                return Qnil;
         
     | 
| 
      
 400 
     | 
    
         
            +
              }
         
     | 
| 
      
 401 
     | 
    
         
            +
             
     | 
| 
      
 402 
     | 
    
         
            +
              rb_str = rb_str_new2(cipher);
         
     | 
| 
      
 403 
     | 
    
         
            +
              rb_enc_associate(rb_str, rb_utf8_encoding());
         
     | 
| 
      
 404 
     | 
    
         
            +
             
     | 
| 
      
 405 
     | 
    
         
            +
              return rb_str;
         
     | 
| 
      
 406 
     | 
    
         
            +
            }
         
     | 
| 
      
 407 
     | 
    
         
            +
             
     | 
| 
      
 408 
     | 
    
         
            +
            #ifdef CLIENT_CONNECT_ATTRS
         
     | 
| 
      
 409 
     | 
    
         
            +
            static int opt_connect_attr_add_i(VALUE key, VALUE value, VALUE arg)
         
     | 
| 
      
 410 
     | 
    
         
            +
            {
         
     | 
| 
      
 411 
     | 
    
         
            +
              mysql_client_wrapper *wrapper = (mysql_client_wrapper *)arg;
         
     | 
| 
      
 412 
     | 
    
         
            +
              rb_encoding *enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
      
 413 
     | 
    
         
            +
              key = rb_str_export_to_enc(key, enc);
         
     | 
| 
      
 414 
     | 
    
         
            +
              value = rb_str_export_to_enc(value, enc);
         
     | 
| 
      
 415 
     | 
    
         
            +
             
     | 
| 
      
 416 
     | 
    
         
            +
              mysql_options4(wrapper->client, MYSQL_OPT_CONNECT_ATTR_ADD, StringValueCStr(key), StringValueCStr(value));
         
     | 
| 
      
 417 
     | 
    
         
            +
              return ST_CONTINUE;
         
     | 
| 
      
 418 
     | 
    
         
            +
            }
         
     | 
| 
      
 419 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 420 
     | 
    
         
            +
             
     | 
| 
      
 421 
     | 
    
         
            +
            static VALUE rb_mysql_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags, VALUE conn_attrs) {
         
     | 
| 
       342 
422 
     | 
    
         
             
              struct nogvl_connect_args args;
         
     | 
| 
       343 
     | 
    
         
            -
              time_t start_time, end_time;
         
     | 
| 
       344 
     | 
    
         
            -
              unsigned int elapsed_time, connect_timeout;
         
     | 
| 
      
 423 
     | 
    
         
            +
              time_t start_time, end_time, elapsed_time, connect_timeout;
         
     | 
| 
       345 
424 
     | 
    
         
             
              VALUE rv;
         
     | 
| 
       346 
425 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       347 
426 
     | 
    
         | 
| 
         @@ -354,6 +433,11 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po 
     | 
|
| 
       354 
433 
     | 
    
         
             
              args.mysql       = wrapper->client;
         
     | 
| 
       355 
434 
     | 
    
         
             
              args.client_flag = NUM2ULONG(flags);
         
     | 
| 
       356 
435 
     | 
    
         | 
| 
      
 436 
     | 
    
         
            +
            #ifdef CLIENT_CONNECT_ATTRS
         
     | 
| 
      
 437 
     | 
    
         
            +
              mysql_options(wrapper->client, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
         
     | 
| 
      
 438 
     | 
    
         
            +
              rb_hash_foreach(conn_attrs, opt_connect_attr_add_i, (VALUE)wrapper);
         
     | 
| 
      
 439 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 440 
     | 
    
         
            +
             
     | 
| 
       357 
441 
     | 
    
         
             
              if (wrapper->connect_timeout)
         
     | 
| 
       358 
442 
     | 
    
         
             
                time(&start_time);
         
     | 
| 
       359 
443 
     | 
    
         
             
              rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0);
         
     | 
| 
         @@ -368,7 +452,7 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po 
     | 
|
| 
       368 
452 
     | 
    
         
             
                    /* avoid an early timeout due to time truncating milliseconds off the start time */
         
     | 
| 
       369 
453 
     | 
    
         
             
                    if (elapsed_time > 0)
         
     | 
| 
       370 
454 
     | 
    
         
             
                      elapsed_time--;
         
     | 
| 
       371 
     | 
    
         
            -
                    if (elapsed_time >= wrapper->connect_timeout)
         
     | 
| 
      
 455 
     | 
    
         
            +
                    if (elapsed_time >= (time_t)wrapper->connect_timeout)
         
     | 
| 
       372 
456 
     | 
    
         
             
                      break;
         
     | 
| 
       373 
457 
     | 
    
         
             
                    connect_timeout = wrapper->connect_timeout - elapsed_time;
         
     | 
| 
       374 
458 
     | 
    
         
             
                    mysql_options(wrapper->client, MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout);
         
     | 
| 
         @@ -380,30 +464,41 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po 
     | 
|
| 
       380 
464 
     | 
    
         
             
                if (wrapper->connect_timeout)
         
     | 
| 
       381 
465 
     | 
    
         
             
                  mysql_options(wrapper->client, MYSQL_OPT_CONNECT_TIMEOUT, &wrapper->connect_timeout);
         
     | 
| 
       382 
466 
     | 
    
         
             
                if (rv == Qfalse)
         
     | 
| 
       383 
     | 
    
         
            -
                   
     | 
| 
      
 467 
     | 
    
         
            +
                  rb_raise_mysql2_error(wrapper);
         
     | 
| 
       384 
468 
     | 
    
         
             
              }
         
     | 
| 
       385 
469 
     | 
    
         | 
| 
       386 
470 
     | 
    
         
             
              wrapper->server_version = mysql_get_server_version(wrapper->client);
         
     | 
| 
       387 
     | 
    
         
            -
              wrapper->connected = 1;
         
     | 
| 
       388 
471 
     | 
    
         
             
              return self;
         
     | 
| 
       389 
472 
     | 
    
         
             
            }
         
     | 
| 
       390 
473 
     | 
    
         | 
| 
       391 
474 
     | 
    
         
             
            /*
         
     | 
| 
       392 
     | 
    
         
            -
             * Immediately disconnect from the server 
     | 
| 
      
 475 
     | 
    
         
            +
             * Immediately disconnect from the server; normally the garbage collector
         
     | 
| 
       393 
476 
     | 
    
         
             
             * will disconnect automatically when a connection is no longer needed.
         
     | 
| 
       394 
477 
     | 
    
         
             
             * Explicitly closing this will free up server resources sooner than waiting
         
     | 
| 
       395 
478 
     | 
    
         
             
             * for the garbage collector.
         
     | 
| 
      
 479 
     | 
    
         
            +
             *
         
     | 
| 
      
 480 
     | 
    
         
            +
             * @return [nil]
         
     | 
| 
       396 
481 
     | 
    
         
             
             */
         
     | 
| 
       397 
482 
     | 
    
         
             
            static VALUE rb_mysql_client_close(VALUE self) {
         
     | 
| 
       398 
483 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       399 
484 
     | 
    
         | 
| 
       400 
     | 
    
         
            -
              if (wrapper-> 
     | 
| 
      
 485 
     | 
    
         
            +
              if (wrapper->client) {
         
     | 
| 
       401 
486 
     | 
    
         
             
                rb_thread_call_without_gvl(nogvl_close, wrapper, RUBY_UBF_IO, 0);
         
     | 
| 
       402 
487 
     | 
    
         
             
              }
         
     | 
| 
       403 
488 
     | 
    
         | 
| 
       404 
489 
     | 
    
         
             
              return Qnil;
         
     | 
| 
       405 
490 
     | 
    
         
             
            }
         
     | 
| 
       406 
491 
     | 
    
         | 
| 
      
 492 
     | 
    
         
            +
            /* call-seq:
         
     | 
| 
      
 493 
     | 
    
         
            +
             *    client.closed?
         
     | 
| 
      
 494 
     | 
    
         
            +
             *
         
     | 
| 
      
 495 
     | 
    
         
            +
             * @return [Boolean]
         
     | 
| 
      
 496 
     | 
    
         
            +
             */
         
     | 
| 
      
 497 
     | 
    
         
            +
            static VALUE rb_mysql_client_closed(VALUE self) {
         
     | 
| 
      
 498 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 499 
     | 
    
         
            +
              return CONNECTED(wrapper) ? Qfalse : Qtrue;
         
     | 
| 
      
 500 
     | 
    
         
            +
            }
         
     | 
| 
      
 501 
     | 
    
         
            +
             
     | 
| 
       407 
502 
     | 
    
         
             
            /*
         
     | 
| 
       408 
503 
     | 
    
         
             
             * mysql_send_query is unlikely to block since most queries are small
         
     | 
| 
       409 
504 
     | 
    
         
             
             * enough to fit in a socket buffer, but sometimes large UPDATE and
         
     | 
| 
         @@ -423,8 +518,8 @@ static VALUE do_send_query(void *args) { 
     | 
|
| 
       423 
518 
     | 
    
         
             
              mysql_client_wrapper *wrapper = query_args->wrapper;
         
     | 
| 
       424 
519 
     | 
    
         
             
              if ((VALUE)rb_thread_call_without_gvl(nogvl_send_query, args, RUBY_UBF_IO, 0) == Qfalse) {
         
     | 
| 
       425 
520 
     | 
    
         
             
                /* an error occurred, we're not active anymore */
         
     | 
| 
       426 
     | 
    
         
            -
                 
     | 
| 
       427 
     | 
    
         
            -
                 
     | 
| 
      
 521 
     | 
    
         
            +
                wrapper->active_thread = Qnil;
         
     | 
| 
      
 522 
     | 
    
         
            +
                rb_raise_mysql2_error(wrapper);
         
     | 
| 
       428 
523 
     | 
    
         
             
              }
         
     | 
| 
       429 
524 
     | 
    
         
             
              return Qnil;
         
     | 
| 
       430 
525 
     | 
    
         
             
            }
         
     | 
| 
         @@ -442,10 +537,9 @@ static void *nogvl_read_query_result(void *ptr) { 
     | 
|
| 
       442 
537 
     | 
    
         
             
            }
         
     | 
| 
       443 
538 
     | 
    
         | 
| 
       444 
539 
     | 
    
         
             
            static void *nogvl_do_result(void *ptr, char use_result) {
         
     | 
| 
       445 
     | 
    
         
            -
              mysql_client_wrapper *wrapper;
         
     | 
| 
      
 540 
     | 
    
         
            +
              mysql_client_wrapper *wrapper = ptr;
         
     | 
| 
       446 
541 
     | 
    
         
             
              MYSQL_RES *result;
         
     | 
| 
       447 
542 
     | 
    
         | 
| 
       448 
     | 
    
         
            -
              wrapper = (mysql_client_wrapper *)ptr;
         
     | 
| 
       449 
543 
     | 
    
         
             
              if (use_result) {
         
     | 
| 
       450 
544 
     | 
    
         
             
                result = mysql_use_result(wrapper->client);
         
     | 
| 
       451 
545 
     | 
    
         
             
              } else {
         
     | 
| 
         @@ -486,11 +580,11 @@ static VALUE rb_mysql_client_async_result(VALUE self) { 
     | 
|
| 
       486 
580 
     | 
    
         
             
              REQUIRE_CONNECTED(wrapper);
         
     | 
| 
       487 
581 
     | 
    
         
             
              if ((VALUE)rb_thread_call_without_gvl(nogvl_read_query_result, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
         
     | 
| 
       488 
582 
     | 
    
         
             
                /* an error occurred, mark this connection inactive */
         
     | 
| 
       489 
     | 
    
         
            -
                 
     | 
| 
       490 
     | 
    
         
            -
                 
     | 
| 
      
 583 
     | 
    
         
            +
                wrapper->active_thread = Qnil;
         
     | 
| 
      
 584 
     | 
    
         
            +
                rb_raise_mysql2_error(wrapper);
         
     | 
| 
       491 
585 
     | 
    
         
             
              }
         
     | 
| 
       492 
586 
     | 
    
         | 
| 
       493 
     | 
    
         
            -
              is_streaming = rb_hash_aref( 
     | 
| 
      
 587 
     | 
    
         
            +
              is_streaming = rb_hash_aref(rb_ivar_get(self, intern_current_query_options), sym_stream);
         
     | 
| 
       494 
588 
     | 
    
         
             
              if (is_streaming == Qtrue) {
         
     | 
| 
       495 
589 
     | 
    
         
             
                result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_use_result, wrapper, RUBY_UBF_IO, 0);
         
     | 
| 
       496 
590 
     | 
    
         
             
              } else {
         
     | 
| 
         @@ -499,17 +593,20 @@ static VALUE rb_mysql_client_async_result(VALUE self) { 
     | 
|
| 
       499 
593 
     | 
    
         | 
| 
       500 
594 
     | 
    
         
             
              if (result == NULL) {
         
     | 
| 
       501 
595 
     | 
    
         
             
                if (mysql_errno(wrapper->client) != 0) {
         
     | 
| 
       502 
     | 
    
         
            -
                   
     | 
| 
      
 596 
     | 
    
         
            +
                  wrapper->active_thread = Qnil;
         
     | 
| 
       503 
597 
     | 
    
         
             
                  rb_raise_mysql2_error(wrapper);
         
     | 
| 
       504 
598 
     | 
    
         
             
                }
         
     | 
| 
       505 
599 
     | 
    
         
             
                /* no data and no error, so query was not a SELECT */
         
     | 
| 
       506 
600 
     | 
    
         
             
                return Qnil;
         
     | 
| 
       507 
601 
     | 
    
         
             
              }
         
     | 
| 
       508 
602 
     | 
    
         | 
| 
       509 
     | 
    
         
            -
               
     | 
| 
       510 
     | 
    
         
            -
               
     | 
| 
      
 603 
     | 
    
         
            +
              // Duplicate the options hash and put the copy in the Result object
         
     | 
| 
      
 604 
     | 
    
         
            +
              current = rb_hash_dup(rb_ivar_get(self, intern_current_query_options));
         
     | 
| 
      
 605 
     | 
    
         
            +
              (void)RB_GC_GUARD(current);
         
     | 
| 
       511 
606 
     | 
    
         
             
              Check_Type(current, T_HASH);
         
     | 
| 
       512 
     | 
    
         
            -
              resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result);
         
     | 
| 
      
 607 
     | 
    
         
            +
              resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result, Qnil);
         
     | 
| 
      
 608 
     | 
    
         
            +
             
     | 
| 
      
 609 
     | 
    
         
            +
              rb_mysql_set_server_query_flags(wrapper->client, resultObj);
         
     | 
| 
       513 
610 
     | 
    
         | 
| 
       514 
611 
     | 
    
         
             
              return resultObj;
         
     | 
| 
       515 
612 
     | 
    
         
             
            }
         
     | 
| 
         @@ -524,31 +621,30 @@ static VALUE disconnect_and_raise(VALUE self, VALUE error) { 
     | 
|
| 
       524 
621 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       525 
622 
     | 
    
         | 
| 
       526 
623 
     | 
    
         
             
              wrapper->active_thread = Qnil;
         
     | 
| 
       527 
     | 
    
         
            -
              wrapper->connected = 0;
         
     | 
| 
       528 
624 
     | 
    
         | 
| 
       529 
625 
     | 
    
         
             
              /* Invalidate the MySQL socket to prevent further communication.
         
     | 
| 
       530 
626 
     | 
    
         
             
               * The GC will come along later and call mysql_close to free it.
         
     | 
| 
       531 
627 
     | 
    
         
             
               */
         
     | 
| 
       532 
     | 
    
         
            -
              if ( 
     | 
| 
       533 
     | 
    
         
            -
                 
     | 
| 
       534 
     | 
    
         
            -
             
     | 
| 
      
 628 
     | 
    
         
            +
              if (CONNECTED(wrapper)) {
         
     | 
| 
      
 629 
     | 
    
         
            +
                if (invalidate_fd(wrapper->client->net.fd) == Qfalse) {
         
     | 
| 
      
 630 
     | 
    
         
            +
                  fprintf(stderr, "[WARN] mysql2 failed to invalidate FD safely, closing unsafely\n");
         
     | 
| 
      
 631 
     | 
    
         
            +
                  close(wrapper->client->net.fd);
         
     | 
| 
      
 632 
     | 
    
         
            +
                }
         
     | 
| 
      
 633 
     | 
    
         
            +
                wrapper->client->net.fd = -1;
         
     | 
| 
       535 
634 
     | 
    
         
             
              }
         
     | 
| 
       536 
635 
     | 
    
         | 
| 
       537 
636 
     | 
    
         
             
              rb_exc_raise(error);
         
     | 
| 
       538 
     | 
    
         
            -
             
     | 
| 
       539 
     | 
    
         
            -
              return Qnil;
         
     | 
| 
       540 
637 
     | 
    
         
             
            }
         
     | 
| 
       541 
638 
     | 
    
         | 
| 
       542 
639 
     | 
    
         
             
            static VALUE do_query(void *args) {
         
     | 
| 
       543 
     | 
    
         
            -
              struct async_query_args *async_args;
         
     | 
| 
      
 640 
     | 
    
         
            +
              struct async_query_args *async_args = args;
         
     | 
| 
       544 
641 
     | 
    
         
             
              struct timeval tv;
         
     | 
| 
       545 
     | 
    
         
            -
              struct timeval* 
     | 
| 
      
 642 
     | 
    
         
            +
              struct timeval *tvp;
         
     | 
| 
       546 
643 
     | 
    
         
             
              long int sec;
         
     | 
| 
       547 
644 
     | 
    
         
             
              int retval;
         
     | 
| 
       548 
645 
     | 
    
         
             
              VALUE read_timeout;
         
     | 
| 
       549 
646 
     | 
    
         | 
| 
       550 
     | 
    
         
            -
               
     | 
| 
       551 
     | 
    
         
            -
              read_timeout = rb_iv_get(async_args->self, "@read_timeout");
         
     | 
| 
      
 647 
     | 
    
         
            +
              read_timeout = rb_ivar_get(async_args->self, intern_read_timeout);
         
     | 
| 
       552 
648 
     | 
    
         | 
| 
       553 
649 
     | 
    
         
             
              tvp = NULL;
         
     | 
| 
       554 
650 
     | 
    
         
             
              if (!NIL_P(read_timeout)) {
         
     | 
| 
         @@ -569,7 +665,7 @@ static VALUE do_query(void *args) { 
     | 
|
| 
       569 
665 
     | 
    
         
             
                retval = rb_wait_for_single_fd(async_args->fd, RB_WAITFD_IN, tvp);
         
     | 
| 
       570 
666 
     | 
    
         | 
| 
       571 
667 
     | 
    
         
             
                if (retval == 0) {
         
     | 
| 
       572 
     | 
    
         
            -
                  rb_raise( 
     | 
| 
      
 668 
     | 
    
         
            +
                  rb_raise(cMysql2TimeoutError, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
         
     | 
| 
       573 
669 
     | 
    
         
             
                }
         
     | 
| 
       574 
670 
     | 
    
         | 
| 
       575 
671 
     | 
    
         
             
                if (retval < 0) {
         
     | 
| 
         @@ -583,28 +679,50 @@ static VALUE do_query(void *args) { 
     | 
|
| 
       583 
679 
     | 
    
         | 
| 
       584 
680 
     | 
    
         
             
              return Qnil;
         
     | 
| 
       585 
681 
     | 
    
         
             
            }
         
     | 
| 
       586 
     | 
    
         
            -
            # 
     | 
| 
       587 
     | 
    
         
            -
            static VALUE finish_and_mark_inactive(void *args) {
         
     | 
| 
       588 
     | 
    
         
            -
              VALUE self;
         
     | 
| 
       589 
     | 
    
         
            -
              MYSQL_RES *result;
         
     | 
| 
       590 
     | 
    
         
            -
             
     | 
| 
       591 
     | 
    
         
            -
              self = (VALUE)args;
         
     | 
| 
      
 682 
     | 
    
         
            +
            #endif
         
     | 
| 
       592 
683 
     | 
    
         | 
| 
      
 684 
     | 
    
         
            +
            static VALUE disconnect_and_mark_inactive(VALUE self) {
         
     | 
| 
       593 
685 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       594 
686 
     | 
    
         | 
| 
      
 687 
     | 
    
         
            +
              /* Check if execution terminated while result was still being read. */
         
     | 
| 
       595 
688 
     | 
    
         
             
              if (!NIL_P(wrapper->active_thread)) {
         
     | 
| 
       596 
     | 
    
         
            -
                 
     | 
| 
       597 
     | 
    
         
            -
             
     | 
| 
       598 
     | 
    
         
            -
             
     | 
| 
       599 
     | 
    
         
            -
             
     | 
| 
       600 
     | 
    
         
            -
             
     | 
| 
       601 
     | 
    
         
            -
             
     | 
| 
      
 689 
     | 
    
         
            +
                if (CONNECTED(wrapper)) {
         
     | 
| 
      
 690 
     | 
    
         
            +
                  /* Invalidate the MySQL socket to prevent further communication. */
         
     | 
| 
      
 691 
     | 
    
         
            +
            #ifndef _WIN32
         
     | 
| 
      
 692 
     | 
    
         
            +
                  if (invalidate_fd(wrapper->client->net.fd) == Qfalse) {
         
     | 
| 
      
 693 
     | 
    
         
            +
                    rb_warn("mysql2 failed to invalidate FD safely, closing unsafely\n");
         
     | 
| 
      
 694 
     | 
    
         
            +
                    close(wrapper->client->net.fd);
         
     | 
| 
      
 695 
     | 
    
         
            +
                  }
         
     | 
| 
      
 696 
     | 
    
         
            +
            #else
         
     | 
| 
      
 697 
     | 
    
         
            +
                  close(wrapper->client->net.fd);
         
     | 
| 
      
 698 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 699 
     | 
    
         
            +
                  wrapper->client->net.fd = -1;
         
     | 
| 
      
 700 
     | 
    
         
            +
                }
         
     | 
| 
      
 701 
     | 
    
         
            +
                /* Skip mysql client check performed before command execution. */
         
     | 
| 
      
 702 
     | 
    
         
            +
                wrapper->client->status = MYSQL_STATUS_READY;
         
     | 
| 
       602 
703 
     | 
    
         
             
                wrapper->active_thread = Qnil;
         
     | 
| 
       603 
704 
     | 
    
         
             
              }
         
     | 
| 
       604 
705 
     | 
    
         | 
| 
       605 
706 
     | 
    
         
             
              return Qnil;
         
     | 
| 
       606 
707 
     | 
    
         
             
            }
         
     | 
| 
       607 
     | 
    
         
            -
             
     | 
| 
      
 708 
     | 
    
         
            +
             
     | 
| 
      
 709 
     | 
    
         
            +
            void rb_mysql_client_set_active_thread(VALUE self) {
         
     | 
| 
      
 710 
     | 
    
         
            +
              VALUE thread_current = rb_thread_current();
         
     | 
| 
      
 711 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 712 
     | 
    
         
            +
             
     | 
| 
      
 713 
     | 
    
         
            +
              // see if this connection is still waiting on a result from a previous query
         
     | 
| 
      
 714 
     | 
    
         
            +
              if (NIL_P(wrapper->active_thread)) {
         
     | 
| 
      
 715 
     | 
    
         
            +
                // mark this connection active
         
     | 
| 
      
 716 
     | 
    
         
            +
                wrapper->active_thread = thread_current;
         
     | 
| 
      
 717 
     | 
    
         
            +
              } else if (wrapper->active_thread == thread_current) {
         
     | 
| 
      
 718 
     | 
    
         
            +
                rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
         
     | 
| 
      
 719 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 720 
     | 
    
         
            +
                VALUE inspect = rb_inspect(wrapper->active_thread);
         
     | 
| 
      
 721 
     | 
    
         
            +
                const char *thr = StringValueCStr(inspect);
         
     | 
| 
      
 722 
     | 
    
         
            +
             
     | 
| 
      
 723 
     | 
    
         
            +
                rb_raise(cMysql2Error, "This connection is in use by: %s", thr);
         
     | 
| 
      
 724 
     | 
    
         
            +
              }
         
     | 
| 
      
 725 
     | 
    
         
            +
            }
         
     | 
| 
       608 
726 
     | 
    
         | 
| 
       609 
727 
     | 
    
         
             
            /* call-seq:
         
     | 
| 
       610 
728 
     | 
    
         
             
             *    client.abandon_results!
         
     | 
| 
         @@ -640,80 +758,49 @@ static VALUE rb_mysql_client_abandon_results(VALUE self) { 
     | 
|
| 
       640 
758 
     | 
    
         
             
             *    client.query(sql, options = {})
         
     | 
| 
       641 
759 
     | 
    
         
             
             *
         
     | 
| 
       642 
760 
     | 
    
         
             
             * Query the database with +sql+, with optional +options+.  For the possible
         
     | 
| 
       643 
     | 
    
         
            -
             * options, see  
     | 
| 
      
 761 
     | 
    
         
            +
             * options, see default_query_options on the Mysql2::Client class.
         
     | 
| 
       644 
762 
     | 
    
         
             
             */
         
     | 
| 
       645 
     | 
    
         
            -
            static VALUE  
     | 
| 
      
 763 
     | 
    
         
            +
            static VALUE rb_mysql_query(VALUE self, VALUE sql, VALUE current) {
         
     | 
| 
       646 
764 
     | 
    
         
             
            #ifndef _WIN32
         
     | 
| 
       647 
765 
     | 
    
         
             
              struct async_query_args async_args;
         
     | 
| 
       648 
766 
     | 
    
         
             
            #endif
         
     | 
| 
       649 
767 
     | 
    
         
             
              struct nogvl_send_query_args args;
         
     | 
| 
       650 
     | 
    
         
            -
              int async = 0;
         
     | 
| 
       651 
     | 
    
         
            -
              VALUE opts, current;
         
     | 
| 
       652 
     | 
    
         
            -
              VALUE thread_current = rb_thread_current();
         
     | 
| 
       653 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       654 
     | 
    
         
            -
              rb_encoding *conn_enc;
         
     | 
| 
       655 
     | 
    
         
            -
            #endif
         
     | 
| 
       656 
768 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       657 
769 
     | 
    
         | 
| 
       658 
770 
     | 
    
         
             
              REQUIRE_CONNECTED(wrapper);
         
     | 
| 
       659 
771 
     | 
    
         
             
              args.mysql = wrapper->client;
         
     | 
| 
       660 
772 
     | 
    
         | 
| 
       661 
     | 
    
         
            -
               
     | 
| 
       662 
     | 
    
         
            -
              RB_GC_GUARD(current);
         
     | 
| 
      
 773 
     | 
    
         
            +
              (void)RB_GC_GUARD(current);
         
     | 
| 
       663 
774 
     | 
    
         
             
              Check_Type(current, T_HASH);
         
     | 
| 
       664 
     | 
    
         
            -
               
     | 
| 
      
 775 
     | 
    
         
            +
              rb_ivar_set(self, intern_current_query_options, current);
         
     | 
| 
       665 
776 
     | 
    
         | 
| 
       666 
     | 
    
         
            -
               
     | 
| 
       667 
     | 
    
         
            -
                rb_funcall(current, intern_merge_bang, 1, opts);
         
     | 
| 
       668 
     | 
    
         
            -
             
     | 
| 
       669 
     | 
    
         
            -
                if (rb_hash_aref(current, sym_async) == Qtrue) {
         
     | 
| 
       670 
     | 
    
         
            -
                  async = 1;
         
     | 
| 
       671 
     | 
    
         
            -
                }
         
     | 
| 
       672 
     | 
    
         
            -
              }
         
     | 
| 
       673 
     | 
    
         
            -
             
     | 
| 
       674 
     | 
    
         
            -
              Check_Type(args.sql, T_STRING);
         
     | 
| 
       675 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       676 
     | 
    
         
            -
              conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
      
 777 
     | 
    
         
            +
              Check_Type(sql, T_STRING);
         
     | 
| 
       677 
778 
     | 
    
         
             
              /* ensure the string is in the encoding the connection is expecting */
         
     | 
| 
       678 
     | 
    
         
            -
              args.sql = rb_str_export_to_enc( 
     | 
| 
       679 
     | 
    
         
            -
            #endif
         
     | 
| 
      
 779 
     | 
    
         
            +
              args.sql = rb_str_export_to_enc(sql, rb_to_encoding(wrapper->encoding));
         
     | 
| 
       680 
780 
     | 
    
         
             
              args.sql_ptr = RSTRING_PTR(args.sql);
         
     | 
| 
       681 
781 
     | 
    
         
             
              args.sql_len = RSTRING_LEN(args.sql);
         
     | 
| 
       682 
     | 
    
         
            -
             
     | 
| 
       683 
     | 
    
         
            -
              /* see if this connection is still waiting on a result from a previous query */
         
     | 
| 
       684 
     | 
    
         
            -
              if (NIL_P(wrapper->active_thread)) {
         
     | 
| 
       685 
     | 
    
         
            -
                /* mark this connection active */
         
     | 
| 
       686 
     | 
    
         
            -
                wrapper->active_thread = thread_current;
         
     | 
| 
       687 
     | 
    
         
            -
              } else if (wrapper->active_thread == thread_current) {
         
     | 
| 
       688 
     | 
    
         
            -
                rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
         
     | 
| 
       689 
     | 
    
         
            -
              } else {
         
     | 
| 
       690 
     | 
    
         
            -
                VALUE inspect = rb_inspect(wrapper->active_thread);
         
     | 
| 
       691 
     | 
    
         
            -
                const char *thr = StringValueCStr(inspect);
         
     | 
| 
       692 
     | 
    
         
            -
             
     | 
| 
       693 
     | 
    
         
            -
                rb_raise(cMysql2Error, "This connection is in use by: %s", thr);
         
     | 
| 
       694 
     | 
    
         
            -
                RB_GC_GUARD(inspect);
         
     | 
| 
       695 
     | 
    
         
            -
              }
         
     | 
| 
       696 
     | 
    
         
            -
             
     | 
| 
       697 
782 
     | 
    
         
             
              args.wrapper = wrapper;
         
     | 
| 
       698 
783 
     | 
    
         | 
| 
      
 784 
     | 
    
         
            +
              rb_mysql_client_set_active_thread(self);
         
     | 
| 
      
 785 
     | 
    
         
            +
             
     | 
| 
       699 
786 
     | 
    
         
             
            #ifndef _WIN32
         
     | 
| 
       700 
787 
     | 
    
         
             
              rb_rescue2(do_send_query, (VALUE)&args, disconnect_and_raise, self, rb_eException, (VALUE)0);
         
     | 
| 
       701 
788 
     | 
    
         | 
| 
       702 
     | 
    
         
            -
              if ( 
     | 
| 
      
 789 
     | 
    
         
            +
              if (rb_hash_aref(current, sym_async) == Qtrue) {
         
     | 
| 
      
 790 
     | 
    
         
            +
                return Qnil;
         
     | 
| 
      
 791 
     | 
    
         
            +
              } else {
         
     | 
| 
       703 
792 
     | 
    
         
             
                async_args.fd = wrapper->client->net.fd;
         
     | 
| 
       704 
793 
     | 
    
         
             
                async_args.self = self;
         
     | 
| 
       705 
794 
     | 
    
         | 
| 
       706 
795 
     | 
    
         
             
                rb_rescue2(do_query, (VALUE)&async_args, disconnect_and_raise, self, rb_eException, (VALUE)0);
         
     | 
| 
       707 
796 
     | 
    
         | 
| 
       708 
     | 
    
         
            -
                return rb_mysql_client_async_result 
     | 
| 
       709 
     | 
    
         
            -
              } else {
         
     | 
| 
       710 
     | 
    
         
            -
                return Qnil;
         
     | 
| 
      
 797 
     | 
    
         
            +
                return rb_ensure(rb_mysql_client_async_result, self, disconnect_and_mark_inactive, self);
         
     | 
| 
       711 
798 
     | 
    
         
             
              }
         
     | 
| 
       712 
799 
     | 
    
         
             
            #else
         
     | 
| 
       713 
800 
     | 
    
         
             
              do_send_query(&args);
         
     | 
| 
       714 
801 
     | 
    
         | 
| 
       715 
802 
     | 
    
         
             
              /* this will just block until the result is ready */
         
     | 
| 
       716 
     | 
    
         
            -
              return rb_ensure(rb_mysql_client_async_result, self,  
     | 
| 
      
 803 
     | 
    
         
            +
              return rb_ensure(rb_mysql_client_async_result, self, disconnect_and_mark_inactive, self);
         
     | 
| 
       717 
804 
     | 
    
         
             
            #endif
         
     | 
| 
       718 
805 
     | 
    
         
             
            }
         
     | 
| 
       719 
806 
     | 
    
         | 
| 
         @@ -726,20 +813,16 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) { 
     | 
|
| 
       726 
813 
     | 
    
         
             
              unsigned char *newStr;
         
     | 
| 
       727 
814 
     | 
    
         
             
              VALUE rb_str;
         
     | 
| 
       728 
815 
     | 
    
         
             
              unsigned long newLen, oldLen;
         
     | 
| 
       729 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       730 
816 
     | 
    
         
             
              rb_encoding *default_internal_enc;
         
     | 
| 
       731 
817 
     | 
    
         
             
              rb_encoding *conn_enc;
         
     | 
| 
       732 
     | 
    
         
            -
            #endif
         
     | 
| 
       733 
818 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       734 
819 
     | 
    
         | 
| 
       735 
820 
     | 
    
         
             
              REQUIRE_CONNECTED(wrapper);
         
     | 
| 
       736 
821 
     | 
    
         
             
              Check_Type(str, T_STRING);
         
     | 
| 
       737 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       738 
822 
     | 
    
         
             
              default_internal_enc = rb_default_internal_encoding();
         
     | 
| 
       739 
823 
     | 
    
         
             
              conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
       740 
824 
     | 
    
         
             
              /* ensure the string is in the encoding the connection is expecting */
         
     | 
| 
       741 
825 
     | 
    
         
             
              str = rb_str_export_to_enc(str, conn_enc);
         
     | 
| 
       742 
     | 
    
         
            -
            #endif
         
     | 
| 
       743 
826 
     | 
    
         | 
| 
       744 
827 
     | 
    
         
             
              oldLen = RSTRING_LEN(str);
         
     | 
| 
       745 
828 
     | 
    
         
             
              newStr = xmalloc(oldLen*2+1);
         
     | 
| 
         @@ -747,21 +830,17 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) { 
     | 
|
| 
       747 
830 
     | 
    
         
             
              newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, RSTRING_PTR(str), oldLen);
         
     | 
| 
       748 
831 
     | 
    
         
             
              if (newLen == oldLen) {
         
     | 
| 
       749 
832 
     | 
    
         
             
                /* no need to return a new ruby string if nothing changed */
         
     | 
| 
       750 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       751 
833 
     | 
    
         
             
                if (default_internal_enc) {
         
     | 
| 
       752 
834 
     | 
    
         
             
                  str = rb_str_export_to_enc(str, default_internal_enc);
         
     | 
| 
       753 
835 
     | 
    
         
             
                }
         
     | 
| 
       754 
     | 
    
         
            -
            #endif
         
     | 
| 
       755 
836 
     | 
    
         
             
                xfree(newStr);
         
     | 
| 
       756 
837 
     | 
    
         
             
                return str;
         
     | 
| 
       757 
838 
     | 
    
         
             
              } else {
         
     | 
| 
       758 
839 
     | 
    
         
             
                rb_str = rb_str_new((const char*)newStr, newLen);
         
     | 
| 
       759 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       760 
840 
     | 
    
         
             
                rb_enc_associate(rb_str, conn_enc);
         
     | 
| 
       761 
841 
     | 
    
         
             
                if (default_internal_enc) {
         
     | 
| 
       762 
842 
     | 
    
         
             
                  rb_str = rb_str_export_to_enc(rb_str, default_internal_enc);
         
     | 
| 
       763 
843 
     | 
    
         
             
                }
         
     | 
| 
       764 
     | 
    
         
            -
            #endif
         
     | 
| 
       765 
844 
     | 
    
         
             
                xfree(newStr);
         
     | 
| 
       766 
845 
     | 
    
         
             
                return rb_str;
         
     | 
| 
       767 
846 
     | 
    
         
             
              }
         
     | 
| 
         @@ -807,10 +886,12 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) { 
     | 
|
| 
       807 
886 
     | 
    
         
             
                  retval = &boolval;
         
     | 
| 
       808 
887 
     | 
    
         
             
                  break;
         
     | 
| 
       809 
888 
     | 
    
         | 
| 
      
 889 
     | 
    
         
            +
            #ifdef MYSQL_SECURE_AUTH
         
     | 
| 
       810 
890 
     | 
    
         
             
                case MYSQL_SECURE_AUTH:
         
     | 
| 
       811 
891 
     | 
    
         
             
                  boolval = (value == Qfalse ? 0 : 1);
         
     | 
| 
       812 
892 
     | 
    
         
             
                  retval = &boolval;
         
     | 
| 
       813 
893 
     | 
    
         
             
                  break;
         
     | 
| 
      
 894 
     | 
    
         
            +
            #endif
         
     | 
| 
       814 
895 
     | 
    
         | 
| 
       815 
896 
     | 
    
         
             
                case MYSQL_READ_DEFAULT_FILE:
         
     | 
| 
       816 
897 
     | 
    
         
             
                  charval = (const char *)StringValueCStr(value);
         
     | 
| 
         @@ -827,6 +908,18 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) { 
     | 
|
| 
       827 
908 
     | 
    
         
             
                  retval  = charval;
         
     | 
| 
       828 
909 
     | 
    
         
             
                  break;
         
     | 
| 
       829 
910 
     | 
    
         | 
| 
      
 911 
     | 
    
         
            +
                case MYSQL_DEFAULT_AUTH:
         
     | 
| 
      
 912 
     | 
    
         
            +
                  charval = (const char *)StringValueCStr(value);
         
     | 
| 
      
 913 
     | 
    
         
            +
                  retval  = charval;
         
     | 
| 
      
 914 
     | 
    
         
            +
                  break;
         
     | 
| 
      
 915 
     | 
    
         
            +
             
     | 
| 
      
 916 
     | 
    
         
            +
            #ifdef HAVE_CONST_MYSQL_ENABLE_CLEARTEXT_PLUGIN
         
     | 
| 
      
 917 
     | 
    
         
            +
                case MYSQL_ENABLE_CLEARTEXT_PLUGIN:
         
     | 
| 
      
 918 
     | 
    
         
            +
                  boolval = (value == Qfalse ? 0 : 1);
         
     | 
| 
      
 919 
     | 
    
         
            +
                  retval = &boolval;
         
     | 
| 
      
 920 
     | 
    
         
            +
                  break;
         
     | 
| 
      
 921 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 922 
     | 
    
         
            +
             
     | 
| 
       830 
923 
     | 
    
         
             
                default:
         
     | 
| 
       831 
924 
     | 
    
         
             
                  return Qfalse;
         
     | 
| 
       832 
925 
     | 
    
         
             
              }
         
     | 
| 
         @@ -863,10 +956,8 @@ static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE klass) { 
     | 
|
| 
       863 
956 
     | 
    
         
             
              version = rb_str_new2(mysql_get_client_info());
         
     | 
| 
       864 
957 
     | 
    
         
             
              header_version = rb_str_new2(MYSQL_LINK_VERSION);
         
     | 
| 
       865 
958 
     | 
    
         | 
| 
       866 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       867 
959 
     | 
    
         
             
              rb_enc_associate(version, rb_usascii_encoding());
         
     | 
| 
       868 
960 
     | 
    
         
             
              rb_enc_associate(header_version, rb_usascii_encoding());
         
     | 
| 
       869 
     | 
    
         
            -
            #endif
         
     | 
| 
       870 
961 
     | 
    
         | 
| 
       871 
962 
     | 
    
         
             
              rb_hash_aset(version_info, sym_id, LONG2NUM(mysql_get_client_version()));
         
     | 
| 
       872 
963 
     | 
    
         
             
              rb_hash_aset(version_info, sym_version, version);
         
     | 
| 
         @@ -882,27 +973,21 @@ static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE klass) { 
     | 
|
| 
       882 
973 
     | 
    
         
             
             */
         
     | 
| 
       883 
974 
     | 
    
         
             
            static VALUE rb_mysql_client_server_info(VALUE self) {
         
     | 
| 
       884 
975 
     | 
    
         
             
              VALUE version, server_info;
         
     | 
| 
       885 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       886 
976 
     | 
    
         
             
              rb_encoding *default_internal_enc;
         
     | 
| 
       887 
977 
     | 
    
         
             
              rb_encoding *conn_enc;
         
     | 
| 
       888 
     | 
    
         
            -
            #endif
         
     | 
| 
       889 
978 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       890 
979 
     | 
    
         | 
| 
       891 
980 
     | 
    
         
             
              REQUIRE_CONNECTED(wrapper);
         
     | 
| 
       892 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       893 
981 
     | 
    
         
             
              default_internal_enc = rb_default_internal_encoding();
         
     | 
| 
       894 
982 
     | 
    
         
             
              conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
       895 
     | 
    
         
            -
            #endif
         
     | 
| 
       896 
983 
     | 
    
         | 
| 
       897 
984 
     | 
    
         
             
              version = rb_hash_new();
         
     | 
| 
       898 
985 
     | 
    
         
             
              rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_server_version(wrapper->client)));
         
     | 
| 
       899 
986 
     | 
    
         
             
              server_info = rb_str_new2(mysql_get_server_info(wrapper->client));
         
     | 
| 
       900 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       901 
987 
     | 
    
         
             
              rb_enc_associate(server_info, conn_enc);
         
     | 
| 
       902 
988 
     | 
    
         
             
              if (default_internal_enc) {
         
     | 
| 
       903 
989 
     | 
    
         
             
                server_info = rb_str_export_to_enc(server_info, default_internal_enc);
         
     | 
| 
       904 
990 
     | 
    
         
             
              }
         
     | 
| 
       905 
     | 
    
         
            -
            #endif
         
     | 
| 
       906 
991 
     | 
    
         
             
              rb_hash_aset(version, sym_version, server_info);
         
     | 
| 
       907 
992 
     | 
    
         
             
              return version;
         
     | 
| 
       908 
993 
     | 
    
         
             
            }
         
     | 
| 
         @@ -912,15 +997,17 @@ static VALUE rb_mysql_client_server_info(VALUE self) { 
     | 
|
| 
       912 
997 
     | 
    
         
             
             *
         
     | 
| 
       913 
998 
     | 
    
         
             
             * Return the file descriptor number for this client.
         
     | 
| 
       914 
999 
     | 
    
         
             
             */
         
     | 
| 
       915 
     | 
    
         
            -
            static VALUE rb_mysql_client_socket(VALUE self) {
         
     | 
| 
       916 
1000 
     | 
    
         
             
            #ifndef _WIN32
         
     | 
| 
      
 1001 
     | 
    
         
            +
            static VALUE rb_mysql_client_socket(VALUE self) {
         
     | 
| 
       917 
1002 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       918 
1003 
     | 
    
         
             
              REQUIRE_CONNECTED(wrapper);
         
     | 
| 
       919 
1004 
     | 
    
         
             
              return INT2NUM(wrapper->client->net.fd);
         
     | 
| 
      
 1005 
     | 
    
         
            +
            }
         
     | 
| 
       920 
1006 
     | 
    
         
             
            #else
         
     | 
| 
      
 1007 
     | 
    
         
            +
            static VALUE rb_mysql_client_socket(RB_MYSQL_UNUSED VALUE self) {
         
     | 
| 
       921 
1008 
     | 
    
         
             
              rb_raise(cMysql2Error, "Raw access to the mysql file descriptor isn't supported on Windows");
         
     | 
| 
       922 
     | 
    
         
            -
            #endif
         
     | 
| 
       923 
1009 
     | 
    
         
             
            }
         
     | 
| 
      
 1010 
     | 
    
         
            +
            #endif
         
     | 
| 
       924 
1011 
     | 
    
         | 
| 
       925 
1012 
     | 
    
         
             
            /* call-seq:
         
     | 
| 
       926 
1013 
     | 
    
         
             
             *    client.last_id
         
     | 
| 
         @@ -1014,13 +1101,30 @@ static void *nogvl_ping(void *ptr) { 
     | 
|
| 
       1014 
1101 
     | 
    
         
             
            static VALUE rb_mysql_client_ping(VALUE self) {
         
     | 
| 
       1015 
1102 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       1016 
1103 
     | 
    
         | 
| 
       1017 
     | 
    
         
            -
              if (!wrapper 
     | 
| 
      
 1104 
     | 
    
         
            +
              if (!CONNECTED(wrapper)) {
         
     | 
| 
       1018 
1105 
     | 
    
         
             
                return Qfalse;
         
     | 
| 
       1019 
1106 
     | 
    
         
             
              } else {
         
     | 
| 
       1020 
1107 
     | 
    
         
             
                return (VALUE)rb_thread_call_without_gvl(nogvl_ping, wrapper->client, RUBY_UBF_IO, 0);
         
     | 
| 
       1021 
1108 
     | 
    
         
             
              }
         
     | 
| 
       1022 
1109 
     | 
    
         
             
            }
         
     | 
| 
       1023 
1110 
     | 
    
         | 
| 
      
 1111 
     | 
    
         
            +
            /* call-seq:
         
     | 
| 
      
 1112 
     | 
    
         
            +
             *    client.set_server_option(value)
         
     | 
| 
      
 1113 
     | 
    
         
            +
             *
         
     | 
| 
      
 1114 
     | 
    
         
            +
             * Enables or disables an option for the connection.
         
     | 
| 
      
 1115 
     | 
    
         
            +
             * Read https://dev.mysql.com/doc/refman/5.7/en/mysql-set-server-option.html
         
     | 
| 
      
 1116 
     | 
    
         
            +
             * for more information.
         
     | 
| 
      
 1117 
     | 
    
         
            +
             */
         
     | 
| 
      
 1118 
     | 
    
         
            +
            static VALUE rb_mysql_client_set_server_option(VALUE self, VALUE value) {
         
     | 
| 
      
 1119 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 1120 
     | 
    
         
            +
             
     | 
| 
      
 1121 
     | 
    
         
            +
              if (mysql_set_server_option(wrapper->client, NUM2INT(value)) == 0) {
         
     | 
| 
      
 1122 
     | 
    
         
            +
                return Qtrue;
         
     | 
| 
      
 1123 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 1124 
     | 
    
         
            +
                return Qfalse;
         
     | 
| 
      
 1125 
     | 
    
         
            +
              }
         
     | 
| 
      
 1126 
     | 
    
         
            +
            }
         
     | 
| 
      
 1127 
     | 
    
         
            +
             
     | 
| 
       1024 
1128 
     | 
    
         
             
            /* call-seq:
         
     | 
| 
       1025 
1129 
     | 
    
         
             
             *    client.more_results?
         
     | 
| 
       1026 
1130 
     | 
    
         
             
             *
         
     | 
| 
         @@ -1029,10 +1133,10 @@ static VALUE rb_mysql_client_ping(VALUE self) { 
     | 
|
| 
       1029 
1133 
     | 
    
         
             
            static VALUE rb_mysql_client_more_results(VALUE self)
         
     | 
| 
       1030 
1134 
     | 
    
         
             
            {
         
     | 
| 
       1031 
1135 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       1032 
     | 
    
         
            -
             
     | 
| 
       1033 
     | 
    
         
            -
             
     | 
| 
       1034 
     | 
    
         
            -
             
     | 
| 
       1035 
     | 
    
         
            -
             
     | 
| 
      
 1136 
     | 
    
         
            +
              if (mysql_more_results(wrapper->client) == 0)
         
     | 
| 
      
 1137 
     | 
    
         
            +
                return Qfalse;
         
     | 
| 
      
 1138 
     | 
    
         
            +
              else
         
     | 
| 
      
 1139 
     | 
    
         
            +
                return Qtrue;
         
     | 
| 
       1036 
1140 
     | 
    
         
             
            }
         
     | 
| 
       1037 
1141 
     | 
    
         | 
| 
       1038 
1142 
     | 
    
         
             
            /* call-seq:
         
     | 
| 
         @@ -1079,15 +1183,15 @@ static VALUE rb_mysql_client_store_result(VALUE self) 
     | 
|
| 
       1079 
1183 
     | 
    
         
             
                return Qnil;
         
     | 
| 
       1080 
1184 
     | 
    
         
             
              }
         
     | 
| 
       1081 
1185 
     | 
    
         | 
| 
       1082 
     | 
    
         
            -
               
     | 
| 
       1083 
     | 
    
         
            -
               
     | 
| 
      
 1186 
     | 
    
         
            +
              // Duplicate the options hash and put the copy in the Result object
         
     | 
| 
      
 1187 
     | 
    
         
            +
              current = rb_hash_dup(rb_ivar_get(self, intern_current_query_options));
         
     | 
| 
      
 1188 
     | 
    
         
            +
              (void)RB_GC_GUARD(current);
         
     | 
| 
       1084 
1189 
     | 
    
         
             
              Check_Type(current, T_HASH);
         
     | 
| 
       1085 
     | 
    
         
            -
              resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result);
         
     | 
| 
      
 1190 
     | 
    
         
            +
              resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result, Qnil);
         
     | 
| 
       1086 
1191 
     | 
    
         | 
| 
       1087 
1192 
     | 
    
         
             
              return resultObj;
         
     | 
| 
       1088 
1193 
     | 
    
         
             
            }
         
     | 
| 
       1089 
1194 
     | 
    
         | 
| 
       1090 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       1091 
1195 
     | 
    
         
             
            /* call-seq:
         
     | 
| 
       1092 
1196 
     | 
    
         
             
             *    client.encoding
         
     | 
| 
       1093 
1197 
     | 
    
         
             
             *
         
     | 
| 
         @@ -1097,7 +1201,39 @@ static VALUE rb_mysql_client_encoding(VALUE self) { 
     | 
|
| 
       1097 
1201 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       1098 
1202 
     | 
    
         
             
              return wrapper->encoding;
         
     | 
| 
       1099 
1203 
     | 
    
         
             
            }
         
     | 
| 
      
 1204 
     | 
    
         
            +
             
     | 
| 
      
 1205 
     | 
    
         
            +
            /* call-seq:
         
     | 
| 
      
 1206 
     | 
    
         
            +
             *    client.automatic_close?
         
     | 
| 
      
 1207 
     | 
    
         
            +
             *
         
     | 
| 
      
 1208 
     | 
    
         
            +
             * @return [Boolean]
         
     | 
| 
      
 1209 
     | 
    
         
            +
             */
         
     | 
| 
      
 1210 
     | 
    
         
            +
            static VALUE get_automatic_close(VALUE self) {
         
     | 
| 
      
 1211 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 1212 
     | 
    
         
            +
              return wrapper->automatic_close ? Qtrue : Qfalse;
         
     | 
| 
      
 1213 
     | 
    
         
            +
            }
         
     | 
| 
      
 1214 
     | 
    
         
            +
             
     | 
| 
      
 1215 
     | 
    
         
            +
            /* call-seq:
         
     | 
| 
      
 1216 
     | 
    
         
            +
             *    client.automatic_close = false
         
     | 
| 
      
 1217 
     | 
    
         
            +
             *
         
     | 
| 
      
 1218 
     | 
    
         
            +
             * Set this to +false+ to leave the connection open after it is garbage
         
     | 
| 
      
 1219 
     | 
    
         
            +
             * collected. To avoid "Aborted connection" errors on the server, explicitly
         
     | 
| 
      
 1220 
     | 
    
         
            +
             * call +close+ when the connection is no longer needed.
         
     | 
| 
      
 1221 
     | 
    
         
            +
             *
         
     | 
| 
      
 1222 
     | 
    
         
            +
             * @see http://dev.mysql.com/doc/en/communication-errors.html
         
     | 
| 
      
 1223 
     | 
    
         
            +
             */
         
     | 
| 
      
 1224 
     | 
    
         
            +
            static VALUE set_automatic_close(VALUE self, VALUE value) {
         
     | 
| 
      
 1225 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 1226 
     | 
    
         
            +
              if (RTEST(value)) {
         
     | 
| 
      
 1227 
     | 
    
         
            +
                wrapper->automatic_close = 1;
         
     | 
| 
      
 1228 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 1229 
     | 
    
         
            +
            #ifndef _WIN32
         
     | 
| 
      
 1230 
     | 
    
         
            +
                wrapper->automatic_close = 0;
         
     | 
| 
      
 1231 
     | 
    
         
            +
            #else
         
     | 
| 
      
 1232 
     | 
    
         
            +
                rb_warn("Connections are always closed by garbage collector on Windows");
         
     | 
| 
       1100 
1233 
     | 
    
         
             
            #endif
         
     | 
| 
      
 1234 
     | 
    
         
            +
              }
         
     | 
| 
      
 1235 
     | 
    
         
            +
              return value;
         
     | 
| 
      
 1236 
     | 
    
         
            +
            }
         
     | 
| 
       1101 
1237 
     | 
    
         | 
| 
       1102 
1238 
     | 
    
         
             
            /* call-seq:
         
     | 
| 
       1103 
1239 
     | 
    
         
             
             *    client.reconnect = true
         
     | 
| 
         @@ -1134,7 +1270,7 @@ static VALUE set_read_timeout(VALUE self, VALUE value) { 
     | 
|
| 
       1134 
1270 
     | 
    
         
             
              /* Set the instance variable here even though _mysql_client_options
         
     | 
| 
       1135 
1271 
     | 
    
         
             
                 might not succeed, because the timeout is used in other ways
         
     | 
| 
       1136 
1272 
     | 
    
         
             
                 elsewhere */
         
     | 
| 
       1137 
     | 
    
         
            -
               
     | 
| 
      
 1273 
     | 
    
         
            +
              rb_ivar_set(self, intern_read_timeout, value);
         
     | 
| 
       1138 
1274 
     | 
    
         
             
              return _mysql_client_options(self, MYSQL_OPT_READ_TIMEOUT, value);
         
     | 
| 
       1139 
1275 
     | 
    
         
             
            }
         
     | 
| 
       1140 
1276 
     | 
    
         | 
| 
         @@ -1150,19 +1286,15 @@ static VALUE set_write_timeout(VALUE self, VALUE value) { 
     | 
|
| 
       1150 
1286 
     | 
    
         | 
| 
       1151 
1287 
     | 
    
         
             
            static VALUE set_charset_name(VALUE self, VALUE value) {
         
     | 
| 
       1152 
1288 
     | 
    
         
             
              char *charset_name;
         
     | 
| 
       1153 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       1154 
     | 
    
         
            -
              size_t charset_name_len;
         
     | 
| 
       1155 
1289 
     | 
    
         
             
              const struct mysql2_mysql_enc_name_to_rb_map *mysql2rb;
         
     | 
| 
       1156 
1290 
     | 
    
         
             
              rb_encoding *enc;
         
     | 
| 
       1157 
1291 
     | 
    
         
             
              VALUE rb_enc;
         
     | 
| 
       1158 
     | 
    
         
            -
            #endif
         
     | 
| 
       1159 
1292 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       1160 
1293 
     | 
    
         | 
| 
      
 1294 
     | 
    
         
            +
              Check_Type(value, T_STRING);
         
     | 
| 
       1161 
1295 
     | 
    
         
             
              charset_name = RSTRING_PTR(value);
         
     | 
| 
       1162 
1296 
     | 
    
         | 
| 
       1163 
     | 
    
         
            -
             
     | 
| 
       1164 
     | 
    
         
            -
              charset_name_len = RSTRING_LEN(value);
         
     | 
| 
       1165 
     | 
    
         
            -
              mysql2rb = mysql2_mysql_enc_name_to_rb(charset_name, charset_name_len);
         
     | 
| 
      
 1297 
     | 
    
         
            +
              mysql2rb = mysql2_mysql_enc_name_to_rb(charset_name, (unsigned int)RSTRING_LEN(value));
         
     | 
| 
       1166 
1298 
     | 
    
         
             
              if (mysql2rb == NULL || mysql2rb->rb_name == NULL) {
         
     | 
| 
       1167 
1299 
     | 
    
         
             
                VALUE inspect = rb_inspect(value);
         
     | 
| 
       1168 
1300 
     | 
    
         
             
                rb_raise(cMysql2Error, "Unsupported charset: '%s'", RSTRING_PTR(inspect));
         
     | 
| 
         @@ -1171,7 +1303,6 @@ static VALUE set_charset_name(VALUE self, VALUE value) { 
     | 
|
| 
       1171 
1303 
     | 
    
         
             
                rb_enc = rb_enc_from_encoding(enc);
         
     | 
| 
       1172 
1304 
     | 
    
         
             
                wrapper->encoding = rb_enc;
         
     | 
| 
       1173 
1305 
     | 
    
         
             
              }
         
     | 
| 
       1174 
     | 
    
         
            -
            #endif
         
     | 
| 
       1175 
1306 
     | 
    
         | 
| 
       1176 
1307 
     | 
    
         
             
              if (mysql_options(wrapper->client, MYSQL_SET_CHARSET_NAME, charset_name)) {
         
     | 
| 
       1177 
1308 
     | 
    
         
             
                /* TODO: warning - unable to set charset */
         
     | 
| 
         @@ -1195,7 +1326,12 @@ static VALUE set_ssl_options(VALUE self, VALUE key, VALUE cert, VALUE ca, VALUE 
     | 
|
| 
       1195 
1326 
     | 
    
         
             
            }
         
     | 
| 
       1196 
1327 
     | 
    
         | 
| 
       1197 
1328 
     | 
    
         
             
            static VALUE set_secure_auth(VALUE self, VALUE value) {
         
     | 
| 
      
 1329 
     | 
    
         
            +
            /* This option was deprecated in MySQL 5.x and removed in MySQL 8.0 */
         
     | 
| 
      
 1330 
     | 
    
         
            +
            #ifdef MYSQL_SECURE_AUTH
         
     | 
| 
       1198 
1331 
     | 
    
         
             
              return _mysql_client_options(self, MYSQL_SECURE_AUTH, value);
         
     | 
| 
      
 1332 
     | 
    
         
            +
            #else
         
     | 
| 
      
 1333 
     | 
    
         
            +
              return Qfalse;
         
     | 
| 
      
 1334 
     | 
    
         
            +
            #endif
         
     | 
| 
       1199 
1335 
     | 
    
         
             
            }
         
     | 
| 
       1200 
1336 
     | 
    
         | 
| 
       1201 
1337 
     | 
    
         
             
            static VALUE set_read_default_file(VALUE self, VALUE value) {
         
     | 
| 
         @@ -1210,19 +1346,43 @@ static VALUE set_init_command(VALUE self, VALUE value) { 
     | 
|
| 
       1210 
1346 
     | 
    
         
             
              return _mysql_client_options(self, MYSQL_INIT_COMMAND, value);
         
     | 
| 
       1211 
1347 
     | 
    
         
             
            }
         
     | 
| 
       1212 
1348 
     | 
    
         | 
| 
      
 1349 
     | 
    
         
            +
            static VALUE set_default_auth(VALUE self, VALUE value) {
         
     | 
| 
      
 1350 
     | 
    
         
            +
              return _mysql_client_options(self, MYSQL_DEFAULT_AUTH, value);
         
     | 
| 
      
 1351 
     | 
    
         
            +
            }
         
     | 
| 
      
 1352 
     | 
    
         
            +
             
     | 
| 
      
 1353 
     | 
    
         
            +
            static VALUE set_enable_cleartext_plugin(VALUE self, VALUE value) {
         
     | 
| 
      
 1354 
     | 
    
         
            +
            #ifdef HAVE_CONST_MYSQL_ENABLE_CLEARTEXT_PLUGIN
         
     | 
| 
      
 1355 
     | 
    
         
            +
              return _mysql_client_options(self, MYSQL_ENABLE_CLEARTEXT_PLUGIN, value);
         
     | 
| 
      
 1356 
     | 
    
         
            +
            #else
         
     | 
| 
      
 1357 
     | 
    
         
            +
              rb_raise(cMysql2Error, "enable-cleartext-plugin is not available, you may need a newer MySQL client library");
         
     | 
| 
      
 1358 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1359 
     | 
    
         
            +
            }
         
     | 
| 
      
 1360 
     | 
    
         
            +
             
     | 
| 
       1213 
1361 
     | 
    
         
             
            static VALUE initialize_ext(VALUE self) {
         
     | 
| 
       1214 
1362 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       1215 
1363 
     | 
    
         | 
| 
       1216 
1364 
     | 
    
         
             
              if ((VALUE)rb_thread_call_without_gvl(nogvl_init, wrapper, RUBY_UBF_IO, 0) == Qfalse) {
         
     | 
| 
       1217 
1365 
     | 
    
         
             
                /* TODO: warning - not enough memory? */
         
     | 
| 
       1218 
     | 
    
         
            -
                 
     | 
| 
      
 1366 
     | 
    
         
            +
                rb_raise_mysql2_error(wrapper);
         
     | 
| 
       1219 
1367 
     | 
    
         
             
              }
         
     | 
| 
       1220 
1368 
     | 
    
         | 
| 
       1221 
1369 
     | 
    
         
             
              wrapper->initialized = 1;
         
     | 
| 
       1222 
1370 
     | 
    
         
             
              return self;
         
     | 
| 
       1223 
1371 
     | 
    
         
             
            }
         
     | 
| 
       1224 
1372 
     | 
    
         | 
| 
      
 1373 
     | 
    
         
            +
            /* call-seq: client.prepare # => Mysql2::Statement
         
     | 
| 
      
 1374 
     | 
    
         
            +
             *
         
     | 
| 
      
 1375 
     | 
    
         
            +
             * Create a new prepared statement.
         
     | 
| 
      
 1376 
     | 
    
         
            +
             */
         
     | 
| 
      
 1377 
     | 
    
         
            +
            static VALUE rb_mysql_client_prepare_statement(VALUE self, VALUE sql) {
         
     | 
| 
      
 1378 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 1379 
     | 
    
         
            +
              REQUIRE_CONNECTED(wrapper);
         
     | 
| 
      
 1380 
     | 
    
         
            +
             
     | 
| 
      
 1381 
     | 
    
         
            +
              return rb_mysql_stmt_new(self, sql);
         
     | 
| 
      
 1382 
     | 
    
         
            +
            }
         
     | 
| 
      
 1383 
     | 
    
         
            +
             
     | 
| 
       1225 
1384 
     | 
    
         
             
            void init_mysql2_client() {
         
     | 
| 
      
 1385 
     | 
    
         
            +
            #ifdef _WIN32
         
     | 
| 
       1226 
1386 
     | 
    
         
             
              /* verify the libmysql we're about to use was the version we were built against
         
     | 
| 
       1227 
1387 
     | 
    
         
             
                 https://github.com/luislavena/mysql-gem/commit/a600a9c459597da0712f70f43736e24b484f8a99 */
         
     | 
| 
       1228 
1388 
     | 
    
         
             
              int i;
         
     | 
| 
         @@ -1237,15 +1397,14 @@ void init_mysql2_client() { 
     | 
|
| 
       1237 
1397 
     | 
    
         
             
                }
         
     | 
| 
       1238 
1398 
     | 
    
         
             
                if (lib[i] != MYSQL_LINK_VERSION[i]) {
         
     | 
| 
       1239 
1399 
     | 
    
         
             
                  rb_raise(rb_eRuntimeError, "Incorrect MySQL client library version! This gem was compiled for %s but the client library is %s.", MYSQL_LINK_VERSION, lib);
         
     | 
| 
       1240 
     | 
    
         
            -
                  return;
         
     | 
| 
       1241 
1400 
     | 
    
         
             
                }
         
     | 
| 
       1242 
1401 
     | 
    
         
             
              }
         
     | 
| 
      
 1402 
     | 
    
         
            +
            #endif
         
     | 
| 
       1243 
1403 
     | 
    
         | 
| 
       1244 
1404 
     | 
    
         
             
              /* Initializing mysql library, so different threads could call Client.new */
         
     | 
| 
       1245 
1405 
     | 
    
         
             
              /* without race condition in the library */
         
     | 
| 
       1246 
1406 
     | 
    
         
             
              if (mysql_library_init(0, NULL, NULL) != 0) {
         
     | 
| 
       1247 
1407 
     | 
    
         
             
                rb_raise(rb_eRuntimeError, "Could not initialize MySQL client library");
         
     | 
| 
       1248 
     | 
    
         
            -
                return;
         
     | 
| 
       1249 
1408 
     | 
    
         
             
              }
         
     | 
| 
       1250 
1409 
     | 
    
         | 
| 
       1251 
1410 
     | 
    
         
             
            #if 0
         
     | 
| 
         @@ -1259,7 +1418,7 @@ void init_mysql2_client() { 
     | 
|
| 
       1259 
1418 
     | 
    
         
             
              rb_define_singleton_method(cMysql2Client, "info", rb_mysql_client_info, 0);
         
     | 
| 
       1260 
1419 
     | 
    
         | 
| 
       1261 
1420 
     | 
    
         
             
              rb_define_method(cMysql2Client, "close", rb_mysql_client_close, 0);
         
     | 
| 
       1262 
     | 
    
         
            -
              rb_define_method(cMysql2Client, " 
     | 
| 
      
 1421 
     | 
    
         
            +
              rb_define_method(cMysql2Client, "closed?", rb_mysql_client_closed, 0);
         
     | 
| 
       1263 
1422 
     | 
    
         
             
              rb_define_method(cMysql2Client, "abandon_results!", rb_mysql_client_abandon_results, 0);
         
     | 
| 
       1264 
1423 
     | 
    
         
             
              rb_define_method(cMysql2Client, "escape", rb_mysql_client_real_escape, 1);
         
     | 
| 
       1265 
1424 
     | 
    
         
             
              rb_define_method(cMysql2Client, "server_info", rb_mysql_client_server_info, 0);
         
     | 
| 
         @@ -1267,18 +1426,21 @@ void init_mysql2_client() { 
     | 
|
| 
       1267 
1426 
     | 
    
         
             
              rb_define_method(cMysql2Client, "async_result", rb_mysql_client_async_result, 0);
         
     | 
| 
       1268 
1427 
     | 
    
         
             
              rb_define_method(cMysql2Client, "last_id", rb_mysql_client_last_id, 0);
         
     | 
| 
       1269 
1428 
     | 
    
         
             
              rb_define_method(cMysql2Client, "affected_rows", rb_mysql_client_affected_rows, 0);
         
     | 
| 
      
 1429 
     | 
    
         
            +
              rb_define_method(cMysql2Client, "prepare", rb_mysql_client_prepare_statement, 1);
         
     | 
| 
       1270 
1430 
     | 
    
         
             
              rb_define_method(cMysql2Client, "thread_id", rb_mysql_client_thread_id, 0);
         
     | 
| 
       1271 
1431 
     | 
    
         
             
              rb_define_method(cMysql2Client, "ping", rb_mysql_client_ping, 0);
         
     | 
| 
       1272 
1432 
     | 
    
         
             
              rb_define_method(cMysql2Client, "select_db", rb_mysql_client_select_db, 1);
         
     | 
| 
      
 1433 
     | 
    
         
            +
              rb_define_method(cMysql2Client, "set_server_option", rb_mysql_client_set_server_option, 1);
         
     | 
| 
       1273 
1434 
     | 
    
         
             
              rb_define_method(cMysql2Client, "more_results?", rb_mysql_client_more_results, 0);
         
     | 
| 
       1274 
1435 
     | 
    
         
             
              rb_define_method(cMysql2Client, "next_result", rb_mysql_client_next_result, 0);
         
     | 
| 
       1275 
1436 
     | 
    
         
             
              rb_define_method(cMysql2Client, "store_result", rb_mysql_client_store_result, 0);
         
     | 
| 
      
 1437 
     | 
    
         
            +
              rb_define_method(cMysql2Client, "automatic_close?", get_automatic_close, 0);
         
     | 
| 
      
 1438 
     | 
    
         
            +
              rb_define_method(cMysql2Client, "automatic_close=", set_automatic_close, 1);
         
     | 
| 
       1276 
1439 
     | 
    
         
             
              rb_define_method(cMysql2Client, "reconnect=", set_reconnect, 1);
         
     | 
| 
       1277 
1440 
     | 
    
         
             
              rb_define_method(cMysql2Client, "warning_count", rb_mysql_client_warning_count, 0);
         
     | 
| 
       1278 
1441 
     | 
    
         
             
              rb_define_method(cMysql2Client, "query_info_string", rb_mysql_info, 0);
         
     | 
| 
       1279 
     | 
    
         
            -
             
     | 
| 
      
 1442 
     | 
    
         
            +
              rb_define_method(cMysql2Client, "ssl_cipher", rb_mysql_get_ssl_cipher, 0);
         
     | 
| 
       1280 
1443 
     | 
    
         
             
              rb_define_method(cMysql2Client, "encoding", rb_mysql_client_encoding, 0);
         
     | 
| 
       1281 
     | 
    
         
            -
            #endif
         
     | 
| 
       1282 
1444 
     | 
    
         | 
| 
       1283 
1445 
     | 
    
         
             
              rb_define_private_method(cMysql2Client, "connect_timeout=", set_connect_timeout, 1);
         
     | 
| 
       1284 
1446 
     | 
    
         
             
              rb_define_private_method(cMysql2Client, "read_timeout=", set_read_timeout, 1);
         
     | 
| 
         @@ -1289,9 +1451,13 @@ void init_mysql2_client() { 
     | 
|
| 
       1289 
1451 
     | 
    
         
             
              rb_define_private_method(cMysql2Client, "default_file=", set_read_default_file, 1);
         
     | 
| 
       1290 
1452 
     | 
    
         
             
              rb_define_private_method(cMysql2Client, "default_group=", set_read_default_group, 1);
         
     | 
| 
       1291 
1453 
     | 
    
         
             
              rb_define_private_method(cMysql2Client, "init_command=", set_init_command, 1);
         
     | 
| 
      
 1454 
     | 
    
         
            +
              rb_define_private_method(cMysql2Client, "default_auth=", set_default_auth, 1);
         
     | 
| 
       1292 
1455 
     | 
    
         
             
              rb_define_private_method(cMysql2Client, "ssl_set", set_ssl_options, 5);
         
     | 
| 
      
 1456 
     | 
    
         
            +
              rb_define_private_method(cMysql2Client, "ssl_mode=", rb_set_ssl_mode_option, 1);
         
     | 
| 
      
 1457 
     | 
    
         
            +
              rb_define_private_method(cMysql2Client, "enable_cleartext_plugin=", set_enable_cleartext_plugin, 1);
         
     | 
| 
       1293 
1458 
     | 
    
         
             
              rb_define_private_method(cMysql2Client, "initialize_ext", initialize_ext, 0);
         
     | 
| 
       1294 
     | 
    
         
            -
              rb_define_private_method(cMysql2Client, "connect",  
     | 
| 
      
 1459 
     | 
    
         
            +
              rb_define_private_method(cMysql2Client, "connect", rb_mysql_connect, 8);
         
     | 
| 
      
 1460 
     | 
    
         
            +
              rb_define_private_method(cMysql2Client, "_query", rb_mysql_query, 2);
         
     | 
| 
       1295 
1461 
     | 
    
         | 
| 
       1296 
1462 
     | 
    
         
             
              sym_id              = ID2SYM(rb_intern("id"));
         
     | 
| 
       1297 
1463 
     | 
    
         
             
              sym_version         = ID2SYM(rb_intern("version"));
         
     | 
| 
         @@ -1302,14 +1468,24 @@ void init_mysql2_client() { 
     | 
|
| 
       1302 
1468 
     | 
    
         
             
              sym_array           = ID2SYM(rb_intern("array"));
         
     | 
| 
       1303 
1469 
     | 
    
         
             
              sym_stream          = ID2SYM(rb_intern("stream"));
         
     | 
| 
       1304 
1470 
     | 
    
         | 
| 
      
 1471 
     | 
    
         
            +
              sym_no_good_index_used = ID2SYM(rb_intern("no_good_index_used"));
         
     | 
| 
      
 1472 
     | 
    
         
            +
              sym_no_index_used      = ID2SYM(rb_intern("no_index_used"));
         
     | 
| 
      
 1473 
     | 
    
         
            +
              sym_query_was_slow     = ID2SYM(rb_intern("query_was_slow"));
         
     | 
| 
      
 1474 
     | 
    
         
            +
             
     | 
| 
      
 1475 
     | 
    
         
            +
              intern_brackets = rb_intern("[]");
         
     | 
| 
       1305 
1476 
     | 
    
         
             
              intern_merge = rb_intern("merge");
         
     | 
| 
       1306 
1477 
     | 
    
         
             
              intern_merge_bang = rb_intern("merge!");
         
     | 
| 
       1307 
     | 
    
         
            -
               
     | 
| 
       1308 
     | 
    
         
            -
               
     | 
| 
      
 1478 
     | 
    
         
            +
              intern_new_with_args = rb_intern("new_with_args");
         
     | 
| 
      
 1479 
     | 
    
         
            +
              intern_current_query_options = rb_intern("@current_query_options");
         
     | 
| 
      
 1480 
     | 
    
         
            +
              intern_read_timeout = rb_intern("@read_timeout");
         
     | 
| 
       1309 
1481 
     | 
    
         | 
| 
       1310 
1482 
     | 
    
         
             
            #ifdef CLIENT_LONG_PASSWORD
         
     | 
| 
       1311 
1483 
     | 
    
         
             
              rb_const_set(cMysql2Client, rb_intern("LONG_PASSWORD"),
         
     | 
| 
       1312 
1484 
     | 
    
         
             
                  LONG2NUM(CLIENT_LONG_PASSWORD));
         
     | 
| 
      
 1485 
     | 
    
         
            +
            #else
         
     | 
| 
      
 1486 
     | 
    
         
            +
              /* HACK because MariaDB 10.2 no longer defines this constant,
         
     | 
| 
      
 1487 
     | 
    
         
            +
               * but we're using it in our default connection flags. */
         
     | 
| 
      
 1488 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("LONG_PASSWORD"), INT2NUM(0));
         
     | 
| 
       1313 
1489 
     | 
    
         
             
            #endif
         
     | 
| 
       1314 
1490 
     | 
    
         | 
| 
       1315 
1491 
     | 
    
         
             
            #ifdef CLIENT_FOUND_ROWS
         
     | 
| 
         @@ -1387,6 +1563,16 @@ void init_mysql2_client() { 
     | 
|
| 
       1387 
1563 
     | 
    
         
             
              rb_const_set(cMysql2Client, rb_intern("SECURE_CONNECTION"), LONG2NUM(0));
         
     | 
| 
       1388 
1564 
     | 
    
         
             
            #endif
         
     | 
| 
       1389 
1565 
     | 
    
         | 
| 
      
 1566 
     | 
    
         
            +
            #ifdef HAVE_CONST_MYSQL_OPTION_MULTI_STATEMENTS_ON
         
     | 
| 
      
 1567 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("OPTION_MULTI_STATEMENTS_ON"),
         
     | 
| 
      
 1568 
     | 
    
         
            +
                  LONG2NUM(MYSQL_OPTION_MULTI_STATEMENTS_ON));
         
     | 
| 
      
 1569 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1570 
     | 
    
         
            +
             
     | 
| 
      
 1571 
     | 
    
         
            +
            #ifdef HAVE_CONST_MYSQL_OPTION_MULTI_STATEMENTS_OFF
         
     | 
| 
      
 1572 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("OPTION_MULTI_STATEMENTS_OFF"),
         
     | 
| 
      
 1573 
     | 
    
         
            +
                  LONG2NUM(MYSQL_OPTION_MULTI_STATEMENTS_OFF));
         
     | 
| 
      
 1574 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1575 
     | 
    
         
            +
             
     | 
| 
       1390 
1576 
     | 
    
         
             
            #ifdef CLIENT_MULTI_STATEMENTS
         
     | 
| 
       1391 
1577 
     | 
    
         
             
              rb_const_set(cMysql2Client, rb_intern("MULTI_STATEMENTS"),
         
     | 
| 
       1392 
1578 
     | 
    
         
             
                  LONG2NUM(CLIENT_MULTI_STATEMENTS));
         
     | 
| 
         @@ -1416,4 +1602,67 @@ void init_mysql2_client() { 
     | 
|
| 
       1416 
1602 
     | 
    
         
             
              rb_const_set(cMysql2Client, rb_intern("BASIC_FLAGS"),
         
     | 
| 
       1417 
1603 
     | 
    
         
             
                  LONG2NUM(CLIENT_BASIC_FLAGS));
         
     | 
| 
       1418 
1604 
     | 
    
         
             
            #endif
         
     | 
| 
      
 1605 
     | 
    
         
            +
             
     | 
| 
      
 1606 
     | 
    
         
            +
            #ifdef CLIENT_CONNECT_ATTRS
         
     | 
| 
      
 1607 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("CONNECT_ATTRS"),
         
     | 
| 
      
 1608 
     | 
    
         
            +
                  LONG2NUM(CLIENT_CONNECT_ATTRS));
         
     | 
| 
      
 1609 
     | 
    
         
            +
            #else
         
     | 
| 
      
 1610 
     | 
    
         
            +
              /* HACK because MySQL 5.5 and earlier don't define this constant,
         
     | 
| 
      
 1611 
     | 
    
         
            +
               * but we're using it in our default connection flags. */
         
     | 
| 
      
 1612 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("CONNECT_ATTRS"),
         
     | 
| 
      
 1613 
     | 
    
         
            +
                  INT2NUM(0));
         
     | 
| 
      
 1614 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1615 
     | 
    
         
            +
             
     | 
| 
      
 1616 
     | 
    
         
            +
            #if defined(FULL_SSL_MODE_SUPPORT) // MySQL 5.7.11 and above
         
     | 
| 
      
 1617 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED));
         
     | 
| 
      
 1618 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_PREFERRED"), INT2NUM(SSL_MODE_PREFERRED));
         
     | 
| 
      
 1619 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(SSL_MODE_REQUIRED));
         
     | 
| 
      
 1620 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_CA"), INT2NUM(SSL_MODE_VERIFY_CA));
         
     | 
| 
      
 1621 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_IDENTITY"), INT2NUM(SSL_MODE_VERIFY_IDENTITY));
         
     | 
| 
      
 1622 
     | 
    
         
            +
            #elif defined(HAVE_CONST_MYSQL_OPT_SSL_ENFORCE) // MySQL 5.7.3 - 5.7.10
         
     | 
| 
      
 1623 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED));
         
     | 
| 
      
 1624 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(SSL_MODE_REQUIRED));
         
     | 
| 
      
 1625 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1626 
     | 
    
         
            +
             
     | 
| 
      
 1627 
     | 
    
         
            +
            #ifndef HAVE_CONST_SSL_MODE_DISABLED
         
     | 
| 
      
 1628 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(0));
         
     | 
| 
      
 1629 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1630 
     | 
    
         
            +
            #ifndef HAVE_CONST_SSL_MODE_PREFERRED
         
     | 
| 
      
 1631 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_PREFERRED"), INT2NUM(0));
         
     | 
| 
      
 1632 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1633 
     | 
    
         
            +
            #ifndef HAVE_CONST_SSL_MODE_REQUIRED
         
     | 
| 
      
 1634 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(0));
         
     | 
| 
      
 1635 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1636 
     | 
    
         
            +
            #ifndef HAVE_CONST_SSL_MODE_VERIFY_CA
         
     | 
| 
      
 1637 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_CA"), INT2NUM(0));
         
     | 
| 
      
 1638 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1639 
     | 
    
         
            +
            #ifndef HAVE_CONST_SSL_MODE_VERIFY_IDENTITY
         
     | 
| 
      
 1640 
     | 
    
         
            +
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_VERIFY_IDENTITY"), INT2NUM(0));
         
     | 
| 
      
 1641 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1642 
     | 
    
         
            +
            }
         
     | 
| 
      
 1643 
     | 
    
         
            +
             
     | 
| 
      
 1644 
     | 
    
         
            +
            #define flag_to_bool(f) ((client->server_status & f) ? Qtrue : Qfalse)
         
     | 
| 
      
 1645 
     | 
    
         
            +
             
     | 
| 
      
 1646 
     | 
    
         
            +
            void rb_mysql_set_server_query_flags(MYSQL *client, VALUE result) {
         
     | 
| 
      
 1647 
     | 
    
         
            +
              VALUE server_flags = rb_hash_new();
         
     | 
| 
      
 1648 
     | 
    
         
            +
             
     | 
| 
      
 1649 
     | 
    
         
            +
            #ifdef HAVE_CONST_SERVER_QUERY_NO_GOOD_INDEX_USED
         
     | 
| 
      
 1650 
     | 
    
         
            +
              rb_hash_aset(server_flags, sym_no_good_index_used, flag_to_bool(SERVER_QUERY_NO_GOOD_INDEX_USED));
         
     | 
| 
      
 1651 
     | 
    
         
            +
            #else
         
     | 
| 
      
 1652 
     | 
    
         
            +
              rb_hash_aset(server_flags, sym_no_good_index_used, Qnil);
         
     | 
| 
      
 1653 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1654 
     | 
    
         
            +
             
     | 
| 
      
 1655 
     | 
    
         
            +
            #ifdef HAVE_CONST_SERVER_QUERY_NO_INDEX_USED
         
     | 
| 
      
 1656 
     | 
    
         
            +
              rb_hash_aset(server_flags, sym_no_index_used, flag_to_bool(SERVER_QUERY_NO_INDEX_USED));
         
     | 
| 
      
 1657 
     | 
    
         
            +
            #else
         
     | 
| 
      
 1658 
     | 
    
         
            +
              rb_hash_aset(server_flags, sym_no_index_used, Qnil);
         
     | 
| 
      
 1659 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1660 
     | 
    
         
            +
             
     | 
| 
      
 1661 
     | 
    
         
            +
            #ifdef HAVE_CONST_SERVER_QUERY_WAS_SLOW
         
     | 
| 
      
 1662 
     | 
    
         
            +
              rb_hash_aset(server_flags, sym_query_was_slow, flag_to_bool(SERVER_QUERY_WAS_SLOW));
         
     | 
| 
      
 1663 
     | 
    
         
            +
            #else
         
     | 
| 
      
 1664 
     | 
    
         
            +
              rb_hash_aset(server_flags, sym_query_was_slow, Qnil);
         
     | 
| 
      
 1665 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 1666 
     | 
    
         
            +
             
     | 
| 
      
 1667 
     | 
    
         
            +
              rb_iv_set(result, "@server_flags", server_flags);
         
     | 
| 
       1419 
1668 
     | 
    
         
             
            }
         
     |