mysql2 0.3.21 → 0.4.10

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -0
  3. data/README.md +132 -55
  4. data/examples/eventmachine.rb +1 -1
  5. data/examples/threaded.rb +4 -6
  6. data/ext/mysql2/client.c +314 -118
  7. data/ext/mysql2/client.h +13 -3
  8. data/ext/mysql2/extconf.rb +111 -44
  9. data/ext/mysql2/infile.c +2 -2
  10. data/ext/mysql2/mysql2_ext.c +1 -0
  11. data/ext/mysql2/mysql2_ext.h +5 -10
  12. data/ext/mysql2/mysql_enc_name_to_ruby.h +2 -2
  13. data/ext/mysql2/mysql_enc_to_ruby.h +25 -22
  14. data/ext/mysql2/result.c +489 -101
  15. data/ext/mysql2/result.h +12 -4
  16. data/ext/mysql2/statement.c +595 -0
  17. data/ext/mysql2/statement.h +19 -0
  18. data/lib/mysql2/client.rb +70 -27
  19. data/lib/mysql2/console.rb +1 -1
  20. data/lib/mysql2/em.rb +5 -6
  21. data/lib/mysql2/error.rb +17 -26
  22. data/lib/mysql2/field.rb +3 -0
  23. data/lib/mysql2/statement.rb +17 -0
  24. data/lib/mysql2/version.rb +1 -1
  25. data/lib/mysql2.rb +37 -35
  26. data/spec/configuration.yml.example +0 -6
  27. data/spec/em/em_spec.rb +22 -21
  28. data/spec/mysql2/client_spec.rb +484 -346
  29. data/spec/mysql2/error_spec.rb +38 -39
  30. data/spec/mysql2/result_spec.rb +256 -230
  31. data/spec/mysql2/statement_spec.rb +776 -0
  32. data/spec/spec_helper.rb +80 -59
  33. data/spec/ssl/ca-cert.pem +17 -0
  34. data/spec/ssl/ca-key.pem +27 -0
  35. data/spec/ssl/ca.cnf +22 -0
  36. data/spec/ssl/cert.cnf +22 -0
  37. data/spec/ssl/client-cert.pem +17 -0
  38. data/spec/ssl/client-key.pem +27 -0
  39. data/spec/ssl/client-req.pem +15 -0
  40. data/spec/ssl/gen_certs.sh +48 -0
  41. data/spec/ssl/pkcs8-client-key.pem +28 -0
  42. data/spec/ssl/pkcs8-server-key.pem +28 -0
  43. data/spec/ssl/server-cert.pem +17 -0
  44. data/spec/ssl/server-key.pem +27 -0
  45. data/spec/ssl/server-req.pem +15 -0
  46. data/support/5072E1F5.asc +432 -0
  47. data/support/mysql_enc_to_ruby.rb +7 -8
  48. data/support/ruby_enc_to_mysql.rb +1 -1
  49. metadata +50 -55
@@ -2,81 +2,80 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Mysql2::Error do
6
- let(:client) { Mysql2::Client.new(DatabaseCredentials['root']) }
7
-
8
- let :error do
5
+ RSpec.describe Mysql2::Error do
6
+ let(:error) do
9
7
  begin
10
- client.query("HAHAHA")
8
+ @client.query("HAHAHA")
11
9
  rescue Mysql2::Error => e
12
10
  error = e
13
- ensure
14
- client.close
15
11
  end
16
12
 
17
13
  error
18
14
  end
19
15
 
20
16
  it "responds to error_number and sql_state, with aliases" do
21
- error.should respond_to(:error_number)
22
- error.should respond_to(:sql_state)
17
+ expect(error).to respond_to(:error_number)
18
+ expect(error).to respond_to(:sql_state)
23
19
 
24
20
  # Mysql gem compatibility
25
- error.should respond_to(:errno)
26
- error.should respond_to(:error)
21
+ expect(error).to respond_to(:errno)
22
+ expect(error).to respond_to(:error)
27
23
  end
28
24
 
29
- if "".respond_to? :encoding
30
- let :error do
31
- client = Mysql2::Client.new(DatabaseCredentials['root'])
25
+ context 'encoding' do
26
+ let(:valid_utf8) { '造字' }
27
+ let(:error) do
32
28
  begin
33
- client.query("\xE9\x80\xA0\xE5\xAD\x97")
29
+ @client.query(valid_utf8)
34
30
  rescue Mysql2::Error => e
35
- error = e
36
- ensure
37
- client.close
31
+ e
38
32
  end
39
-
40
- error
41
33
  end
42
34
 
43
- let :bad_err do
44
- client = Mysql2::Client.new(DatabaseCredentials['root'])
35
+ let(:invalid_utf8) { ["e5c67d1f"].pack('H*').force_encoding(Encoding::UTF_8) }
36
+ let(:bad_err) do
45
37
  begin
46
- client.query("\xE5\xC6\x7D\x1F")
38
+ @client.query(invalid_utf8)
47
39
  rescue Mysql2::Error => e
48
- error = e
49
- ensure
50
- client.close
40
+ e
51
41
  end
