mysql2 0.2.24 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/CHANGELOG.md +148 -0
  5. data/Gemfile +3 -0
  6. data/README.rdoc +257 -0
  7. data/Rakefile +5 -0
  8. data/benchmark/active_record.rb +51 -0
  9. data/benchmark/active_record_threaded.rb +42 -0
  10. data/benchmark/allocations.rb +33 -0
  11. data/benchmark/escape.rb +36 -0
  12. data/benchmark/query_with_mysql_casting.rb +80 -0
  13. data/benchmark/query_without_mysql_casting.rb +47 -0
  14. data/benchmark/sequel.rb +37 -0
  15. data/benchmark/setup_db.rb +119 -0
  16. data/benchmark/threaded.rb +44 -0
  17. data/ext/mysql2/client.c +272 -849
  18. data/ext/mysql2/client.h +12 -27
  19. data/ext/mysql2/extconf.rb +14 -72
  20. data/ext/mysql2/mysql2_ext.h +4 -7
  21. data/ext/mysql2/result.c +123 -319
  22. data/ext/mysql2/result.h +1 -4
  23. data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +64 -0
  24. data/lib/active_record/fiber_patches.rb +104 -0
  25. data/lib/mysql2.rb +5 -20
  26. data/lib/mysql2/client.rb +200 -50
  27. data/lib/mysql2/em.rb +3 -13
  28. data/lib/mysql2/em_fiber.rb +31 -0
  29. data/lib/mysql2/error.rb +6 -71
  30. data/lib/mysql2/version.rb +2 -2
  31. data/mysql2.gemspec +32 -0
  32. data/spec/em/em_fiber_spec.rb +22 -0
  33. data/spec/em/em_spec.rb +9 -74
  34. data/spec/mysql2/client_spec.rb +126 -593
  35. data/spec/mysql2/error_spec.rb +44 -58
  36. data/spec/mysql2/result_spec.rb +85 -257
  37. data/spec/spec_helper.rb +3 -24
  38. data/tasks/benchmarks.rake +20 -0
  39. data/tasks/compile.rake +71 -0
  40. data/tasks/rspec.rake +16 -0
  41. data/tasks/vendor_mysql.rake +40 -0
  42. metadata +179 -92
  43. checksums.yaml +0 -7
  44. data/README.md +0 -524
  45. data/ext/mysql2/infile.c +0 -122
  46. data/ext/mysql2/infile.h +0 -1
  47. data/ext/mysql2/mysql_enc_name_to_ruby.h +0 -168
  48. data/ext/mysql2/mysql_enc_to_ruby.h +0 -246
  49. data/ext/mysql2/wait_for_single_fd.h +0 -36
  50. data/lib/active_record/connection_adapters/mysql2_adapter.rb +0 -635
  51. data/lib/arel/engines/sql/compilers/mysql2_compiler.rb +0 -11
  52. data/lib/mysql2/console.rb +0 -5
  53. data/spec/configuration.yml.example +0 -17
  54. data/spec/my.cnf.example +0 -9
  55. data/spec/test_data +0 -1
  56. data/support/mysql_enc_to_ruby.rb +0 -82
  57. data/support/ruby_enc_to_mysql.rb +0 -61
data/lib/mysql2/em.rb CHANGED
@@ -15,28 +15,18 @@ module Mysql2
15
15
  def notify_readable
16
16
  detach
17
17
  begin
18
- result = @client.async_result
18
+ @deferable.succeed(@client.async_result)
19
19
  rescue Exception => e
20
20
  @deferable.fail(e)
21
- else
22
- @deferable.succeed(result)
23
21
  end
24
22
  end
25
23
  end
26
24
 
27
- def close(*args)
28
- if @watch
29
- @watch.detach
30
- end
31
- super(*args)
32
- end
33
-
34
25
  def query(sql, opts={})
35
26
  if ::EM.reactor_running?
36
27
  super(sql, opts.merge(:async => true))
37
28
  deferable = ::EM::DefaultDeferrable.new
38
- @watch = ::EM.watch(self.socket, Watcher, self, deferable)
39
- @watch.notify_readable = true
29
+ ::EM.watch(self.socket, Watcher, self, deferable).notify_readable = true
40
30
  deferable
41
31
  else
42
32
  super(sql, opts)
@@ -44,4 +34,4 @@ module Mysql2
44
34
  end
45
35
  end
46
36
  end
47
- end
37
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require 'mysql2/em'
4
+ require 'fiber'
5
+
6
+ module Mysql2
7
+ module EM
8
+ module Fiber
9
+ class Client < ::Mysql2::EM::Client
10
+ def query(sql, opts={})
11
+ if ::EM.reactor_running?
12
+ deferable = super(sql, opts)
13
+
14
+ fiber = ::Fiber.current
15
+ deferable.callback do |result|
16
+ fiber.resume(result)
17
+ end
18
+ deferable.errback do |err|
19
+ fiber.resume(err)
20
+ end
21
+ ::Fiber.yield.tap do |result|
22
+ raise result if result.is_a?(::Exception)
23
+ end
24
+ else
25
+ super(sql, opts)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/mysql2/error.rb CHANGED
@@ -1,80 +1,15 @@
1
- # encoding: UTF-8
2
-
3
1
  module Mysql2
4
2
  class Error < StandardError
5
- REPLACEMENT_CHAR = '?'
6
- ENCODE_OPTS = {:undef => :replace, :invalid => :replace, :replace => REPLACEMENT_CHAR}
3
+ attr_accessor :error_number, :sql_state
7
4
 
8
- attr_accessor :error_number
9
- attr_reader :sql_state
10
- attr_writer :server_version
5
+ def initialize msg
6
+ super
7
+ @error_number = nil
8
+ @sql_state = nil
9
+ end
11
10
 
12
11
  # Mysql gem compatibility
13
12
  alias_method :errno, :error_number
14
13
  alias_method :error, :message
