mysql2 0.4.6 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.md +82 -52
 - data/examples/eventmachine.rb +0 -2
 - data/examples/threaded.rb +2 -4
 - data/ext/mysql2/client.c +171 -75
 - data/ext/mysql2/client.h +2 -41
 - data/ext/mysql2/extconf.rb +30 -23
 - data/ext/mysql2/mysql2_ext.c +2 -1
 - data/ext/mysql2/mysql2_ext.h +8 -8
 - data/ext/mysql2/mysql_enc_to_ruby.h +10 -0
 - data/ext/mysql2/result.c +24 -77
 - data/ext/mysql2/result.h +2 -3
 - data/ext/mysql2/statement.c +101 -73
 - data/ext/mysql2/statement.h +0 -2
 - data/ext/mysql2/wait_for_single_fd.h +2 -1
 - data/lib/mysql2/client.rb +37 -31
 - data/lib/mysql2/em.rb +2 -4
 - data/lib/mysql2/error.rb +49 -20
 - data/lib/mysql2/result.rb +2 -0
 - data/lib/mysql2/statement.rb +3 -9
 - data/lib/mysql2/version.rb +1 -1
 - data/lib/mysql2.rb +14 -15
 - data/spec/em/em_spec.rb +6 -6
 - data/spec/mysql2/client_spec.rb +300 -215
 - data/spec/mysql2/error_spec.rb +3 -9
 - data/spec/mysql2/result_spec.rb +124 -158
 - data/spec/mysql2/statement_spec.rb +138 -185
 - data/spec/spec_helper.rb +79 -61
 - data/support/5072E1F5.asc +432 -0
 - data/support/mysql_enc_to_ruby.rb +2 -2
 - data/support/ruby_enc_to_mysql.rb +5 -5
 - metadata +16 -14
 
    
        data/ext/mysql2/statement.c
    CHANGED
    
    | 
         @@ -1,12 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #include <mysql2_ext.h>
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            VALUE  
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            static VALUE sym_stream, intern_new_with_args, intern_each, intern_to_s;
         
     | 
| 
      
 3 
     | 
    
         
            +
            extern VALUE mMysql2, cMysql2Error;
         
     | 
| 
      
 4 
     | 
    
         
            +
            static VALUE cMysql2Statement, cBigDecimal, cDateTime, cDate;
         
     | 
| 
      
 5 
     | 
    
         
            +
            static VALUE sym_stream, intern_new_with_args, intern_each, intern_to_s, intern_merge_bang;
         
     | 
| 
       6 
6 
     | 
    
         
             
            static VALUE intern_sec_fraction, intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year;
         
     | 
| 
       7 
     | 
    
         
            -
            #ifndef HAVE_RB_BIG_CMP
         
     | 
| 
       8 
     | 
    
         
            -
            static ID id_cmp;
         
     | 
| 
       9 
     | 
    
         
            -
            #endif
         
     | 
| 
       10 
7 
     | 
    
         | 
| 
       11 
8 
     | 
    
         
             
            #define GET_STATEMENT(self) \
         
     | 
| 
       12 
9 
     | 
    
         
             
              mysql_stmt_wrapper *stmt_wrapper; \
         
     | 
| 
         @@ -21,7 +18,7 @@ static void rb_mysql_stmt_mark(void * ptr) { 
     | 
|
| 
       21 
18 
     | 
    
         
             
              rb_gc_mark(stmt_wrapper->client);
         
     | 
| 
       22 
19 
     | 
    
         
             
            }
         
     | 
| 
       23 