42
+ end
43
+
44
+ before do
45
+ pending('String#encoding is not defined') unless String.public_method_defined?(:encoding)
46
+
47
+ # sanity check
48
+ expect(valid_utf8.encoding).to eql(Encoding::UTF_8)
49
+ expect(valid_utf8).to be_valid_encoding
52
50
 
53
- error
51
+ expect(invalid_utf8.encoding).to eql(Encoding::UTF_8)
52
+ expect(invalid_utf8).to_not be_valid_encoding
54
53
  end
55
54
 
56
55
  it "returns error messages as UTF-8 by default" do
57
56
  with_internal_encoding nil do
58
- error.message.encoding.should eql(Encoding::UTF_8)
59
- error.message.valid_encoding?
57
+ expect(error.message.encoding).to eql(Encoding::UTF_8)
58
+ expect(error.message).to be_valid_encoding
60
59
 
61
- bad_err.message.encoding.should eql(Encoding::UTF_8)
62
- bad_err.message.valid_encoding?
60
+ expect(bad_err.message.encoding).to eql(Encoding::UTF_8)
61
+ expect(bad_err.message).to be_valid_encoding
63
62
 
64
- bad_err.message.should include("??}\u001F")
63
+ expect(bad_err.message).to include("??}\u001F")
65
64
  end
66
65
  end
67
66
 
68
67
  it "returns sql state as ASCII" do
69
- error.sql_state.encoding.should eql(Encoding::US_ASCII)
70
- error.sql_state.valid_encoding?
68
+ expect(error.sql_state.encoding).to eql(Encoding::US_ASCII)
69
+ expect(error.sql_state).to be_valid_encoding
71
70
  end
72
71
 
73
72
  it "returns error messages and sql state in Encoding.default_internal if set" do
74
- with_internal_encoding 'UTF-16LE' do
75
- error.message.encoding.should eql(Encoding.default_internal)
76
- error.message.valid_encoding?
73
+ with_internal_encoding Encoding::UTF_16LE do
74
+ expect(error.message.encoding).to eql(Encoding.default_internal)
75
+ expect(error.message).to be_valid_encoding
77
76
 
78
- bad_err.message.encoding.should eql(Encoding.default_internal)
79
- bad_err.message.valid_encoding?
77
+ expect(bad_err.message.encoding).to eql(Encoding.default_internal)
78
+ expect(bad_err.message).to be_valid_encoding
80
79
  end
81
80
  end
82
81
  end
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
  require 'spec_helper'
3
3
 
4
- describe Mysql2::Result do
4
+ RSpec.describe Mysql2::Result do
5
5
  before(:each) do
6
6
  @result = @client.query "SELECT 1"
7
7
  end
@@ -15,33 +15,37 @@ describe Mysql2::Result do
15
15
  end
16
16
 
17
17
  it "should have included Enumerable" do
18
- Mysql2::Result.ancestors.include?(Enumerable).should be_true
18
+ expect(Mysql2::Result.ancestors.include?(Enumerable)).to be true
19
19
  end
20
20
 
21
21
  it "should respond to #each" do
22
- @result.should respond_to(:each)
22
+ expect(@result).to respond_to(:each)
23
+ end
24
+
25
+ it "should respond to #free" do
26
+ expect(@result).to respond_to(:free)
23
27
  end
24
28
 
25
29
  it "should raise a Mysql2::Error exception upon a bad query" do
26
- lambda {
30
+ expect {
27
31
  @client.query "bad sql"
28
- }.should raise_error(Mysql2::Error)
32
+ }.to raise_error(Mysql2::Error)
29
33
 
30
- lambda {
34
+ expect {
31
35
  @client.query "SELECT 1"
32
- }.should_not raise_error(Mysql2::Error)
36
+ }.not_to raise_error
33
37
  end
34
38
 
35
39
  it "should respond to #count, which is aliased as #size" do
36
40
  r = @client.query "SELECT 1"
37
- r.should respond_to :count
38
- r.should respond_to :size
41
+ expect(r).to respond_to :count
42
+ expect(r).to respond_to :size
39
43
  end
40
44
 
41
45
  it "should be able to return the number of rows in the result set" do
42
46
  r = @client.query "SELECT 1"
43
- r.count.should eql(1)
44
- r.size.should eql(1)
47
+ expect(r.count).to eql(1)
48
+ expect(r.size).to eql(1)
45
49
  end
46
50
 
47
51
  context "metadata queries" do
@@ -53,44 +57,44 @@ describe Mysql2::Result do
53
57
  context "#each" do
54
58
  it "should yield rows as hash's" do
55
59
  @result.each do |row|
56
- row.class.should eql(Hash)
60
+ expect(row).to be_an_instance_of(Hash)
57
61
  end
58
62
  end
59
63
 
60
64
  it "should yield rows as hash's with symbol keys if :symbolize_keys was set to true" do
61
65
  @result.each(:symbolize_keys => true) do |row|
62
- row.keys.first.class.should eql(Symbol)
66
+ expect(row.keys.first).to be_an_instance_of(Symbol)
63
67
  end
64
68
  end
65
69
 
66
70
  it "should be able to return results as an array" do
67
71
  @result.each(:as => :array) do |row|
68
- row.class.should eql(Array)
72
+ expect(row).to be_an_instance_of(Array)
69
73
  end
70
74
  end
71
75
 