15
-
16
- def initialize(msg, server_version=nil)
17
- self.server_version = server_version
18
-
19
- super(clean_message(msg))
20
- end
21
-
22
- def sql_state=(state)
23
- @sql_state = ''.respond_to?(:encode) ? state.encode(ENCODE_OPTS) : state
24
- end
25
-
26
- private
27
-
28
- # In MySQL 5.5+ error messages are always constructed server-side as UTF-8
29
- # then returned in the encoding set by the `character_set_results` system
30
- # variable.
31
- #
32
- # See http://dev.mysql.com/doc/refman/5.5/en/charset-errors.html for
33
- # more contetx.
34
- #
35
- # Before MySQL 5.5 error message template strings are in whatever encoding
36
- # is associated with the error message language.
37
- # See http://dev.mysql.com/doc/refman/5.1/en/error-message-language.html
38
- # for more information.
39
- #
40
- # The issue is that the user-data inserted in the message could potentially
41
- # be in any encoding MySQL supports and is insert into the latin1, euckr or
42
- # koi8r string raw. Meaning there's a high probability the string will be
43
- # corrupt encoding-wise.
44
- #
45
- # See http://dev.mysql.com/doc/refman/5.1/en/charset-errors.html for
46
- # more information.
47
- #
48
- # So in an attempt to make sure the error message string is always in a valid
49
- # encoding, we'll assume UTF-8 and clean the string of anything that's not a
50
- # valid UTF-8 character.
51
- #
52
- # Except for if we're on 1.8, where we'll do nothing ;)
53
- #
54
- # Returns a valid UTF-8 string in Ruby 1.9+, the original string on Ruby 1.8
55
- def clean_message(message)
56
- return message if !message.respond_to?(:encoding)
57
-
58
- if @server_version && @server_version > 50500
59
- message.encode(ENCODE_OPTS)
60
- else
61
- if message.respond_to? :scrub
62
- message.scrub(REPLACEMENT_CHAR).encode(ENCODE_OPTS)
63
- else
64
- # This is ugly as hell but Ruby 1.9 doesn't provide a way to clean a string
65
- # and retain it's valid UTF-8 characters, that I know of.
66
-
67
- new_message = "".force_encoding(Encoding::UTF_8)
68
- message.chars.each do |char|
69
- if char.valid_encoding?
70
- new_message << char
71
- else
72
- new_message << REPLACEMENT_CHAR
73
- end
74
- end
75
- new_message.encode(ENCODE_OPTS)
76
- end
77
- end
78
- end
79
14
  end
80
15
  end
@@ -1,3 +1,3 @@
1
1
  module Mysql2
2
- VERSION = "0.2.24"
3
- end
2
+ VERSION = "0.3.0"
3
+ end
data/mysql2.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ require File.expand_path('../lib/mysql2/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{mysql2}
5
+ s.version = Mysql2::VERSION
6
+ s.authors = ["Brian Lopez"]
7
+ s.date = Time.now.utc.strftime("%Y-%m-%d")
8
+ s.email = %q{seniorlopez@gmail.com}
9
+ s.extensions = ["ext/mysql2/extconf.rb"]
10
+ s.extra_rdoc_files = [
11
+ "README.rdoc"
12
+ ]
13
+ s.files = `git ls-files`.split("\n")
14
+ s.homepage = %q{http://github.com/brianmario/mysql2}
15
+ s.rdoc_options = ["--charset=UTF-8"]
16
+ s.require_paths = ["lib", "ext"]
17
+ s.rubygems_version = %q{1.4.2}
18
+ s.summary = %q{A simple, fast Mysql library for Ruby, binding to libmysql}
19
+ s.test_files = `git ls-files spec examples`.split("\n")
20
+
21
+ # tests
22
+ s.add_development_dependency 'eventmachine'
23
+ s.add_development_dependency 'rake-compiler', "~> 0.7.7"
24
+ s.add_development_dependency 'rspec'
25
+ # benchmarks
26
+ s.add_development_dependency 'activerecord'
27
+ s.add_development_dependency 'mysql'
28
+ s.add_development_dependency 'do_mysql'
29
+ s.add_development_dependency 'sequel'
30
+ s.add_development_dependency 'faker'
31
+ end
32
+
@@ -0,0 +1,22 @@
1
+ # encoding: UTF-8
2
+ if defined? EventMachine && defined? Fiber
3
+ require 'spec_helper'
4
+ require 'mysql2/em_fiber'
5
+
6
+ describe Mysql2::EM::Fiber::Client do
7
+ it 'should support queries' do
8
+ results = []
9
+ EM.run do
10
+ Fiber.new {
11
+ client1 = Mysql2::EM::Fiber::Client.new
12
+ results = client1.query "SELECT sleep(0.1) as first_query"
13
+ EM.stop_event_loop
14
+ }.resume
15
+ end
16
+
17
+ results.first.keys.should include("first_query")
18
+ end
19
+ end
20
+ else
21
+ puts "Either EventMachine or Fibers not available. Skipping tests that use them."
22
+ end
data/spec/em/em_spec.rb CHANGED
@@ -1,26 +1,23 @@
1
1
  # encoding: UTF-8
2
- require 'spec_helper'
3
- begin
4
- require 'eventmachine'
2
+ if defined? EventMachine
3
+ require 'spec_helper'
5
4
  require 'mysql2/em'
6
5
 
7
6
  describe Mysql2::EM::Client do
8
7
  it "should support async queries" do
9
8
  results = []
10
9
  EM.run do
11
- client1 = Mysql2::EM::Client.new DatabaseCredentials['root']
10
+ client1 = Mysql2::EM::Client.new
12
11
  defer1 = client1.query "SELECT sleep(0.1) as first_query"
13
12
  defer1.callback do |result|
14
13
  results << result.first
15
- client1.close
16
14
  EM.stop_event_loop
17
15
  end
18
16
 
19
- client2 = Mysql2::EM::Client.new DatabaseCredentials['root']
17
+ client2 = Mysql2::EM::Client.new
20
18
  defer2 = client2.query "SELECT sleep(0.025) second_query"
21
19
  defer2.callback do |result|
22
20
  results << result.first
23
- client2.close
24
21
  end
25
22
  end
26
23
 
@@ -31,14 +28,13 @@ begin
31
28
  it "should support queries in callbacks" do
32
29
  results = []
33
30
  EM.run do
34
- client = Mysql2::EM::Client.new DatabaseCredentials['root']
31
+ client = Mysql2::EM::Client.new
35
32
  defer1 = client.query "SELECT sleep(0.025) as first_query"
36
33
  defer1.callback do |result|
37
34
  results << result.first
38
35
  defer2 = client.query "SELECT sleep(0.025) as second_query"
39
- defer2.callback do |r|
40
- results << r.first
41
- client.close
36
+ defer2.callback do |result|
37
+ results << result.first
42
38
  EM.stop_event_loop
43
39
  end
44
40
  end
@@ -47,68 +43,7 @@ begin
47
43
  results[0].keys.should include("first_query")
48
44
  results[1].keys.should include("second_query")
49
45
  end
50
-
51
- it "should not swallow exceptions raised in callbacks" do
52
- lambda {
53
- EM.run do
54
- client = Mysql2::EM::Client.new DatabaseCredentials['root']
55
- defer = client.query "SELECT sleep(0.1) as first_query"
56
- defer.callback do |result|
57
- client.close
58
- raise 'some error'
59
- end
60
- defer.errback do |err|
61
- # This _shouldn't_ be run, but it needed to prevent the specs from
62
- # freezing if this test fails.
63
- EM.stop_event_loop
64
- end
65
- end
66
- }.should raise_error
67
- end
68
-
69
- context 'when an exception is raised by the client' do
70
- let(:client) { Mysql2::EM::Client.new DatabaseCredentials['root'] }
71
- let(:error) { StandardError.new('some error') }
72
- before { client.stub(:async_result).and_raise(error) }
73
-
74
- it "should swallow exceptions raised in by the client" do
75
- errors = []
76
- EM.run do
77
- defer = client.query "SELECT sleep(0.1) as first_query"
78
- defer.callback do |result|
79
- # This _shouldn't_ be run, but it is needed to prevent the specs from
80
- # freezing if this test fails.
81
- EM.stop_event_loop
82
- end
83
- defer.errback do |err|
84
- errors << err
85
- EM.stop_event_loop
86
- end
87
- end
88
- errors.should == [error]
89
- end
90
-
91
- it "should fail the deferrable" do
92
- callbacks_run = []
93
- EM.run do
94
- defer = client.query "SELECT sleep(0.025) as first_query"
95
- EM.add_timer(0.1) do
96
- defer.callback do |result|
97
- callbacks_run << :callback
98
- # This _shouldn't_ be run, but it is needed to prevent the specs from
99
- # freezing if this test fails.
100
- EM.stop_event_loop
101
- end
102
- defer.errback do |err|
103
- callbacks_run << :errback
104
- EM.stop_event_loop
105
- end
106
- end
107
- end
108
- callbacks_run.should == [:errback]
109
- end
110
- end
111
46
  end
112
- rescue LoadError
47
+ else
113
48
  puts "EventMachine not installed, skipping the specs that use it"
114
- end
49
+ end
@@ -2,47 +2,16 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Mysql2::Client do
5
- context "using defaults file" do
6
- let(:cnf_file) { File.expand_path('../../my.cnf', __FILE__) }
7
-
8
- it "should not raise an exception for valid defaults group" do
9
- lambda {
10
- opts = DatabaseCredentials['root'].merge(:default_file => cnf_file, :default_group => "test")
11
- @client = Mysql2::Client.new(opts)
12
- }.should_not raise_error(Mysql2::Error)
13
- end
14
-
15
- it "should not raise an exception without default group" do
16
- lambda {
17
- @client = Mysql2::Client.new(DatabaseCredentials['root'].merge(:default_file => cnf_file))
18
- }.should_not raise_error(Mysql2::Error)
19
- end
20
- end
21
-
22
- it "should raise an exception upon connection failure" do
23
- lambda {
24
- # The odd local host IP address forces the mysql client library to
25
- # use a TCP socket rather than a domain socket.
26
- Mysql2::Client.new DatabaseCredentials['root'].merge('host' => '127.0.0.2', 'port' => 999999)
27
- }.should raise_error(Mysql2::Error)
5
+ before(:each) do
6
+ @client = Mysql2::Client.new
28
7
  end
29
8
 
30
9
  if defined? Encoding
31
10
  it "should raise an exception on create for invalid encodings" do
32
11
  lambda {
33
- Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => "fake"))
12
+ c = Mysql2::Client.new(:encoding => "fake")
34
13
  }.should raise_error(Mysql2::Error)
