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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1 -220
- data/LICENSE +21 -0
- data/README.md +370 -79
- data/examples/eventmachine.rb +1 -1
- data/examples/threaded.rb +4 -6
- data/ext/mysql2/client.c +1017 -305
- data/ext/mysql2/client.h +35 -11
- data/ext/mysql2/extconf.rb +222 -34
- data/ext/mysql2/infile.c +122 -0
- data/ext/mysql2/infile.h +1 -0
- data/ext/mysql2/mysql2_ext.c +1 -0
- data/ext/mysql2/mysql2_ext.h +12 -14
- data/ext/mysql2/mysql_enc_name_to_ruby.h +168 -0
- data/ext/mysql2/mysql_enc_to_ruby.h +249 -0
- data/ext/mysql2/result.c +664 -166
- data/ext/mysql2/result.h +16 -6
- data/ext/mysql2/statement.c +595 -0
- data/ext/mysql2/statement.h +19 -0
- data/lib/mysql2/client.rb +118 -211
- data/lib/mysql2/console.rb +5 -0
- data/lib/mysql2/em.rb +23 -5
- data/lib/mysql2/error.rb +62 -6
- data/lib/mysql2/field.rb +3 -0
- data/lib/mysql2/statement.rb +17 -0
- data/lib/mysql2/version.rb +1 -1
- data/lib/mysql2.rb +66 -3
- data/spec/configuration.yml.example +11 -0
- data/spec/em/em_spec.rb +96 -10
- data/spec/my.cnf.example +9 -0
- data/spec/mysql2/client_spec.rb +779 -205
- data/spec/mysql2/error_spec.rb +58 -45
- data/spec/mysql2/result_spec.rb +316 -159
- data/spec/mysql2/statement_spec.rb +776 -0
- data/spec/spec_helper.rb +97 -56
- data/spec/ssl/ca-cert.pem +17 -0
- data/spec/ssl/ca-key.pem +27 -0
- data/spec/ssl/ca.cnf +22 -0
- data/spec/ssl/cert.cnf +22 -0
- data/spec/ssl/client-cert.pem +17 -0
- data/spec/ssl/client-key.pem +27 -0
- data/spec/ssl/client-req.pem +15 -0
- data/spec/ssl/gen_certs.sh +48 -0
- data/spec/ssl/pkcs8-client-key.pem +28 -0
- data/spec/ssl/pkcs8-server-key.pem +28 -0
- data/spec/ssl/server-cert.pem +17 -0
- data/spec/ssl/server-key.pem +27 -0
- data/spec/ssl/server-req.pem +15 -0
- data/spec/test_data +1 -0
- data/support/5072E1F5.asc +432 -0
- data/support/libmysql.def +219 -0
- data/support/mysql_enc_to_ruby.rb +81 -0
- data/support/ruby_enc_to_mysql.rb +61 -0
- metadata +77 -196
- data/.gitignore +0 -12
- data/.rspec +0 -3
- data/.rvmrc +0 -1
- data/.travis.yml +0 -7
- data/Gemfile +0 -3
- data/MIT-LICENSE +0 -20
- data/Rakefile +0 -5
- data/benchmark/active_record.rb +0 -51
- data/benchmark/active_record_threaded.rb +0 -42
- data/benchmark/allocations.rb +0 -33
- data/benchmark/escape.rb +0 -36
- data/benchmark/query_with_mysql_casting.rb +0 -80
- data/benchmark/query_without_mysql_casting.rb +0 -56
- data/benchmark/sequel.rb +0 -37
- data/benchmark/setup_db.rb +0 -119
- data/benchmark/threaded.rb +0 -44
- data/mysql2.gemspec +0 -29
- data/tasks/benchmarks.rake +0 -20
- data/tasks/compile.rake +0 -71
- data/tasks/rspec.rake +0 -16
- data/tasks/vendor_mysql.rake +0 -40
data/spec/mysql2/result_spec.rb
CHANGED
@@ -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
|
-
@
|
6
|
+
@result = @client.query "SELECT 1"
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
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).
|
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.
|
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
|
-
|
30
|
+
expect {
|
23
31
|
@client.query "bad sql"
|
24
|
-
}.
|
32
|
+
}.to raise_error(Mysql2::Error)
|
25
33
|
|
26
|
-
|
34
|
+
expect {
|
27
35
|
@client.query "SELECT 1"
|
28
|
-
}.
|
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.
|
34
|
-
r.
|
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.
|
40
|
-
r.size.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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"].
|
103
|
-
result["tiny_int_test"].
|
104
|
-
result["bool_cast_test"].
|
105
|
-
result["int_test"].
|
106
|
-
result["date_test"].
|
107
|
-
result["enum_test"].
|
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'].
|
112
|
-
@test_result['null_test'].
|
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
|
116
|
-
@test_result['
|
117
|
-
@test_result['
|
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].
|
122
|
-
@test_result['tiny_int_test'].
|
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
|
-
|
126
|
-
|
127
|
-
id1
|
128
|
-
@client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (0)'
|
129
|
-
|
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
|
-
|
132
|
-
|
133
|
-
|
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
|
-
|
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].
|
141
|
-
@test_result['small_int_test'].
|
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].
|
146
|
-
@test_result['medium_int_test'].
|
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].
|
151
|
-
@test_result['int_test'].
|
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].
|
156
|
-
@test_result['big_int_test'].
|
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].
|
161
|
-
@test_result['year_test'].
|
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'].
|
166
|
-
@test_result['decimal_test'].
|
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'].
|
171
|
-
@test_result['float_test'].
|
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'].
|
176
|
-
@test_result['double_test'].
|
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'].
|
181
|
-
@test_result['date_time_test'].strftime("%Y-%m-%d %H:%M:%S").
|
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.
|
186
|
-
|
320
|
+
klass = if RUBY_VERSION =~ /1.8/
|
321
|
+
DateTime
|
187
322
|
else
|
188
|
-
|
323
|
+
Time
|
189
324
|
end
|
190
325
|
|
191
326
|
it "should return DateTime when timestamp is < 1901-12-13 20:45:52" do
|
192
|
-
|
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'].
|
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
|
-
|
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'].
|
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.
|
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'].
|
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'].
|
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'].
|
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'].
|
233
|
-
@test_result['timestamp_test'].strftime("%Y-%m-%d %H:%M:%S").
|
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'].
|
238
|
-
@test_result['time_test'].strftime("%Y-%m-%d %H:%M:%S").
|
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'].
|
243
|
-
@test_result['date_test'].strftime("%Y-%m-%d").
|
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'].
|
248
|
-
@test_result['enum_test'].
|
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
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
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.
|
397
|
+
expect(result['enum_test'].encoding).to eql(Encoding::UTF_8)
|
257
398
|
|
258
|
-
client2 =
|
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.
|
401
|
+
expect(result['enum_test'].encoding).to eql(Encoding::ASCII)
|
262
402
|
end
|
403
|
+
end
|
263
404
|
|
264
|
-
|
265
|
-
|
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.
|
268
|
-
|
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.
|
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'].
|
277
|
-
@test_result['set_test'].
|
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
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
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.
|
429
|
+
expect(result['set_test'].encoding).to eql(Encoding::UTF_8)
|
286
430
|
|
287
|
-
client2 =
|
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.
|
433
|
+
expect(result['set_test'].encoding).to eql(Encoding::ASCII)
|
291
434
|
end
|
435
|
+
end
|
292
436
|
|
293
|
-
|
294
|
-
|
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.
|
297
|
-
|
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.
|
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'].
|
306
|
-
@test_result['binary_test'].
|
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
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
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.
|
461
|
+
expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
|
315
462
|
end
|
463
|
+
end
|
316
464
|
|
317
|
-
|
318
|
-
|
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.
|
321
|
-
|
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.
|
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].
|
343
|
-
@test_result[field].
|
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
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
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.
|
503
|
+
expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
|
353
504
|
end
|
505
|
+
end
|
354
506
|
|
355
|
-
|
356
|
-
|
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.
|
359
|
-
|
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.
|
515
|
+
expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
|
362
516
|
end
|
363
|
-
|
364
|
-
|
365
|
-
|
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.
|
522
|
+
expect(result[field].encoding).to eql(Encoding::UTF_8)
|
368
523
|
|
369
|
-
client2 =
|
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.
|
526
|
+
expect(result[field].encoding).to eql(Encoding::ASCII)
|
373
527
|
end
|
528
|
+
end
|
374
529
|
|
375
|
-
|
376
|
-
|
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.
|
379
|
-
|
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.
|
538
|
+
expect(result[field].encoding).to eql(Encoding.default_internal)
|
382
539
|
end
|
383
540
|
end
|
384
541
|
end
|