72
76
  it "should cache previously yielded results by default" do
73
- @result.first.object_id.should eql(@result.first.object_id)
77
+ expect(@result.first.object_id).to eql(@result.first.object_id)
74
78
  end
75
79
 
76
80
  it "should not cache previously yielded results if cache_rows is disabled" do
77
81
  result = @client.query "SELECT 1", :cache_rows => false
78
- result.first.object_id.should_not eql(result.first.object_id)
82
+ expect(result.first.object_id).not_to eql(result.first.object_id)
79
83
  end
80
84
 
81
85
  it "should be able to iterate a second time even if cache_rows is disabled" do
82
86
  result = @client.query "SELECT 1 UNION SELECT 2", :cache_rows => false
83
- result.to_a.should eql(result.to_a)
87
+ expect(result.to_a).to eql(result.to_a)
84
88
  end
85
89
 
86
90
  it "should yield different value for #first if streaming" do
87
91
  result = @client.query "SELECT 1 UNION SELECT 2", :stream => true, :cache_rows => false
88
- result.first.should_not eql(result.first)
92
+ expect(result.first).not_to eql(result.first)
89
93
  end
90
94
 
91
95
  it "should yield the same value for #first if streaming is disabled" do
92
96
  result = @client.query "SELECT 1 UNION SELECT 2", :stream => false
93
- result.first.should eql(result.first)
97
+ expect(result.first).to eql(result.first)
94
98
  end
95
99
 
96
100
  it "should throw an exception if we try to iterate twice when streaming is enabled" do
@@ -109,64 +113,63 @@ describe Mysql2::Result do
109
113
  end
110
114
 
111
115
  it "method should exist" do
112
- @test_result.should respond_to(:fields)
116
+ expect(@test_result).to respond_to(:fields)
113
117
  end
114
118
 
115
119
  it "should return an array of field names in proper order" do
116
120
  result = @client.query "SELECT 'a', 'b', 'c'"
117
- result.fields.should eql(['a', 'b', 'c'])
121
+ expect(result.fields).to eql(%w(a b c))
118
122
  end
119
123
  end
120
124
 
121
125
  context "streaming" do
122
126
  it "should maintain a count while streaming" do
123
127
  result = @client.query('SELECT 1', :stream => true, :cache_rows => false)
124
- result.count.should eql(0)
128
+ expect(result.count).to eql(0)
125
129
  result.each.to_a
126
- result.count.should eql(1)
130
+ expect(result.count).to eql(1)
127
131
  end
128
132
 
129
133
  it "should retain the count when mixing first and each" do
130
134
  result = @client.query("SELECT 1 UNION SELECT 2", :stream => true, :cache_rows => false)
131
- result.count.should eql(0)
135
+ expect(result.count).to eql(0)
132
136
  result.first
133
- result.count.should eql(1)
137
+ expect(result.count).to eql(1)
134
138
  result.each.to_a
135
- result.count.should eql(2)
139
+ expect(result.count).to eql(2)
136
140
  end
137
141
 
138
142
  it "should not yield nil at the end of streaming" do
139
143
  result = @client.query('SELECT * FROM mysql2_test', :stream => true, :cache_rows => false)
140
- result.each { |r| r.should_not be_nil}
144
+ result.each { |r| expect(r).not_to be_nil }
141
145
  end
142
146
 
143
147
  it "#count should be zero for rows after streaming when there were no results" do
148
+ @client.query "USE test"
144
149
  result = @client.query("SELECT * FROM mysql2_test WHERE null_test IS NOT NULL", :stream => true, :cache_rows => false)
145
- result.count.should eql(0)
150
+ expect(result.count).to eql(0)
146
151
  result.each.to_a
147
- result.count.should eql(0)
152
+ expect(result.count).to eql(0)
148
153
  end
149
154
 
150
155
  it "should raise an exception if streaming ended due to a timeout" do
151
- # Create an extra client instance, since we're going to time it out
152
- client = Mysql2::Client.new DatabaseCredentials['root']
153
- client.query "CREATE TEMPORARY TABLE streamingTest (val BINARY(255)) ENGINE=MEMORY"
156
+ @client.query "CREATE TEMPORARY TABLE streamingTest (val BINARY(255)) ENGINE=MEMORY"
154
157
 
155
158
  # Insert enough records to force the result set into multiple reads
156
159
  # (the BINARY type is used simply because it forces full width results)
157
160
  10000.times do |i|
158
- client.query "INSERT INTO streamingTest (val) VALUES ('Foo #{i}')"
161
+ @client.query "INSERT INTO streamingTest (val) VALUES ('Foo #{i}')"
159
162
  end
160
163
 
161
- client.query "SET net_write_timeout = 1"
162
- res = client.query "SELECT * FROM streamingTest", :stream => true, :cache_rows => false
164
+ @client.query "SET net_write_timeout = 1"
165
+ res = @client.query "SELECT * FROM streamingTest", :stream => true, :cache_rows => false
163
166
 
164
- lambda {
165
- res.each_with_index do |row, i|
167
+ expect {
168
+ res.each_with_index do |_, i|
166
169
  # Exhaust the first result packet then trigger a timeout
167
170
  sleep 2 if i > 0 && i % 1000 == 0
168
171
  end
169
- }.should raise_error(Mysql2::Error, /Lost connection/)
172
+ }.to raise_error(Mysql2::Error, /Lost connection/)
170
173
  end