35
14
  end
36
-
37
- it "should not raise an exception on create for a valid encoding" do
38
- lambda {
39
- Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => "utf8"))
40
- }.should_not raise_error(Mysql2::Error)
41
-
42
- lambda {
43
- Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => "big5"))
44
- }.should_not raise_error(Mysql2::Error)
45
- end
46
15
  end
47
16
 
48
17
  it "should accept connect flags and pass them to #connect" do
@@ -54,7 +23,7 @@ describe Mysql2::Client do
54
23
  end
55
24
  end
56
25
  client = klient.new :flags => Mysql2::Client::FOUND_ROWS
57
- (client.connect_args.last[6] & Mysql2::Client::FOUND_ROWS).should be_true
26
+ (client.connect_args.last.last & Mysql2::Client::FOUND_ROWS).should be_true
58
27
  end
59
28
 
60
29
  it "should default flags to (REMEMBER_OPTIONS, LONG_PASSWORD, LONG_FLAG, TRANSACTIONS, PROTOCOL_41, SECURE_CONNECTION)" do
@@ -66,7 +35,7 @@ describe Mysql2::Client do
66
35
  end
67
36
  end
68
37
  client = klient.new
69
- (client.connect_args.last[6] & (Mysql2::Client::REMEMBER_OPTIONS |
38
+ (client.connect_args.last.last & (Mysql2::Client::REMEMBER_OPTIONS |
70
39
  Mysql2::Client::LONG_PASSWORD |
71
40
  Mysql2::Client::LONG_FLAG |
72
41
  Mysql2::Client::TRANSACTIONS |
@@ -74,66 +43,19 @@ describe Mysql2::Client do
74
43
  Mysql2::Client::SECURE_CONNECTION)).should be_true
75
44
  end
76
45
 
77
- it "should execute init command" do
78
- options = DatabaseCredentials['root'].dup
79
- options[:init_command] = "SET @something = 'setting_value';"
80
- client = Mysql2::Client.new(options)
81
- result = client.query("SELECT @something;")
82
- result.first['@something'].should eq('setting_value')
83
- end
84
-
85
- it "should send init_command after reconnect" do
86
- options = DatabaseCredentials['root'].dup
87
- options[:init_command] = "SET @something = 'setting_value';"
88
- options[:reconnect] = true
89
- client = Mysql2::Client.new(options)
90
-
91
- result = client.query("SELECT @something;")
92
- result.first['@something'].should eq('setting_value')
93
-
94
- # get the current connection id
95
- result = client.query("SELECT CONNECTION_ID()")
96
- first_conn_id = result.first['CONNECTION_ID()']
97
-
98
- # break the current connection
99
- begin
100
- client.query("KILL #{first_conn_id}")
101
- rescue Mysql2::Error
102
- end
103
-
104
- client.ping # reconnect now
105
-
106
- # get the new connection id
107
- result = client.query("SELECT CONNECTION_ID()")
108
- second_conn_id = result.first['CONNECTION_ID()']
109
-
110
- # confirm reconnect by checking the new connection id
111
- first_conn_id.should_not == second_conn_id
112
-
113
- # At last, check that the init command executed
114
- result = client.query("SELECT @something;")
115
- result.first['@something'].should eq('setting_value')
116
- end
117
-
118
46
  it "should have a global default_query_options hash" do
119
47
  Mysql2::Client.should respond_to(:default_query_options)
120
48
  end
121
49
 
122
50
  it "should be able to connect via SSL options" do
123
- ssl = @client.query "SHOW VARIABLES LIKE 'have_ssl'"
124
- ssl_uncompiled = ssl.any? {|x| x['Value'] == 'OFF'}
125
- pending("DON'T WORRY, THIS TEST PASSES - but SSL is not compiled into your MySQL daemon.") if ssl_uncompiled
126
- ssl_disabled = ssl.any? {|x| x['Value'] == 'DISABLED'}
127
- pending("DON'T WORRY, THIS TEST PASSES - but SSL is not enabled in your MySQL daemon.") if ssl_disabled
128
-
129
- # You may need to adjust the lines below to match your SSL certificate paths
51
+ 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.")
130
52
  ssl_client = nil
131
53
  lambda {
132
54
  ssl_client = Mysql2::Client.new(
133
- :sslkey => '/etc/mysql/client-key.pem',
134
- :sslcert => '/etc/mysql/client-cert.pem',
135
- :sslca => '/etc/mysql/ca-cert.pem',
136
- :sslcapath => '/etc/mysql/',
55
+ :sslkey => '/path/to/client-key.pem',
56
+ :sslcert => '/path/to/client-cert.pem',
57
+ :sslca => '/path/to/ca-cert.pem',
58
+ :sslcapath => '/path/to/newcerts/',
137
59
  :sslcipher => 'DHE-RSA-AES256-SHA'
138
60
  )
139
61
  }.should_not raise_error(Mysql2::Error)
@@ -141,64 +63,11 @@ describe Mysql2::Client do
141
63
  results = ssl_client.query("SHOW STATUS WHERE Variable_name = \"Ssl_version\" OR Variable_name = \"Ssl_cipher\"").to_a
142
64
  results[0]['Variable_name'].should eql('Ssl_cipher')
143
65
  results[0]['Value'].should_not be_nil
144
- results[0]['Value'].should be_kind_of(String)
145
- results[0]['Value'].should_not be_empty
66
+ results[0]['Value'].class.should eql(String)
146
67
 
147
68
  results[1]['Variable_name'].should eql('Ssl_version')
148
69
  results[1]['Value'].should_not be_nil
149
- results[1]['Value'].should be_kind_of(String)
150
- results[1]['Value'].should_not be_empty
151
-
152
- ssl_client.close
153
- end
154
-
155
- it "should not leave dangling connections after garbage collection" do
156
- GC.start
157
- sleep 0.300 # Let GC do its work
158
- client = Mysql2::Client.new(DatabaseCredentials['root'])
159
- before_count = client.query("SHOW STATUS LIKE 'Threads_connected'").first['Value'].to_i
160
-
161
- 10.times do
162
- Mysql2::Client.new(DatabaseCredentials['root']).query('SELECT 1')
163
- end
164
- after_count = client.query("SHOW STATUS LIKE 'Threads_connected'").first['Value'].to_i
165
- after_count.should == before_count + 10
166
-
167
- GC.start
168
- sleep 0.300 # Let GC do its work
169
- final_count = client.query("SHOW STATUS LIKE 'Threads_connected'").first['Value'].to_i
170
- final_count.should == before_count
171
- end
172
-
173
- if Process.respond_to?(:fork)
174
- it "should not close connections when running in a child process" do
175
- GC.start
176
- sleep 1 if defined? Rubinius # Let the rbx GC thread do its work
177
- client = Mysql2::Client.new(DatabaseCredentials['root'])
178
-
179
- fork do
180
- client.query('SELECT 1')
181
- client = nil
182
- GC.start
183
- sleep 1 if defined? Rubinius # Let the rbx GC thread do its work
184
- end
185
-
186
- Process.wait
187
-
188
- # this will throw an error if the underlying socket was shutdown by the
189
- # child's GC
190
- expect { client.query('SELECT 1') }.to_not raise_exception
191
- end
192
- end
193
-
194
- it "should be able to connect to database with numeric-only name" do
195
- lambda {
196
- creds = DatabaseCredentials['numericuser']
197
- @client.query "CREATE DATABASE IF NOT EXISTS `#{creds['database']}`"
198
- @client.query "GRANT ALL ON `#{creds['database']}`.* TO #{creds['username']}@`#{creds['host']}`"
199
- client = Mysql2::Client.new creds
200
- @client.query "DROP DATABASE IF EXISTS `#{creds['database']}`"
201
- }.should_not raise_error
70
+ results[1]['Value'].class.should eql(String)
202
71
  end
203
72
 
204
73
  it "should respond to #close" do
@@ -216,160 +85,22 @@ describe Mysql2::Client do
216
85
  @client.should respond_to(:query)
217
86
  end
218
87
 
219
- it "should respond to #warning_count" do
220
- @client.should respond_to(:warning_count)
221
- end
222
-
223
- context "#warning_count" do
224
- context "when no warnings" do
225
- it "should 0" do
226
- @client.query('select 1')
227
- @client.warning_count.should == 0
228
- end
229
- end
230
- context "when has a warnings" do
231
- it "should > 0" do
232
- # "the statement produces extra information that can be viewed by issuing a SHOW WARNINGS"
233
- # http://dev.mysql.com/doc/refman/5.0/en/explain-extended.html
234
- @client.query("explain extended select 1")
235
- @client.warning_count.should > 0
236
- end
237
- end
238
- end
239
-
240
- it "should respond to #query_info" do
241
- @client.should respond_to(:query_info)
242
- end
243
-
244
- context "#query_info" do
245
- context "when no info present" do
246
- it "should 0" do
247
- @client.query('select 1')
248
- @client.query_info.should be_empty
249
- @client.query_info_string.should be_nil
250
- end
251
- end
252
- context "when has some info" do
253
- it "should retrieve it" do
254
- @client.query "USE test"
255
- @client.query "CREATE TABLE IF NOT EXISTS infoTest (`id` int(11) NOT NULL AUTO_INCREMENT, blah INT(11), PRIMARY KEY (`id`))"
256
-
257
- # http://dev.mysql.com/doc/refman/5.0/en/mysql-info.html says
258
- # # 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).
259
- @client.query("INSERT INTO infoTest (blah) VALUES (1234),(4535)")
260
-
261
- @client.query_info.should eql({:records => 2, :duplicates => 0, :warnings => 0})
262
- @client.query_info_string.should eq('Records: 2 Duplicates: 0 Warnings: 0')
263
-
264
- @client.query "DROP TABLE infoTest"
265
- end
266
- end
267
- end
268
-
269
- context ":local_infile" do
270
- before(:all) do
271
- @client_i = Mysql2::Client.new DatabaseCredentials['root'].merge(:local_infile => true)
272
- local = @client_i.query "SHOW VARIABLES LIKE 'local_infile'"
273
- local_enabled = local.any? {|x| x['Value'] == 'ON'}
274
- pending("DON'T WORRY, THIS TEST PASSES - but LOCAL INFILE is not enabled in your MySQL daemon.") unless local_enabled
275
-
276
- @client_i.query %[
277
- CREATE TABLE IF NOT EXISTS infileTest (
278
- id MEDIUMINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
279
- foo VARCHAR(10),
280
- bar MEDIUMTEXT
281
- )
282
- ]
283
- end
284
-
285
- after(:all) do
286
- @client_i.query "DROP TABLE infileTest"
287
- end
288
-
289
- it "should raise an error when local_infile is disabled" do
290
- client = Mysql2::Client.new DatabaseCredentials['root'].merge(:local_infile => false)
291
- lambda {
292
- client.query "LOAD DATA LOCAL INFILE 'spec/test_data' INTO TABLE infileTest"
293
- }.should raise_error(Mysql2::Error, %r{command is not allowed})
294
- end
295
-
296
- it "should raise an error when a non-existent file is loaded" do
297
- lambda {
298
- @client_i.query "LOAD DATA LOCAL INFILE 'this/file/is/not/here' INTO TABLE infileTest"
299
- }.should_not raise_error(Mysql2::Error, %r{file not found: this/file/is/not/here})
300
- end
301
-
302
- it "should LOAD DATA LOCAL INFILE" do
303
- @client_i.query "LOAD DATA LOCAL INFILE 'spec/test_data' INTO TABLE infileTest"
304
- info = @client_i.query_info
305
- info.should eql({:records => 1, :deleted => 0, :skipped => 0, :warnings => 0})
306
-
307
- result = @client_i.query "SELECT * FROM infileTest"
308
- result.first.should eql({'id' => 1, 'foo' => 'Hello', 'bar' => 'World'})
309
- end
310
- end
311
-
312
- it "should expect connect_timeout to be a positive integer" do
313
- lambda {
314
- Mysql2::Client.new(:connect_timeout => -1)
315
- }.should raise_error(Mysql2::Error)
316
- end
317
-
318
88
  it "should expect read_timeout to be a positive integer" do
319
89
  lambda {
320
90
  Mysql2::Client.new(:read_timeout => -1)
321
91
  }.should raise_error(Mysql2::Error)
322
92
  end
323
93
 
324
- it "should expect write_timeout to be a positive integer" do
325
- lambda {
326
- Mysql2::Client.new(:write_timeout => -1)
327
- }.should raise_error(Mysql2::Error)
328
- end
329
-
330
94
  context "#query" do
331
- it "should let you query again if iterating is finished when streaming" do
332
- @client.query("SELECT 1 UNION SELECT 2", :stream => true, :cache_rows => false).each.to_a
333
-
334
- expect {
335
- @client.query("SELECT 1 UNION SELECT 2", :stream => true, :cache_rows => false)
336
- }.to_not raise_exception(Mysql2::Error)
337
- end
338
-
339
- it "should not let you query again if iterating is not finished when streaming" do
340
- @client.query("SELECT 1 UNION SELECT 2", :stream => true, :cache_rows => false).first
341
-
342
- expect {
343
- @client.query("SELECT 1 UNION SELECT 2", :stream => true, :cache_rows => false)
344
- }.to raise_exception(Mysql2::Error)
345
- end
346
-
347
95
  it "should only accept strings as the query parameter" do
348
96
  lambda {
349
97
  @client.query ["SELECT 'not right'"]
350
98
  }.should raise_error(TypeError)
351
99
  end
352
100
 
353
- it "should not retain query options set on a query for subsequent queries, but should retain it in the result" do
354
- result = @client.query "SELECT 1", :something => :else
355
- @client.query_options[:something].should be_nil
356
- result.instance_variable_get('@query_options').should eql(@client.query_options.merge(:something => :else))
357
- @client.instance_variable_get('@current_query_options').should eql(@client.query_options.merge(:something => :else))
358
-
359
- result = @client.query "SELECT 1"
360
- result.instance_variable_get('@query_options').should eql(@client.query_options)
361
- @client.instance_variable_get('@current_query_options').should eql(@client.query_options)
362
- end
363
-
364
- it "should allow changing query options for subsequent queries" do
365
- @client.query_options.merge!(:something => :else)
366
- result = @client.query "SELECT 1"
367
- @client.query_options[:something].should eql(:else)
368
- result.instance_variable_get('@query_options')[:something].should eql(:else)
369
-
370
- # Clean up after this test
371
- @client.query_options.delete(:something)
372
- @client.query_options[:something].should be_nil
101
+ it "should accept an options hash that inherits from Mysql2::Client.default_query_options" do
102
+ @client.query "SELECT 1", :something => :else
103
+ @client.query_options.should eql(@client.query_options.merge(:something => :else))
373
104
  end
374
105
 
375
106
  it "should return results as a hash by default" do
@@ -385,6 +116,13 @@ describe Mysql2::Client do
385
116
  @client.query("SELECT 1", :symbolize_keys => true).first.keys[0].class.should eql(Symbol)
386
117
  end
387
118
 
119
+ it "should not allow another query to be sent without fetching a result first" do
120
+ @client.query("SELECT 1", :async => true)
121
+ lambda {
122
+ @client.query("SELECT 1")
123
+ }.should raise_error(Mysql2::Error)
124
+ end
125
+
388
126
  it "should require an open connection" do
389
127
  @client.close
390
128
  lambda {
@@ -392,241 +130,41 @@ describe Mysql2::Client do
392
130
  }.should raise_error(Mysql2::Error)
393
131
  end
394
132
 
395
- if RUBY_PLATFORM !~ /mingw|mswin/
396
- it "should not allow another query to be sent without fetching a result first" do
397
- @client.query("SELECT 1", :async => true)
398
- lambda {
399
- @client.query("SELECT 1")
400
- }.should raise_error(Mysql2::Error)
401
- end
402
-
403
- it "should describe the thread holding the active query" do
404
- thr = Thread.new { @client.query("SELECT 1", :async => true) }
405
-
406
- thr.join
407
- begin
408
- @client.query("SELECT 1")
409
- rescue Mysql2::Error => e
410
- message = e.message
411
- end
412
- re = Regexp.escape(thr.inspect)
413
- message.should match(Regexp.new(re))
414
- end
415
-
416
- it "should timeout if we wait longer than :read_timeout" do
417
- client = Mysql2::Client.new(DatabaseCredentials['root'].merge(:read_timeout => 1))
418
- lambda {
419
- client.query("SELECT sleep(2)")
420
- }.should raise_error(Mysql2::Error)
421
- end
422
-
423
- if !defined? Rubinius
424
- # XXX this test is not deterministic (because Unix signal handling is not)
425
- # and may fail on a loaded system
426
- it "should run signal handlers while waiting for a response" do
427
- mark = {}
428
- trap(:USR1) { mark[:USR1] = Time.now }
429
- begin
430
- mark[:START] = Time.now
431
- pid = fork do
432
- sleep 1 # wait for client "SELECT sleep(2)" query to start
433
- Process.kill(:USR1, Process.ppid)
434
- sleep # wait for explicit kill to prevent GC disconnect
435
- end
436
- @client.query("SELECT sleep(2)")
437
- mark[:END] = Time.now
438
- mark.include?(:USR1).should be_true
439
- (mark[:USR1] - mark[:START]).should >= 1
440
- (mark[:USR1] - mark[:START]).should < 1.3
441
- (mark[:END] - mark[:USR1]).should > 0.9
442
- (mark[:END] - mark[:START]).should >= 2
443
- (mark[:END] - mark[:START]).should < 2.3
444
- Process.kill(:TERM, pid)
445
- Process.waitpid2(pid)
446
- ensure
447
- trap(:USR1, 'DEFAULT')
448
- end
449
- end
450
- end
451
-
452
- it "#socket should return a Fixnum (file descriptor from C)" do
453
- @client.socket.class.should eql(Fixnum)
454
- @client.socket.should_not eql(0)
455
- end
456
-
457
- it "#socket should require an open connection" do
458
- @client.close
459
- lambda {
460
- @client.socket
461
- }.should raise_error(Mysql2::Error)
462
- end
463
-
464
- it "should close the connection when an exception is raised" do
465
- begin
466
- Timeout.timeout(1, Timeout::Error) do
467
- @client.query("SELECT sleep(2)")
468
- end
469
- rescue Timeout::Error
470
- end
471
-
472
- lambda {
473
- @client.query("SELECT 1")
474
- }.should raise_error(Mysql2::Error, 'closed MySQL connection')
475
- end
476
-
477
- it "should handle Timeouts without leaving the connection hanging if reconnect is true" do
478
- client = Mysql2::Client.new(DatabaseCredentials['root'].merge(:reconnect => true))
479
- begin
480
- Timeout.timeout(1, Timeout::Error) do
481
- client.query("SELECT sleep(2)")
482
- end
483
- rescue Timeout::Error
484
- end
485
-
486
- lambda {
487
- client.query("SELECT 1")
488
- }.should_not raise_error(Mysql2::Error)
489
- end
490
-
491
- it "should handle Timeouts without leaving the connection hanging if reconnect is set to true after construction true" do
492
- client = Mysql2::Client.new(DatabaseCredentials['root'])
493
- begin
494
- Timeout.timeout(1, Timeout::Error) do
495
- client.query("SELECT sleep(2)")
496
- end
497
- rescue Timeout::Error
498
- end
499
-
500
- lambda {
501
- client.query("SELECT 1")
502
- }.should raise_error(Mysql2::Error)
503
-
504
- client.reconnect = true
133
+ it "should timeout if we wait longer than :read_timeout" do
134
+ client = Mysql2::Client.new(:read_timeout => 1)
135
+ lambda {
136
+ client.query("SELECT sleep(2)")
137
+ }.should raise_error(Mysql2::Error)
138
+ end
505
139
 
140
+ # XXX this test is not deterministic (because Unix signal handling is not)
141
+ # and may fail on a loaded system
142
+ if RUBY_PLATFORM !~ /mingw|mswin/
143
+ it "should run signal handlers while waiting for a response" do
144
+ mark = {}
145
+ trap(:USR1) { mark[:USR1] = Time.now }
506
146
  begin
507
- Timeout.timeout(1, Timeout::Error) do
508
- client.query("SELECT sleep(2)")
509
- end
510
- rescue Timeout::Error
511
- end
512
-
513
- lambda {
514
- client.query("SELECT 1")
515
- }.should_not raise_error(Mysql2::Error)
516
-
517
- end
518
-
519
- it "threaded queries should be supported" do
520
- threads, results = [], {}
521
- lock = Mutex.new
522
- connect = lambda{
523
- Mysql2::Client.new(DatabaseCredentials['root'])
524
- }
525
- Timeout.timeout(0.7) do
526
- 5.times {
527
- threads << Thread.new do
528
- result = connect.call.query("SELECT sleep(0.5) as result")
529
- lock.synchronize do
530
- results[Thread.current.object_id] = result
531
- end
532
- end
533
- }
534
- end
535
- threads.each{|t| t.join }
536
- results.keys.sort.should eql(threads.map{|t| t.object_id }.sort)
537
- end
538
-
539
- it "evented async queries should be supported" do
540
- # should immediately return nil
541
- @client.query("SELECT sleep(0.1)", :async => true).should eql(nil)
542
-
543
- io_wrapper = IO.for_fd(@client.socket)
544
- loops = 0
545
- loop do
546
- if IO.select([io_wrapper], nil, nil, 0.05)
547
- break
548
- else
549
- loops += 1
147
+ mark[:START] = Time.now
148
+ pid = fork do
149
+ sleep 1 # wait for client "SELECT sleep(2)" query to start
150
+ Process.kill(:USR1, Process.ppid)
151
+ sleep # wait for explicit kill to prevent GC disconnect
550
152
  end
153
+ @client.query("SELECT sleep(2)")
154
+ mark[:END] = Time.now
155
+ mark.include?(:USR1).should be_true
156
+ (mark[:USR1] - mark[:START]).should >= 1
157
+ (mark[:USR1] - mark[:START]).should < 1.1
158
+ (mark[:END] - mark[:USR1]).should > 0.9
159
+ (mark[:END] - mark[:START]).should >= 2
160
+ (mark[:END] - mark[:START]).should < 2.1
161
+ Process.kill(:TERM, pid)
162
+ Process.waitpid2(pid)
163
+ ensure
164
+ trap(:USR1, 'DEFAULT')
551
165
  end
552
-
553
- # make sure we waited some period of time
554
- (loops >= 1).should be_true
555
-
556
- result = @client.async_result
557
- result.class.should eql(Mysql2::Result)
558
166
  end
559
167
  end
560
-
561
- context "Multiple results sets" do
562
- before(:each) do
563
- @multi_client = Mysql2::Client.new(DatabaseCredentials['root'].merge(:flags => Mysql2::Client::MULTI_STATEMENTS))
564
- end
565
-
566
- it "should raise an exception when one of multiple statements fails" do
567
- result = @multi_client.query("SELECT 1 as 'set_1'; SELECT * FROM invalid_table_name;SELECT 2 as 'set_2';")
568
- result.first['set_1'].should be(1)
569
- lambda {
570
- @multi_client.next_result
571
- }.should raise_error(Mysql2::Error)
572
- @multi_client.next_result.should be_false
573
- end
574
-
575
- it "returns multiple result sets" do
576
- @multi_client.query( "select 1 as 'set_1'; select 2 as 'set_2'").first.should eql({ 'set_1' => 1 })
577
-
578
- @multi_client.next_result.should be_true
579
- @multi_client.store_result.first.should eql({ 'set_2' => 2 })
580
-
581
- @multi_client.next_result.should be_false
582
- end
583
-
584
- it "does not interfere with other statements" do
585
- @multi_client.query( "select 1 as 'set_1'; select 2 as 'set_2'")
586
- while( @multi_client.next_result )
587
- @multi_client.store_result
588
- end
589
-
590
- @multi_client.query( "select 3 as 'next'").first.should == { 'next' => 3 }
591
- end
592
-
593
- it "will raise on query if there are outstanding results to read" do
594
- @multi_client.query("SELECT 1; SELECT 2; SELECT 3")
595
- lambda {
596
- @multi_client.query("SELECT 4")
597
- }.should raise_error(Mysql2::Error)
598
- end
599
-
600
- it "#abandon_results! should work" do
601
- @multi_client.query("SELECT 1; SELECT 2; SELECT 3")
602
- @multi_client.abandon_results!
603
- lambda {
604
- @multi_client.query("SELECT 4")
605
- }.should_not raise_error(Mysql2::Error)
606
- end
607
-
608
- it "#more_results? should work" do
609
- @multi_client.query( "select 1 as 'set_1'; select 2 as 'set_2'")
610
- @multi_client.more_results?.should be_true
611
-
612
- @multi_client.next_result
613
- @multi_client.store_result
614
-
615
- @multi_client.more_results?.should be_false
616
- end
617
- end
618
- end
619
-
620
- it "should respond to #socket" do
621
- @client.should respond_to(:socket)
622
- end
623
-
624
- if RUBY_PLATFORM =~ /mingw|mswin/
625
- it "#socket should raise as it's not supported" do
626
- lambda {
627
- @client.socket
628
- }.should raise_error(Mysql2::Error)
629
- end
630
168
  end
631
169
 
632
170
  it "should respond to escape" do
@@ -655,7 +193,7 @@ describe Mysql2::Client do
655
193
  }.should_not raise_error(SystemStackError)
656
194
  end
657
195
 
658
- unless RUBY_VERSION =~ /1.8/
196
+ if RUBY_VERSION =~ /1.9/
659
197
  it "should carry over the original string's encoding" do
660
198
  str = "abc'def\"ghi\0jkl%mno"
661
199
  escaped = Mysql2::Client.escape(str)
@@ -718,22 +256,18 @@ describe Mysql2::Client do
718
256
  if defined? Encoding
719
257
  context "strings returned by #info" do
720
258
  it "should default to the connection's encoding if Encoding.default_internal is nil" do
721
- with_internal_encoding nil do
722
- @client.info[:version].encoding.should eql(Encoding.find('utf-8'))
259
+ Encoding.default_internal = nil
260
+ @client.info[:version].encoding.should eql(Encoding.find('utf-8'))
723
261
 
724
- client2 = Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => 'ascii'))
725
- client2.info[:version].encoding.should eql(Encoding.find('us-ascii'))
726
- end
262
+ client2 = Mysql2::Client.new :encoding => 'ascii'
263
+ client2.info[:version].encoding.should eql(Encoding.find('us-ascii'))
727
264
  end
