mysql2 0.3.10 → 0.3.11

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.
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.11 (December 6th, 2011)
4
+ * change mysql error detection strategy from using mysql_field_count to the more explicit mysql_errno
5
+ * bugfix to avoid race condition with active connections that error out
6
+ * revert back to using xmalloc/xfree for allocations
7
+ * avoid potentially unsafe Ruby C API usage w/o GVL
8
+ * reacquire GVL before retrying on EINTR on connect
9
+
3
10
  ## 0.3.10 (November 9th, 2011)
4
11
 
5
12
  ## 0.3.9 (November 9th, 2011)
@@ -48,6 +55,13 @@
48
55
  * BREAKING CHANGE: the ActiveRecord adapter has been pulled into Rails 3.1 and is no longer part of the gem
49
56
  * added Mysql2::Client.escape (class-level) for raw one-off non-encoding-aware escaping
50
57
 
58
+ ## 0.2.18 (December 6th, 2011)
59
+ * change mysql error detection strategy from using mysql_field_count to the more explicit mysql_errno
60
+ * bugfix to avoid race condition with active connections that error out
61
+ * revert back to using xmalloc/xfree for allocations
62
+ * avoid potentially unsafe Ruby C API usage w/o GVL
63
+ * reacquire GVL before retrying on EINTR on connect
64
+
51
65
  ## 0.2.17 (November 9th, 2011)
52
66
 
53
67
  ## 0.2.16 (November 9th, 2011)
data/README.md CHANGED
@@ -317,6 +317,15 @@ bundle install
317
317
  rake