171
174
  end
172
175
 
@@ -177,273 +180,297 @@ describe Mysql2::Result do
177
180
 
178
181
  it "should return nil values for NULL and strings for everything else when :cast is false" do
179
182
  result = @client.query('SELECT null_test, tiny_int_test, bool_cast_test, int_test, date_test, enum_test FROM mysql2_test WHERE bool_cast_test = 1 LIMIT 1', :cast => false).first
180
- result["null_test"].should be_nil
181
- result["tiny_int_test"].should eql("1")
182
- result["bool_cast_test"].should eql("1")
183
- result["int_test"].should eql("10")
184
- result["date_test"].should eql("2010-04-04")
185
- result["enum_test"].should eql("val1")
183
+ expect(result["null_test"]).to be_nil
184
+ expect(result["tiny_int_test"]).to eql("1")
185
+ expect(result["bool_cast_test"]).to eql("1")
186
+ expect(result["int_test"]).to eql("10")
187
+ expect(result["date_test"]).to eql("2010-04-04")
188
+ expect(result["enum_test"]).to eql("val1")
186
189
  end
187
190
 
188
191
  it "should return nil for a NULL value" do
189
- @test_result['null_test'].class.should eql(NilClass)
190
- @test_result['null_test'].should eql(nil)
192
+ expect(@test_result['null_test']).to be_an_instance_of(NilClass)
193
+ expect(@test_result['null_test']).to eql(nil)
191
194
  end
192
195
 
193
196
  it "should return String for a BIT(64) value" do
194
- @test_result['bit_test'].class.should eql(String)
195
- @test_result['bit_test'].should eql("\000\000\000\000\000\000\000\005")
197
+ expect(@test_result['bit_test']).to be_an_instance_of(String)
198
+ expect(@test_result['bit_test']).to eql("\000\000\000\000\000\000\000\005")
196
199
  end
197
200
 
198
201
  it "should return String for a BIT(1) value" do
199
- @test_result['single_bit_test'].class.should eql(String)
200
- @test_result['single_bit_test'].should eql("\001")
202
+ expect(@test_result['single_bit_test']).to be_an_instance_of(String)
203
+ expect(@test_result['single_bit_test']).to eql("\001")
201
204
  end
202
205
 
203
206
  it "should return Fixnum for a TINYINT value" do
204
- [Fixnum, Bignum].should include(@test_result['tiny_int_test'].class)
205
- @test_result['tiny_int_test'].should eql(1)
207
+ expect([Fixnum, Bignum]).to include(@test_result['tiny_int_test'].class)
208
+ expect(@test_result['tiny_int_test']).to eql(1)
206
209
  end
207
210
 
208
- it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do
209
- @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (1)'
210
- id1 = @client.last_id
211
- @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (0)'
212
- id2 = @client.last_id
213
- @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (-1)'
214
- id3 = @client.last_id
211
+ context "cast booleans for TINYINT if :cast_booleans is enabled" do
212
+ # rubocop:disable Style/Semicolon
213
+ let(:id1) { @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 1)'; @client.last_id }
214
+ let(:id2) { @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 0)'; @client.last_id }
215
+ let(:id3) { @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (-1)'; @client.last_id }
216
+ # rubocop:enable Style/Semicolon
215
217
 
216
- result1 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = 1 LIMIT 1', :cast_booleans => true
217
- result2 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = 0 LIMIT 1', :cast_booleans => true
218
- result3 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = -1 LIMIT 1', :cast_booleans => true
219
- result1.first['bool_cast_test'].should be_true
220
- result2.first['bool_cast_test'].should be_false
221
- result3.first['bool_cast_test'].should be_true
218
+ after do
219
+ @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})"
220
+ end
222
221
 
223
- @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})"
222
+ it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do
223
+ result1 = @client.query "SELECT bool_cast_test FROM mysql2_test WHERE id = #{id1} LIMIT 1", :cast_booleans => true
224
+ result2 = @client.query "SELECT bool_cast_test FROM mysql2_test WHERE id = #{id2} LIMIT 1", :cast_booleans => true
225
+ result3 = @client.query "SELECT bool_cast_test FROM mysql2_test WHERE id = #{id3} LIMIT 1", :cast_booleans => true
226
+ expect(result1.first['bool_cast_test']).to be true
227
+ expect(result2.first['bool_cast_test']).to be false
228
+ expect(result3.first['bool_cast_test']).to be true
229
+ end
224
230
  end
225
231
 
