mysql2 0.3.12b6 → 0.3.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -44,6 +44,17 @@ static VALUE rb_hash_dup(VALUE other) {
44
44
  mysql_client_wrapper *wrapper; \
45
45
  Data_Get_Struct(self, mysql_client_wrapper, wrapper)
46
46
 
47
+ /*
48
+ * compatability with mysql-connector-c, where LIBMYSQL_VERSION is the correct
49
+ * variable to use, but MYSQL_SERVER_VERSION gives the correct numbers when
50
+ * linking against the server itself
51
+ */
52
+ #ifdef LIBMYSQL_VERSION
53
+ #define MYSQL_LINK_VERSION LIBMYSQL_VERSION
54
+ #else
55
+ #define MYSQL_LINK_VERSION MYSQL_SERVER_VERSION
56
+ #endif
57
+
47
58
  /*
48
59
  * used to pass all arguments to mysql_real_connect while inside
49
60
  * rb_thread_blocking_region
@@ -182,13 +193,15 @@ static VALUE nogvl_close(void *ptr) {
182
193
  return Qnil;
183
194
  }
184
195
 
185
- static void rb_mysql_client_free(void * ptr) {
196
+ static void rb_mysql_client_free(void *ptr) {
186
197
  mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;
187
198
 
188
- nogvl_close(wrapper);
189
-
190
- xfree(wrapper->client);
191
- xfree(ptr);
199
+ wrapper->refcount--;
200
+ if (wrapper->refcount == 0) {
201
+ nogvl_close(wrapper);
202
+ xfree(wrapper->client);
203
+ xfree(wrapper);
204
+ }
192
205
  }
193
206
 
194
207
  static VALUE allocate(VALUE klass) {
@@ -200,6 +213,7 @@ static VALUE allocate(VALUE klass) {
200
213
  wrapper->reconnect_enabled = 0;
201
214
  wrapper->connected = 0; /* means that a database connection is open */
202
215
  wrapper->initialized = 0; /* means that that the wrapper is initialized */
216
+ wrapper->refcount = 1;
203
217
  wrapper->client = (MYSQL*)xmalloc(sizeof(MYSQL));
204
218
  return obj;
205
219
  }
@@ -245,6 +259,25 @@ static VALUE rb_mysql_client_warning_count(VALUE self) {
245
259
  return UINT2NUM(warning_count);
246
260
  }
247
261
 
262
+ static VALUE rb_mysql_info(VALUE self) {
263
+ const char *info;
264
+ VALUE rb_str;
265
+ GET_CLIENT(self);
266
+
267
+ info = mysql_info(wrapper->client);
268
+
269
+ if (info == NULL) {
270
+ return Qnil;
271
+ }
272
+
273
+ rb_str = rb_str_new2(info);
274
+ #ifdef HAVE_RUBY_ENCODING_H
275
+ rb_enc_associate(rb_str, rb_utf8_encoding());
276
+ #endif
277
+
278
+ return rb_str;
279
+ }
280
+
248
281
  static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags) {
249
282
  struct nogvl_connect_args args;
250
283
  VALUE rv;
@@ -361,9 +394,7 @@ static VALUE nogvl_use_result(void *ptr) {
361
394
  static VALUE rb_mysql_client_async_result(VALUE self) {
362
395
  MYSQL_RES * result;
363
396
  VALUE resultObj;
364
- #ifdef HAVE_RUBY_ENCODING_H
365
- mysql2_result_wrapper * result_wrapper;
366
- #endif
397
+ VALUE current, is_streaming;
367
398
  GET_CLIENT(self);
368
399
 
369
400
  /* if we're not waiting on a result, do nothing */
@@ -377,7 +408,7 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
377
408
  return rb_raise_mysql2_error(wrapper);
378
409
  }
379
410
 
380
- VALUE is_streaming = rb_hash_aref(rb_iv_get(self, "@current_query_options"), sym_stream);
411
+ is_streaming = rb_hash_aref(rb_iv_get(self, "@current_query_options"), sym_stream);
381
412
  if(is_streaming == Qtrue) {
382
413
  result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_use_result, wrapper, RUBY_UBF_IO, 0);
383
414
  } else {
@@ -393,14 +424,11 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
393
424
  return Qnil;
394
425
  }
395
426
 
396
- resultObj = rb_mysql_result_to_obj(result);
397
- /* pass-through query options for result construction later */
398
- rb_iv_set(resultObj, "@query_options", rb_hash_dup(rb_iv_get(self, "@current_query_options")));
427
+ current = rb_hash_dup(rb_iv_get(self, "@current_query_options"));
428
+ RB_GC_GUARD(current);
429
+ Check_Type(current, T_HASH);
430
+ resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result);
399
431
 
400
- #ifdef HAVE_RUBY_ENCODING_H
401
- GetMysql2Result(resultObj, result_wrapper);
402
- result_wrapper->encoding = wrapper->encoding;
403
- #endif
404
432
  return resultObj;
405
433
  }
406
434
 
@@ -545,10 +573,13 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
545
573
  REQUIRE_CONNECTED(wrapper);
546
574
  args.mysql = wrapper->client;
547
575
 
