mysql2 0.1.5 → 0.1.6

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,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.6 (May 14th, 2010)
4
+ * more fixes to the AR adapter related to casting
5
+ * add missing index creation override method to AR adapter
6
+ * added sql_state and error_number methods to the Mysql2::Error exception class
7
+
3
8
  ## 0.1.5 (May 12th, 2010)
4
9
  * quite a few patches from Eric Wong related to thread-safety, non-blocking I/O and general cleanup
5
10
  ** wrap mysql_real_connect with rb_thread_blocking_region
@@ -109,7 +109,7 @@ The specs pass on my system (SL 10.6.3, x86_64) in these rubies:
109
109
  * ree-1.8.7-2010.01
110
110
  * 1.9.1-p378
111
111
  * ruby-trunk
112
- * rbx-head
112
+ * rbx-head - broken at the moment, working with the rbx team for a solution
113
113
 
114
114
  The ActiveRecord driver should work on 2.3.5 and 3.0
115
115
 
@@ -137,4 +137,8 @@ then iterating over every row using an #each like method yielding a block:
137
137
  Mysql
138
138
  7.330000 0.350000 7.680000 ( 8.013160)
139
139
  do_mysql
140
- 1.740000 0.220000 1.960000 ( 2.909290)
140
+ 1.740000 0.220000 1.960000 ( 2.909290)
141
+
142
+ == Special Thanks
143
+
144
+ * Eric Wong - for the contribution (and informative explanations of) of some thread-safety, non-blocking I/O and cleanup patches. You rock dude
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.5
1
+ 0.1.6
@@ -140,8 +140,7 @@ static VALUE rb_mysql_client_new(int argc, VALUE * argv, VALUE klass) {
140
140
 
141
141
  if (rb_thread_blocking_region(nogvl_init, &args, RUBY_UBF_IO, 0) == Qfalse) {
142
142
  // TODO: warning - not enough memory?
143
- rb_raise(cMysql2Error, "%s", mysql_error(args.mysql));
144
- return Qnil;
143
+ return rb_raise_mysql2_error(args.mysql);
145
144
  }
146
145
 
147
146
  // set default reconnect behavior
@@ -168,8 +167,7 @@ static VALUE rb_mysql_client_new(int argc, VALUE * argv, VALUE klass) {
168
167
 
169
168
  if (rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0) == Qfalse) {
170
169
  // unable to connect
171
- rb_raise(cMysql2Error, "%s", mysql_error(args.mysql));
172
- return Qnil;
170
+ return rb_raise_mysql2_error(args.mysql);;
173
171
  }
174
172
 
175
173
  client->client = args.mysql;
@@ -268,10 +266,13 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
268
266
  Check_Type(args.sql, T_STRING);
269
267
 
270
268
  GetMysql2Client(self, args.mysql);
271
- if (rb_thread_blocking_region(nogvl_send_query, &args, RUBY_UBF_IO, 0) == Qfalse) {
272
- rb_raise(cMysql2Error, "%s", mysql_error(args.mysql));
269
+ if (!args.mysql) {
270
+ rb_raise(cMysql2Error, "closed MySQL connection");
273
271
  return Qnil;
274
272
  }
273
+ if (rb_thread_blocking_region(nogvl_send_query, &args, RUBY_UBF_IO, 0) == Qfalse) {
274
+ return rb_raise_mysql2_error(args.mysql);;
275
+ }
275
276
 
276
277
  if (!async) {
277
278
  // the below code is largely from do_mysql
@@ -308,7 +309,10 @@ static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
308
309
  char escaped[(oldLen*2)+1];
309
310
 
310
311
  GetMysql2Client(self, client);
311
-
312
+ if (!client) {
313
+ rb_raise(cMysql2Error, "closed MySQL connection");
314
+ return Qnil;
315
+ }
312
316
  newLen = mysql_real_escape_string(client, escaped, RSTRING_PTR(str), RSTRING_LEN(str));
313
317
  if (newLen == oldLen) {
314
318
  // no need to return a new ruby string if nothing changed
@@ -334,6 +338,10 @@ static VALUE rb_mysql_client_server_info(VALUE self) {
334
338
  VALUE version;
335
339
 
336
340
  GetMysql2Client(self, client);
341
+ if (!client) {
342
+ rb_raise(cMysql2Error, "closed MySQL connection");
343
+ return Qnil;
344
+ }
337
345
  version = rb_hash_new();
338
346
  rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_server_version(client)));
339
347
  rb_hash_aset(version, sym_version, rb_str_new2(mysql_get_server_info(client)));
@@ -341,7 +349,11 @@ static VALUE rb_mysql_client_server_info(VALUE self) {
341
349
  }
342
350
 
343
351
  static VALUE rb_mysql_client_socket(VALUE self) {
344
- MYSQL * client = GetMysql2Client(self, client);;
352
+ MYSQL * client = GetMysql2Client(self, client);
353
+ if (!client) {
354
+ rb_raise(cMysql2Error, "closed MySQL connection");
355
+ return Qnil;
356
+ }
345
357
  return INT2NUM(client->net.fd);
346
358
  }
347
359
 
@@ -369,16 +381,18 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
369
381
  MYSQL * client;
370
382
  MYSQL_RES * result;
371
383
  GetMysql2Client(self, client);
372
-
373
- if (rb_thread_blocking_region(nogvl_read_query_result, client, RUBY_UBF_IO, 0) == Qfalse) {
374
- rb_raise(cMysql2Error, "%s", mysql_error(client));
384
+ if (!client) {
385
+ rb_raise(cMysql2Error, "closed MySQL connection");
375
386
  return Qnil;
376
387
  }
388
+ if (rb_thread_blocking_region(nogvl_read_query_result, client, RUBY_UBF_IO, 0) == Qfalse) {
389
+ return rb_raise_mysql2_error(client);
390
+ }
377
391
 
378
392
  result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, client, RUBY_UBF_IO, 0);
379
393
  if (result == NULL) {
380
394
  if (mysql_field_count(client) != 0) {
381
- rb_raise(cMysql2Error, "%s", mysql_error(client));
395
+ rb_raise_mysql2_error(client);
382
396
  }
383
397
  return Qnil;
384
398
  }
@@ -389,14 +403,20 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
389
403
  static VALUE rb_mysql_client_last_id(VALUE self) {
390
404
  MYSQL * client;
391
405
  GetMysql2Client(self, client);
392
-
406
+ if (!client) {
407
+ rb_raise(cMysql2Error, "closed MySQL connection");
408
+ return Qnil;
409
+ }
393
410
  return ULL2NUM(mysql_insert_id(client));
394
411
  }
395
412
 
396
413
  static VALUE rb_mysql_client_affected_rows(VALUE self) {
397
414
  MYSQL * client;
398
415
  GetMysql2Client(self, client);
399
-
416
+ if (!client) {
417
+ rb_raise(cMysql2Error, "closed MySQL connection");
418
+ return Qnil;
419
+ }
400
420
  return ULL2NUM(mysql_affected_rows(client));
401
421
  }
402
422
 
@@ -542,6 +562,7 @@ static VALUE rb_mysql_result_fetch_row(int argc, VALUE * argv, VALUE self) {
542
562
  } else {
543
563
  if (month < 1 || day < 1) {
544
564
  rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
565
+ val = Qnil;
545
566
  } else {
546
567
  val = rb_funcall(rb_cTime, intern_local, 6, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
547
568
  }
@@ -557,6 +578,7 @@ static VALUE rb_mysql_result_fetch_row(int argc, VALUE * argv, VALUE self) {
557
578
  } else {
558
579
  if (month < 1 || day < 1) {
559
580
  rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
581
+ val = Qnil;
560
582
  } else {
561
583
  val = rb_funcall(cDate, intern_new, 3, INT2NUM(year), INT2NUM(month), INT2NUM(day));
562
584
  }
@@ -648,6 +670,22 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
648
670
  return wrapper->rows;
649
671
  }
650
672
 
673
+ static VALUE rb_mysql_error_error_number(VALUE obj) {
674
+ return rb_iv_get(obj, "error_number");
675
+ }
676
+
677
+ static VALUE rb_mysql_error_sql_state(VALUE obj) {
678
+ return rb_iv_get(obj, "sql_state");
679
+ }
680
+
681
+ static VALUE rb_raise_mysql2_error(MYSQL *client) {
682
+ VALUE e = rb_exc_new2(cMysql2Error, mysql_error(client));
683
+ rb_iv_set(e, "error_number", INT2FIX(mysql_errno(client)));
684
+ rb_iv_set(e, "sql_state", rb_tainted_str_new2(mysql_sqlstate(client)));
685
+ rb_exc_raise(e);
686
+ return Qnil;
687
+ }
688
+
651
689
  /* Ruby Extension initializer */
652
690
  void Init_mysql2_ext() {
653
691
  rb_require("date");
@@ -673,6 +711,8 @@ void Init_mysql2_ext() {
673
711
  rb_define_method(cMysql2Client, "affected_rows", rb_mysql_client_affected_rows, 0);
674
712
 
675
713
  cMysql2Error = rb_define_class_under(mMysql2, "Error", rb_eStandardError);
714
+ rb_define_method(cMysql2Error, "error_number", rb_mysql_error_error_number, 0);
715
+ rb_define_method(cMysql2Error, "sql_state", rb_mysql_error_sql_state, 0);
676
716
 
677
717
  cMysql2Result = rb_define_class_under(mMysql2, "Result", rb_cObject);
678
718
  rb_define_method(cMysql2Result, "each", rb_mysql_result_each, -1);
@@ -70,6 +70,11 @@ static void rb_mysql_result_free(void * wrapper);
70
70
  static void rb_mysql_result_mark(void * wrapper);
71
71
  static void rb_mysql_result_free_result(mysql2_result_wrapper * wrapper);
72
72
 
73
+ /* Mysql2::Error */
74
+ static VALUE rb_raise_mysql2_error(MYSQL *client);
75
+ static VALUE rb_mysql_error_error_number(VALUE obj);
76
+ static VALUE rb_mysql_error_sql_state(VALUE obj);
77
+
73
78
  /*
74
79
  * used to pass all arguments to mysql_real_connect while inside
75
80
  * rb_thread_blocking_region
@@ -52,26 +52,33 @@ module ActiveRecord
52
52
  def type_cast(value)
53
53
  return nil if value.nil?
54
54
  case type
55
- when :string then value
56
- when :text then value
57
- when :integer then value.is_a?(Fixnum) ? value : (value.to_i rescue value ? 1 : 0)
58
- when :float then value.class == Float ? value : value.to_f
59
- when :decimal then value.class == BigDecimal ? value : self.class.value_to_decimal(value)
60
- when :datetime then value.class == Time ? value : self.class.string_to_time(value)
61
- when :timestamp then value.class == Time ? value : self.class.string_to_time(value)
62
- when :time then value.class == Time ? value : self.class.string_to_dummy_time(value)
63
- when :date then value.class == Date ? value : self.class.string_to_date(value)
64
- when :binary then value
65
- when :boolean then self.class.value_to_boolean(value)
55
+ when :string then value
56
+ when :text then value
57
+ when :integer then value.to_i rescue value ? 1 : 0
58
+ when :float then value.to_f # returns self if it's already a Float
59
+ when :decimal then self.class.value_to_decimal(value)
60
+ when :datetime, :timestamp then value.class == Time ? value : self.class.string_to_time(value)
61
+ when :time then value.class == Time ? value : self.class.string_to_dummy_time(value)
62
+ when :date then value.class == Date ? value : self.class.string_to_date(value)
63
+ when :binary then value
64
+ when :boolean then self.class.value_to_boolean(value)
66
65
  else value
67
66
  end
68
67
  end
69
68
 
70
69
  def type_cast_code(var_name)
71
70
  case type
72
- when :boolean then "#{self.class.name}.value_to_boolean(#{var_name})"
73
- else
74
- nil
71
+ when :string then nil
72
+ when :text then nil
73
+ when :integer then "#{var_name}.to_i rescue #{var_name} ? 1 : 0"
74
+ when :float then "#{var_name}.to_f"
75
+ when :decimal then "#{self.class.name}.value_to_decimal(#{var_name})"
76
+ when :datetime, :timestamp then "#{var_name}.class == Time ? #{var_name} : #{self.class.name}.string_to_time(#{var_name})"
77
+ when :time then "#{var_name}.class == Time ? #{var_name} : #{self.class.name}.string_to_dummy_time(#{var_name})"
78
+ when :date then "#{var_name}.class == Date ? #{var_name} : #{self.class.name}.string_to_date(#{var_name})"
79
+ when :binary then nil
80
+ when :boolean then "#{self.class.name}.value_to_boolean(#{var_name})"
81
+ else nil
75
82
  end
76
83
  end
77
84
 
@@ -234,10 +241,11 @@ module ActiveRecord
234
241
  end
235
242
 
236
243
  def disconnect!
237
- @connection = nil
244
+ @connection.close
238
245
  end
239
246
 
240
247
  def reset!
248
+ disconnect!
241
249
  @connection = Mysql2::Client.new(@config)
242
250
  end
243
251
 
@@ -523,6 +531,19 @@ module ActiveRecord
523
531
  end
524
532
 
525
533
  protected
534
+ def quoted_columns_for_index(column_names, options = {})
535
+ length = options[:length] if options.is_a?(Hash)
536
+
537
+ quoted_column_names = case length
538
+ when Hash
539
+ column_names.map {|name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) }
540
+ when Fixnum
541
+ column_names.map {|name| "#{quote_column_name(name)}(#{length})"}
542
+ else
543
+ column_names.map {|name| quote_column_name(name) }
544
+ end
545
+ end
546
+
526
547
  # TODO: implement error_number method on Mysql2::Exception
527
548
  def translate_exception(exception, message)
528
549
  return super unless exception.respond_to?(:error_number)
@@ -5,5 +5,5 @@ require 'mysql2_ext'
5
5
  #
6
6
  # A modern, simple and very fast Mysql library for Ruby - binding to libmysql
7
7
  module Mysql2
8
- VERSION = "0.1.5"
8
+ VERSION = "0.1.6"
9
9
  end
@@ -150,12 +150,12 @@ module Sequel
150
150
 
151
151
  # Closes given database connection.
152
152
  def disconnect_connection(c)
153
- c = nil
153
+ c.close
154
154
  end
155
155
 
156
156
  # Convert tinyint(1) type to boolean if convert_tinyint_to_bool is true
157
157
  def schema_column_type(db_type)
158
- Sequel::MySQL.convert_tinyint_to_bool && db_type == 'tinyint(1)' ? :boolean : super
158
+ Sequel::Mysql2.convert_tinyint_to_bool && db_type == 'tinyint(1)' ? :boolean : super
159
159
  end
160
160
  end
161
161
 
@@ -204,12 +204,12 @@ module Sequel
204
204
 
205
205
  # Insert a new value into this dataset
206
206
  def insert(*values)
207
- execute_dui(insert_sql(*values)){|c| return c.insert_id}
207
+ execute_dui(insert_sql(*values)){|c| return c.last_id}
208
208
  end
209
209
 
210
210
  # Replace (update or insert) the matching row.
211
211
  def replace(*args)
212
- execute_dui(replace_sql(*args)){|c| return c.insert_id}
212
+ execute_dui(replace_sql(*args)){|c| return c.last_id}
213
213
  end
214
214
 
215
215
  # Update the matching rows.
@@ -229,9 +229,9 @@ module Sequel
229
229
  super(sql, {:type=>:dui}.merge(opts), &block)
230
230
  end
231
231
 
232
- # Handle correct quoting of strings using ::MySQL.quote.
232
+ # Handle correct quoting of strings using ::Mysql2#escape.
233
233
  def literal_string(v)
234
- db.synchronize{|c| "'#{c.quote(v)}'"}
234
+ db.synchronize{|c| "'#{c.escape(v)}'"}
235
235
  end
236
236
  end
237
237
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mysql2}
8
- s.version = "0.1.5"
8
+ s.version = "0.1.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Brian Lopez"]
12
- s.date = %q{2010-05-12}
12
+ s.date = %q{2010-05-14}
13
13
  s.email = %q{seniorlopez@gmail.com}
14
14
  s.extensions = ["ext/extconf.rb"]
15
15
  s.extra_rdoc_files = [
@@ -41,6 +41,7 @@ Gem::Specification.new do |s|
41
41
  "spec/active_record/active_record_spec.rb",
42
42
  "spec/em/em_spec.rb",
43
43
  "spec/mysql2/client_spec.rb",
44
+ "spec/mysql2/error_spec.rb",
44
45
  "spec/mysql2/result_spec.rb",
45
46
  "spec/rcov.opts",
46
47
  "spec/spec.opts",
@@ -55,6 +56,7 @@ Gem::Specification.new do |s|
55
56
  "spec/active_record/active_record_spec.rb",
56
57
  "spec/em/em_spec.rb",
57
58
  "spec/mysql2/client_spec.rb",
59
+ "spec/mysql2/error_spec.rb",
58
60
  "spec/mysql2/result_spec.rb",
59
61
  "spec/spec_helper.rb",
60
62
  "examples/eventmachine.rb"
@@ -6,11 +6,6 @@ describe Mysql2::Client do
6
6
  @client = Mysql2::Client.new
7
7
  end
8
8
 
9
- after(:each) do
10
- # forcefully clean up old connections
11
- GC.start
12
- end
13
-
14
9
  it "should be able to connect via SSL options" do
15
10
  pending("DON'T WORRY, THIS TEST PASSES :) - but is machine-specific. You need to have MySQL running with SSL configured and enabled. Then update the paths in this test to your needs and remove the pending state.")
16
11
  ssl_client = nil
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
3
+
4
+ describe Mysql2::Error do
5
+ before(:each) do
6
+ @error = Mysql2::Error.new "testing"
7
+ end
8
+
9
+ it "should respond to #error_number" do
10
+ @error.should respond_to(:error_number)
11
+ end
12
+
13
+ it "should respond to #sql_state" do
14
+ @error.should respond_to(:sql_state)
15
+ end
16
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 5
9
- version: 0.1.5
8
+ - 6
9
+ version: 0.1.6
10
10
  platform: ruby
11
11
  authors:
12
12
  - Brian Lopez
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-12 00:00:00 -07:00
17
+ date: 2010-05-14 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -52,6 +52,7 @@ files:
52
52
  - spec/active_record/active_record_spec.rb
53
53
  - spec/em/em_spec.rb
54
54
  - spec/mysql2/client_spec.rb
55
+ - spec/mysql2/error_spec.rb
55
56
  - spec/mysql2/result_spec.rb
56
57
  - spec/rcov.opts
57
58
  - spec/spec.opts
@@ -91,6 +92,7 @@ test_files:
91
92
  - spec/active_record/active_record_spec.rb
92
93
  - spec/em/em_spec.rb
93
94
  - spec/mysql2/client_spec.rb
95
+ - spec/mysql2/error_spec.rb
94
96
  - spec/mysql2/result_spec.rb
95
97
  - spec/spec_helper.rb
96
98
  - examples/eventmachine.rb