mysql2 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -9,3 +9,4 @@ mkmf.log
9
9
  pkg/
10
10
  tmp
11
11
  vendor
12
+ lib/mysql2/mysql2.rb
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --colour
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.5 (October 19th, 2010)
4
+ * fixes for easier Win32 binary gem deployment for targeting 1.8 and 1.9 in the same gem
5
+ * refactor of connection checks and management to avoid race conditions with the GC/threading to prevent the unexpected loss of connections
6
+ * update the default flags during connection
7
+ * add support for setting wait_timeout on AR adapter
8
+ * upgrade to rspec2
9
+ * bugfix for an edge case where the GC would clean up a Mysql2::Client object before the underlying MYSQL pointer had been initialized
10
+ * fix to CFLAGS to allow compilation on SPARC with sunstudio compiler - Anko painting <anko.com+github@gmail.com>
11
+
3
12
  ## 0.2.4 (September 17th, 2010)
4
13
  * a few patches for win32 support from Luis Lavena - thanks man!
5
14
  * bugfix from Eric Wong to avoid a potential stack overflow during Mysql2::Client#escape
@@ -234,7 +234,7 @@ then iterating over every row using an #each like method yielding a block:
234
234
 
235
235
  == Special Thanks
236
236
 
237
- * Eric Wong - for the contribution (and informative explanations of) of some thread-safety, non-blocking I/O and cleanup patches. You rock dude
237
+ * Eric Wong - for the contribution (and the informative explanations) of some thread-safety, non-blocking I/O and cleanup patches. You rock dude
238
238
  * Yury Korolev (http://github.com/yury) - for TONS of help testing the ActiveRecord adapter
239
239
  * Aaron Patterson (http://github.com/tenderlove) - tons of contributions, suggestions and general badassness
240
240
  * Mike Perham (http://github.com/mperham) - Async ActiveRecord adapter (uses Fibers and EventMachine)
data/Rakefile CHANGED
@@ -1,42 +1,5 @@
1
1
  # encoding: UTF-8
2
- begin
3
- require 'jeweler'
4
- JEWELER = Jeweler::Tasks.new do |gem|
5
- gem.name = "mysql2"
6
- gem.summary = "A simple, fast Mysql library for Ruby, binding to libmysql"
7
- gem.email = "seniorlopez@gmail.com"
8
- gem.homepage = "http://github.com/brianmario/mysql2"
9
- gem.authors = ["Brian Lopez"]
10
- gem.require_paths = ["lib", "ext"]
11
- gem.extra_rdoc_files = `git ls-files *.rdoc`.split("\n")
12
- gem.files = `git ls-files`.split("\n")
13
- gem.extensions = ["ext/mysql2/extconf.rb"]
14
- gem.files.include %w(lib/jeweler/templates/.document lib/jeweler/templates/.gitignore)
15
- # gem.rubyforge_project = "mysql2"
16
- end
17
- rescue LoadError
18
- puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler -s http://gems.github.com"
19
- end
20
-
21
2
  require 'rake'
22
- require 'spec/rake/spectask'
23
-
24
- desc "Run all examples with RCov"
25
- Spec::Rake::SpecTask.new('spec:rcov') do |t|
26
- t.spec_files = FileList['spec/']
27
- t.rcov = true
28
- t.rcov_opts = lambda do
29
- IO.readlines("spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
30
- end
31
- end
32
- Spec::Rake::SpecTask.new('spec') do |t|
33
- t.spec_files = FileList['spec/']
34
- t.spec_opts << '--options' << 'spec/spec.opts'
35
- t.verbose = true
36
- t.warning = true
37
- end
38
-
39
- task :default => :spec
40
3
 
41
4
  # Load custom tasks
42
5
  Dir['tasks/*.rake'].sort.each { |f| load f }
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.4
1
+ 0.2.5
@@ -9,7 +9,7 @@ static ID sym_id, sym_version, sym_async, sym_symbolize_keys, sym_as, sym_array;
9
9
  static ID intern_merge, intern_error_number_eql, intern_sql_state_eql;
10
10
 
11
11
  #define REQUIRE_OPEN_DB(wrapper) \
12
- if(wrapper->closed || !wrapper->client->net.vio) { \
12
+ if(wrapper->closed) { \
13
13
  rb_raise(cMysql2Error, "closed MySQL connection"); \
14
14
  return Qnil; \
15
15
  }
@@ -83,11 +83,11 @@ static VALUE rb_raise_mysql2_error(MYSQL *client) {
83
83
  }
84
84
 
85
85
  static VALUE nogvl_init(void *ptr) {
86
- MYSQL **client = (MYSQL **)ptr;
86
+ MYSQL *client;
87
87
 
88
88
  /* may initialize embedded server and read /etc/services off disk */
89
- *client = mysql_init(NULL);
90
- return *client ? Qtrue : Qfalse;
89
+ client = mysql_init((MYSQL *)ptr);
90
+ return client ? Qtrue : Qfalse;
91
91
  }
92
92
 
93
93
  static VALUE nogvl_connect(void *ptr) {
@@ -104,54 +104,52 @@ static VALUE nogvl_connect(void *ptr) {
104
104
  return client ? Qtrue : Qfalse;
105
105
  }
106
106
 
107
- static void rb_mysql_client_free(void * ptr) {
108
- mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;
109
-
110
- /*
111
- * we'll send a QUIT message to the server, but that message is more of a
112
- * formality than a hard requirement since the socket is getting shutdown
113
- * anyways, so ensure the socket write does not block our interpreter
114
- */
115
- int fd = wrapper->client->net.fd;
107
+ static VALUE nogvl_close(void *ptr) {
108
+ mysql_client_wrapper *wrapper = ptr;
109
+ if (!wrapper->closed) {
110
+ wrapper->closed = 1;
116
111
 
117
- if (fd >= 0) {
118
112
  /*
113
+ * we'll send a QUIT message to the server, but that message is more of a
114
+ * formality than a hard requirement since the socket is getting shutdown
115
+ * anyways, so ensure the socket write does not block our interpreter
116
+ *
117
+ *
119
118
  * if the socket is dead we have no chance of blocking,
120
119
  * so ignore any potential fcntl errors since they don't matter
121
120
  */
122
121
  #ifndef _WIN32
123
- int flags = fcntl(fd, F_GETFL);
122
+ int flags = fcntl(wrapper->client->net.fd, F_GETFL);
124
123
  if (flags > 0 && !(flags & O_NONBLOCK))
125
- fcntl(fd, F_SETFL, flags | O_NONBLOCK);
124
+ fcntl(wrapper->client->net.fd, F_SETFL, flags | O_NONBLOCK);
126
125
  #else
127
126
  u_long iMode = 1;
128
- ioctlsocket(fd, FIONBIO, &iMode);
127
+ ioctlsocket(wrapper->client->net.fd, FIONBIO, &iMode);
129
128
  #endif
130
- }
131
129
 
132
- /* It's safe to call mysql_close() on an already closed connection. */
133
- if (!wrapper->closed) {
134
130
  mysql_close(wrapper->client);
131
+ free(wrapper->client);
135
132
  }
136
- xfree(ptr);
137
- }
138
133
 
139
- static VALUE nogvl_close(void * ptr) {
140
- mysql_client_wrapper *wrapper = ptr;
141
- if (!wrapper->closed) {
142
- mysql_close(wrapper->client);
143
- wrapper->closed = 1;
144
- }
145
134
  return Qnil;
146
135
  }
147
136
 
137
+ static void rb_mysql_client_free(void * ptr) {
138
+ mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;
139
+
140
+ nogvl_close(wrapper);
141
+
142
+ xfree(ptr);
143
+ }
144
+
148
145
  static VALUE allocate(VALUE klass) {
149
146
  VALUE obj;
150
147
  mysql_client_wrapper * wrapper;
151
148
  obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
152
149
  wrapper->encoding = Qnil;
153
150
  wrapper->active = 0;
154
- wrapper->closed = 0;
151
+ wrapper->closed = 1;
152
+ wrapper->client = (MYSQL*)malloc(sizeof(MYSQL));
155
153
  return obj;
156
154
  }
157
155
 
@@ -166,7 +164,7 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
166
164
  args.passwd = NIL_P(pass) ? NULL : StringValuePtr(pass);
167
165
  args.db = NIL_P(database) ? NULL : StringValuePtr(database);
168
166
  args.mysql = wrapper->client;
169
- args.client_flag = NUM2INT(flags);
167
+ args.client_flag = NUM2ULONG(flags);
170
168
 
171
169
  if (rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0) == Qfalse) {
172
170
  // unable to connect
@@ -185,7 +183,9 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
185
183
  static VALUE rb_mysql_client_close(VALUE self) {
186
184
  GET_CLIENT(self);
187
185
 
188
- rb_thread_blocking_region(nogvl_close, wrapper, RUBY_UBF_IO, 0);
186
+ if (!wrapper->closed) {
187
+ rb_thread_blocking_region(nogvl_close, wrapper, RUBY_UBF_IO, 0);
188
+ }
189
189
 
190
190
  return Qnil;
191
191
  }
@@ -334,6 +334,7 @@ static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
334
334
  unsigned long newLen, oldLen;
335
335
  GET_CLIENT(self);
336
336
 
337
+ REQUIRE_OPEN_DB(wrapper);
337
338
  Check_Type(str, T_STRING);
338
339
  #ifdef HAVE_RUBY_ENCODING_H
339
340
  rb_encoding *default_internal_enc = rb_default_internal_encoding();
@@ -345,7 +346,6 @@ static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
345
346
  oldLen = RSTRING_LEN(str);
346
347
  newStr = rb_str_new(0, oldLen*2+1);
347
348
 
348
- REQUIRE_OPEN_DB(wrapper);
349
349
  newLen = mysql_real_escape_string(wrapper->client, RSTRING_PTR(newStr), StringValuePtr(str), oldLen);
350
350
  if (newLen == oldLen) {
351
351
  // no need to return a new ruby string if nothing changed
@@ -365,6 +365,7 @@ static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
365
365
  static VALUE rb_mysql_client_info(VALUE self) {
366
366
  VALUE version = rb_hash_new(), client_info;
367
367
  GET_CLIENT(self);
368
+
368
369
  #ifdef HAVE_RUBY_ENCODING_H
369
370
  rb_encoding *default_internal_enc = rb_default_internal_encoding();
370
371
  rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
@@ -385,13 +386,13 @@ static VALUE rb_mysql_client_info(VALUE self) {
385
386
  static VALUE rb_mysql_client_server_info(VALUE self) {
386
387
  VALUE version, server_info;
387
388
  GET_CLIENT(self);
389
+
390
+ REQUIRE_OPEN_DB(wrapper);
388
391
  #ifdef HAVE_RUBY_ENCODING_H
389
392
  rb_encoding *default_internal_enc = rb_default_internal_encoding();
390
393
  rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
391
394
  #endif
392
395
 
393
- REQUIRE_OPEN_DB(wrapper);
394
-
395
396
  version = rb_hash_new();
396
397
  rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_server_version(wrapper->client)));
397
398
  server_info = rb_str_new2(mysql_get_server_info(wrapper->client));
@@ -419,8 +420,14 @@ static VALUE rb_mysql_client_last_id(VALUE self) {
419
420
 
420
421
  static VALUE rb_mysql_client_affected_rows(VALUE self) {
421
422
  GET_CLIENT(self);
423
+ my_ulonglong retVal;
424
+
422
425
  REQUIRE_OPEN_DB(wrapper);
423
- return ULL2NUM(mysql_affected_rows(wrapper->client));
426
+ retVal = mysql_affected_rows(wrapper->client);
427
+ if (retVal == (my_ulonglong)-1) {
428
+ rb_raise_mysql2_error(wrapper->client);
429
+ }
430
+ return ULL2NUM(retVal);
424
431
  }
425
432
 
426
433
  static VALUE set_reconnect(VALUE self, VALUE value) {
@@ -500,11 +507,12 @@ static VALUE set_ssl_options(VALUE self, VALUE key, VALUE cert, VALUE ca, VALUE
500
507
  static VALUE init_connection(VALUE self) {
501
508
  GET_CLIENT(self);
502
509
 
503
- if (rb_thread_blocking_region(nogvl_init, ((void *) &wrapper->client), RUBY_UBF_IO, 0) == Qfalse) {
510
+ if (rb_thread_blocking_region(nogvl_init, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
504
511
  /* TODO: warning - not enough memory? */
505
512
  return rb_raise_mysql2_error(wrapper->client);
506
513
  }
507
514
 
515
+ wrapper->closed = 0;
508
516
  return self;
509
517
  }
510
518
 
@@ -57,7 +57,7 @@ end
57
57
  asplode h unless have_header h
58
58
  end
59
59
 
60
- unless RUBY_PLATFORM =~ /mswin/
60
+ unless RUBY_PLATFORM =~ /mswin/ or RUBY_PLATFORM =~ /sparc/
61
61
  $CFLAGS << ' -Wall -funroll-loops'
62
62
  end
63
63
  # $CFLAGS << ' -O0 -ggdb3 -Wextra'
@@ -617,8 +617,15 @@ module ActiveRecord
617
617
  # Turn this off. http://dev.rubyonrails.org/ticket/6778
618
618
  variable_assignments = ['SQL_AUTO_IS_NULL=0']
619
619
  encoding = @config[:encoding]
620
+
621
+ # make sure we set the encoding
620
622
  variable_assignments << "NAMES '#{encoding}'" if encoding
621
623
 
624
+ # increase timeout so mysql server doesn't disconnect us
625
+ wait_timeout = @config[:wait_timeout]
626
+ wait_timeout = 2592000 unless wait_timeout.is_a?(Fixnum)
627
+ variable_assignments << "@@wait_timeout = #{wait_timeout}"
628
+
622
629
  execute("SET #{variable_assignments.join(', ')}", :skip_logging)
623
630
  end
624
631
 
@@ -12,5 +12,5 @@ require 'mysql2/result'
12
12
  #
13
13
  # A modern, simple and very fast Mysql library for Ruby - binding to libmysql
14
14
  module Mysql2
15
- VERSION = "0.2.4"
15
+ VERSION = "0.2.5"
16
16
  end
@@ -8,7 +8,8 @@ module Mysql2
8
8
  :symbolize_keys => false, # return field names as symbols instead of strings
9
9
  :database_timezone => :local, # timezone Mysql2 will assume datetime objects are stored in
10
10
  :application_timezone => nil, # timezone Mysql2 will convert to before handing the object back to the caller
11
- :cache_rows => true # tells Mysql2 to use it's internal row cache for results
11
+ :cache_rows => true, # tells Mysql2 to use it's internal row cache for results
12
+ :connect_flags => REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION
12
13
  }
13
14
 
14
15
  def initialize(opts = {})
@@ -31,7 +32,7 @@ module Mysql2
31
32
  port = opts[:port] || 3306
32
33
  database = opts[:database]
33
34
  socket = opts[:socket]
34
- flags = opts[:flags] || 0
35
+ flags = opts[:flags] ? opts[:flags] | @query_options[:connect_flags] : @query_options[:connect_flags]
35
36
 
36
37
  connect user, pass, host, port, database, socket, flags
37
38
  end
@@ -13,12 +13,12 @@ module Mysql2
13
13
  end
14
14
 
15
15
  def notify_readable
16
+ detach
16
17
  begin
17
18
  @deferable.succeed(@client.async_result)
18
19
  rescue Exception => e
19
20
  @deferable.fail(e)
20
21
  end
21
- detach
22
22
  end
23
23
  end
24
24
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mysql2}
8
- s.version = "0.2.4"
8
+ s.version = "0.2.5"
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-09-17}
12
+ s.date = %q{2010-10-19}
13
13
  s.email = %q{seniorlopez@gmail.com}
14
14
  s.extensions = ["ext/mysql2/extconf.rb"]
15
15
  s.extra_rdoc_files = [
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
17
17
  ]
18
18
  s.files = [
19
19
  ".gitignore",
20
+ ".rspec",
20
21
  "CHANGELOG.md",
21
22
  "MIT-LICENSE",
22
23
  "README.rdoc",
@@ -29,7 +30,6 @@ Gem::Specification.new do |s|
29
30
  "benchmark/query_without_mysql_casting.rb",
30
31
  "benchmark/sequel.rb",
31
32
  "benchmark/setup_db.rb",
32
- "benchmark/thread_alone.rb",
33
33
  "examples/eventmachine.rb",
34
34
  "examples/threaded.rb",
35
35
  "ext/mysql2/client.c",
@@ -54,10 +54,11 @@ Gem::Specification.new do |s|
54
54
  "spec/mysql2/error_spec.rb",
55
55
  "spec/mysql2/result_spec.rb",
56
56
  "spec/rcov.opts",
57
- "spec/spec.opts",
58
57
  "spec/spec_helper.rb",
59
58
  "tasks/benchmarks.rake",
60
59
  "tasks/compile.rake",
60
+ "tasks/jeweler.rake",
61
+ "tasks/rspec.rake",
61
62
  "tasks/vendor_mysql.rake"
62
63
  ]
63
64
  s.homepage = %q{http://github.com/brianmario/mysql2}
@@ -1,26 +1,49 @@
1
1
  # encoding: UTF-8
2
- require 'spec_helper'
3
- require 'mysql2/em'
2
+ if defined? EventMachine
3
+ require 'spec_helper'
4
+ require 'mysql2/em'
4
5
 
5
- describe Mysql2::EM::Client do
6
- it "should support async queries" do
7
- results = []
8
- EM.run do
9
- client1 = Mysql2::EM::Client.new
10
- defer1 = client1.query "SELECT sleep(0.05) as first_query"
11
- defer1.callback do |result|
12
- results << result.first
13
- EM.stop_event_loop
6
+ describe Mysql2::EM::Client do
7
+ it "should support async queries" do
8
+ results = []
9
+ EM.run do
10
+ client1 = Mysql2::EM::Client.new
11
+ defer1 = client1.query "SELECT sleep(0.1) as first_query"
12
+ defer1.callback do |result|
13
+ results << result.first
14
+ EM.stop_event_loop
15
+ end
16
+
17
+ client2 = Mysql2::EM::Client.new
18
+ defer2 = client2.query "SELECT sleep(0.025) second_query"
19
+ defer2.callback do |result|
20
+ results << result.first
21
+ end
14
22
  end
15
23
 
16
- client2 = Mysql2::EM::Client.new
17
- defer2 = client2.query "SELECT sleep(0.025) second_query"
18
- defer2.callback do |result|
19
- results << result.first
24
+ results[0].keys.should include("second_query")
25
+ results[1].keys.should include("first_query")
26
+ end
27
+
28
+ it "should support queries in callbacks" do
29
+ results = []
30
+ EM.run do
31
+ client = Mysql2::EM::Client.new
32
+ defer1 = client.query "SELECT sleep(0.025) as first_query"
33
+ defer1.callback do |result|
34
+ results << result.first
35
+ defer2 = client.query "SELECT sleep(0.025) as second_query"
36
+ defer2.callback do |result|
37
+ results << result.first
38
+ EM.stop_event_loop
39
+ end
40
+ end
20
41
  end
42
+
43
+ results[0].keys.should include("first_query")
44
+ results[1].keys.should include("second_query")
21
45
  end
22
-
23
- results[0].keys.should include("second_query")
24
- results[1].keys.should include("first_query")
25
46
  end
26
- end
47
+ else
48
+ puts "EventMachine not installed, skipping the specs that use it"
49
+ end
@@ -23,10 +23,10 @@ describe Mysql2::Client do
23
23
  end
24
24
  end
25
25
  client = klient.new :flags => Mysql2::Client::FOUND_ROWS
26
- client.connect_args.last.last.should == Mysql2::Client::FOUND_ROWS
26
+ (client.connect_args.last.last & Mysql2::Client::FOUND_ROWS).should be_true
27
27
  end
28
28
 
29
- it "should default flags to 0" do
29
+ it "should default flags to (REMEMBER_OPTIONS, LONG_PASSWORD, LONG_FLAG, TRANSACTIONS, PROTOCOL_41, SECURE_CONNECTION)" do
30
30
  klient = Class.new(Mysql2::Client) do
31
31
  attr_reader :connect_args
32
32
  def connect *args
@@ -35,7 +35,12 @@ describe Mysql2::Client do
35
35
  end
36
36
  end
37
37
  client = klient.new
38
- client.connect_args.last.last.should == 0
38
+ (client.connect_args.last.last & (Mysql2::Client::REMEMBER_OPTIONS |
39
+ Mysql2::Client::LONG_PASSWORD |
40
+ Mysql2::Client::LONG_FLAG |
41
+ Mysql2::Client::TRANSACTIONS |
42
+ Mysql2::Client::PROTOCOL_41 |
43
+ Mysql2::Client::SECURE_CONNECTION)).should be_true
39
44
  end
40
45
 
41
46
  it "should have a global default_query_options hash" do
@@ -71,6 +76,9 @@ describe Mysql2::Client do
71
76
 
72
77
  it "should be able to close properly" do
73
78
  @client.close.should be_nil
79
+ lambda {
80
+ @client.query "SELECT 1"
81
+ }.should raise_error(Mysql2::Error)
74
82
  end
75
83
 
76
84
  it "should respond to #query" do
@@ -103,6 +111,13 @@ describe Mysql2::Client do
103
111
  }.should raise_error(Mysql2::Error)
104
112
  end
105
113
 
114
+ it "should require an open connection" do
115
+ @client.close
116
+ lambda {
117
+ @client.query "SELECT 1"
118
+ }.should raise_error(Mysql2::Error)
119
+ end
120
+
106
121
  # XXX this test is not deterministic (because Unix signal handling is not)
107
122
  # and may fail on a loaded system
108
123
  if RUBY_PLATFORM !~ /mingw|mswin/
@@ -137,25 +152,34 @@ describe Mysql2::Client do
137
152
  @client.should respond_to(:escape)
138
153
  end
139
154
 
140
- it "#escape should return a new SQL-escape version of the passed string" do
141
- @client.escape("abc'def\"ghi\0jkl%mno").should eql("abc\\'def\\\"ghi\\0jkl%mno")
142
- end
155
+ context "#escape" do
156
+ it "should return a new SQL-escape version of the passed string" do
157
+ @client.escape("abc'def\"ghi\0jkl%mno").should eql("abc\\'def\\\"ghi\\0jkl%mno")
158
+ end
143
159
 
144
- it "#escape should return the passed string if nothing was escaped" do
145
- str = "plain"
146
- @client.escape(str).object_id.should eql(str.object_id)
147
- end
160
+ it "should return the passed string if nothing was escaped" do
161
+ str = "plain"
162
+ @client.escape(str).object_id.should eql(str.object_id)
163
+ end
148
164
 
149
- it "#escape should not overflow the thread stack" do
150
- lambda {
151
- Thread.new { @client.escape("'" * 256 * 1024) }.join
152
- }.should_not raise_error(SystemStackError)
153
- end
165
+ it "should not overflow the thread stack" do
166
+ lambda {
167
+ Thread.new { @client.escape("'" * 256 * 1024) }.join
168
+ }.should_not raise_error(SystemStackError)
169
+ end
154
170
 
155
- it "#escape should not overflow the process stack" do
156
- lambda {
157
- Thread.new { @client.escape("'" * 1024 * 1024 * 4) }.join
158
- }.should_not raise_error(SystemStackError)
171
+ it "should not overflow the process stack" do
172
+ lambda {
173
+ Thread.new { @client.escape("'" * 1024 * 1024 * 4) }.join
174
+ }.should_not raise_error(SystemStackError)
175
+ end
176
+
177
+ it "should require an open connection" do
178
+ @client.close
179
+ lambda {
180
+ @client.escape ""
181
+ }.should raise_error(Mysql2::Error)
182
+ end
159
183
  end
160
184
 
161
185
  it "should respond to #info" do
@@ -203,6 +227,13 @@ describe Mysql2::Client do
203
227
  server_info[:version].class.should eql(String)
204
228
  end
205
229
 
230
+ it "#server_info should require an open connection" do
231
+ @client.close
232
+ lambda {
233
+ @client.server_info
234
+ }.should raise_error(Mysql2::Error)
235
+ end
236
+
206
237
  if defined? Encoding
207
238
  context "strings returned by #server_info" do
208
239
  it "should default to the connection's encoding if Encoding.default_internal is nil" do
@@ -231,6 +262,13 @@ describe Mysql2::Client do
231
262
  @client.socket.should_not eql(0)
232
263
  end
233
264
 
265
+ it "#socket should require an open connection" do
266
+ @client.close
267
+ lambda {
268
+ @client.socket
269
+ }.should raise_error(Mysql2::Error)
270
+ end
271
+
234
272
  it "should raise a Mysql2::Error exception upon connection failure" do
235
273
  lambda {
236
274
  bad_client = Mysql2::Client.new :host => "dfjhdi9wrhw", :username => 'asdfasdf8d2h'
@@ -1,10 +1,11 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'rubygems'
3
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
4
+ require 'rspec'
4
5
  require 'mysql2'
5
6
  require 'timeout'
6
7
 
7
- Spec::Runner.configure do |config|
8
+ RSpec.configure do |config|
8
9
  config.before(:all) do
9
10
  client = Mysql2::Client.new :database => 'test'
10
11
  client.query %[
@@ -1,9 +1,8 @@
1
1
  gem 'rake-compiler', '~> 0.7.1'
2
2
  require "rake/extensiontask"
3
3
 
4
- MYSQL_VERSION = "5.1.50"
5
- MYSQL_MIRROR = ENV['MYSQL_MIRROR'] || "http://mysql.mirrors.pair.com"
6
-
4
+ MYSQL_VERSION = "5.1.51"
5
+ MYSQL_MIRROR = ENV['MYSQL_MIRROR'] || "http://mysql.he.net/"
7
6
 
8
7
  def gemspec
9
8
  @clean_gemspec ||= eval(File.read(File.expand_path('../../mysql2.gemspec', __FILE__)))
@@ -13,15 +12,24 @@ Rake::ExtensionTask.new("mysql2", gemspec) do |ext|
13
12
  # reference where the vendored MySQL got extracted
14
13
  mysql_lib = File.expand_path(File.join(File.dirname(__FILE__), '..', 'vendor', "mysql-#{MYSQL_VERSION}-win32"))
15
14
 
15
+ # DRY options feed into compile or cross-compile process
16
+ windows_options = [
17
+ "--with-mysql-include=#{mysql_lib}/include",
18
+ "--with-mysql-lib=#{mysql_lib}/lib/opt"
19
+ ]
20
+
16
21
  # automatically add build options to avoid need of manual input
17
22
  if RUBY_PLATFORM =~ /mswin|mingw/ then
18
- ext.config_options << "--with-mysql-include=#{mysql_lib}/include"
19
- ext.config_options << "--with-mysql-lib=#{mysql_lib}/lib/opt"
23
+ ext.config_options = windows_options
20
24
  else
21
25
  ext.cross_compile = true
22
26
  ext.cross_platform = ['x86-mingw32', 'x86-mswin32-60']
23
- ext.cross_config_options << "--with-mysql-include=#{mysql_lib}/include"
24
- ext.cross_config_options << "--with-mysql-lib=#{mysql_lib}/lib/opt"
27
+ ext.cross_config_options = windows_options
28
+
29
+ # inject 1.8/1.9 pure-ruby entry point when cross compiling only
30
+ ext.cross_compiling do |spec|
31
+ spec.files << 'lib/mysql2/mysql2.rb'
32
+ end
25
33
  end
26
34
 
27
35
  ext.lib_dir = File.join 'lib', 'mysql2'
@@ -30,3 +38,17 @@ Rake::ExtensionTask.new("mysql2", gemspec) do |ext|
30
38
  CLEAN.include "#{ext.lib_dir}/*.#{RbConfig::CONFIG['DLEXT']}"
31
39
  end
32
40
  Rake::Task[:spec].prerequisites << :compile
41
+
42
+ file 'lib/mysql2/mysql2.rb' do |t|
43
+ name = gemspec.name
44
+ File.open(t.name, 'wb') do |f|
45
+ f.write <<-eoruby
46
+ RUBY_VERSION =~ /(\\d+.\\d+)/
47
+ require "#{name}/\#{$1}/#{name}"
48
+ eoruby
49
+ end
50
+ end
51
+
52
+ if Rake::Task.task_defined?(:cross)
53
+ Rake::Task[:cross].prerequisites << "lib/mysql2/mysql2.rb"
54
+ end
@@ -0,0 +1,17 @@
1
+ begin
2
+ require 'jeweler'
3
+ JEWELER = Jeweler::Tasks.new do |gem|
4
+ gem.name = "mysql2"
5
+ gem.summary = "A simple, fast Mysql library for Ruby, binding to libmysql"
6
+ gem.email = "seniorlopez@gmail.com"
7
+ gem.homepage = "http://github.com/brianmario/mysql2"
8
+ gem.authors = ["Brian Lopez"]
9
+ gem.require_paths = ["lib", "ext"]
10
+ gem.extra_rdoc_files = `git ls-files *.rdoc`.split("\n")
11
+ gem.files = `git ls-files`.split("\n")
12
+ gem.extensions = ["ext/mysql2/extconf.rb"]
13
+ gem.files.include %w(lib/jeweler/templates/.document lib/jeweler/templates/.gitignore)
14
+ end
15
+ rescue LoadError
16
+ puts "jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
17
+ end
@@ -0,0 +1,16 @@
1
+ begin
2
+ require 'rspec'
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run all examples with RCov"
6
+ RSpec::Core::RakeTask.new('spec:rcov') do |t|
7
+ t.rcov = true
8
+ end
9
+ RSpec::Core::RakeTask.new('spec') do |t|
10
+ t.verbose = true
11
+ end
12
+
13
+ task :default => :spec
14
+ rescue LoadError
15
+ puts "rspec, or one of its dependencies, is not available. Install it with: sudo gem install rspec"
16
+ 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: 31
4
+ hash: 29
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 4
10
- version: 0.2.4
9
+ - 5
10
+ version: 0.2.5
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: 2010-09-17 00:00:00 -07:00
18
+ date: 2010-10-19 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -29,6 +29,7 @@ extra_rdoc_files:
29
29
  - README.rdoc
30
30
  files:
31
31
  - .gitignore
32
+ - .rspec
32
33
  - CHANGELOG.md
33
34
  - MIT-LICENSE
34
35
  - README.rdoc
@@ -41,7 +42,6 @@ files:
41
42
  - benchmark/query_without_mysql_casting.rb
42
43
  - benchmark/sequel.rb
43
44
  - benchmark/setup_db.rb
44
- - benchmark/thread_alone.rb
45
45
  - examples/eventmachine.rb
46
46
  - examples/threaded.rb
47
47
  - ext/mysql2/client.c
@@ -66,10 +66,11 @@ files:
66
66
  - spec/mysql2/error_spec.rb
67
67
  - spec/mysql2/result_spec.rb
68
68
  - spec/rcov.opts
69
- - spec/spec.opts
70
69
  - spec/spec_helper.rb
71
70
  - tasks/benchmarks.rake
72
71
  - tasks/compile.rake
72
+ - tasks/jeweler.rake
73
+ - tasks/rspec.rake
73
74
  - tasks/vendor_mysql.rake
74
75
  has_rdoc: true
75
76
  homepage: http://github.com/brianmario/mysql2
@@ -1,20 +0,0 @@
1
- # encoding: UTF-8
2
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
3
-
4
- require 'rubygems'
5
- require 'benchmark'
6
- require 'mysql2'
7
-
8
- iterations = 1000
9
- client = Mysql2::Client.new(:host => "localhost", :username => "root", :database => "test")
10
- query = lambda{ iterations.times{ client.query("SELECT mysql2_test.* FROM mysql2_test") } }
11
- Benchmark.bmbm do |x|
12
- x.report('select') do
13
- query.call
14
- end
15
- x.report('rb_thread_select') do
16
- thread = Thread.new{ sleep(10) }
17
- query.call
18
- thread.kill
19
- end
20
- end
@@ -1,2 +0,0 @@
1
- --format specdoc
2
- --colour