318
318
  ```
319
319
 
320
+ The tests require the "test" database to exist, and expect to connect
321
+ both as root and the running user, both with a blank password:
322
+
323
+ ``` sql
324
+ CREATE DATABASE test;
325
+ CREATE USER '<user>'@'localhost' IDENTIFIED BY '';
326
+ GRANT ALL PRIVILEGES ON test.* TO '<user>'@'localhost';
327
+ ```
328
+
320
329
  ## Special Thanks
321
330
 
322
331
  * Eric Wong - for the contribution (and the informative explanations) of some thread-safety, non-blocking I/O and cleanup patches. You rock dude
@@ -46,6 +46,8 @@ struct nogvl_connect_args {
46
46
  struct nogvl_send_query_args {
47
47
  MYSQL *mysql;
48
48
  VALUE sql;
49
+ const char *sql_ptr;
50
+ long sql_len;
49
51
  mysql_client_wrapper *wrapper;
50
52
  };
51
53
 
@@ -112,12 +114,10 @@ static VALUE nogvl_connect(void *ptr) {
112
114
  struct nogvl_connect_args *args = ptr;
113
115
  MYSQL *client;
114
116
 
115
- do {
116
- client = mysql_real_connect(args->mysql, args->host,
117
- args->user, args->passwd,
118
- args->db, args->port, args->unix_socket,
119
- args->client_flag);
120
- } while (! client && errno == EINTR && (errno = 0) == 0);
117
+ client = mysql_real_connect(args->mysql, args->host,
118
+ args->user, args->passwd,
119
+ args->db, args->port, args->unix_socket,
120
+ args->client_flag);
121
121
 
122
122
  return client ? Qtrue : Qfalse;
123
123
  }
@@ -147,7 +147,7 @@ static VALUE nogvl_close(void *ptr) {
147
147
  #endif
148
148
 
149
149
  mysql_close(wrapper->client);
150
- free(wrapper->client);
150
+ xfree(wrapper->client);
151
151
  }
152
152
 
153
153
  return Qnil;
@@ -158,7 +158,7 @@ static void rb_mysql_client_free(void * ptr) {
158
158
 
159
159
  nogvl_close(wrapper);
160
160
 
161
- free(ptr);
161
+ xfree(ptr);
162
162
  }
163
163
 
164
164
  static VALUE allocate(VALUE klass) {
@@ -169,7 +169,7 @@ static VALUE allocate(VALUE klass) {
169
169
  wrapper->active = 0;
170
170
  wrapper->reconnect_enabled = 0;
171
171
  wrapper->closed = 1;
172
- wrapper->client = (MYSQL*)malloc(sizeof(MYSQL));
172
+ wrapper->client = (MYSQL*)xmalloc(sizeof(MYSQL));
173
173
  return obj;
174
174
  }
175
175
 
@@ -181,25 +181,26 @@ static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) {
181
181
  Check_Type(str, T_STRING);
182
182
 
183
183
  oldLen = RSTRING_LEN(str);
184
- newStr = malloc(oldLen*2+1);
184
+ newStr = xmalloc(oldLen*2+1);
185
185
 
186
186
  newLen = mysql_escape_string((char *)newStr, StringValuePtr(str), oldLen);
187
187
  if (newLen == oldLen) {
188
188
  // no need to return a new ruby string if nothing changed
189
- free(newStr);
189
+ xfree(newStr);
190
190
  return str;
191
191
  } else {
192
192
  rb_str = rb_str_new((const char*)newStr, newLen);
193
193
  #ifdef HAVE_RUBY_ENCODING_H
194
194
  rb_enc_copy(rb_str, str);
195
195
  #endif
196
- free(newStr);
196
+ xfree(newStr);
197
197
  return rb_str;
198
198
  }
199
199
  }
200
200
 
201
201
  static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags) {
202
202
  struct nogvl_connect_args args;
203
+ VALUE rv;
203
204
  GET_CLIENT(self);
204
205
 
205
206
  args.host = NIL_P(host) ? "localhost" : StringValuePtr(host);
@@ -211,9 +212,14 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
211
212
  args.mysql = wrapper->client;
212
213
  args.client_flag = NUM2ULONG(flags);
213
214
 
214
- if (rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0) == Qfalse) {
215
- // unable to connect
216
- return rb_raise_mysql2_error(wrapper);
215
+ rv = rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0);
216
+ if (rv == Qfalse) {
217
+ while (rv == Qfalse && errno == EINTR) {
218
+ errno = 0;
219
+ rv = rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0);
220
+ }
221
+ if (rv == Qfalse)
222
+ return rb_raise_mysql2_error(wrapper);
217
223
  }
218
224
 
219
225
  return self;
@@ -243,10 +249,8 @@ static VALUE rb_mysql_client_close(VALUE self) {
243
249
  static VALUE nogvl_send_query(void *ptr) {
244
250
  struct nogvl_send_query_args *args = ptr;
245
251
  int rv;
246
- const char *sql = StringValuePtr(args->sql);
247
- long sql_len = RSTRING_LEN(args->sql);
248
252
 
249
- rv = mysql_send_query(args->mysql, sql, sql_len);
253
+ rv = mysql_send_query(args->mysql, args->sql_ptr, args->sql_len);
250
254
 
251
255
  return rv == 0 ? Qtrue : Qfalse;
252
256
  }
@@ -311,9 +315,11 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
311
315
  result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
312
316
 
313
317
  if (result == NULL) {
314
- if (mysql_field_count(wrapper->client) != 0) {
318
+ if (mysql_errno(wrapper->client) != 0) {
319
+ MARK_CONN_INACTIVE(self);
315
320
  rb_raise_mysql2_error(wrapper);
316
321
  }
322
+ // no data and no error, so query was not a SELECT
317
323
  return Qnil;
318
324
  }
319
325
 
@@ -450,6 +456,8 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
450
456
  // ensure the string is in the encoding the connection is expecting
451
457
  args.sql = rb_str_export_to_enc(args.sql, conn_enc);
452
458
  #endif
459
+ args.sql_ptr = StringValuePtr(args.sql);
460
+ args.sql_len = RSTRING_LEN(args.sql);
453
461
 
454
462
  // see if this connection is still waiting on a result from a previous query
455
463
  if (wrapper->active == 0) {
@@ -502,12 +510,12 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
502
510
  #endif
503
511
 
504
512
  oldLen = RSTRING_LEN(str);
505
- newStr = malloc(oldLen*2+1);
513
+ newStr = xmalloc(oldLen*2+1);
506
514
 
507
515
  newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, StringValuePtr(str), oldLen);
508
516
  if (newLen == oldLen) {
509
517
  // no need to return a new ruby string if nothing changed
510
- free(newStr);
518
+ xfree(newStr);
511
519
  return str;
512
520
  } else {
513
521
  rb_str = rb_str_new((const char*)newStr, newLen);
@@ -517,7 +525,7 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
517
525
  rb_str = rb_str_export_to_enc(rb_str, default_internal_enc);
518
526
  }
519
527
  #endif
520
- free(newStr);
528
+ xfree(newStr);
521
529
  return rb_str;
522
530
  }
523
531
  }
@@ -80,7 +80,7 @@ static void rb_mysql_result_free(void * wrapper) {
80
80
  mysql2_result_wrapper * w = wrapper;
81
81
  /* FIXME: this may call flush_use_result, which can hit the socket */
82
82
  rb_mysql_result_free_result(w);
83
- free(wrapper);
83
+ xfree(wrapper);
84
84
  }
85
85
 
86
86
  /*
@@ -1,3 +1,3 @@
1
1
  module Mysql2
2
- VERSION = "0.3.10"
2
+ VERSION = "0.3.11"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql2
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 10
10
- version: 0.3.10
9
+ - 11
10
+ version: 0.3.11
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brian Lopez
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-09 00:00:00 -08:00
18
+ date: 2011-12-06 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -232,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
232
232
  requirements: []
233
233
 
234
234
  rubyforge_project:
235
- rubygems_version: 1.6.2
235
+ rubygems_version: 1.3.9.3
236
236
  signing_key:
237
237
  specification_version: 3
238
238
  summary: A simple, fast Mysql library for Ruby, binding to libmysql