20 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
            static void *nogvl_stmt_close(void * 
     | 
| 
      
 21 
     | 
    
         
            +
            static void *nogvl_stmt_close(void *ptr) {
         
     | 
| 
       25 
22 
     | 
    
         
             
              mysql_stmt_wrapper *stmt_wrapper = ptr;
         
     | 
| 
       26 
23 
     | 
    
         
             
              if (stmt_wrapper->stmt) {
         
     | 
| 
       27 
24 
     | 
    
         
             
                mysql_stmt_close(stmt_wrapper->stmt);
         
     | 
| 
         @@ -30,7 +27,7 @@ static void *nogvl_stmt_close(void * ptr) { 
     | 
|
| 
       30 
27 
     | 
    
         
             
              return NULL;
         
     | 
| 
       31 
28 
     | 
    
         
             
            }
         
     | 
| 
       32 
29 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
            static void rb_mysql_stmt_free(void * 
     | 
| 
      
 30 
     | 
    
         
            +
            static void rb_mysql_stmt_free(void *ptr) {
         
     | 
| 
       34 
31 
     | 
    
         
             
              mysql_stmt_wrapper *stmt_wrapper = ptr;
         
     | 
| 
       35 
32 
     | 
    
         
             
              decr_mysql2_stmt(stmt_wrapper);
         
     | 
| 
       36 
33 
     | 
    
         
             
            }
         
     | 
| 
         @@ -50,7 +47,6 @@ void rb_raise_mysql2_stmt_error(mysql_stmt_wrapper *stmt_wrapper) { 
     | 
|
| 
       50 
47 
     | 
    
         
             
              VALUE rb_error_msg = rb_str_new2(mysql_stmt_error(stmt_wrapper->stmt));
         
     | 
| 
       51 
48 
     | 
    
         
             
              VALUE rb_sql_state = rb_tainted_str_new2(mysql_stmt_sqlstate(stmt_wrapper->stmt));
         
     | 
| 
       52 
49 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       54 
50 
     | 
    
         
             
              rb_encoding *conn_enc;
         
     | 
| 
       55 
51 
     | 
    
         
             
              conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
       56 
52 
     | 
    
         | 
| 
         @@ -62,7 +58,6 @@ void rb_raise_mysql2_stmt_error(mysql_stmt_wrapper *stmt_wrapper) { 
     | 
|
| 
       62 
58 
     | 
    
         
             
                rb_error_msg = rb_str_export_to_enc(rb_error_msg, default_internal_enc);
         
     | 
| 
       63 
59 
     | 
    
         
             
                rb_sql_state = rb_str_export_to_enc(rb_sql_state, default_internal_enc);
         
     | 
| 
       64 
60 
     | 
    
         
             
              }
         
     | 
| 
       65 
     | 
    
         
            -
            #endif
         
     | 
| 
       66 
61 
     | 
    
         | 
| 
       67 
62 
     | 
    
         
             
              e = rb_funcall(cMysql2Error, intern_new_with_args, 4,
         
     | 
| 
       68 
63 
     | 
    
         
             
                             rb_error_msg,
         
     | 
| 
         @@ -96,9 +91,7 @@ static void *nogvl_prepare_statement(void *ptr) { 
     | 
|
| 
       96 
91 
     | 
    
         
             
            VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
         
     | 
| 
       97 
92 
     | 
    
         
             
              mysql_stmt_wrapper *stmt_wrapper;
         
     | 
| 
       98 
93 
     | 
    
         
             
              VALUE rb_stmt;
         
     | 
| 
       99 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       100 
94 
     | 
    
         
             
              rb_encoding *conn_enc;
         
     | 
| 
       101 
     | 
    
         
            -
            #endif
         
     | 
| 
       102 
95 
     | 
    
         | 
| 
       103 
96 
     | 
    
         
             
              Check_Type(sql, T_STRING);
         
     | 
| 
       104 
97 
     | 
    
         | 
| 
         @@ -114,9 +107,7 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) { 
     | 
|
| 
       114 
107 
     | 
    
         
             
              {
         
     | 
| 
       115 
108 
     | 
    
         
             
                GET_CLIENT(rb_client);
         
     | 
| 
       116 
109 
     | 
    
         
             
                stmt_wrapper->stmt = mysql_stmt_init(wrapper->client);
         
     | 
| 
       117 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       118 
110 
     | 
    
         
             
                conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
       119 
     | 
    
         
            -
            #endif
         
     | 
| 
       120 
111 
     | 
    
         
             
              }
         
     | 
| 
       121 
112 
     | 
    
         
             
              if (stmt_wrapper->stmt == NULL) {
         
     | 
| 
       122 
113 
     | 
    
         
             
                rb_raise(cMysql2Error, "Unable to initialize prepared statement: out of memory");
         
     | 
| 
         @@ -124,7 +115,7 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) { 
     | 
|
| 
       124 
115 
     | 
    
         | 
| 
       125 
116 
     | 
    
         
             
              // set STMT_ATTR_UPDATE_MAX_LENGTH attr
         
     | 
| 
       126 
117 
     | 
    
         
             
              {
         
     | 
| 
       127 
     | 
    
         
            -
                 
     | 
| 
      
 118 
     | 
    
         
            +
                my_bool truth = 1;
         
     | 
| 
       128 
119 
     | 
    
         
             
                if (mysql_stmt_attr_set(stmt_wrapper->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &truth)) {
         
     | 
| 
       129 
120 
     | 
    
         
             
                  rb_raise(cMysql2Error, "Unable to initialize prepared statement: set STMT_ATTR_UPDATE_MAX_LENGTH");
         
     | 
| 
       130 
121 
     | 
    
         
             
                }
         
     | 
| 
         @@ -134,11 +125,8 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) { 
     | 
|
| 
       134 
125 
     | 
    
         
             
              {
         
     | 
| 
       135 
126 
     | 
    
         
             
                struct nogvl_prepare_statement_args args;
         
     | 
| 
       136 
127 
     | 
    
         
             
                args.stmt = stmt_wrapper->stmt;
         
     | 
| 
       137 
     | 
    
         
            -
                args.sql = sql;
         
     | 
| 
       138 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       139 
128 
     | 
    
         
             
                // ensure the string is in the encoding the connection is expecting
         
     | 
| 
       140 
     | 
    
         
            -
                args.sql = rb_str_export_to_enc( 
     | 
| 
       141 
     | 
    
         
            -
            #endif
         
     | 
| 
      
 129 
     | 
    
         
            +
                args.sql = rb_str_export_to_enc(sql, conn_enc);
         
     | 
| 
       142 
130 
     | 
    
         
             
                args.sql_ptr = RSTRING_PTR(sql);
         
     | 
| 
       143 
131 
     | 
    
         
             
                args.sql_len = RSTRING_LEN(sql);
         
     | 
| 
       144 
132 
     | 
    
         | 
| 
         @@ -154,7 +142,7 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) { 
     | 
|
| 
       154 
142 
     | 
    
         
             
             *
         
     | 
| 
       155 
143 
     | 
    
         
             
             * Returns the number of parameters the prepared statement expects.
         
     | 
| 
       156 
144 
     | 
    
         
             
             */
         
     | 
| 
       157 
     | 
    
         
            -
            static VALUE  
     | 
| 
      
 145 
     | 
    
         
            +
            static VALUE rb_mysql_stmt_param_count(VALUE self) {
         
     | 
| 
       158 
146 
     | 
    
         
             
              GET_STATEMENT(self);
         
     | 
| 
       159 
147 
     | 
    
         | 
| 
       160 
148 
     | 
    
         
             
              return ULL2NUM(mysql_stmt_param_count(stmt_wrapper->stmt));
         
     | 
| 
         @@ -164,13 +152,13 @@ static VALUE param_count(VALUE self) { 
     | 
|
| 
       164 
152 
     | 
    
         
             
             *
         
     | 
| 
       165 
153 
     | 
    
         
             
             * Returns the number of fields the prepared statement returns.
         
     | 
| 
       166 
154 
     | 
    
         
             
             */
         
     | 
| 
       167 
     | 
    
         
            -
            static VALUE  
     | 
| 
      
 155 
     | 
    
         
            +
            static VALUE rb_mysql_stmt_field_count(VALUE self) {
         
     | 
| 
       168 
156 
     | 
    
         
             
              GET_STATEMENT(self);
         
     | 
| 
       169 
157 
     | 
    
         | 
| 
       170 
158 
     | 
    
         
             
              return UINT2NUM(mysql_stmt_field_count(stmt_wrapper->stmt));
         
     | 
| 
       171 
159 
     | 
    
         
             
            }
         
     | 
| 
       172 
160 
     | 
    
         | 
| 
       173 
     | 
    
         
            -
            static void * 
     | 
| 
      
 161 
     | 
    
         
            +
            static void *nogvl_stmt_execute(void *ptr) {
         
     | 
| 
       174 
162 
     | 
    
         
             
              MYSQL_STMT *stmt = ptr;
         
     | 
| 
       175 
163 
     | 
    
         | 
| 
       176 
164 
     | 
    
         
             
              if (mysql_stmt_execute(stmt)) {
         
     | 
| 
         @@ -196,7 +184,7 @@ static void set_buffer_for_string(MYSQL_BIND* bind_buffer, unsigned long *length 
     | 
|
| 
       196 
184 
     | 
    
         
             
             * the buffer is a Ruby string pointer and not our memory to manage.
         
     | 
| 
       197 
185 
     | 
    
         
             
             */
         
     | 
| 
       198 
186 
     | 
    
         
             
            #define FREE_BINDS                                          \
         
     | 
| 
       199 
     | 
    
         
            -
              for (i = 0; i <  
     | 
| 
      
 187 
     | 
    
         
            +
              for (i = 0; i < bind_count; i++) {                        \
         
     | 
| 
       200 
188 
     | 
    
         
             
                if (bind_buffers[i].buffer && NIL_P(params_enc[i])) {   \
         
     | 
| 
       201 
189 
     | 
    
         
             
                  xfree(bind_buffers[i].buffer);                        \
         
     | 
| 
       202 
190 
     | 
    
         
             
                }                                                       \
         
     | 
| 
         @@ -211,6 +199,8 @@ static int my_big2ll(VALUE bignum, LONG_LONG *ptr) 
     | 
|
| 
       211 
199 
     | 
    
         
             
            {
         
     | 
| 
       212 
200 
     | 
    
         
             
              unsigned LONG_LONG num;
         
     | 
| 
       213 
201 
     | 
    
         
             
              size_t len;
         
     | 
| 
      
 202 
     | 
    
         
            +
            // rb_absint_size was added in 2.1.0. See:
         
     | 
| 
      
 203 
     | 
    
         
            +
            // https://github.com/ruby/ruby/commit/9fea875
         
     | 
| 
       214 
204 
     | 
    
         
             
            #ifdef HAVE_RB_ABSINT_SIZE
         
     | 
| 
       215 
205 
     | 
    
         
             
              int nlz_bits = 0;
         
     | 
| 
       216 
206 
     | 
    
         
             
              len = rb_absint_size(bignum, &nlz_bits);
         
     | 
| 
         @@ -229,16 +219,15 @@ static int my_big2ll(VALUE bignum, LONG_LONG *ptr) 
     | 
|
| 
       229 
219 
     | 
    
         
             
            #ifdef HAVE_RB_ABSINT_SIZE
         
     | 
| 
       230 
220 
     | 
    
         
             
                    nlz_bits == 0 &&
         
     | 
| 
       231 
221 
     | 
    
         
             
            #endif
         
     | 
| 
      
 222 
     | 
    
         
            +
            // rb_absint_singlebit_p was added in 2.1.0. See:
         
     | 
| 
      
 223 
     | 
    
         
            +
            // https://github.com/ruby/ruby/commit/e5ff9d5
         
     | 
| 
       232 
224 
     | 
    
         
             
            #if defined(HAVE_RB_ABSINT_SIZE) && defined(HAVE_RB_ABSINT_SINGLEBIT_P)
         
     | 
| 
       233 
225 
     | 
    
         
             
                    /* Optimized to avoid object allocation for Ruby 2.1+
         
     | 
| 
       234 
226 
     | 
    
         
             
                     * only -0x8000000000000000 is safe if `len == 8 && nlz_bits == 0`
         
     | 
| 
       235 
227 
     | 
    
         
             
                     */
         
     | 
| 
       236 
228 
     | 
    
         
             
                    !rb_absint_singlebit_p(bignum)
         
     | 
| 
       237 
     | 
    
         
            -
            #elif defined(HAVE_RB_BIG_CMP)
         
     | 
| 
       238 
     | 
    
         
            -
                    rb_big_cmp(bignum, LL2NUM(LLONG_MIN)) == INT2FIX(-1)
         
     | 
| 
       239 
229 
     | 
    
         
             
            #else
         
     | 
| 
       240 
     | 
    
         
            -
                     
     | 
| 
       241 
     | 
    
         
            -
                    rb_funcall(bignum, id_cmp, 1, LL2NUM(LLONG_MIN)) == INT2FIX(-1)
         
     | 
| 
      
 230 
     | 
    
         
            +
                    rb_big_cmp(bignum, LL2NUM(LLONG_MIN)) == INT2FIX(-1)
         
     | 
| 
       242 
231 
     | 
    
         
             
            #endif
         
     | 
| 
       243 
232 
     | 
    
         
             
                   ) {
         
     | 
| 
       244 
233 
     | 
    
         
             
                  goto overflow;
         
     | 
| 
         @@ -254,44 +243,45 @@ overflow: 
     | 
|
| 
       254 
243 
     | 
    
         
             
             *
         
     | 
| 
       255 
244 
     | 
    
         
             
             * Executes the current prepared statement, returns +result+.
         
     | 
| 
       256 
245 
     | 
    
         
             
             */
         
     | 
| 
       257 
     | 
    
         
            -
            static VALUE  
     | 
| 
      
 246 
     | 
    
         
            +
            static VALUE rb_mysql_stmt_execute(int argc, VALUE *argv, VALUE self) {
         
     | 
| 
       258 
247 
     | 
    
         
             
              MYSQL_BIND *bind_buffers = NULL;
         
     | 
| 
       259 
248 
     | 
    
         
             
              unsigned long *length_buffers = NULL;
         
     | 
| 
       260 
249 
     | 
    
         
             
              unsigned long bind_count;
         
     | 
| 
       261 
     | 
    
         
            -
              long i;
         
     | 
| 
      
 250 
     | 
    
         
            +
              unsigned long i;
         
     | 
| 
       262 
251 
     | 
    
         
             
              MYSQL_STMT *stmt;
         
     | 
| 
       263 
252 
     | 
    
         
             
              MYSQL_RES *metadata;
         
     | 
| 
      
 253 
     | 
    
         
            +
              VALUE opts;
         
     | 
| 
       264 
254 
     | 
    
         
             
              VALUE current;
         
     | 
| 
       265 
255 
     | 
    
         
             
              VALUE resultObj;
         
     | 
| 
       266 
     | 
    
         
            -
              VALUE *params_enc;
         
     | 
| 
      
 256 
     | 
    
         
            +
              VALUE *params_enc = NULL;
         
     | 
| 
       267 
257 
     | 
    
         
             
              int is_streaming;
         
     | 
| 
       268 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       269 
258 
     | 
    
         
             
              rb_encoding *conn_enc;
         
     | 
| 
       270 
     | 
    
         
            -
            #endif
         
     | 
| 
       271 
259 
     | 
    
         | 
| 
       272 
260 
     | 
    
         
             
              GET_STATEMENT(self);
         
     | 
| 
       273 
261 
     | 
    
         
             
              GET_CLIENT(stmt_wrapper->client);
         
     | 
| 
       274 
262 
     | 
    
         | 
| 
       275 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       276 
263 
     | 
    
         
             
              conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
       277 
     | 
    
         
            -
            #endif
         
     | 
| 
       278 
     | 
    
         
            -
             
     | 
| 
       279 
     | 
    
         
            -
              /* Scratch space for string encoding exports, allocate on the stack. */
         
     | 
| 
       280 
     | 
    
         
            -
              params_enc = alloca(sizeof(VALUE) * argc);
         
     | 
| 
       281 
264 
     | 
    
         | 
| 
       282 
265 
     | 
    
         
             
              stmt = stmt_wrapper->stmt;
         
     | 
| 
       283 
     | 
    
         
            -
             
     | 
| 
       284 
266 
     | 
    
         
             
              bind_count = mysql_stmt_param_count(stmt);
         
     | 
| 
       285 
     | 
    
         
            -
             
     | 
| 
       286 
     | 
    
         
            -
             
     | 
| 
      
 267 
     | 
    
         
            +
             
     | 
| 
      
 268 
     | 
    
         
            +
              // Get count of ordinary arguments, and extract hash opts/keyword arguments
         
     | 
| 
      
 269 
     | 
    
         
            +
              // Use a local scope to avoid leaking the temporary count variable
         
     | 
| 
      
 270 
     | 
    
         
            +
              {
         
     | 
| 
      
 271 
     | 
    
         
            +
                int c = rb_scan_args(argc, argv, "*:", NULL, &opts);
         
     | 
| 
      
 272 
     | 
    
         
            +
                if (c != (long)bind_count) {
         
     | 
| 
      
 273 
     | 
    
         
            +
                  rb_raise(cMysql2Error, "Bind parameter count (%ld) doesn't match number of arguments (%d)", bind_count, c);
         
     | 
| 
      
 274 
     | 
    
         
            +
                }
         
     | 
| 
       287 
275 
     | 
    
         
             
              }
         
     | 
| 
       288 
276 
     | 
    
         | 
| 
       289 
277 
     | 
    
         
             
              // setup any bind variables in the query
         
     | 
| 
       290 
278 
     | 
    
         
             
              if (bind_count > 0) {
         
     | 
| 
      
 279 
     | 
    
         
            +
                // Scratch space for string encoding exports, allocate on the stack
         
     | 
| 
      
 280 
     | 
    
         
            +
                params_enc = alloca(sizeof(VALUE) * bind_count);
         
     | 
| 
       291 
281 
     | 
    
         
             
                bind_buffers = xcalloc(bind_count, sizeof(MYSQL_BIND));
         
     | 
| 
       292 
282 
     | 
    
         
             
                length_buffers = xcalloc(bind_count, sizeof(unsigned long));
         
     | 
| 
       293 
283 
     | 
    
         | 
| 
       294 
     | 
    
         
            -
                for (i = 0; i <  
     | 
| 
      
 284 
     | 
    
         
            +
                for (i = 0; i < bind_count; i++) {
         
     | 
| 
       295 
285 
     | 
    
         
             
                  bind_buffers[i].buffer = NULL;
         
     | 
| 
       296 
286 
     | 
    
         
             
                  params_enc[i] = Qnil;
         
     | 
| 
       297 
287 
     | 
    
         | 
| 
         @@ -319,12 +309,8 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       319 
309 
     | 
    
         
             
                          *(LONG_LONG*)(bind_buffers[i].buffer) = num;
         
     | 
| 
       320 
310 
     | 
    
         
             
                        } else {
         
     | 
| 
       321 
311 
     | 
    
         
             
                          /* The bignum was larger than we can fit in LONG_LONG, send it as a string */
         
     | 
| 
       322 
     | 
    
         
            -
                          VALUE rb_val_as_string = rb_big2str(argv[i], 10);
         
     | 
| 
       323 
312 
     | 
    
         
             
                          bind_buffers[i].buffer_type = MYSQL_TYPE_NEWDECIMAL;
         
     | 
| 
       324 
     | 
    
         
            -
                          params_enc[i] =  
     | 
| 
       325 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       326 
     | 
    
         
            -
                          params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc);
         
     | 
| 
       327 
     | 
    
         
            -
            #endif
         
     | 
| 
      
 313 
     | 
    
         
            +
                          params_enc[i] = rb_str_export_to_enc(rb_big2str(argv[i], 10), conn_enc);
         
     | 
| 
       328 
314 
     | 
    
         
             
                          set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]);
         
     | 
| 
       329 
315 
     | 
    
         
             
                        }
         
     | 
| 
       330 
316 
     | 
    
         
             
                      }
         
     | 
| 
         @@ -338,11 +324,19 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       338 
324 
     | 
    
         
             
                      bind_buffers[i].buffer_type = MYSQL_TYPE_STRING;
         
     | 
| 
       339 
325 
     | 
    
         | 
| 
       340 
326 
     | 
    
         
             
                      params_enc[i] = argv[i];
         
     | 
| 
       341 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       342 
327 
     | 
    
         
             
                      params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc);
         
     | 
| 
       343 
     | 
    
         
            -
            #endif
         
     | 
| 
       344 
328 
     | 
    
         
             
                      set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]);
         
     | 
| 
       345 
329 
     | 
    
         
             
                      break;
         
     | 
| 
      
 330 
     | 
    
         
            +
                    case T_TRUE:
         
     | 
| 
      
 331 
     | 
    
         
            +
                      bind_buffers[i].buffer_type = MYSQL_TYPE_TINY;
         
     | 
| 
      
 332 
     | 
    
         
            +
                      bind_buffers[i].buffer = xmalloc(sizeof(signed char));
         
     | 
| 
      
 333 
     | 
    
         
            +
                      *(signed char*)(bind_buffers[i].buffer) = 1;
         
     | 
| 
      
 334 
     | 
    
         
            +
                      break;
         
     | 
| 
      
 335 
     | 
    
         
            +
                    case T_FALSE:
         
     | 
| 
      
 336 
     | 
    
         
            +
                      bind_buffers[i].buffer_type = MYSQL_TYPE_TINY;
         
     | 
| 
      
 337 
     | 
    
         
            +
                      bind_buffers[i].buffer = xmalloc(sizeof(signed char));
         
     | 
| 
      
 338 
     | 
    
         
            +
                      *(signed char*)(bind_buffers[i].buffer) = 0;
         
     | 
| 
      
 339 
     | 
    
         
            +
                      break;
         
     | 
| 
       346 
340 
     | 
    
         
             
                    default:
         
     | 
| 
       347 
341 
     | 
    
         
             
                      // TODO: what Ruby type should support MYSQL_TYPE_TIME
         
     | 
| 
       348 
342 
     | 
    
         
             
                      if (CLASS_OF(argv[i]) == rb_cTime || CLASS_OF(argv[i]) == cDateTime) {
         
     | 
| 
         @@ -395,9 +389,7 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       395 
389 
     | 
    
         
             
                        VALUE rb_val_as_string = rb_funcall(argv[i], intern_to_s, 0);
         
     | 
| 
       396 
390 
     | 
    
         | 
| 
       397 
391 
     | 
    
         
             
                        params_enc[i] = rb_val_as_string;
         
     | 
| 
       398 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       399 
392 
     | 
    
         
             
                        params_enc[i] = rb_str_export_to_enc(params_enc[i], conn_enc);
         
     | 
| 
       400 
     | 
    
         
            -
            #endif
         
     | 
| 
       401 
393 
     | 
    
         
             
                        set_buffer_for_string(&bind_buffers[i], &length_buffers[i], params_enc[i]);
         
     | 
| 
       402 
394 
     | 
    
         
             
                      }
         
     | 
| 
       403 
395 
     | 
    
         
             
                      break;
         
     | 
| 
         @@ -411,7 +403,40 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       411 
403 
     | 
    
         
             
                }
         
     | 
| 
       412 
404 
     | 
    
         
             
              }
         
     | 
| 
       413 
405 
     | 
    
         | 
| 
       414 
     | 
    
         
            -
               
     | 
| 
      
 406 
     | 
    
         
            +
              // Duplicate the options hash, merge! extra opts, put the copy into the Result object
         
     | 
| 
      
 407 
     | 
    
         
            +
              current = rb_hash_dup(rb_iv_get(stmt_wrapper->client, "@query_options"));
         
     | 
| 
      
 408 
     | 
    
         
            +
              (void)RB_GC_GUARD(current);
         
     | 
| 
      
 409 
     | 
    
         
            +
              Check_Type(current, T_HASH);
         
     | 
| 
      
 410 
     | 
    
         
            +
             
     | 
| 
      
 411 
     | 
    
         
            +
              // Merge in hash opts/keyword arguments
         
     | 
| 
      
 412 
     | 
    
         
            +
              if (!NIL_P(opts)) {
         
     | 
| 
      
 413 
     | 
    
         
            +
                rb_funcall(current, intern_merge_bang, 1, opts);
         
     | 
| 
      
 414 
     | 
    
         
            +
              }
         
     | 
| 
      
 415 
     | 
    
         
            +
             
     | 
| 
      
 416 
     | 
    
         
            +
              is_streaming = (Qtrue == rb_hash_aref(current, sym_stream));
         
     | 
| 
      
 417 
     | 
    
         
            +
             
     | 
| 
      
 418 
     | 
    
         
            +
              // From stmt_execute to mysql_stmt_result_metadata to stmt_store_result, no
         
     | 
| 
      
 419 
     | 
    
         
            +
              // Ruby API calls are allowed so that GC is not invoked. If the connection is
         
     | 
| 
      
 420 
     | 
    
         
            +
              // in results-streaming-mode for Statement A, and in the middle Statement B
         
     | 
| 
      
 421 
     | 
    
         
            +
              // gets garbage collected, a message will be sent to the server notifying it
         
     | 
| 
      
 422 
     | 
    
         
            +
              // to release Statement B, resulting in the following error:
         
     | 
| 
      
 423 
     | 
    
         
            +
              //   Commands out of sync; you can't run this command now
         
     | 
| 
      
 424 
     | 
    
         
            +
              //
         
     | 
| 
      
 425 
     | 
    
         
            +
              // In streaming mode, statement execute must return a cursor because we
         
     | 
| 
      
 426 
     | 
    
         
            +
              // cannot prevent other Statement objects from being garbage collected
         
     | 
| 
      
 427 
     | 
    
         
            +
              // between fetches of each row of the result set. The following error
         
     | 
| 
      
 428 
     | 
    
         
            +
              // occurs if cursor mode is not set:
         
     | 
| 
      
 429 
     | 
    
         
            +
              //   Row retrieval was canceled by mysql_stmt_close
         
     | 
| 
      
 430 
     | 
    
         
            +
             
     | 
| 
      
 431 
     | 
    
         
            +
              if (is_streaming) {
         
     | 
| 
      
 432 
     | 
    
         
            +
                unsigned long type = CURSOR_TYPE_READ_ONLY;
         
     | 
| 
      
 433 
     | 
    
         
            +
                if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &type)) {
         
     | 
| 
      
 434 
     | 
    
         
            +
                  FREE_BINDS;
         
     | 
| 
      
 435 
     | 
    
         
            +
                  rb_raise(cMysql2Error, "Unable to stream prepared statement, could not set CURSOR_TYPE_READ_ONLY");
         
     | 
| 
      
 436 
     | 
    
         
            +
                }
         
     | 
| 
      
 437 
     | 
    
         
            +
              }
         
     | 
| 
      
 438 
     | 
    
         
            +
             
     | 
| 
      
 439 
     | 
    
         
            +
              if ((VALUE)rb_thread_call_without_gvl(nogvl_stmt_execute, stmt, RUBY_UBF_IO, 0) == Qfalse) {
         
     | 
| 
       415 
440 
     | 
    
         
             
                FREE_BINDS;
         
     | 
| 
       416 
441 
     | 
    
         
             
                rb_raise_mysql2_stmt_error(stmt_wrapper);
         
     | 
| 
       417 
442 
     | 
    
         
             
              }
         
     | 
| 
         @@ -429,11 +454,6 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       429 
454 
     | 
    
         
             
                return Qnil;
         
     | 
| 
       430 
455 
     | 
    
         
             
              }
         
     | 
| 
       431 
456 
     | 
    
         | 
| 
       432 
     | 
    
         
            -
              current = rb_hash_dup(rb_iv_get(stmt_wrapper->client, "@query_options"));
         
     | 
| 
       433 
     | 
    
         
            -
              (void)RB_GC_GUARD(current);
         
     | 
| 
       434 
     | 
    
         
            -
              Check_Type(current, T_HASH);
         
     | 
| 
       435 
     | 
    
         
            -
             
     | 
| 
       436 
     | 
    
         
            -
              is_streaming = (Qtrue == rb_hash_aref(current, sym_stream));
         
     | 
| 
       437 
457 
     | 
    
         
             
              if (!is_streaming) {
         
     | 
| 
       438 
458 
     | 
    
         
             
                // recieve the whole result set from the server
         
     | 
| 
       439 
459 
     | 
    
         
             
                if (mysql_stmt_store_result(stmt)) {
         
     | 
| 
         @@ -445,6 +465,8 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       445 
465 
     | 
    
         | 
| 
       446 
466 
     | 
    
         
             
              resultObj = rb_mysql_result_to_obj(stmt_wrapper->client, wrapper->encoding, current, metadata, self);
         
     | 
| 
       447 
467 
     | 
    
         | 
| 
      
 468 
     | 
    
         
            +
              rb_mysql_set_server_query_flags(wrapper->client, resultObj);
         
     | 
| 
      
 469 
     | 
    
         
            +
             
     | 
| 
       448 
470 
     | 
    
         
             
              if (!is_streaming) {
         
     | 
| 
       449 
471 
     | 
    
         
             
                // cache all result
         
     | 
| 
       450 
472 
     | 
    
         
             
                rb_funcall(resultObj, intern_each, 0);
         
     | 
| 
         @@ -457,42 +479,47 @@ static VALUE execute(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       457 
479 
     | 
    
         
             
             *
         
     | 
| 
       458 
480 
     | 
    
         
             
             * Returns a list of fields that will be returned by this statement.
         
     | 
| 
       459 
481 
     | 
    
         
             
             */
         
     | 
| 
       460 
     | 
    
         
            -
            static VALUE  
     | 
| 
      
 482 
     | 
    
         
            +
            static VALUE rb_mysql_stmt_fields(VALUE self) {
         
     | 
| 
       461 
483 
     | 
    
         
             
              MYSQL_FIELD *fields;
         
     | 
| 
       462 
484 
     | 
    
         
             
              MYSQL_RES *metadata;
         
     | 
| 
       463 
485 
     | 
    
         
             
              unsigned int field_count;
         
     | 
| 
       464 
486 
     | 
    
         
             
              unsigned int i;
         
     | 
| 
       465 
487 
     | 
    
         
             
              VALUE field_list;
         
     | 
| 
       466 
488 
     | 
    
         
             
              MYSQL_STMT* stmt;
         
     | 
| 
       467 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       468 
489 
     | 
    
         
             
              rb_encoding *default_internal_enc, *conn_enc;
         
     | 
| 
       469 
     | 
    
         
            -
            #endif
         
     | 
| 
       470 
490 
     | 
    
         
             
              GET_STATEMENT(self);
         
     | 
| 
      
 491 
     | 
    
         
            +
              GET_CLIENT(stmt_wrapper->client);
         
     | 
| 
       471 
492 
     | 
    
         
             
              stmt = stmt_wrapper->stmt;
         
     | 
| 
       472 
493 
     | 
    
         | 
| 
       473 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       474 
494 
     | 
    
         
             
              default_internal_enc = rb_default_internal_encoding();
         
     | 
| 
       475 
495 
     | 
    
         
             
              {
         
     | 
| 
       476 
496 
     | 
    
         
             
                GET_CLIENT(stmt_wrapper->client);
         
     | 
| 
       477 
497 
     | 
    
         
             
                conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
       478 
498 
     | 
    
         
             
              }
         
     | 
| 
       479 
     | 
    
         
            -
            #endif
         
     | 
| 
       480 
499 
     | 
    
         | 
| 
       481 
     | 
    
         
            -
              metadata 
     | 
| 
      
 500 
     | 
    
         
            +
              metadata = mysql_stmt_result_metadata(stmt);
         
     | 
| 
      
 501 
     | 
    
         
            +
              if (metadata == NULL) {
         
     | 
| 
      
 502 
     | 
    
         
            +
                if (mysql_stmt_errno(stmt) != 0) {
         
     | 
| 
      
 503 
     | 
    
         
            +
                  // either CR_OUT_OF_MEMORY or CR_UNKNOWN_ERROR. both fatal.
         
     | 
| 
      
 504 
     | 
    
         
            +
                  wrapper->active_thread = Qnil;
         
     | 
| 
      
 505 
     | 
    
         
            +
                  rb_raise_mysql2_stmt_error(stmt_wrapper);
         
     | 
| 
      
 506 
     | 
    
         
            +
                }
         
     | 
| 
      
 507 
     | 
    
         
            +
                // no data and no error, so query was not a SELECT
         
     | 
| 
      
 508 
     | 
    
         
            +
                return Qnil;
         
     | 
| 
      
 509 
     | 
    
         
            +
              }
         
     | 
| 
      
 510 
     | 
    
         
            +
             
     | 
| 
       482 
511 
     | 
    
         
             
              fields      = mysql_fetch_fields(metadata);
         
     | 
| 
       483 
512 
     | 
    
         
             
              field_count = mysql_stmt_field_count(stmt);
         
     | 
| 
       484 
513 
     | 
    
         
             
              field_list  = rb_ary_new2((long)field_count);
         
     | 
| 
       485 
514 
     | 
    
         | 
| 
       486 
     | 
    
         
            -
              for(i = 0; i < field_count; i++) {
         
     | 
| 
      
 515 
     | 
    
         
            +
              for (i = 0; i < field_count; i++) {
         
     | 
| 
       487 
516 
     | 
    
         
             
                VALUE rb_field;
         
     | 
| 
       488 
517 
     | 
    
         | 
| 
       489 
518 
     | 
    
         
             
                rb_field = rb_str_new(fields[i].name, fields[i].name_length);
         
     | 
| 
       490 
     | 
    
         
            -
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       491 
519 
     | 
    
         
             
                rb_enc_associate(rb_field, conn_enc);
         
     | 
| 
       492 
520 
     | 
    
         
             
                if (default_internal_enc) {
         
     | 
| 
       493 
521 
     | 
    
         
             
                 rb_field = rb_str_export_to_enc(rb_field, default_internal_enc);
         
     | 
| 
       494 
522 
     | 
    
         
             
               }
         
     | 
| 
       495 
     | 
    
         
            -
            #endif
         
     | 
| 
       496 
523 
     | 
    
         | 
| 
       497 
524 
     | 
    
         
             
                rb_ary_store(field_list, (long)i, rb_field);
         
     | 
| 
       498 
525 
     | 
    
         
             
              }
         
     | 
| 
         @@ -543,12 +570,15 @@ static VALUE rb_mysql_stmt_close(VALUE self) { 
     | 
|
| 
       543 
570 
     | 
    
         
             
            }
         
     | 
| 
       544 
571 
     | 
    
         | 
| 
       545 
572 
     | 
    
         
             
            void init_mysql2_statement() {
         
     | 
| 
       546 
     | 
    
         
            -
               
     | 
| 
      
 573 
     | 
    
         
            +
              cDate = rb_const_get(rb_cObject, rb_intern("Date"));
         
     | 
| 
      
 574 
     | 
    
         
            +
              cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
         
     | 
| 
      
 575 
     | 
    
         
            +
              cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
         
     | 
| 
       547 
576 
     | 
    
         | 
| 
       548 
     | 
    
         
            -
               
     | 
| 
       549 
     | 
    
         
            -
              rb_define_method(cMysql2Statement, " 
     | 
| 
       550 
     | 
    
         
            -
              rb_define_method(cMysql2Statement, " 
     | 
| 
       551 
     | 
    
         
            -
              rb_define_method(cMysql2Statement, " 
     | 
| 
      
 577 
     | 
    
         
            +
              cMysql2Statement = rb_define_class_under(mMysql2, "Statement", rb_cObject);
         
     | 
| 
      
 578 
     | 
    
         
            +
              rb_define_method(cMysql2Statement, "param_count", rb_mysql_stmt_param_count, 0);
         
     | 
| 
      
 579 
     | 
    
         
            +
              rb_define_method(cMysql2Statement, "field_count", rb_mysql_stmt_field_count, 0);
         
     | 
| 
      
 580 
     | 
    
         
            +
              rb_define_method(cMysql2Statement, "_execute", rb_mysql_stmt_execute, -1);
         
     | 
| 
      
 581 
     | 
    
         
            +
              rb_define_method(cMysql2Statement, "fields", rb_mysql_stmt_fields, 0);
         
     | 
| 
       552 
582 
     | 
    
         
             
              rb_define_method(cMysql2Statement, "last_id", rb_mysql_stmt_last_id, 0);
         
     | 
| 
       553 
583 
     | 
    
         
             
              rb_define_method(cMysql2Statement, "affected_rows", rb_mysql_stmt_affected_rows, 0);
         
     | 
| 
       554 
584 
     | 
    
         
             
              rb_define_method(cMysql2Statement, "close", rb_mysql_stmt_close, 0);
         
     | 
| 
         @@ -568,7 +598,5 @@ void init_mysql2_statement() { 
     | 
|
| 
       568 
598 
     | 
    
         
             
              intern_year = rb_intern("year");
         
     | 
| 
       569 
599 
     | 
    
         | 
| 
       570 
600 
     | 
    
         
             
              intern_to_s = rb_intern("to_s");
         
     | 
| 
       571 
     | 
    
         
            -
             
     | 
| 
       572 
     | 
    
         
            -
              id_cmp = rb_intern("<=>");
         
     | 
| 
       573 
     | 
    
         
            -
            #endif
         
     | 
| 
      
 601 
     | 
    
         
            +
              intern_merge_bang = rb_intern("merge!");
         
     | 
| 
       574 
602 
     | 
    
         
             
            }
         
     | 
    
        data/ext/mysql2/statement.h
    CHANGED
    
    
| 
         @@ -1,5 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            /*
         
     | 
| 
       2 
     | 
    
         
            -
             * backwards compatibility for  
     | 
| 
      
 2 
     | 
    
         
            +
             * backwards compatibility for Rubinius. See
         
     | 
| 
      
 3 
     | 
    
         
            +
             * https://github.com/rubinius/rubinius/issues/3771.
         
     | 
| 
       3 
4 
     | 
    
         
             
             *
         
     | 
| 
       4 
5 
     | 
    
         
             
             * Ruby 1.9.3 provides this API which allows the use of ppoll() on Linux
         
     | 
| 
       5 
6 
     | 
    
         
             
             * to minimize select() and malloc() overhead on high-numbered FDs.
         
     | 
    
        data/lib/mysql2/client.rb
    CHANGED
    
    | 
         @@ -4,22 +4,22 @@ module Mysql2 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
                def self.default_query_options
         
     | 
| 
       6 
6 
     | 
    
         
             
                  @default_query_options ||= {
         
     | 
| 
       7 
     | 
    
         
            -
                    : 
     | 
| 
       8 
     | 
    
         
            -
                    : 
     | 
| 
       9 
     | 
    
         
            -
                    : 
     | 
| 
       10 
     | 
    
         
            -
                    : 
     | 
| 
       11 
     | 
    
         
            -
                    : 
     | 
| 
       12 
     | 
    
         
            -
                    : 
     | 
| 
       13 
     | 
    
         
            -
                    : 
     | 
| 
       14 
     | 
    
         
            -
                    : 
     | 
| 
       15 
     | 
    
         
            -
                    : 
     | 
| 
       16 
     | 
    
         
            -
                    : 
     | 
| 
       17 
     | 
    
         
            -
                    : 
     | 
| 
      
 7 
     | 
    
         
            +
                    as: :hash,                   # the type of object you want each row back as; also supports :array (an array of values)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    async: false,                # don't wait for a result after sending the query, you'll have to monitor the socket yourself then eventually call Mysql2::Client#async_result
         
     | 
| 
      
 9 
     | 
    
         
            +
                    cast_booleans: false,        # cast tinyint(1) fields as true/false in ruby
         
     | 
| 
      
 10 
     | 
    
         
            +
                    symbolize_keys: false,       # return field names as symbols instead of strings
         
     | 
| 
      
 11 
     | 
    
         
            +
                    database_timezone: :local,   # timezone Mysql2 will assume datetime objects are stored in
         
     | 
| 
      
 12 
     | 
    
         
            +
                    application_timezone: nil,   # timezone Mysql2 will convert to before handing the object back to the caller
         
     | 
| 
      
 13 
     | 
    
         
            +
                    cache_rows: true,            # tells Mysql2 to use its internal row cache for results
         
     | 
| 
      
 14 
     | 
    
         
            +
                    connect_flags: REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION | CONNECT_ATTRS,
         
     | 
| 
      
 15 
     | 
    
         
            +
                    cast: true,
         
     | 
| 
      
 16 
     | 
    
         
            +
                    default_file: nil,
         
     | 
| 
      
 17 
     | 
    
         
            +
                    default_group: nil,
         
     | 
| 
       18 
18 
     | 
    
         
             
                  }
         
     | 
| 
       19 
19 
     | 
    
         
             
                end
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
                def initialize(opts = {})
         
     | 
| 
       22 
     | 
    
         
            -
                   
     | 
| 
      
 22 
     | 
    
         
            +
                  raise Mysql2::Error, "Options parameter must be a Hash" unless opts.is_a? Hash
         
     | 
| 
       23 
23 
     | 
    
         
             
                  opts = Mysql2::Util.key_hash_as_symbols(opts)
         
     | 
| 
       24 
24 
     | 
    
         
             
                  @read_timeout = nil
         
     | 
| 
       25 
25 
     | 
    
         
             
                  @query_options = self.class.default_query_options.dup
         
     | 
| 
         @@ -31,10 +31,10 @@ module Mysql2 
     | 
|
| 
       31 
31 
     | 
    
         
             
                  opts[:connect_timeout] = 120 unless opts.key?(:connect_timeout)
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
                  # TODO: stricter validation rather than silent massaging
         
     | 
| 
       34 
     | 
    
         
            -
                  [ 
     | 
| 
      
 34 
     | 
    
         
            +
                  %i[reconnect connect_timeout local_infile read_timeout write_timeout default_file default_group secure_auth init_command automatic_close enable_cleartext_plugin].each do |key|
         
     | 
| 
       35 
35 
     | 
    
         
             
                    next unless opts.key?(key)
         
     | 
| 
       36 
36 
     | 
    
         
             
                    case key
         
     | 
| 
       37 
     | 
    
         
            -
                    when :reconnect, :local_infile, :secure_auth, :automatic_close
         
     | 
| 
      
 37 
     | 
    
         
            +
                    when :reconnect, :local_infile, :secure_auth, :automatic_close, :enable_cleartext_plugin
         
     | 
| 
       38 
38 
     | 
    
         
             
                      send(:"#{key}=", !!opts[key]) # rubocop:disable Style/DoubleNegation
         
     | 
| 
       39 
39 
     | 
    
         
             
                    when :connect_timeout, :read_timeout, :write_timeout
         
     | 
| 
       40 
40 
     | 
    
         
             
                      send(:"#{key}=", Integer(opts[key])) unless opts[key].nil?
         
     | 
| 
         @@ -47,26 +47,26 @@ module Mysql2 
     | 
|
| 
       47 
47 
     | 
    
         
             
                  self.charset_name = opts[:encoding] || 'utf8'
         
     | 
| 
       48 
48 
     | 
    
         | 
| 
       49 
49 
     | 
    
         
             
                  ssl_options = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher)
         
     | 
| 
       50 
     | 
    
         
            -
                  ssl_set(*ssl_options) if ssl_options.any?
         
     | 
| 
      
 50 
     | 
    
         
            +
                  ssl_set(*ssl_options) if ssl_options.any? || opts.key?(:sslverify)
         
     | 
| 
       51 
51 
     | 
    
         
             
                  self.ssl_mode = parse_ssl_mode(opts[:ssl_mode]) if opts[:ssl_mode]
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                  case opts[:flags]
         
     | 
| 
      
 53 
     | 
    
         
            +
                  flags = case opts[:flags]
         
     | 
| 
       54 
54 
     | 
    
         
             
                  when Array
         
     | 
| 
       55 
     | 
    
         
            -
                     
     | 
| 
      
 55 
     | 
    
         
            +
                    parse_flags_array(opts[:flags], @query_options[:connect_flags])
         
     | 
| 
       56 
56 
     | 
    
         
             
                  when String
         
     | 
| 
       57 
     | 
    
         
            -
                     
     | 
| 
      
 57 
     | 
    
         
            +
                    parse_flags_array(opts[:flags].split(' '), @query_options[:connect_flags])
         
     | 
| 
       58 
58 
     | 
    
         
             
                  when Integer
         
     | 
| 
       59 
     | 
    
         
            -
                     
     | 
| 
      
 59 
     | 
    
         
            +
                    @query_options[:connect_flags] | opts[:flags]
         
     | 
| 
       60 
60 
     | 
    
         
             
                  else
         
     | 
| 
       61 
     | 
    
         
            -
                     
     | 
| 
      
 61 
     | 
    
         
            +
                    @query_options[:connect_flags]
         
     | 
| 
       62 
62 
     | 
    
         
             
                  end
         
     | 
| 
       63 
63 
     | 
    
         | 
| 
       64 
64 
     | 
    
         
             
                  # SSL verify is a connection flag rather than a mysql_ssl_set option
         
     | 
| 
       65 
     | 
    
         
            -
                  flags |= SSL_VERIFY_SERVER_CERT if opts[:sslverify] 
     | 
| 
      
 65 
     | 
    
         
            +
                  flags |= SSL_VERIFY_SERVER_CERT if opts[:sslverify]
         
     | 
| 
       66 
66 
     | 
    
         | 
| 
       67 
     | 
    
         
            -
                  if [ 
     | 
| 
      
 67 
     | 
    
         
            +
                  if %i[user pass hostname dbname db sock].any? { |k| @query_options.key?(k) }
         
     | 
| 
       68 
68 
     | 
    
         
             
                    warn "============= WARNING FROM mysql2 ============="
         
     | 
| 
       69 
     | 
    
         
            -
                    warn "The options :user, :pass, :hostname, :dbname, :db, and :sock will be  
     | 
| 
      
 69 
     | 
    
         
            +
                    warn "The options :user, :pass, :hostname, :dbname, :db, and :sock are deprecated and will be removed at some point in the future."
         
     | 
| 
       70 
70 
     | 
    
         
             
                    warn "Instead, please use :username, :password, :host, :port, :database, :socket, :flags for the options."
         
     | 
| 
       71 
71 
     | 
    
         
             
                    warn "============= END WARNING FROM mysql2 ========="
         
     | 
| 
       72 
72 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -85,8 +85,9 @@ module Mysql2 
     | 
|
| 
       85 
85 
     | 
    
         
             
                  port = port.to_i unless port.nil?
         
     | 
| 
       86 
86 
     | 
    
         
             
                  database = database.to_s unless database.nil?
         
     | 
| 
       87 
87 
     | 
    
         
             
                  socket = socket.to_s unless socket.nil?
         
     | 
| 
      
 88 
     | 
    
         
            +
                  conn_attrs = parse_connect_attrs(opts[:connect_attrs])
         
     | 
| 
       88 
89 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
                  connect user, pass, host, port, database, socket, flags
         
     | 
| 
      
 90 
     | 
    
         
            +
                  connect user, pass, host, port, database, socket, flags, conn_attrs
         
     | 
| 
       90 
91 
     | 
    
         
             
                end
         
     | 
| 
       91 
92 
     | 
    
         | 
| 
       92 
93 
     | 
    
         
             
                def parse_ssl_mode(mode)
         
     | 
| 
         @@ -114,14 +115,19 @@ module Mysql2 
     | 
|
| 
       114 
115 
     | 
    
         
             
                  end
         
     | 
| 
       115 
116 
     | 
    
         
             
                end
         
     | 
| 
       116 
117 
     | 
    
         | 
| 
       117 
     | 
    
         
            -
                 
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
      
 118 
     | 
    
         
            +
                # Set default program_name in performance_schema.session_connect_attrs
         
     | 
| 
      
 119 
     | 
    
         
            +
                # and performance_schema.session_account_connect_attrs
         
     | 
| 
      
 120 
     | 
    
         
            +
                def parse_connect_attrs(conn_attrs)
         
     | 
| 
      
 121 
     | 
    
         
            +
                  return {} if Mysql2::Client::CONNECT_ATTRS.zero?
         
     | 
| 
      
 122 
     | 
    
         
            +
                  conn_attrs ||= {}
         
     | 
| 
      
 123 
     | 
    
         
            +
                  conn_attrs[:program_name] ||= $PROGRAM_NAME
         
     | 
| 
      
 124 
     | 
    
         
            +
                  conn_attrs.each_with_object({}) do |(key, value), hash|
         
     | 
| 
      
 125 
     | 
    
         
            +
                    hash[key.to_s] = value.to_s
         
     | 
| 
       122 
126 
     | 
    
         
             
                  end
         
     | 
| 
       123 
     | 
    
         
            -
                 
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                def query(sql, options = {})
         
     | 
| 
      
 130 
     | 
    
         
            +
                  Thread.handle_interrupt(::Mysql2::Util::TIMEOUT_ERROR_CLASS => :never) do
         
     | 
| 
       125 
131 
     | 
    
         
             
                    _query(sql, @query_options.merge(options))
         
     | 
| 
       126 
132 
     | 
    
         
             
                  end
         
     | 
| 
       127 
133 
     | 
    
         
             
                end
         
     | 
    
        data/lib/mysql2/em.rb
    CHANGED
    
    | 
         @@ -1,5 +1,3 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # encoding: utf-8
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
1 
     | 
    
         
             
            require 'eventmachine'
         
     | 
| 
       4 
2 
     | 
    
         
             
            require 'mysql2'
         
     | 
| 
       5 
3 
     | 
    
         | 
| 
         @@ -17,7 +15,7 @@ module Mysql2 
     | 
|
| 
       17 
15 
     | 
    
         
             
                      detach
         
     | 
| 
       18 
16 
     | 
    
         
             
                      begin
         
     | 
| 
       19 
17 
     | 
    
         
             
                        result = @client.async_result
         
     | 
| 
       20 
     | 
    
         
            -
                      rescue => e
         
     | 
| 
      
 18 
     | 
    
         
            +
                      rescue StandardError => e
         
     | 
| 
       21 
19 
     | 
    
         
             
                        @deferable.fail(e)
         
     | 
| 
       22 
20 
     | 
    
         
             
                      else
         
     | 
| 
       23 
21 
     | 
    
         
             
                        @deferable.succeed(result)
         
     | 
| 
         @@ -41,7 +39,7 @@ module Mysql2 
     | 
|
| 
       41 
39 
     | 
    
         | 
| 
       42 
40 
     | 
    
         
             
                  def query(sql, opts = {})
         
     | 
| 
       43 
41 
     | 
    
         
             
                    if ::EM.reactor_running?
         
     | 
| 
       44 
     | 
    
         
            -
                      super(sql, opts.merge(: 
     | 
| 
      
 42 
     | 
    
         
            +
                      super(sql, opts.merge(async: true))
         
     | 
| 
       45 
43 
     | 
    
         
             
                      deferable = ::EM::DefaultDeferrable.new
         
     | 
| 
       46 
44 
     | 
    
         
             
                      @watch = ::EM.watch(socket, Watcher, self, deferable)
         
     | 
| 
       47 
45 
     | 
    
         
             
                      @watch.notify_readable = true
         
     | 
    
        data/lib/mysql2/error.rb
    CHANGED
    
    | 
         @@ -1,32 +1,65 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # encoding: UTF-8
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
1 
     | 
    
         
             
            module Mysql2
         
     | 
| 
       4 
2 
     | 
    
         
             
              class Error < StandardError
         
     | 
| 
       5 
3 
     | 
    
         
             
                ENCODE_OPTS = {
         
     | 
| 
       6 
     | 
    
         
            -
                  : 
     | 
| 
       7 
     | 
    
         
            -
                  : 
     | 
| 
       8 
     | 
    
         
            -
                  : 
     | 
| 
      
 4 
     | 
    
         
            +
                  undef: :replace,
         
     | 
| 
      
 5 
     | 
    
         
            +
                  invalid: :replace,
         
     | 
| 
      
 6 
     | 
    
         
            +
                  replace: '?'.freeze,
         
     | 
| 
      
 7 
     | 
    
         
            +
                }.freeze
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                ConnectionError = Class.new(Error)
         
     | 
| 
      
 10 
     | 
    
         
            +
                TimeoutError = Class.new(Error)
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                CODES = {
         
     | 
| 
      
 13 
     | 
    
         
            +
                  1205 => TimeoutError, # ER_LOCK_WAIT_TIMEOUT
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  1044 => ConnectionError, # ER_DBACCESS_DENIED_ERROR
         
     | 
| 
      
 16 
     | 
    
         
            +
                  1045 => ConnectionError, # ER_ACCESS_DENIED_ERROR
         
     | 
| 
      
 17 
     | 
    
         
            +
                  1152 => ConnectionError, # ER_ABORTING_CONNECTION
         
     | 
| 
      
 18 
     | 
    
         
            +
                  1153 => ConnectionError, # ER_NET_PACKET_TOO_LARGE
         
     | 
| 
      
 19 
     | 
    
         
            +
                  1154 => ConnectionError, # ER_NET_READ_ERROR_FROM_PIPE
         
     | 
| 
      
 20 
     | 
    
         
            +
                  1155 => ConnectionError, # ER_NET_FCNTL_ERROR
         
     | 
| 
      
 21 
     | 
    
         
            +
                  1156 => ConnectionError, # ER_NET_PACKETS_OUT_OF_ORDER
         
     | 
| 
      
 22 
     | 
    
         
            +
                  1157 => ConnectionError, # ER_NET_UNCOMPRESS_ERROR
         
     | 
| 
      
 23 
     | 
    
         
            +
                  1158 => ConnectionError, # ER_NET_READ_ERROR
         
     | 
| 
      
 24 
     | 
    
         
            +
                  1159 => ConnectionError, # ER_NET_READ_INTERRUPTED
         
     | 
| 
      
 25 
     | 
    
         
            +
                  1160 => ConnectionError, # ER_NET_ERROR_ON_WRITE
         
     | 
| 
      
 26 
     | 
    
         
            +
                  1161 => ConnectionError, # ER_NET_WRITE_INTERRUPTED
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  2001 => ConnectionError, # CR_SOCKET_CREATE_ERROR
         
     | 
| 
      
 29 
     | 
    
         
            +
                  2002 => ConnectionError, # CR_CONNECTION_ERROR
         
     | 
| 
      
 30 
     | 
    
         
            +
                  2003 => ConnectionError, # CR_CONN_HOST_ERROR
         
     | 
| 
      
 31 
     | 
    
         
            +
                  2004 => ConnectionError, # CR_IPSOCK_ERROR
         
     | 
| 
      
 32 
     | 
    
         
            +
                  2005 => ConnectionError, # CR_UNKNOWN_HOST
         
     | 
| 
      
 33 
     | 
    
         
            +
                  2006 => ConnectionError, # CR_SERVER_GONE_ERROR
         
     | 
| 
      
 34 
     | 
    
         
            +
                  2007 => ConnectionError, # CR_VERSION_ERROR
         
     | 
| 
      
 35 
     | 
    
         
            +
                  2009 => ConnectionError, # CR_WRONG_HOST_INFO
         
     | 
| 
      
 36 
     | 
    
         
            +
                  2012 => ConnectionError, # CR_SERVER_HANDSHAKE_ERR
         
     | 
| 
      
 37 
     | 
    
         
            +
                  2013 => ConnectionError, # CR_SERVER_LOST
         
     | 
| 
      
 38 
     | 
    
         
            +
                  2020 => ConnectionError, # CR_NET_PACKET_TOO_LARGE
         
     | 
| 
      
 39 
     | 
    
         
            +
                  2026 => ConnectionError, # CR_SSL_CONNECTION_ERROR
         
     | 
| 
      
 40 
     | 
    
         
            +
                  2027 => ConnectionError, # CR_MALFORMED_PACKET
         
     | 
| 
      
 41 
     | 
    
         
            +
                  2047 => ConnectionError, # CR_CONN_UNKNOW_PROTOCOL
         
     | 
| 
      
 42 
     | 
    
         
            +
                  2048 => ConnectionError, # CR_INVALID_CONN_HANDLE
         
     | 
| 
      
 43 
     | 
    
         
            +
                  2049 => ConnectionError, # CR_UNUSED_1
         
     | 
| 
       9 
44 
     | 
    
         
             
                }.freeze
         
     | 
| 
       10 
45 
     | 
    
         | 
| 
       11 
46 
     | 
    
         
             
                attr_reader :error_number, :sql_state
         
     | 
| 
       12 
47 
     | 
    
         | 
| 
       13 
48 
     | 
    
         
             
                # Mysql gem compatibility
         
     | 
| 
       14 
     | 
    
         
            -
                 
     | 
| 
       15 
     | 
    
         
            -
                 
     | 
| 
      
 49 
     | 
    
         
            +
                alias errno error_number
         
     | 
| 
      
 50 
     | 
    
         
            +
                alias error message
         
     | 
| 
       16 
51 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                def initialize(msg)
         
     | 
| 
       18 
     | 
    
         
            -
                  @server_version  
     | 
| 
      
 52 
     | 
    
         
            +
                def initialize(msg, server_version = nil, error_number = nil, sql_state = nil)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @server_version = server_version
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @error_number = error_number
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @sql_state = sql_state ? sql_state.encode(ENCODE_OPTS) : nil
         
     | 
| 
       19 
56 
     | 
    
         | 
| 
       20 
57 
     | 
    
         
             
                  super(clean_message(msg))
         
     | 
| 
       21 
58 
     | 
    
         
             
                end
         
     | 
| 
       22 
59 
     | 
    
         | 
| 
       23 
60 
     | 
    
         
             
                def self.new_with_args(msg, server_version, error_number, sql_state)
         
     | 
| 
       24 
     | 
    
         
            -
                   
     | 
| 
       25 
     | 
    
         
            -
                   
     | 
| 
       26 
     | 
    
         
            -
                  err.instance_variable_set('@error_number', error_number)
         
     | 
| 
       27 
     | 
    
         
            -
                  err.instance_variable_set('@sql_state', sql_state.respond_to?(:encode) ? sql_state.encode(ENCODE_OPTS) : sql_state)
         
     | 
| 
       28 
     | 
    
         
            -
                  err.send(:initialize, msg)
         
     | 
| 
       29 
     | 
    
         
            -
                  err
         
     | 
| 
      
 61 
     | 
    
         
            +
                  error_class = CODES.fetch(error_number, self)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  error_class.new(msg, server_version, error_number, sql_state)
         
     | 
| 
       30 
63 
     | 
    
         
             
                end
         
     | 
| 
       31 
64 
     | 
    
         | 
| 
       32 
65 
     | 
    
         
             
                private
         
     | 
| 
         @@ -55,12 +88,8 @@ module Mysql2 
     | 
|
| 
       55 
88 
     | 
    
         
             
                # encoding, we'll assume UTF-8 and clean the string of anything that's not a
         
     | 
| 
       56 
89 
     | 
    
         
             
                # valid UTF-8 character.
         
     | 
| 
       57 
90 
     | 
    
         
             
                #
         
     | 
| 
       58 
     | 
    
         
            -
                #  
     | 
| 
       59 
     | 
    
         
            -
                #
         
     | 
| 
       60 
     | 
    
         
            -
                # Returns a valid UTF-8 string in Ruby 1.9+, the original string on Ruby 1.8
         
     | 
| 
      
 91 
     | 
    
         
            +
                # Returns a valid UTF-8 string.
         
     | 
| 
       61 
92 
     | 
    
         
             
                def clean_message(message)
         
     | 
| 
       62 
     | 
    
         
            -
                  return message unless message.respond_to?(:encode)
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
93 
     | 
    
         
             
                  if @server_version && @server_version > 50500
         
     | 
| 
       65 
94 
     | 
    
         
             
                    message.encode(ENCODE_OPTS)
         
     | 
| 
       66 
95 
     | 
    
         
             
                  else
         
     |