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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -0
- data/README.md +132 -55
- data/examples/eventmachine.rb +1 -1
- data/examples/threaded.rb +4 -6
- data/ext/mysql2/client.c +314 -118
- data/ext/mysql2/client.h +13 -3
- data/ext/mysql2/extconf.rb +111 -44
- data/ext/mysql2/infile.c +2 -2
- data/ext/mysql2/mysql2_ext.c +1 -0
- data/ext/mysql2/mysql2_ext.h +5 -10
- data/ext/mysql2/mysql_enc_name_to_ruby.h +2 -2
- data/ext/mysql2/mysql_enc_to_ruby.h +25 -22
- data/ext/mysql2/result.c +489 -101
- data/ext/mysql2/result.h +12 -4
- data/ext/mysql2/statement.c +595 -0
- data/ext/mysql2/statement.h +19 -0
- data/lib/mysql2/client.rb +70 -27
- data/lib/mysql2/console.rb +1 -1
- data/lib/mysql2/em.rb +5 -6
- data/lib/mysql2/error.rb +17 -26
- 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 +37 -35
- data/spec/configuration.yml.example +0 -6
- data/spec/em/em_spec.rb +22 -21
- data/spec/mysql2/client_spec.rb +484 -346
- data/spec/mysql2/error_spec.rb +38 -39
- data/spec/mysql2/result_spec.rb +256 -230
- data/spec/mysql2/statement_spec.rb +776 -0
- data/spec/spec_helper.rb +80 -59
- 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/support/5072E1F5.asc +432 -0
- data/support/mysql_enc_to_ruby.rb +7 -8
- data/support/ruby_enc_to_mysql.rb +1 -1
- metadata +50 -55
data/spec/mysql2/error_spec.rb
CHANGED
@@ -2,81 +2,80 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Mysql2::Error do
|
6
|
-
let(:
|
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.
|
22
|
-
error.
|
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.
|
26
|
-
error.
|
21
|
+
expect(error).to respond_to(:errno)
|
22
|
+
expect(error).to respond_to(:error)
|
27
23
|
end
|
28
24
|
|
29
|
-
|
30
|
-
let
|
31
|
-
|
25
|
+
context 'encoding' do
|
26
|
+
let(:valid_utf8) { '造字' }
|
27
|
+
let(:error) do
|
32
28
|
begin
|
33
|
-
client.query(
|
29
|
+
@client.query(valid_utf8)
|
34
30
|
rescue Mysql2::Error => e
|
35
|
-
|
36
|
-
ensure
|
37
|
-
client.close
|
31
|
+
e
|
38
32
|
end
|
39
|
-
|
40
|
-
error
|
41
33
|
end
|
42
34
|
|
43
|
-
let
|
44
|
-
|
35
|
+
let(:invalid_utf8) { ["e5c67d1f"].pack('H*').force_encoding(Encoding::UTF_8) }
|
36
|
+
let(:bad_err) do
|
45
37
|
begin
|
46
|
-
client.query(
|
38
|
+
@client.query(invalid_utf8)
|
47
39
|
rescue Mysql2::Error => e
|
48
|
-
|
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
|
-
|
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.
|
59
|
-
error.message.
|
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.
|
62
|
-
bad_err.message.
|
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.
|
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.
|
70
|
-
error.sql_state.
|
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
|
75
|
-
error.message.encoding.
|
76
|
-
error.message.
|
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.
|
79
|
-
bad_err.message.
|
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
|
data/spec/mysql2/result_spec.rb
CHANGED
@@ -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).
|
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.
|
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
|
-
|
30
|
+
expect {
|
27
31
|
@client.query "bad sql"
|
28
|
-
}.
|
32
|
+
}.to raise_error(Mysql2::Error)
|
29
33
|
|
30
|
-
|
34
|
+
expect {
|
31
35
|
@client.query "SELECT 1"
|
32
|
-
}.
|
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.
|
38
|
-
r.
|
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.
|
44
|
-
r.size.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
128
|
+
expect(result.count).to eql(0)
|
125
129
|
result.each.to_a
|
126
|
-
result.count.
|
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.
|
135
|
+
expect(result.count).to eql(0)
|
132
136
|
result.first
|
133
|
-
result.count.
|
137
|
+
expect(result.count).to eql(1)
|
134
138
|
result.each.to_a
|
135
|
-
result.count.
|
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.
|
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.
|
150
|
+
expect(result.count).to eql(0)
|
146
151
|
result.each.to_a
|
147
|
-
result.count.
|
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
|
-
|
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
|
-
|
165
|
-
res.each_with_index do |
|
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
|
-
}.
|
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"].
|
181
|
-
result["tiny_int_test"].
|
182
|
-
result["bool_cast_test"].
|
183
|
-
result["int_test"].
|
184
|
-
result["date_test"].
|
185
|
-
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")
|
186
189
|
end
|
187
190
|
|
188
191
|
it "should return nil for a NULL value" do
|
189
|
-
@test_result['null_test'].
|
190
|
-
@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)
|
191
194
|
end
|
192
195
|
|
193
196
|
it "should return String for a BIT(64) value" do
|
194
|
-
@test_result['bit_test'].
|
195
|
-
@test_result['bit_test'].
|
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'].
|
200
|
-
@test_result['single_bit_test'].
|
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].
|
205
|
-
@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)
|
206
209
|
end
|
207
210
|
|
208
|
-
|
209
|
-
|
210
|
-
id1
|
211
|
-
@client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (0)'
|
212
|
-
|
213
|
-
|
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
|
-
|
217
|
-
|
218
|
-
|
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
|
-
|
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
|
-
|
227
|
-
|
228
|
-
id1
|
229
|
-
@client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'
|
230
|
-
|
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
|
-
|
233
|
-
|
234
|
-
|
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
|
-
|
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].
|
242
|
-
@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)
|
243
253
|
end
|
244
254
|
|
245
255
|
it "should return Fixnum for a MEDIUMINT value" do
|
246
|
-
[Fixnum, Bignum].
|
247
|
-
@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)
|
248
258
|
end
|
249
259
|
|
250
260
|
it "should return Fixnum for an INT value" do
|
251
|
-
[Fixnum, Bignum].
|
252
|
-
@test_result['int_test'].
|
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].
|
257
|
-
@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)
|
258
268
|
end
|
259
269
|
|
260
270
|
it "should return Fixnum for a YEAR value" do
|
261
|
-
[Fixnum, Bignum].
|
262
|
-
@test_result['year_test'].
|
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'].
|
267
|
-
@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)
|
268
278
|
end
|
269
279
|
|
270
280
|
it "should return Float for a FLOAT value" do
|
271
|
-
@test_result['float_test'].
|
272
|
-
@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)
|
273
283
|
end
|
274
284
|
|
275
285
|
it "should return Float for a DOUBLE value" do
|
276
|
-
@test_result['double_test'].
|
277
|
-
@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)
|
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'].
|
282
|
-
@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
|
283
317
|
end
|
284
318
|
|
285
319
|
if 1.size == 4 # 32bit
|
286
|
-
|
287
|
-
|
320
|
+
klass = if RUBY_VERSION =~ /1.8/
|
321
|
+
DateTime
|
288
322
|
else
|
289
|
-
|
323
|
+
Time
|
290
324
|
end
|
291
325
|
|
292
326
|
it "should return DateTime when timestamp is < 1901-12-13 20:45:52" do
|
293
|
-
|
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'].
|
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
|
-
|
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'].
|
335
|
+
expect(r.first['test']).to be_an_instance_of(klass)
|
302
336
|
end
|
303
337
|
elsif 1.size == 8 # 64bit
|
304
|
-
|
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'].
|
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'].
|
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'].
|
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'].
|
334
|
-
@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')
|
335
369
|
end
|
336
370
|
|
337
371
|
it "should return Time for a TIME value" do
|
338
|
-
@test_result['time_test'].
|
339
|
-
@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')
|
340
374
|
end
|
341
375
|
|
342
376
|
it "should return Date for a DATE value" do
|
343
|
-
@test_result['date_test'].
|
344
|
-
@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')
|
345
379
|
end
|
346
380
|
|
347
381
|
it "should return String for an ENUM value" do
|
348
|
-
@test_result['enum_test'].
|
349
|
-
@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')
|
350
384
|
end
|
351
385
|
|
352
386
|
it "should raise an error given an invalid DATETIME" do
|
353
|
-
|
354
|
-
|
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
|
-
|
363
|
-
|
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
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
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
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
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
|
-
|
383
|
-
|
384
|
-
|
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'].
|
392
|
-
@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')
|
393
421
|
end
|
394
422
|
|
395
|
-
|
396
|
-
|
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
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
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
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
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
|
-
|
416
|
-
|
417
|
-
|
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'].
|
425
|
-
@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}")
|
426
453
|
end
|
427
454
|
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
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
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
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
|
-
|
444
|
-
|
445
|
-
|
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].
|
466
|
-
@test_result[field].
|
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
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
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
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
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
|
-
|
486
|
-
|
487
|
-
|
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
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
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
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
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
|
-
|
510
|
-
|
511
|
-
|
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
|