548
- rb_iv_set(self, "@current_query_options", rb_hash_dup(rb_iv_get(self, "@query_options")));
549
- current = rb_iv_get(self, "@current_query_options");
576
+ current = rb_hash_dup(rb_iv_get(self, "@query_options"));
577
+ RB_GC_GUARD(current);
578
+ Check_Type(current, T_HASH);
579
+ rb_iv_set(self, "@current_query_options", current);
580
+
550
581
  if (rb_scan_args(argc, argv, "11", &args.sql, &opts) == 2) {
551
- opts = rb_funcall(current, intern_merge_bang, 1, opts);
582
+ rb_funcall(current, intern_merge_bang, 1, opts);
552
583
 
553
584
  if (rb_hash_aref(current, sym_async) == Qtrue) {
554
585
  async = 1;
@@ -926,10 +957,7 @@ static VALUE rb_mysql_client_store_result(VALUE self)
926
957
  {
927
958
  MYSQL_RES * result;
928
959
  VALUE resultObj;
929
- #ifdef HAVE_RUBY_ENCODING_H
930
- mysql2_result_wrapper * result_wrapper;
931
- #endif
932
-
960
+ VALUE current;
933
961
  GET_CLIENT(self);
934
962
 
935
963
  result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
@@ -942,16 +970,12 @@ static VALUE rb_mysql_client_store_result(VALUE self)
942
970
  return Qnil;
943
971
  }
944
972
 
945
- resultObj = rb_mysql_result_to_obj(result);
946
- /* pass-through query options for result construction later */
947
- rb_iv_set(resultObj, "@query_options", rb_hash_dup(rb_iv_get(self, "@current_query_options")));
973
+ current = rb_hash_dup(rb_iv_get(self, "@current_query_options"));
974
+ RB_GC_GUARD(current);
975
+ Check_Type(current, T_HASH);
976
+ resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result);
948
977
 
949
- #ifdef HAVE_RUBY_ENCODING_H
950
- GetMysql2Result(resultObj, result_wrapper);
951
- result_wrapper->encoding = wrapper->encoding;
952
- #endif
953
978
  return resultObj;
954
-
955
979
  }
956
980
 
957
981
  #ifdef HAVE_RUBY_ENCODING_H