728
265
 
729
266
  it "should use Encoding.default_internal" do
730
- with_internal_encoding 'utf-8' do
731
- @client.info[:version].encoding.should eql(Encoding.default_internal)
732
- end
733
-
734
- with_internal_encoding 'us-ascii' do
735
- @client.info[:version].encoding.should eql(Encoding.default_internal)
736
- end
267
+ Encoding.default_internal = Encoding.find('utf-8')
268
+ @client.info[:version].encoding.should eql(Encoding.default_internal)
269
+ Encoding.default_internal = Encoding.find('us-ascii')
270
+ @client.info[:version].encoding.should eql(Encoding.default_internal)
737
271
  end
738
272
  end
739
273
  end
@@ -761,40 +295,87 @@ describe Mysql2::Client do
761
295
  if defined? Encoding
762
296
  context "strings returned by #server_info" do
763
297
  it "should default to the connection's encoding if Encoding.default_internal is nil" do
764
- with_internal_encoding nil do
765
- @client.server_info[:version].encoding.should eql(Encoding.find('utf-8'))
298
+ Encoding.default_internal = nil
299
+ @client.server_info[:version].encoding.should eql(Encoding.find('utf-8'))
766
300
 
767
- client2 = Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => 'ascii'))
768
- client2.server_info[:version].encoding.should eql(Encoding.find('us-ascii'))
769
- end
301
+ client2 = Mysql2::Client.new :encoding => 'ascii'
302
+ client2.server_info[:version].encoding.should eql(Encoding.find('us-ascii'))
770
303
  end
