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