mysql2 0.2.4 → 0.2.5

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.
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