771
304
 
772
305
  it "should use Encoding.default_internal" do
773
- with_internal_encoding 'utf-8' do
774
- @client.server_info[:version].encoding.should eql(Encoding.default_internal)
775
- end
776
-
777
- with_internal_encoding 'us-ascii' do
778
- @client.server_info[:version].encoding.should eql(Encoding.default_internal)
779
- end
306
+ Encoding.default_internal = Encoding.find('utf-8')
307
+ @client.server_info[:version].encoding.should eql(Encoding.default_internal)
308
+ Encoding.default_internal = Encoding.find('us-ascii')
309
+ @client.server_info[:version].encoding.should eql(Encoding.default_internal)
780
310
  end
781
311
  end
782
312
  end
783
313
 
314
+ it "should respond to #socket" do
315
+ @client.should respond_to(:socket)
316
+ end
317
+
318
+ it "#socket should return a Fixnum (file descriptor from C)" do
319
+ @client.socket.class.should eql(Fixnum)
320
+ @client.socket.should_not eql(0)
321
+ end
322
+
323
+ it "#socket should require an open connection" do
324
+ @client.close
325
+ lambda {
326
+ @client.socket
327
+ }.should raise_error(Mysql2::Error)
328
+ end
329
+
784
330
  it "should raise a Mysql2::Error exception upon connection failure" do