226
- it "should return TrueClass or FalseClass for a BIT(1) value if :cast_booleans is enabled" do
227
- @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (1)'
228
- id1 = @client.last_id
229
- @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'
230
- id2 = @client.last_id
232
+ context "cast booleans for BIT(1) if :cast_booleans is enabled" do
233
+ # rubocop:disable Style/Semicolon
234
+ let(:id1) { @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (1)'; @client.last_id }
235
+ let(:id2) { @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'; @client.last_id }
236
+ # rubocop:enable Style/Semicolon
231
237
 
232
- result1 = @client.query "SELECT single_bit_test FROM mysql2_test WHERE id = #{id1}", :cast_booleans => true
233
- result2 = @client.query "SELECT single_bit_test FROM mysql2_test WHERE id = #{id2}", :cast_booleans => true
234
- result1.first['single_bit_test'].should be_true
235
- result2.first['single_bit_test'].should be_false
238
+ after do
239
+ @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
240
+ end
236
241
 
237
- @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
242
+ it "should return TrueClass or FalseClass for a BIT(1) value if :cast_booleans is enabled" do
243
+ result1 = @client.query "SELECT single_bit_test FROM mysql2_test WHERE id = #{id1}", :cast_booleans => true
244
+ result2 = @client.query "SELECT single_bit_test FROM mysql2_test WHERE id = #{id2}", :cast_booleans => true
245
+ expect(result1.first['single_bit_test']).to be true
246
+ expect(result2.first['single_bit_test']).to be false
247
+ end
238
248
  end
239
249
 
240
250
  it "should return Fixnum for a SMALLINT value" do
241
- [Fixnum, Bignum].should include(@test_result['small_int_test'].class)
242
- @test_result['small_int_test'].should eql(10)
251
+ expect([Fixnum, Bignum]).to include(@test_result['small_int_test'].class)
252
+ expect(@test_result['small_int_test']).to eql(10)
243
253
  end
244
254
 
245
255
  it "should return Fixnum for a MEDIUMINT value" do
246
- [Fixnum, Bignum].should include(@test_result['medium_int_test'].class)
247
- @test_result['medium_int_test'].should eql(10)
256
+ expect([Fixnum, Bignum]).to include(@test_result['medium_int_test'].class)
257
+ expect(@test_result['medium_int_test']).to eql(10)
248
258
  end
249
259
 
250
260
  it "should return Fixnum for an INT value" do
251
- [Fixnum, Bignum].should include(@test_result['int_test'].class)
252
- @test_result['int_test'].should eql(10)
261
+ expect([Fixnum, Bignum]).to include(@test_result['int_test'].class)
262
+ expect(@test_result['int_test']).to eql(10)
253
263
  end
254
264
 
255
265
  it "should return Fixnum for a BIGINT value" do
256
- [Fixnum, Bignum].should include(@test_result['big_int_test'].class)
257
- @test_result['big_int_test'].should eql(10)
266
+ expect([Fixnum, Bignum]).to include(@test_result['big_int_test'].class)
267
+ expect(@test_result['big_int_test']).to eql(10)
258
268
  end
259
269
 
260
270
  it "should return Fixnum for a YEAR value" do
261
- [Fixnum, Bignum].should include(@test_result['year_test'].class)
262
- @test_result['year_test'].should eql(2009)
271
+ expect([Fixnum, Bignum]).to include(@test_result['year_test'].class)
272
+ expect(@test_result['year_test']).to eql(2009)
263
273
  end
264
274
 
265
275
  it "should return BigDecimal for a DECIMAL value" do
266
- @test_result['decimal_test'].class.should eql(BigDecimal)
267
- @test_result['decimal_test'].should eql(10.3)
276
+ expect(@test_result['decimal_test']).to be_an_instance_of(BigDecimal)
277
+ expect(@test_result['decimal_test']).to eql(10.3)
268
278
  end
269
279
 
270
280
  it "should return Float for a FLOAT value" do
271
- @test_result['float_test'].class.should eql(Float)
272
- @test_result['float_test'].should eql(10.3)
281
+ expect(@test_result['float_test']).to be_an_instance_of(Float)
282
+ expect(@test_result['float_test']).to eql(10.3)
273
283
  end
274
284
 
275
285
  it "should return Float for a DOUBLE value" do
276
- @test_result['double_test'].class.should eql(Float)
277
- @test_result['double_test'].should eql(10.3)
286
+ expect(@test_result['double_test']).to be_an_instance_of(Float)
287
+ expect(@test_result['double_test']).to eql(10.3)
278
288
  end
279
289
 
280
290
  it "should return Time for a DATETIME value when within the supported range" do
281
- @test_result['date_time_test'].class.should eql(Time)
282
- @test_result['date_time_test'].strftime("%Y-%m-%d %H:%M:%S").should eql('2010-04-04 11:44:00')
291
+ expect(@test_result['date_time_test']).to be_an_instance_of(Time)
292
+ expect(@test_result['date_time_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2010-04-04 11:44:00')
293
+ end
294
+
295
+ it "should return Time values with microseconds" do
296
+ now = Time.now
297
+ if RUBY_VERSION =~ /1.8/ || @client.server_info[:id] / 100 < 506
298
+ result = @client.query("SELECT CAST('#{now.strftime('%F %T %z')}' AS DATETIME) AS a")
299
+ expect(result.first['a'].strftime('%F %T %z')).to eql(now.strftime('%F %T %z'))
300
+ else
301
+ result = @client.query("SELECT CAST('#{now.strftime('%F %T.%6N %z')}' AS DATETIME(6)) AS a")
302
+ # microseconds is 6 digits after the decimal, but only test on 5 significant figures
303
+ expect(result.first['a'].strftime('%F %T.%5N %z')).to eql(now.strftime('%F %T.%5N %z'))
304
+ end
305
+ end
306
+
307
+ it "should return DateTime values with microseconds" do
308
+ now = DateTime.now
309
+ if RUBY_VERSION =~ /1.8/ || @client.server_info[:id] / 100 < 506
310
+ result = @client.query("SELECT CAST('#{now.strftime('%F %T %z')}' AS DATETIME) AS a")
311
+ expect(result.first['a'].strftime('%F %T %z')).to eql(now.strftime('%F %T %z'))
312
+ else
313
+ result = @client.query("SELECT CAST('#{now.strftime('%F %T.%6N %z')}' AS DATETIME(6)) AS a")
314
+ # microseconds is 6 digits after the decimal, but only test on 5 significant figures
315
+ expect(result.first['a'].strftime('%F %T.%5N %z')).to eql(now.strftime('%F %T.%5N %z'))
316
+ end
283
317
  end
284
318
 
285
319
  if 1.size == 4 # 32bit
286
- unless RUBY_VERSION =~ /1.8/
287
- klass = Time
320
+ klass = if RUBY_VERSION =~ /1.8/
321
+ DateTime
288
322
  else
289
- klass = DateTime
323
+ Time
290
324
  end
291
325
 
292
326
  it "should return DateTime when timestamp is < 1901-12-13 20:45:52" do
293
- # 1901-12-13T20:45:52 is the min for 32bit Ruby 1.8
327
+ # 1901-12-13T20:45:52 is the min for 32bit Ruby 1.8
294
328
  r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
295
- r.first['test'].class.should eql(klass)
329
+ expect(r.first['test']).to be_an_instance_of(klass)
296
330
  end
297
331
 
298
332
  it "should return DateTime when timestamp is > 2038-01-19T03:14:07" do
299
- # 2038-01-19T03:14:07 is the max for 32bit Ruby 1.8
333
+ # 2038-01-19T03:14:07 is the max for 32bit Ruby 1.8
300
334
  r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
301
- r.first['test'].class.should eql(klass)
335
+ expect(r.first['test']).to be_an_instance_of(klass)
302
336
  end
303
337
  elsif 1.size == 8 # 64bit
304
- unless RUBY_VERSION =~ /1.8/
305
- it "should return Time when timestamp is < 1901-12-13 20:45:52" do
306
- r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
307
- r.first['test'].class.should eql(Time)
308
- end
309
-
310
- it "should return Time when timestamp is > 2038-01-19T03:14:07" do
311
- r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
312
- r.first['test'].class.should eql(Time)
313
- end
314
- else
338
+ if RUBY_VERSION =~ /1.8/
315
339
  it "should return Time when timestamp is > 0138-12-31 11:59:59" do
316
340
  r = @client.query("SELECT CAST('0139-1-1 00:00:00' AS DATETIME) as test")
317
- r.first['test'].class.should eql(Time)
341
+ expect(r.first['test']).to be_an_instance_of(Time)
318
342
  end
319
343
 
320
344
  it "should return DateTime when timestamp is < 0139-1-1T00:00:00" do
321
345
  r = @client.query("SELECT CAST('0138-12-31 11:59:59' AS DATETIME) as test")
322
- r.first['test'].class.should eql(DateTime)
346
+ expect(r.first['test']).to be_an_instance_of(DateTime)
323
347
  end
324
348
 
325
349
  it "should return Time when timestamp is > 2038-01-19T03:14:07" do
326
350
  r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
327
- r.first['test'].class.should eql(Time)
351
+ expect(r.first['test']).to be_an_instance_of(Time)
352
+ end
353
+ else
354
+ it "should return Time when timestamp is < 1901-12-13 20:45:52" do
355
+ r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
356
+ expect(r.first['test']).to be_an_instance_of(Time)
357
+ end
358
+
359
+ it "should return Time when timestamp is > 2038-01-19T03:14:07" do
360
+ r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
361
+ expect(r.first['test']).to be_an_instance_of(Time)
328
362
  end
329
363
  end
330
364
  end
331
365
 
332
366
  it "should return Time for a TIMESTAMP value when within the supported range" do
333
- @test_result['timestamp_test'].class.should eql(Time)
334
- @test_result['timestamp_test'].strftime("%Y-%m-%d %H:%M:%S").should eql('2010-04-04 11:44:00')
367
+ expect(@test_result['timestamp_test']).to be_an_instance_of(Time)
368
+ expect(@test_result['timestamp_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2010-04-04 11:44:00')
335
369
  end
336
370
 
337
371
  it "should return Time for a TIME value" do
338
- @test_result['time_test'].class.should eql(Time)
339
- @test_result['time_test'].strftime("%Y-%m-%d %H:%M:%S").should eql('2000-01-01 11:44:00')
372
+ expect(@test_result['time_test']).to be_an_instance_of(Time)
373
+ expect(@test_result['time_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2000-01-01 11:44:00')
340
374
  end
341
375
 
342
376
  it "should return Date for a DATE value" do
343
- @test_result['date_test'].class.should eql(Date)
344
- @test_result['date_test'].strftime("%Y-%m-%d").should eql('2010-04-04')
377
+ expect(@test_result['date_test']).to be_an_instance_of(Date)
378
+ expect(@test_result['date_test'].strftime("%Y-%m-%d")).to eql('2010-04-04')
345
379
  end
346
380
 
347
381
  it "should return String for an ENUM value" do
348
- @test_result['enum_test'].class.should eql(String)
349
- @test_result['enum_test'].should eql('val1')
382
+ expect(@test_result['enum_test']).to be_an_instance_of(String)
383
+ expect(@test_result['enum_test']).to eql('val1')
350
384
  end
351
385
 
352
386
  it "should raise an error given an invalid DATETIME" do
353
- begin
354
- @client.query("SELECT CAST('1972-00-27 00:00:00' AS DATETIME) as bad_datetime").each
355
- rescue Mysql2::Error => e
356
- error = e
357
- end
358
-
359
- error.message.should eql("Invalid date in field 'bad_datetime': 1972-00-27 00:00:00")
387
+ expect { @client.query("SELECT CAST('1972-00-27 00:00:00' AS DATETIME) as bad_datetime").each }.to \
388
+ raise_error(Mysql2::Error, "Invalid date in field 'bad_datetime': 1972-00-27 00:00:00")
360
389
  end
361
390
 
362
- if defined? Encoding
363
- context "string encoding for ENUM values" do
364
- it "should default to the connection's encoding if Encoding.default_internal is nil" do
365
- with_internal_encoding nil do
366
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
367
- result['enum_test'].encoding.should eql(Encoding.find('utf-8'))
391
+ context "string encoding for ENUM values" do
392
+ before { pending('Encoding is undefined') unless defined?(Encoding) }
368
393
 
369
- client2 = Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => 'ascii'))
370
- result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
371
- result['enum_test'].encoding.should eql(Encoding.find('us-ascii'))
372
- client2.close
373
- end
394
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
395
+ with_internal_encoding nil do
396
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
397
+ expect(result['enum_test'].encoding).to eql(Encoding::UTF_8)
398
+
399
+ client2 = new_client(:encoding => 'ascii')
400
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
401
+ expect(result['enum_test'].encoding).to eql(Encoding::ASCII)
374
402
  end
403
+ end
375
404
 
376
- it "should use Encoding.default_internal" do
377
- with_internal_encoding 'utf-8' do
378
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
379
- result['enum_test'].encoding.should eql(Encoding.default_internal)
380
- end
405
+ it "should use Encoding.default_internal" do
406
+ with_internal_encoding Encoding::UTF_8 do
407
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
408
+ expect(result['enum_test'].encoding).to eql(Encoding.default_internal)
409
+ end
381
410
 
382
- with_internal_encoding 'us-ascii' do
383
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
384
- result['enum_test'].encoding.should eql(Encoding.default_internal)
385
- end
411
+ with_internal_encoding Encoding::ASCII do
412
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
413
+ expect(result['enum_test'].encoding).to eql(Encoding.default_internal)
386
414
  end
387
415
  end
388
416
  end
389
417
 
390
418
  it "should return String for a SET value" do
391
- @test_result['set_test'].class.should eql(String)
392
- @test_result['set_test'].should eql('val1,val2')
419
+ expect(@test_result['set_test']).to be_an_instance_of(String)
420
+ expect(@test_result['set_test']).to eql('val1,val2')
393
421
  end
394
422
 
395
- if defined? Encoding
396
- context "string encoding for SET values" do
397
- it "should default to the connection's encoding if Encoding.default_internal is nil" do
398
- with_internal_encoding nil do
399
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
400
- result['set_test'].encoding.should eql(Encoding.find('utf-8'))
423
+ context "string encoding for SET values" do
424
+ before { pending('Encoding is undefined') unless defined?(Encoding) }
401
425
 
402
- client2 = Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => 'ascii'))
403
- result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
404
- result['set_test'].encoding.should eql(Encoding.find('us-ascii'))
405
- client2.close
406
- end
426
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
427
+ with_internal_encoding nil do
428
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
429
+ expect(result['set_test'].encoding).to eql(Encoding::UTF_8)
430
+
431
+ client2 = new_client(:encoding => 'ascii')
432
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
433
+ expect(result['set_test'].encoding).to eql(Encoding::ASCII)
407
434
  end
435
+ end
408
436
 
409
- it "should use Encoding.default_internal" do
410
- with_internal_encoding 'utf-8' do
411
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
412
- result['set_test'].encoding.should eql(Encoding.default_internal)
413
- end
437
+ it "should use Encoding.default_internal" do
438
+ with_internal_encoding Encoding::UTF_8 do
439
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
440
+ expect(result['set_test'].encoding).to eql(Encoding.default_internal)
441
+ end
414
442
 
415
- with_internal_encoding 'us-ascii' do
416
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
417
- result['set_test'].encoding.should eql(Encoding.default_internal)
418
- end
443
+ with_internal_encoding Encoding::ASCII do
444
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
445
+ expect(result['set_test'].encoding).to eql(Encoding.default_internal)
419
446
  end
420
447
  end
421
448
  end
422
449
 
423
450
  it "should return String for a BINARY value" do
424
- @test_result['binary_test'].class.should eql(String)
425
- @test_result['binary_test'].should eql("test#{"\000"*6}")
451
+ expect(@test_result['binary_test']).to be_an_instance_of(String)
452
+ expect(@test_result['binary_test']).to eql("test#{"\000" * 6}")
426
453
  end
427
454
 
428
- if defined? Encoding
429
- context "string encoding for BINARY values" do
430
- it "should default to binary if Encoding.default_internal is nil" do
431
- with_internal_encoding nil do
432
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
433
- result['binary_test'].encoding.should eql(Encoding.find('binary'))
434
- end
455
+ context "string encoding for BINARY values" do
456
+ before { pending('Encoding is undefined') unless defined?(Encoding) }
457
+
458
+ it "should default to binary if Encoding.default_internal is nil" do
459
+ with_internal_encoding nil do
460
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
461
+ expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
435
462
  end
463
+ end
436
464
 
437
- it "should not use Encoding.default_internal" do
438
- with_internal_encoding 'utf-8' do
439
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
440
- result['binary_test'].encoding.should eql(Encoding.find('binary'))
441
- end
465
+ it "should not use Encoding.default_internal" do
466
+ with_internal_encoding Encoding::UTF_8 do
467
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
468
+ expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
469
+ end
442
470
 
443
- with_internal_encoding 'us-ascii' do
444
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
445
- result['binary_test'].encoding.should eql(Encoding.find('binary'))
446
- end
471
+ with_internal_encoding Encoding::ASCII do
472
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
473
+ expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
447
474
  end
448
475
  end
449
476
  end
@@ -459,57 +486,56 @@ describe Mysql2::Result do
459
486
  'medium_blob_test' => 'MEDIUMBLOB',
460
487
  'medium_text_test' => 'MEDIUMTEXT',
461
488
  'long_blob_test' => 'LONGBLOB',
462
- 'long_text_test' => 'LONGTEXT'
489
+ 'long_text_test' => 'LONGTEXT',
463
490
  }.each do |field, type|
