mysql2 0.2.24 → 0.3.0

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