785
331
  lambda {
786
- Mysql2::Client.new :host => "localhost", :username => 'asdfasdf8d2h', :password => 'asdfasdfw42'
332
+ bad_client = Mysql2::Client.new :host => "localhost", :username => 'asdfasdf8d2h', :password => 'asdfasdfw42'
787
333
  }.should raise_error(Mysql2::Error)
788
334
 
789
335
  lambda {
790
- Mysql2::Client.new DatabaseCredentials['root']
336
+ good_client = Mysql2::Client.new
791
337
  }.should_not raise_error(Mysql2::Error)
792
338
  end
793
339
 
340
+ it "threaded queries should be supported" do
341
+ threads, results = [], {}
342
+ connect = lambda{ Mysql2::Client.new(:host => "localhost", :username => "root") }
343
+ Timeout.timeout(0.7) do
344
+ 5.times {
345
+ threads << Thread.new do
346
+ results[Thread.current.object_id] = connect.call.query("SELECT sleep(0.5) as result")
347
+ end
348
+ }
349
+ end
350
+ threads.each{|t| t.join }
351
+ results.keys.sort.should eql(threads.map{|t| t.object_id }.sort)
352
+ end
353
+
354
+ it "evented async queries should be supported" do
355
+ # should immediately return nil
356
+ @client.query("SELECT sleep(0.1)", :async => true).should eql(nil)
357
+
358
+ io_wrapper = IO.for_fd(@client.socket)
359
+ loops = 0
360
+ loop do
361
+ if IO.select([io_wrapper], nil, nil, 0.05)
362
+ break
363
+ else
364
+ loops += 1
365
+ end
366
+ end
367
+
368
+ # make sure we waited some period of time
369
+ (loops >= 1).should be_true
370
+
371
+ result = @client.async_result
372
+ result.class.should eql(Mysql2::Result)
373
+ end
374
+
794
375
  context 'write operations api' do