464
491
  it "should return a String for #{type}" do
465
- @test_result[field].class.should eql(String)
466
- @test_result[field].should eql("test")
492
+ expect(@test_result[field]).to be_an_instance_of(String)
493
+ expect(@test_result[field]).to eql("test")
467
494
  end
468
495
 
469
- if defined? Encoding
470
- context "string encoding for #{type} values" do
471
- if ['VARBINARY', 'TINYBLOB', 'BLOB', 'MEDIUMBLOB', 'LONGBLOB'].include?(type)
472
- it "should default to binary if Encoding.default_internal is nil" do
473
- with_internal_encoding nil do
474
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
475
- result['binary_test'].encoding.should eql(Encoding.find('binary'))
476
- end
496
+ context "string encoding for #{type} values" do
497
+ before { pending('Encoding is undefined') unless defined?(Encoding) }
498
+
499
+ if %w(VARBINARY TINYBLOB BLOB MEDIUMBLOB LONGBLOB).include?(type)
500
+ it "should default to binary if Encoding.default_internal is nil" do
501
+ with_internal_encoding nil do
502
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
503
+ expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
477
504
  end
505
+ end
478
506
 
479
- it "should not use Encoding.default_internal" do
480
- with_internal_encoding 'utf-8' do
481
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
482
- result['binary_test'].encoding.should eql(Encoding.find('binary'))
483
- end
507
+ it "should not use Encoding.default_internal" do
508
+ with_internal_encoding Encoding::UTF_8 do
509
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
510
+ expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
511
+ end
484
512
 