@@ -1051,14 +1075,12 @@ static VALUE set_charset_name(VALUE self, VALUE value) {
1051
1075
  static VALUE set_ssl_options(VALUE self, VALUE key, VALUE cert, VALUE ca, VALUE capath, VALUE cipher) {
1052
1076
  GET_CLIENT(self);
1053
1077
 
1054
- if(!NIL_P(ca) || !NIL_P(key)) {
1055
- mysql_ssl_set(wrapper->client,
1056
- NIL_P(key) ? NULL : StringValuePtr(key),
1057
- NIL_P(cert) ? NULL : StringValuePtr(cert),
1058
- NIL_P(ca) ? NULL : StringValuePtr(ca),
1059
- NIL_P(capath) ? NULL : StringValuePtr(capath),
1060
- NIL_P(cipher) ? NULL : StringValuePtr(cipher));
1061
- }
1078
+ mysql_ssl_set(wrapper->client,
1079
+ NIL_P(key) ? NULL : StringValuePtr(key),
1080
+ NIL_P(cert) ? NULL : StringValuePtr(cert),
1081
+ NIL_P(ca) ? NULL : StringValuePtr(ca),
1082
+ NIL_P(capath) ? NULL : StringValuePtr(capath),
1083
+ NIL_P(cipher) ? NULL : StringValuePtr(cipher));
1062
1084
 
1063
1085
  return self;
1064
1086
  }
@@ -1081,14 +1103,15 @@ void init_mysql2_client() {
1081
1103
  int i;
1082
1104
  int dots = 0;
1083
1105
  const char *lib = mysql_get_client_info();
1084
- for (i = 0; lib[i] != 0 && MYSQL_SERVER_VERSION[i] != 0; i++) {
1106
+
1107
+ for (i = 0; lib[i] != 0 && MYSQL_LINK_VERSION[i] != 0; i++) {
1085
1108
  if (lib[i] == '.') {
1086
1109
  dots++;
1087
1110
  /* we only compare MAJOR and MINOR */
1088
1111
  if (dots == 2) break;
1089
1112
  }
1090
- if (lib[i] != MYSQL_SERVER_VERSION[i]) {
1091
- rb_raise(rb_eRuntimeError, "Incorrect MySQL client library version! This gem was compiled for %s but the client library is %s.", MYSQL_SERVER_VERSION, lib);
1113
+ if (lib[i] != MYSQL_LINK_VERSION[i]) {
1114
+ 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);
1092
1115
  return;
1093
1116
  }
1094
1117
  }
@@ -1120,6 +1143,7 @@ void init_mysql2_client() {
1120
1143
  rb_define_method(cMysql2Client, "store_result", rb_mysql_client_store_result, 0);
1121
1144
  rb_define_method(cMysql2Client, "reconnect=", set_reconnect, 1);
1122
1145
  rb_define_method(cMysql2Client, "warning_count", rb_mysql_client_warning_count, 0);
1146
+ rb_define_method(cMysql2Client, "query_info_string", rb_mysql_info, 0);
1123
1147
  #ifdef HAVE_RUBY_ENCODING_H
1124
1148
  rb_define_method(cMysql2Client, "encoding", rb_mysql_client_encoding, 0);
1125
1149
  #endif
@@ -38,6 +38,8 @@ typedef struct {
38
38
  int active;
39
39
  int connected;
40
40
  int initialized;
41
+ int refcount;
42
+ int freed;
41
43
  MYSQL *client;
42
44
  } mysql_client_wrapper;
43
45
 
@@ -9,6 +9,7 @@ end
9
9
  have_func('rb_thread_blocking_region')
10
10
  have_func('rb_wait_for_single_fd')
11
11
  have_func('rb_hash_dup')
12
+ have_func('rb_intern3')
12
13
 
13
14
  # borrowed from mysqlplus
14
15
  # http://github.com/oldmoe/mysqlplus/blob/master/ext/extconf.rb
@@ -29,6 +30,14 @@ GLOB = "{#{dirs.join(',')}}/{mysql_config,mysql_config5}"
29
30
 
30
31
  if RUBY_PLATFORM =~ /mswin|mingw/
31
32
  inc, lib = dir_config('mysql')
33
+
34
+ # Ruby versions not incorporating the mkmf fix at
35
+ # https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/39717
36
+ # do not properly search for lib directories, and must be corrected
37
+ unless lib[-3, 3] == 'lib'
38
+ @libdir_basename = 'lib'
39
+ inc, lib = dir_config('mysql')
40
+ end
32
41
  exit 1 unless have_library("libmysql")
33
42
  elsif mc = (with_config('mysql-config') || Dir[GLOB].first) then
34
43
  mc = Dir[GLOB].first if mc == true
@@ -69,8 +78,13 @@ end
69
78
  if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
70
79
  $CFLAGS << ' -Wall -funroll-loops'
71
80
 
72
- if hard_mysql_path = $libs[%r{-L(/[^ ]+)}, 1]
73
- $LDFLAGS << " -Wl,-rpath,#{hard_mysql_path}"
81
+ if libdir = $libs[%r{-L(/[^ ]+)}, 1]
82
+ # The following comment and test is borrowed from the Pg gem:
83
+ # Try to use runtime path linker option, even if RbConfig doesn't know about it.
84
+ # The rpath option is usually set implicit by dir_config(), but so far not on Mac OS X.
85
+ if RbConfig::CONFIG["RPATHFLAG"].to_s.empty? && try_link('int main() {return 0;}', " -Wl,-rpath,#{libdir}")
86
+ $LDFLAGS << " -Wl,-rpath,#{libdir}"
87
+ end
74
88
  end
75
89
  end
76
90
 
@@ -64,22 +64,33 @@ static void rb_mysql_result_mark(void * wrapper) {
64
64
  rb_gc_mark(w->fields);
65
65
  rb_gc_mark(w->rows);
66
66
  rb_gc_mark(w->encoding);
67
+ rb_gc_mark(w->client);
67
68
  }
68
69
  }
69
70
 
70
71
  /* this may be called manually or during GC */
71
72
  static void rb_mysql_result_free_result(mysql2_result_wrapper * wrapper) {
72
73
  if (wrapper && wrapper->resultFreed != 1) {
74
+ /* FIXME: this may call flush_use_result, which can hit the socket */
73
75
  mysql_free_result(wrapper->result);
74
76
  wrapper->resultFreed = 1;
75
77
  }
76
78
  }
77
79
 
78
80
  /* this is called during GC */
79
- static void rb_mysql_result_free(void * wrapper) {
80
- mysql2_result_wrapper * w = wrapper;
81
- /* FIXME: this may call flush_use_result, which can hit the socket */
82
- rb_mysql_result_free_result(w);
81
+ static void rb_mysql_result_free(void *ptr) {
82
+ mysql2_result_wrapper * wrapper = ptr;
83
+ rb_mysql_result_free_result(wrapper);
84
+
85
+ // If the GC gets to client first it will be nil
86
+ if (wrapper->client != Qnil) {
87
+ wrapper->client_wrapper->refcount--;
88
+ if (wrapper->client_wrapper->refcount == 0) {
89
+ xfree(wrapper->client_wrapper->client);
90
+ xfree(wrapper->client_wrapper);
91
+ }
92
+ }
93
+
83
94
  xfree(wrapper);
84
95
  }
85
96
 
@@ -114,15 +125,18 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int
114
125
 
115
126
  field = mysql_fetch_field_direct(wrapper->result, idx);
116
127
  if (symbolize_keys) {
117
- VALUE colStr;
118
128
  char buf[field->name_length+1];
119
129
  memcpy(buf, field->name, field->name_length);
120
130
  buf[field->name_length] = 0;
131
+
132
+ #ifdef HAVE_RB_INTERN3
133
+ rb_field = rb_intern3(buf, field->name_length, rb_utf8_encoding());
134
+ rb_field = ID2SYM(rb_field);
135
+ #else
136
+ VALUE colStr;
121
137
  colStr = rb_str_new2(buf);
122
- #ifdef HAVE_RUBY_ENCODING_H
123
- rb_enc_associate(colStr, rb_utf8_encoding());
124
- #endif
125
138
  rb_field = ID2SYM(rb_to_id(colStr));
139
+ #endif
126
140
  } else {
127
141
  rb_field = rb_str_new(field->name, field->name_length);
128
142
  #ifdef HAVE_RUBY_ENCODING_H
@@ -223,7 +237,11 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
223
237
  val = Qnil;
224
238
  break;
225
239
  case MYSQL_TYPE_BIT: /* BIT field (MySQL 5.0.3 and up) */
226
- val = rb_str_new(row[i], fieldLengths[i]);
240
+ if (castBool && fields[i].length == 1) {
241
+ val = *row[i] == 1 ? Qtrue : Qfalse;
242
+ }else{
243
+ val = rb_str_new(row[i], fieldLengths[i]);
244
+ }
227
245
  break;
228
246
  case MYSQL_TYPE_TINY: /* TINYINT field */
229
247
  if (castBool && fields[i].length == 1) {
@@ -376,6 +394,7 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
376
394
  GetMysql2Result(self, wrapper);
377
395
 
378
396
  defaults = rb_iv_get(self, "@query_options");
397
+ Check_Type(defaults, T_HASH);
379
398
  if (rb_hash_aref(defaults, sym_symbolize_keys) == Qtrue) {
380
399
  symbolizeKeys = 1;
381
400
  }
@@ -405,6 +424,7 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
405
424
  GetMysql2Result(self, wrapper);
406
425
 
407
426
  defaults = rb_iv_get(self, "@query_options");
427
+ Check_Type(defaults, T_HASH);
408
428
  if (rb_scan_args(argc, argv, "01&", &opts, &block) == 1) {
409
429
  opts = rb_funcall(defaults, intern_merge, 1, opts);
410
430
  } else {
@@ -558,7 +578,7 @@ static VALUE rb_mysql_result_count(VALUE self) {
558
578
  }
559
579
 
560
580
  /* Mysql2::Result */
561
- VALUE rb_mysql_result_to_obj(MYSQL_RES * r) {
581
+ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_RES *r) {
562
582
  VALUE obj;
563
583
  mysql2_result_wrapper * wrapper;
564
584
  obj = Data_Make_Struct(cMysql2Result, mysql2_result_wrapper, rb_mysql_result_mark, rb_mysql_result_free, wrapper);
@@ -569,9 +589,16 @@ VALUE rb_mysql_result_to_obj(MYSQL_RES * r) {
569
589
  wrapper->result = r;
570
590
  wrapper->fields = Qnil;
571
591
  wrapper->rows = Qnil;
572
- wrapper->encoding = Qnil;
592
+ wrapper->encoding = encoding;
573
593
  wrapper->streamingComplete = 0;
594
+ wrapper->client = client;
595
+ wrapper->client_wrapper = DATA_PTR(client);
596
+ wrapper->client_wrapper->refcount++;
597
+
574
598
  rb_obj_call_init(obj, 0, NULL);
599
+
600
+ rb_iv_set(obj, "@query_options", options);
601
+
575
602
  return obj;
576
603
  }
577
604
 
@@ -2,11 +2,12 @@
2
2
  #define MYSQL2_RESULT_H
3
3
 
4
4
  void init_mysql2_result();
5
- VALUE rb_mysql_result_to_obj(MYSQL_RES * r);
5
+ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_RES *r);
6
6
 
7
7
  typedef struct {
8
8
  VALUE fields;
9
9
  VALUE rows;
10
+ VALUE client;
10
11
  VALUE encoding;
11
12
  unsigned int numberOfFields;
12
13
  unsigned long numberOfRows;
@@ -14,6 +15,7 @@ typedef struct {
14
15
  char streamingComplete;
15
16
  char resultFreed;
16
17
  MYSQL_RES *result;
18
+ mysql_client_wrapper *client_wrapper;
17
19
  } mysql2_result_wrapper;
18
20
 
19
21
  #define GetMysql2Result(obj, sval) (sval = (mysql2_result_wrapper*)DATA_PTR(obj));
@@ -36,7 +36,8 @@ module Mysql2
36
36
  # force the encoding to utf8
37
37
  self.charset_name = opts[:encoding] || 'utf8'
38
38
 
39
- ssl_set(*opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher))
39
+ ssl_options = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher)
40
+ ssl_set(*ssl_options) if ssl_options.any?
40
41
 
41
42
  if [:user,:pass,:hostname,:dbname,:db,:sock].any?{|k| @query_options.has_key?(k) }
42
43
  warn "============= WARNING FROM mysql2 ============="
@@ -60,6 +61,14 @@ module Mysql2
60
61
  @@default_query_options
61
62
  end
62
63
 
64
+ def query_info
65
+ info = query_info_string
66
+ return {} unless info
67
+ info_hash = {}
68
+ info.split.each_slice(2) { |s| info_hash[s[0].downcase.delete(':').to_sym] = s[1].to_i }
69
+ info_hash
70
+ end
71
+
63
72
  private
64
73
  def self.local_offset
65
74
  ::Time.local(2010).utc_offset.to_r / 86400
@@ -0,0 +1,5 @@
1
+ # Loaded by script/console. Land helpers here.
2
+
3
+ Pry.config.prompt = lambda do |context, nesting, pry|
4
+ "[mysql2] #{context}> "
5
+ end
@@ -1,3 +1,3 @@
1
1
  module Mysql2
2
- VERSION = "0.3.12b6"
2
+ VERSION = "0.3.12"
3
3
  end
@@ -81,11 +81,13 @@ describe Mysql2::Client do
81
81
  results = ssl_client.query("SHOW STATUS WHERE Variable_name = \"Ssl_version\" OR Variable_name = \"Ssl_cipher\"").to_a
82
82
  results[0]['Variable_name'].should eql('Ssl_cipher')
83
83
  results[0]['Value'].should_not be_nil
84
- results[0]['Value'].class.should eql(String)
84
+ results[0]['Value'].should be_kind_of(String)
85
+ results[0]['Value'].should_not be_empty
85
86
 
86
87
  results[1]['Variable_name'].should eql('Ssl_version')
87
88
  results[1]['Value'].should_not be_nil
88
- results[1]['Value'].class.should eql(String)
89
+ results[1]['Value'].should be_kind_of(String)
90
+ results[1]['Value'].should_not be_empty
89
91
  end
90
92
 
91
93
  it "should respond to #close" do
@@ -128,6 +130,42 @@ describe Mysql2::Client do
128
130
  end
129
131
  end
130
132
 
133
+ it "should respond to #query_info" do
134
+ @client.should respond_to(:query_info)
135
+ end
136
+
137
+ context "#query_info" do
138
+ context "when no info present" do
139
+ before(:each) do
140
+ @client.query('select 1')
141
+ end
142
+ it "should 0" do
143
+ @client.query_info.should be_empty
144
+ @client.query_info_string.should be_nil
145
+ end
146
+ end
147
+ context "when has some info" do
148
+ before(:each) do
149
+ @client.query "USE test"
150
+ @client.query "CREATE TABLE IF NOT EXISTS infoTest (`id` int(11) NOT NULL AUTO_INCREMENT, blah INT(11), PRIMARY KEY (`id`))"
151
+ end
152
+
153
+ after(:each) do
154
+ @client.query "DROP TABLE infoTest"
155
+ end
156
+
157
+ before(:each) do
158
+ # http://dev.mysql.com/doc/refman/5.0/en/mysql-info.html says
159
+ # # Note that mysql_info() returns a non-NULL value for INSERT ... VALUES only for the multiple-row form of the statement (that is, only if multiple value lists are specified).
160
+ @client.query("INSERT INTO infoTest (blah) VALUES (1234),(4535)")
161
+ end
162
+ it "should retrieve it" do
163
+ @client.query_info.should == {:records => 2, :duplicates => 0, :warnings => 0}
164
+ @client.query_info_string.should eq 'Records: 2 Duplicates: 0 Warnings: 0'
165
+ end
166
+ end
167
+ end
168
+
131
169
  it "should expect connect_timeout to be a positive integer" do
132
170
  lambda {
133
171
  Mysql2::Client.new(:connect_timeout => -1)
@@ -255,10 +293,10 @@ describe Mysql2::Client do
255
293
  mark[:END] = Time.now
256
294
  mark.include?(:USR1).should be_true
257
295
  (mark[:USR1] - mark[:START]).should >= 1
258
- (mark[:USR1] - mark[:START]).should < 1.1
296
+ (mark[:USR1] - mark[:START]).should < 1.3
259
297
  (mark[:END] - mark[:USR1]).should > 0.9
260
298
  (mark[:END] - mark[:START]).should >= 2
261
- (mark[:END] - mark[:START]).should < 2.1
299
+ (mark[:END] - mark[:START]).should < 2.3
262
300
  Process.kill(:TERM, pid)
263
301
  Process.waitpid2(pid)
264
302
  ensure
@@ -160,11 +160,16 @@ describe Mysql2::Result do
160
160
  @test_result['null_test'].should eql(nil)
161
161
  end
162
162
 
163
- it "should return Fixnum for a BIT value" do
163
+ it "should return String for a BIT(64) value" do
164
164
  @test_result['bit_test'].class.should eql(String)
165
165
  @test_result['bit_test'].should eql("\000\000\000\000\000\000\000\005")
166
166
  end
167
167
 
168
+ it "should return String for a BIT(1) value" do
169
+ @test_result['single_bit_test'].class.should eql(String)
170
+ @test_result['single_bit_test'].should eql("\001")
171
+ end
172
+
168
173
  it "should return Fixnum for a TINYINT value" do
169
174
  [Fixnum, Bignum].should include(@test_result['tiny_int_test'].class)
170
175
  @test_result['tiny_int_test'].should eql(1)
@@ -188,6 +193,20 @@ describe Mysql2::Result do
188
193
  @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})"
189
194
  end
190
195
 
196
+ it "should return TrueClass or FalseClass for a BIT(1) value if :cast_booleans is enabled" do
197
+ @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (1)'
198
+ id1 = @client.last_id
199
+ @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'
200
+ id2 = @client.last_id
201
+
202
+ result1 = @client.query "SELECT single_bit_test FROM mysql2_test WHERE id = #{id1}", :cast_booleans => true
203
+ result2 = @client.query "SELECT single_bit_test FROM mysql2_test WHERE id = #{id2}", :cast_booleans => true
204
+ result1.first['single_bit_test'].should be_true
205
+ result2.first['single_bit_test'].should be_false
206
+
207
+ @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
208
+ end
209
+
191
210
  it "should return Fixnum for a SMALLINT value" do
192
211
  [Fixnum, Bignum].should include(@test_result['small_int_test'].class)
193
212
  @test_result['small_int_test'].should eql(10)
@@ -14,6 +14,7 @@ RSpec.configure do |config|
14
14
  id MEDIUMINT NOT NULL AUTO_INCREMENT,
15
15
  null_test VARCHAR(10),
16
16
  bit_test BIT(64),
17
+ single_bit_test BIT(1),
17
18
  tiny_int_test TINYINT,
18
19
  bool_cast_test TINYINT(1),
19
20
  small_int_test SMALLINT,
@@ -50,7 +51,7 @@ RSpec.configure do |config|
50
51
  client.query "DELETE FROM mysql2_test;"
51
52
  client.query %[
52
53
  INSERT INTO mysql2_test (
53
- null_test, bit_test, tiny_int_test, bool_cast_test, small_int_test, medium_int_test, int_test, big_int_test,
54
+ null_test, bit_test, single_bit_test, tiny_int_test, bool_cast_test, small_int_test, medium_int_test, int_test, big_int_test,
54
55
  float_test, float_zero_test, double_test, decimal_test, decimal_zero_test, date_test, date_time_test, timestamp_test, time_test,
55
56
  year_test, char_test, varchar_test, binary_test, varbinary_test, tiny_blob_test,
56
57
  tiny_text_test, blob_test, text_test, medium_blob_test, medium_text_test,
@@ -58,7 +59,7 @@ RSpec.configure do |config|
58
59
  )
59
60
 
60
61
  VALUES (
61
- NULL, b'101', 1, 1, 10, 10, 10, 10,
62
+ NULL, b'101', b'1', 1, 1, 10, 10, 10, 10,
62
63
  10.3, 0, 10.3, 10.3, 0, '2010-4-4', '2010-4-4 11:44:00', '2010-4-4 11:44:00', '11:44:00',
63
64
  2009, "test", "test", "test", "test", "test",
64
65
  "test", "test", "test", "test", "test",
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.12b6
5
- prerelease: 6
4
+ version: 0.3.12
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Brian Lopez
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-21 00:00:00.000000000 Z
12
+ date: 2013-07-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -82,7 +82,6 @@ extensions:
82
82
  - ext/mysql2/extconf.rb
83
83
  extra_rdoc_files: []
84
84
  files:
85
- - CHANGELOG.md
86
85
  - MIT-LICENSE
87
86
  - README.md
88
87
  - ext/mysql2/client.c
@@ -97,6 +96,7 @@ files:
97
96
  - ext/mysql2/wait_for_single_fd.h
98
97
  - lib/mysql2.rb
99
98
  - lib/mysql2/client.rb
99
+ - lib/mysql2/console.rb
100
100
  - lib/mysql2/em.rb
101
101
  - lib/mysql2/error.rb
102
102
  - lib/mysql2/result.rb
@@ -113,7 +113,8 @@ files:
113
113
  - spec/rcov.opts
114
114
  - spec/spec_helper.rb
115
115
  homepage: http://github.com/brianmario/mysql2
116
- licenses: []
116
+ licenses:
117
+ - MIT
117
118
  post_install_message:
118
119
  rdoc_options:
119
120
  - --charset=UTF-8
@@ -128,9 +129,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
128
129
  required_rubygems_version: !ruby/object:Gem::Requirement
129
130
  none: false
130
131
  requirements:
131
- - - ! '>'
132
+ - - ! '>='
132
133
  - !ruby/object:Gem::Version
133
- version: 1.3.1
134
+ version: '0'
134
135
  requirements: []
135
136
  rubyforge_project:
136
137
  rubygems_version: 1.8.23
@@ -1,276 +0,0 @@
1
- # Changelog
2
-
3
- ## 0.3.12 (not yet released)
4
- ## 0.3.12b5 (December 14, 2012)
5
- * builds on Ruby 2.0-head and Rubinius 2.0-dev
6
- * encoding names now stored in a Gperf lookup rather than an array
7
- * long-standing bug fix: options set on a single query must not be applied to subsequent queries
8
- * add method warning_count
9
- * add method abandon_results!
10
- * add setter for reconnect option
11
- * remove options method (added in 0.3.12b1)
12
- * support microsecond Time resolution
13
- * several INT / UINT fixes
14
-
15
- ## 0.3.12b4 (August 22, 2012)
16
- * add write_timeout as well
17
-
18
- ## 0.3.12b3 (August 22, 2012)
19
- * several INT / LONG fixes
20
- * fix linking to MySQL 5.5
21
-
22
- ## 0.3.12b2 (August 10, 2012)
23
- * more_results is now more_results?
24
-
25
- ## 0.3.12b1 (August 8, 2012)
26
- * several threading and async bug fixes
27
- * better handling of read and write timeouts
28
- * add :local_infile connection option
29
- * add MULTI_STATEMENTS connection flag and methods store_result, next_result, more_results
30
- * add select_db and options methods
31
- * add :stream query option
32
- * add support for utf8mb4 encoding
33
- * deprecation warnings for the :user, :pass, :hostname, :dbname, :db, :sock connection options
34
-
35
- ## 0.3.11 (December 6th, 2011)
36
- * change mysql error detection strategy from using mysql_field_count to the more explicit mysql_errno
37
- * bugfix to avoid race condition with active connections that error out
38
- * revert back to using xmalloc/xfree for allocations
39
- * avoid potentially unsafe Ruby C API usage w/o GVL
40
- * reacquire GVL before retrying on EINTR on connect
41
-
42
- ## 0.3.10 (November 9th, 2011)
43
-
44
- ## 0.3.9 (November 9th, 2011)
45
-
46
- ## 0.3.8 (November 9th, 2011)
47
- * remove fiber support from mysql2, the code has moved to the
48
- em-synchrony gem.
49
- * use rb_wait_for_single_fd() if available
50
- * fixed a bug with inheriting query options
51
- * remove ext/ from the default loadpath
52
- * fix build issues on OSX with Xcode 4.2 (gcc-llvm compiler)
53
-
54
- ## 0.3.7 (August 16th, 2011)
55
- * ensure symbolized column names support encodings in 1.9
56
-
57
- ## 0.3.6 (June 17th, 2011)
58
- * fix bug in Time/DateTime range detection
59
- * (win32) fix bug where the Mysql2::Client object wasn't cleaned up properly if interrupted during a query
60
- * add Mysql2::Result#count (aliased as size) to get the row count for the dataset
61
- this can be especially helpful if you want to get the number of rows without having to inflate
62
- the entire dataset into ruby (since this happens lazily)
63
-
64
- ## 0.3.5 (June 15th, 2011)
65
- * bug fix for Time/DateTime usage depending on 32/64bit Ruby
66
-
67
- ## 0.3.4 (June 15th, 2011)
68
- * fix a long standing bug where a signal would interrupt rb_thread_select and put the connection in a permanently broken state
69
- * turn on casting in the ActiveRecord again, users can disable it if they need to for performance reasons
70
-
71
- ## 0.3.3 (June 14th, 2011)
72
- * disable async support, and access to the underlying file descriptor under Windows. It's never worked reliably and ruby-core has a lot of work to do in order to make it possible.
73
- * added support for turning eager-casting off. This is especially useful in ORMs that will lazily cast values upon access.
74
- * added a warning if a 0.2.x release is being used with ActiveRecord 3.1 since both the 0.2.x releases and AR 3.1 have mysql2 adapters, we want you to use the one in AR 3.1
75
- * added Mysql2::Client.escape (class-level method)
76
- * disabled eager-casting in the bundled ActiveRecord adapter (for Rails 3.0 or less)
77
-
78
- ## 0.3.2 (April 26th, 2011)
79
- * Fix typo in initialization for older ActiveRecord versions
80
-
81
- ## 0.3.1 (April 26th, 2011)
82
- * Fix typo in initialization for older ActiveRecord versions
83
-
84
- ## 0.3.0 (April 26th, 2011)
85
- * switch to MySQL Connector/C for win32 builds
86
- * win32 bugfixes
87
- * BREAKING CHANGE: the ActiveRecord adapter has been pulled into Rails 3.1 and is no longer part of the gem
88
- * added Mysql2::Client.escape (class-level) for raw one-off non-encoding-aware escaping
89
-
90
- ## 0.2.18 (December 6th, 2011)
91
- * change mysql error detection strategy from using mysql_field_count to the more explicit mysql_errno
92
- * bugfix to avoid race condition with active connections that error out
93
- * revert back to using xmalloc/xfree for allocations
94
- * avoid potentially unsafe Ruby C API usage w/o GVL
95
- * reacquire GVL before retrying on EINTR on connect
96
-
97
- ## 0.2.17 (November 9th, 2011)
98
-
99
- ## 0.2.16 (November 9th, 2011)
100
-
101
- ## 0.2.15 (November 9th, 2011)
102
-
103
- ## 0.2.14 (November 9th, 2011)
104
- * use rb_wait_for_single_fd() if available
105
- * fixed a bug with inheriting query options
106
- * remove ext/ from the default loadpath
107
- * fix build issues on OSX with Xcode 4.2 (gcc-llvm compiler)
108
-
109
- ## 0.2.13 (August 16th, 2011)
110
- * fix stupid bug around symbol encoding support (thanks coderrr!)
111
-
112
- ## 0.2.12 (August 16th, 2011)
113
- * ensure symbolized column names support encodings in 1.9
114
- * plugging sql vulnerability in mysql2 adapter
115
-
116
- ## 0.2.11 (June 17th, 2011)
117
- * fix bug in Time/DateTime range detection
118
- * (win32) fix bug where the Mysql2::Client object wasn't cleaned up properly if interrupted during a query
119
- * add Mysql2::Result#count (aliased as size) to get the row count for the dataset
120
- this can be especially helpful if you want to get the number of rows without having to inflate
121
- the entire dataset into ruby (since this happens lazily)
122
-
123
- ## 0.2.10 (June 15th, 2011)
124
- * bug fix for Time/DateTime usage depending on 32/64bit Ruby
125
-
126
- ## 0.2.9 (June 15th, 2011)
127
- * fix a long standing bug where a signal would interrupt rb_thread_select and put the connection in a permanently broken state
128
- * turn on casting in the ActiveRecord again, users can disable it if they need to for performance reasons
129
-
130
- ## 0.2.8 (June 14th, 2011)
131
- * disable async support, and access to the underlying file descriptor under Windows. It's never worked reliably and ruby-core has a lot of work to do in order to make it possible.
132
- * added support for turning eager-casting off. This is especially useful in ORMs that will lazily cast values upon access.
133
- * added a warning if a 0.2.x release is being used with ActiveRecord 3.1 since both the 0.2.x releases and AR 3.1 have mysql2 adapters, we want you to use the one in AR 3.1
134
- * added Mysql2::Client.escape (class-level method)
135
- * disabled eager-casting in the bundled ActiveRecord adapter (for Rails 3.0 or less)
136
-
137
- ## 0.2.7 (March 28th, 2011)
138
- * various fixes for em_mysql2 and fiber usage
139
- * use our own Mysql2IndexDefinition class for better compatibility across ActiveRecord versions
140
- * ensure the query is a string earlier in the Mysql2::Client#query codepath for 1.9
141
- * only set binary ruby encoding on fields that have a binary flag *and* encoding set
142
- * a few various optimizations
143
- * add support for :read_timeout to be set on a connection
144
- * Fix to install with MariDB on Windows
145
- * add fibered em connection without activerecord
146
- * fix some 1.9.3 compilation warnings
147
- * add LD_RUN_PATH when using hard coded mysql paths - this should help users with MySQL installed in non-standard locations
148
- * for windows support, duplicate the socket from libmysql and create a temporary CRT fd
149
- * fix for handling years before 1970 on Windows
150
- * fixes to the Fiber adapter
151
- * set wait_timeout maximum on Windows to 2147483
152
- * update supported range for Time objects
153
- * upon being required, make sure the libmysql we're using is the one we were built against
154
- * add Mysql2::Client#thread_id
155
- * add Mysql2::Client#ping
156
- * switch connection check in AR adapter to use Mysql2::Client#ping for efficiency
157
- * prefer linking against thread-safe version of libmysqlclient
158
- * define RSTRING_NOT_MODIFIED for an awesome rbx speed boost
159
- * expose Mysql2::Client#encoding in 1.9, make sure we set the error message and sqlstate encodings accordingly
160
- * do not segfault when raising for invalid charset (found in 1.9.3dev)
161
-
162
- ## 0.2.6 (October 19th, 2010)
163
- * version bump since the 0.2.5 win32 binary gems were broken
164
-
165
- ## 0.2.5 (October 19th, 2010)
166
- * fixes for easier Win32 binary gem deployment for targeting 1.8 and 1.9 in the same gem
167
- * refactor of connection checks and management to avoid race conditions with the GC/threading to prevent the unexpected loss of connections
168
- * update the default flags during connection
169
- * add support for setting wait_timeout on AR adapter
170
- * upgrade to rspec2
171
- * bugfix for an edge case where the GC would clean up a Mysql2::Client object before the underlying MYSQL pointer had been initialized
172
- * fix to CFLAGS to allow compilation on SPARC with sunstudio compiler - Anko painting <anko.com+github@gmail.com>
173
-
174
- ## 0.2.4 (September 17th, 2010)
175
- * a few patches for win32 support from Luis Lavena - thanks man!
176
- * bugfix from Eric Wong to avoid a potential stack overflow during Mysql2::Client#escape
177
- * added the ability to turn internal row caching on/off via the :cache_rows => true/false option
178
- * a couple of small patches for rbx compatibility
179
- * set IndexDefinition#length in AR adapter - Kouhei Yanagita <yanagi@shakenbu.org>
180
- * fix a long-standing data corruption bug - thank you thank you thank you to @joedamato (http://github.com/ice799)
181
- * bugfix from calling mysql_close on a closed/freed connection surfaced by the above fix
182
-
183
- ## 0.2.3 (August 20th, 2010)
184
- * connection flags can now be passed to the constructor via the :flags key
185
- * switch AR adapter connection over to use FOUND_ROWS option
186
- * patch to ensure we use DateTime objects in place of Time for timestamps that are out of the supported range on 32bit platforms < 1.9.2
187
-
188
- ## 0.2.2 (August 19th, 2010)
189
- * Change how AR adapter would send initial commands upon connecting
190
- ** we can make multiple session variable assignments in a single query
191
- * fix signal handling when waiting on queries
192
- * retry connect if interrupted by signals
193
-
194
- ## 0.2.1 (August 16th, 2010)
195
- * bring mysql2 ActiveRecord adapter back into gem
196
-
197
- ## 0.2.0 (August 16th, 2010)
198
- * switch back to letting libmysql manage all allocation/thread-state/freeing for the connection
199
- * cache various numeric type conversions in hot-spots of the code for a little speed boost
200
- * ActiveRecord adapter moved into Rails 3 core
201
- ** Don't worry 2.3.x users! We'll either release the adapter as a separate gem, or try to get it into 2.3.9
202
- * Fix for the "closed MySQL connection" error (GH #31)
203
- * Fix for the "can't modify frozen object" error in 1.9.2 (GH #37)
204
- * Introduce cascading query and result options (more info in README)
205
- * Sequel adapter pulled into core (will be in the next release - 3.15.0 at the time of writing)
206
- * add a safety check when attempting to send a query before a result has been fetched
207
-
208
- ## 0.1.9 (July 17th, 2010)
209
- * Support async ActiveRecord access with fibers and EventMachine (mperham)
210
- * string encoding support for 1.9, respecting Encoding.default_internal
211
- * added support for rake-compiler (tenderlove)
212
- * bugfixes for ActiveRecord driver
213
- ** one minor bugfix for TimeZone support
214
- ** fix the select_rows method to return what it should according to the docs (r-stu31)
215
- * Mysql2::Client#fields method added - returns the array of field names from a resultset, as strings
216
- * Sequel adapter
217
- ** bugfix regarding sybolized field names (Eric Wong)
218
- ** fix query logging in Sequel adapter
219
- * Lots of nice code cleanup (tenderlove)
220
- ** Mysql2::Error definition moved to pure-Ruby
221
- ** Mysql2::client#initialize definition moved to pure-Ruby
222
- ** Mysql2::Result partially moved to pure-Ruby
223
-
224
- ## 0.1.8 (June 2nd, 2010)
225
- * fixes for AR adapter for timezone juggling
226
- * fixes to be able to run benchmarks and specs under 1.9.2
227
-
228
- ## 0.1.7 (May 22nd, 2010)
229
- * fix a bug when using the disconnect! method on a closed connection in the AR driver
230
-
231
- ## 0.1.6 (May 14th, 2010)
232
- * more fixes to the AR adapter related to casting
233
- * add missing index creation override method to AR adapter
234
- * added sql_state and error_number methods to the Mysql2::Error exception class
235
-
236
- ## 0.1.5 (May 12th, 2010)
237
- * quite a few patches from Eric Wong related to thread-safety, non-blocking I/O and general cleanup
238
- ** wrap mysql_real_connect with rb_thread_blocking_region
239
- ** release GVL for possibly blocking mysql_* library calls
240
- ** [cleanup] quiet down warnings
241
- ** [cleanup] make all C symbols static
242
- ** add Mysql2::Client#close method
243
- ** correctly free the wrapped result in case of EOF
244
- ** Fix memory leak from the result wrapper struct itself
245
- ** make Mysql2::Client destructor safely non-blocking
246
- * bug fixes for ActiveRecord adapter
247
- ** added casting for default values since they all come back from Mysql as strings (!?!)
248
- ** missing constant was added
249
- ** fixed a typo in the show_variable method
250
- * switched over sscanf for date/time parsing in C
251
- * made some specs a little finer-grained
252
- * initial Sequel adapter added
253
- * updated query benchmarks to reflect the difference between casting in C and in Ruby
254
-
255
- ## 0.1.4 (April 23rd, 2010)
256
- * optimization: implemented a local cache for rows that are lazily created in ruby during iteration. The MySQL C result is freed as soon as all the results have been cached
257
- * optimization: implemented a local cache for field names so every row reuses the same objects as field names/keys
258
- * refactor the Mysql2 connection adapter for ActiveRecord to not extend the Mysql adapter - now being a free-standing connection adapter
259
-
260
- ## 0.1.3 (April 15th, 2010)
261
- * added an EventMachine Deferrable API
262
- * added an ActiveRecord connection adapter
263
- ** should be compatible with 2.3.5 and 3.0 (including Arel)
264
-
265
- ## 0.1.2 (April 9th, 2010)
266
- * fix a bug (copy/paste fail) around checking for empty TIME values and returning nil (thanks @marius)
267
-
268
- ## 0.1.1 (April 6th, 2010)
269
- * added affected_rows method (mysql_affected_rows)
270
- * added last_id method (last_insert_id)
271
- * enable reconnect option by default
272
- * added initial async query support
273
- * updated extconf (thanks to the mysqlplus project) for easier gem building
274
-
275
- ## 0.1.0 (April 6th, 2010)
276
- * initial release