795
376
  before(:each) do
796
377
  @client.query "USE test"
797
- @client.query "CREATE TABLE IF NOT EXISTS lastIdTest (`id` BIGINT NOT NULL AUTO_INCREMENT, blah INT(11), PRIMARY KEY (`id`))"
378
+ @client.query "CREATE TABLE lastIdTest (`id` int(11) NOT NULL AUTO_INCREMENT, blah INT(11), PRIMARY KEY (`id`))"
798
379
  end
799
380
 
800
381
  after(:each) do
@@ -821,15 +402,6 @@ describe Mysql2::Client do
821
402
  @client.query "UPDATE lastIdTest SET blah=4321 WHERE id=1"
822
403
  @client.affected_rows.should eql(1)
823
404
  end
824
-
825
- it "#last_id should handle BIGINT auto-increment ids above 32 bits" do
826
- # The id column type must be BIGINT. Surprise: INT(x) is limited to 32-bits for all values of x.
827
- # Insert a row with a given ID, this should raise the auto-increment state
828
- @client.query "INSERT INTO lastIdTest (id, blah) VALUES (5000000000, 5000)"
829
- @client.last_id.should eql(5000000000)
830
- @client.query "INSERT INTO lastIdTest (blah) VALUES (5001)"
831
- @client.last_id.should eql(5000000001)
832
- end
833
405
  end