485
- with_internal_encoding 'us-ascii' do
486
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
487
- result['binary_test'].encoding.should eql(Encoding.find('binary'))
488
- end
513
+ with_internal_encoding Encoding::ASCII do
514
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
515
+ expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
489
516
  end
490
- else
491
- it "should default to utf-8 if Encoding.default_internal is nil" do
492
- with_internal_encoding nil do
493
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
494
- result[field].encoding.should eql(Encoding.find('utf-8'))
495
-
496
- client2 = Mysql2::Client.new(DatabaseCredentials['root'].merge(:encoding => 'ascii'))
497
- result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
498
- result[field].encoding.should eql(Encoding.find('us-ascii'))
499
- client2.close
500
- end
517
+ end
518
+ else
519
+ it "should default to utf-8 if Encoding.default_internal is nil" do
520
+ with_internal_encoding nil do
521
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
522
+ expect(result[field].encoding).to eql(Encoding::UTF_8)
523
+
524
+ client2 = new_client(:encoding => 'ascii')
525
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
526
+ expect(result[field].encoding).to eql(Encoding::ASCII)
501
527
  end
528
+ end
502
529
 
503
- it "should use Encoding.default_internal" do
504
- with_internal_encoding 'utf-8' do
505
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
506
- result[field].encoding.should eql(Encoding.default_internal)
507
- end
530
+ it "should use Encoding.default_internal" do
531
+ with_internal_encoding Encoding::UTF_8 do
532
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
533
+ expect(result[field].encoding).to eql(Encoding.default_internal)
534
+ end
508
535
 
509
- with_internal_encoding 'us-ascii' do
510
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
511
- result[field].encoding.should eql(Encoding.default_internal)
512
- end
536
+ with_internal_encoding Encoding::ASCII do
537
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
538
+ expect(result[field].encoding).to eql(Encoding.default_internal)
513
539
  end
514
540
  end
515
541
  end