834
406
 
835
407
  it "should respond to #thread_id" do
@@ -844,54 +416,15 @@ describe Mysql2::Client do
844
416
  @client.should respond_to(:ping)
845
417
  end
846
418
 
847
- context "select_db" do
848
- before(:each) do
849
- 2.times do |i|
850
- @client.query("CREATE DATABASE test_selectdb_#{i}")
851
- @client.query("USE test_selectdb_#{i}")
852
- @client.query("CREATE TABLE test#{i} (`id` int NOT NULL PRIMARY KEY)")
853
- end
854
- end
855
-
856
- after(:each) do
857
- 2.times do |i|
858
- @client.query("DROP DATABASE test_selectdb_#{i}")
859
- end
860
- end
861
-
862
- it "should respond to #select_db" do
863
- @client.should respond_to(:select_db)
864
- end
865
-
866
- it "should switch databases" do
867
- @client.select_db("test_selectdb_0")
868
- @client.query("SHOW TABLES").first.values.first.should eql("test0")
869
- @client.select_db("test_selectdb_1")
870
- @client.query("SHOW TABLES").first.values.first.should eql("test1")
871
- @client.select_db("test_selectdb_0")
872
- @client.query("SHOW TABLES").first.values.first.should eql("test0")
873
- end
874
-
875
- it "should raise a Mysql2::Error when the database doesn't exist" do
876
- lambda {
877
- @client.select_db("nopenothere")
878
- }.should raise_error(Mysql2::Error)
879
- end
880
-
881
- it "should return the database switched to" do
882
- @client.select_db("test_selectdb_1").should eq("test_selectdb_1")
883
- end
884
- end
885
-
886
419
  it "#thread_id should return a boolean" do
887
420
  @client.ping.should eql(true)
888
421
  @client.close
889
422
  @client.ping.should eql(false)
890
423
  end
891
424
 
892
- unless RUBY_VERSION =~ /1.8/
893
- it "should respond to #encoding" do
894
- @client.should respond_to(:encoding)
895
- end
425
+ if RUBY_VERSION =~ /1.9/
426
+ it "should respond to #encoding" do
427
+ @client.should respond_to(:encoding)
896
428
  end
897
429
  end
430
+ end