mysql2 0.4.3 → 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/README.md +76 -51
- data/ext/mysql2/client.c +165 -30
- data/ext/mysql2/client.h +1 -8
- data/ext/mysql2/extconf.rb +26 -2
- data/ext/mysql2/mysql2_ext.h +0 -4
- data/ext/mysql2/result.c +29 -18
- data/ext/mysql2/result.h +3 -2
- data/ext/mysql2/statement.c +106 -15
- data/lib/mysql2/client.rb +19 -6
- data/lib/mysql2/version.rb +1 -1
- data/spec/configuration.yml.example +0 -6
- data/spec/em/em_spec.rb +1 -0
- data/spec/mysql2/client_spec.rb +152 -104
- data/spec/mysql2/error_spec.rb +4 -6
- data/spec/mysql2/result_spec.rb +67 -36
- data/spec/mysql2/statement_spec.rb +133 -52
- data/spec/spec_helper.rb +73 -59
- data/spec/ssl/gen_certs.sh +1 -1
- data/support/5072E1F5.asc +432 -0
- metadata +12 -11
data/spec/mysql2/result_spec.rb
CHANGED
|
@@ -82,6 +82,11 @@ RSpec.describe Mysql2::Result do
|
|
|
82
82
|
expect(result.first.object_id).not_to eql(result.first.object_id)
|
|
83
83
|
end
|
|
84
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
|
+
|
|
85
90
|
it "should yield different value for #first if streaming" do
|
|
86
91
|
result = @client.query "SELECT 1 UNION SELECT 2", :stream => true, :cache_rows => false
|
|
87
92
|
expect(result.first).not_to eql(result.first)
|
|
@@ -148,18 +153,16 @@ RSpec.describe Mysql2::Result do
|
|
|
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
167
|
expect {
|
|
165
168
|
res.each_with_index do |_, i|
|
|
@@ -205,36 +208,43 @@ RSpec.describe Mysql2::Result do
|
|
|
205
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
|
-
expect(result1.first['bool_cast_test']).to be true
|
|
220
|
-
expect(result2.first['bool_cast_test']).to be false
|
|
221
|
-
expect(result3.first['bool_cast_test']).to 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
|
-
expect(result2.first['single_bit_test']).to 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
|
|
@@ -282,6 +292,30 @@ RSpec.describe Mysql2::Result do
|
|
|
282
292
|
expect(@test_result['date_time_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2010-04-04 11:44:00')
|
|
283
293
|
end
|
|
284
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
|
|
317
|
+
end
|
|
318
|
+
|
|
285
319
|
if 1.size == 4 # 32bit
|
|
286
320
|
klass = if RUBY_VERSION =~ /1.8/
|
|
287
321
|
DateTime
|
|
@@ -362,10 +396,9 @@ RSpec.describe Mysql2::Result do
|
|
|
362
396
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
363
397
|
expect(result['enum_test'].encoding).to eql(Encoding::UTF_8)
|
|
364
398
|
|
|
365
|
-
client2 =
|
|
399
|
+
client2 = new_client(:encoding => 'ascii')
|
|
366
400
|
result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
367
401
|
expect(result['enum_test'].encoding).to eql(Encoding::ASCII)
|
|
368
|
-
client2.close
|
|
369
402
|
end
|
|
370
403
|
end
|
|
371
404
|
|
|
@@ -395,10 +428,9 @@ RSpec.describe Mysql2::Result do
|
|
|
395
428
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
396
429
|
expect(result['set_test'].encoding).to eql(Encoding::UTF_8)
|
|
397
430
|
|
|
398
|
-
client2 =
|
|
431
|
+
client2 = new_client(:encoding => 'ascii')
|
|
399
432
|
result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
400
433
|
expect(result['set_test'].encoding).to eql(Encoding::ASCII)
|
|
401
|
-
client2.close
|
|
402
434
|
end
|
|
403
435
|
end
|
|
404
436
|
|
|
@@ -489,10 +521,9 @@ RSpec.describe Mysql2::Result do
|
|
|
489
521
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
490
522
|
expect(result[field].encoding).to eql(Encoding::UTF_8)
|
|
491
523
|
|
|
492
|
-
client2 =
|
|
524
|
+
client2 = new_client(:encoding => 'ascii')
|
|
493
525
|
result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
494
526
|
expect(result[field].encoding).to eql(Encoding::ASCII)
|
|
495
|
-
client2.close
|
|
496
527
|
end
|
|
497
528
|
end
|
|
498
529
|
|
|
@@ -3,14 +3,16 @@ require './spec/spec_helper.rb'
|
|
|
3
3
|
|
|
4
4
|
RSpec.describe Mysql2::Statement do
|
|
5
5
|
before :each do
|
|
6
|
-
@client =
|
|
6
|
+
@client = new_client(:encoding => "utf8")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def stmt_count
|
|
10
|
+
@client.query("SHOW STATUS LIKE 'Prepared_stmt_count'").first['Value'].to_i
|
|
7
11
|
end
|
|
8
12
|
|
|
9
13
|
it "should create a statement" do
|
|
10
14
|
statement = nil
|
|
11
|
-
expect { statement = @client.prepare 'SELECT 1' }.to change
|
|
12
|
-
@client.query("SHOW STATUS LIKE 'Prepared_stmt_count'").first['Value'].to_i
|
|
13
|
-
}.by(1)
|
|
15
|
+
expect { statement = @client.prepare 'SELECT 1' }.to change(&method(:stmt_count)).by(1)
|
|
14
16
|
expect(statement).to be_an_instance_of(Mysql2::Statement)
|
|
15
17
|
end
|
|
16
18
|
|
|
@@ -59,6 +61,32 @@ RSpec.describe Mysql2::Statement do
|
|
|
59
61
|
expect(rows).to eq([{ "1" => 1 }])
|
|
60
62
|
end
|
|
61
63
|
|
|
64
|
+
it "should handle booleans" do
|
|
65
|
+
stmt = @client.prepare('SELECT ? AS `true`, ? AS `false`')
|
|
66
|
+
result = stmt.execute(true, false)
|
|
67
|
+
expect(result.to_a).to eq(['true' => 1, 'false' => 0])
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should handle bignum but in int64_t" do
|
|
71
|
+
stmt = @client.prepare('SELECT ? AS max, ? AS min')
|
|
72
|
+
int64_max = (1 << 63) - 1
|
|
73
|
+
int64_min = -(1 << 63)
|
|
74
|
+
result = stmt.execute(int64_max, int64_min)
|
|
75
|
+
expect(result.to_a).to eq(['max' => int64_max, 'min' => int64_min])
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should handle bignum but beyond int64_t" do
|
|
79
|
+
stmt = @client.prepare('SELECT ? AS max1, ? AS max2, ? AS max3, ? AS min1, ? AS min2, ? AS min3')
|
|
80
|
+
int64_max1 = (1 << 63)
|
|
81
|
+
int64_max2 = (1 << 64) - 1
|
|
82
|
+
int64_max3 = 1 << 64
|
|
83
|
+
int64_min1 = -(1 << 63) - 1
|
|
84
|
+
int64_min2 = -(1 << 64) + 1
|
|
85
|
+
int64_min3 = -0xC000000000000000
|
|
86
|
+
result = stmt.execute(int64_max1, int64_max2, int64_max3, int64_min1, int64_min2, int64_min3)
|
|
87
|
+
expect(result.to_a).to eq(['max1' => int64_max1, 'max2' => int64_max2, 'max3' => int64_max3, 'min1' => int64_min1, 'min2' => int64_min2, 'min3' => int64_min3])
|
|
88
|
+
end
|
|
89
|
+
|
|
62
90
|
it "should keep its result after other query" do
|
|
63
91
|
@client.query 'USE test'
|
|
64
92
|
@client.query 'CREATE TABLE IF NOT EXISTS mysql2_stmt_q(a int)'
|
|
@@ -108,6 +136,37 @@ RSpec.describe Mysql2::Statement do
|
|
|
108
136
|
expect(result.first.first[1]).to be_an_instance_of(Time)
|
|
109
137
|
end
|
|
110
138
|
|
|
139
|
+
it "should prepare Date values" do
|
|
140
|
+
now = Date.today
|
|
141
|
+
statement = @client.prepare('SELECT ? AS a')
|
|
142
|
+
result = statement.execute(now)
|
|
143
|
+
expect(result.first['a'].to_s).to eql(now.strftime('%F'))
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "should prepare Time values with microseconds" do
|
|
147
|
+
now = Time.now
|
|
148
|
+
statement = @client.prepare('SELECT ? AS a')
|
|
149
|
+
result = statement.execute(now)
|
|
150
|
+
if RUBY_VERSION =~ /1.8/
|
|
151
|
+
expect(result.first['a'].strftime('%F %T %z')).to eql(now.strftime('%F %T %z'))
|
|
152
|
+
else
|
|
153
|
+
# microseconds is six digits after the decimal, but only test on 5 significant figures
|
|
154
|
+
expect(result.first['a'].strftime('%F %T.%5N %z')).to eql(now.strftime('%F %T.%5N %z'))
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "should prepare DateTime values with microseconds" do
|
|
159
|
+
now = DateTime.now
|
|
160
|
+
statement = @client.prepare('SELECT ? AS a')
|
|
161
|
+
result = statement.execute(now)
|
|
162
|
+
if RUBY_VERSION =~ /1.8/
|
|
163
|
+
expect(result.first['a'].strftime('%F %T %z')).to eql(now.strftime('%F %T %z'))
|
|
164
|
+
else
|
|
165
|
+
# microseconds is six digits after the decimal, but only test on 5 significant figures
|
|
166
|
+
expect(result.first['a'].strftime('%F %T.%5N %z')).to eql(now.strftime('%F %T.%5N %z'))
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
111
170
|
it "should tell us about the fields" do
|
|
112
171
|
statement = @client.prepare 'SELECT 1 as foo, 2'
|
|
113
172
|
statement.execute
|
|
@@ -117,6 +176,13 @@ RSpec.describe Mysql2::Statement do
|
|
|
117
176
|
expect(list[1]).to eq('2')
|
|
118
177
|
end
|
|
119
178
|
|
|
179
|
+
it "should handle as a decimal binding a BigDecimal" do
|
|
180
|
+
stmt = @client.prepare('SELECT ? AS decimal_test')
|
|
181
|
+
test_result = stmt.execute(BigDecimal.new("123.45")).first
|
|
182
|
+
expect(test_result['decimal_test']).to be_an_instance_of(BigDecimal)
|
|
183
|
+
expect(test_result['decimal_test']).to eql(123.45)
|
|
184
|
+
end
|
|
185
|
+
|
|
120
186
|
it "should update a DECIMAL value passing a BigDecimal" do
|
|
121
187
|
@client.query 'USE test'
|
|
122
188
|
@client.query 'DROP TABLE IF EXISTS mysql2_stmt_decimal_test'
|
|
@@ -128,6 +194,14 @@ RSpec.describe Mysql2::Statement do
|
|
|
128
194
|
expect(test_result['decimal_test']).to eql(123.45)
|
|
129
195
|
end
|
|
130
196
|
|
|
197
|
+
it "should warn but still work if cache_rows is set to false" do
|
|
198
|
+
@client.query_options.merge!(:cache_rows => false)
|
|
199
|
+
statement = @client.prepare 'SELECT 1'
|
|
200
|
+
result = nil
|
|
201
|
+
expect { result = statement.execute.to_a }.to output(/:cache_rows is forced for prepared statements/).to_stderr
|
|
202
|
+
expect(result.length).to eq(1)
|
|
203
|
+
end
|
|
204
|
+
|
|
131
205
|
context "utf8_db" do
|
|
132
206
|
before(:each) do
|
|
133
207
|
@client.query("DROP DATABASE IF EXISTS test_mysql2_stmt_utf8")
|
|
@@ -260,18 +334,19 @@ RSpec.describe Mysql2::Statement do
|
|
|
260
334
|
end
|
|
261
335
|
|
|
262
336
|
context "#fields" do
|
|
263
|
-
before(:each) do
|
|
264
|
-
@client.query "USE test"
|
|
265
|
-
@test_result = @client.prepare("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").execute
|
|
266
|
-
end
|
|
267
|
-
|
|
268
337
|
it "method should exist" do
|
|
269
|
-
|
|
338
|
+
stmt = @client.prepare("SELECT 1")
|
|
339
|
+
expect(stmt).to respond_to(:fields)
|
|
270
340
|
end
|
|
271
341
|
|
|
272
342
|
it "should return an array of field names in proper order" do
|
|
273
|
-
|
|
274
|
-
expect(
|
|
343
|
+
stmt = @client.prepare("SELECT 'a', 'b', 'c'")
|
|
344
|
+
expect(stmt.fields).to eql(%w(a b c))
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
it "should return nil for statement with no result fields" do
|
|
348
|
+
stmt = @client.prepare("INSERT INTO mysql2_test () VALUES ()")
|
|
349
|
+
expect(stmt.fields).to eql(nil)
|
|
275
350
|
end
|
|
276
351
|
end
|
|
277
352
|
|
|
@@ -301,36 +376,47 @@ RSpec.describe Mysql2::Statement do
|
|
|
301
376
|
expect(@test_result['tiny_int_test']).to eql(1)
|
|
302
377
|
end
|
|
303
378
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
id2
|
|
309
|
-
|
|
310
|
-
|
|
379
|
+
context "cast booleans for TINYINT if :cast_booleans is enabled" do
|
|
380
|
+
# rubocop:disable Style/Semicolon
|
|
381
|
+
let(:client) { new_client(:cast_booleans => true) }
|
|
382
|
+
let(:id1) { client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 1)'; client.last_id }
|
|
383
|
+
let(:id2) { client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 0)'; client.last_id }
|
|
384
|
+
let(:id3) { client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (-1)'; client.last_id }
|
|
385
|
+
# rubocop:enable Style/Semicolon
|
|
311
386
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
expect(result1.first['bool_cast_test']).to be true
|
|
316
|
-
expect(result2.first['bool_cast_test']).to be false
|
|
317
|
-
expect(result3.first['bool_cast_test']).to be true
|
|
387
|
+
after do
|
|
388
|
+
client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})"
|
|
389
|
+
end
|
|
318
390
|
|
|
319
|
-
|
|
391
|
+
it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do
|
|
392
|
+
query = client.prepare 'SELECT bool_cast_test FROM mysql2_test WHERE id = ?'
|
|
393
|
+
result1 = query.execute id1
|
|
394
|
+
result2 = query.execute id2
|
|
395
|
+
result3 = query.execute id3
|
|
396
|
+
expect(result1.first['bool_cast_test']).to be true
|
|
397
|
+
expect(result2.first['bool_cast_test']).to be false
|
|
398
|
+
expect(result3.first['bool_cast_test']).to be true
|
|
399
|
+
end
|
|
320
400
|
end
|
|
321
401
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
id2
|
|
402
|
+
context "cast booleans for BIT(1) if :cast_booleans is enabled" do
|
|
403
|
+
# rubocop:disable Style/Semicolon
|
|
404
|
+
let(:client) { new_client(:cast_booleans => true) }
|
|
405
|
+
let(:id1) { client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (1)'; client.last_id }
|
|
406
|
+
let(:id2) { client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'; client.last_id }
|
|
407
|
+
# rubocop:enable Style/Semicolon
|
|
327
408
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
expect(result2.first['single_bit_test']).to be false
|
|
409
|
+
after do
|
|
410
|
+
client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
|
|
411
|
+
end
|
|
332
412
|
|
|
333
|
-
|
|
413
|
+
it "should return TrueClass or FalseClass for a BIT(1) value if :cast_booleans is enabled" do
|
|
414
|
+
query = client.prepare 'SELECT single_bit_test FROM mysql2_test WHERE id = ?'
|
|
415
|
+
result1 = query.execute id1
|
|
416
|
+
result2 = query.execute id2
|
|
417
|
+
expect(result1.first['single_bit_test']).to be true
|
|
418
|
+
expect(result2.first['single_bit_test']).to be false
|
|
419
|
+
end
|
|
334
420
|
end
|
|
335
421
|
|
|
336
422
|
it "should return Fixnum for a SMALLINT value" do
|
|
@@ -387,39 +473,39 @@ RSpec.describe Mysql2::Statement do
|
|
|
387
473
|
|
|
388
474
|
it "should return DateTime when timestamp is < 1901-12-13 20:45:52" do
|
|
389
475
|
# 1901-12-13T20:45:52 is the min for 32bit Ruby 1.8
|
|
390
|
-
r = @client.
|
|
476
|
+
r = @client.prepare("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test").execute
|
|
391
477
|
expect(r.first['test']).to be_an_instance_of(klass)
|
|
392
478
|
end
|
|
393
479
|
|
|
394
480
|
it "should return DateTime when timestamp is > 2038-01-19T03:14:07" do
|
|
395
481
|
# 2038-01-19T03:14:07 is the max for 32bit Ruby 1.8
|
|
396
|
-
r = @client.
|
|
482
|
+
r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
|
|
397
483
|
expect(r.first['test']).to be_an_instance_of(klass)
|
|
398
484
|
end
|
|
399
485
|
elsif 1.size == 8 # 64bit
|
|
400
486
|
if RUBY_VERSION =~ /1.8/
|
|
401
487
|
it "should return Time when timestamp is > 0138-12-31 11:59:59" do
|
|
402
|
-
r = @client.
|
|
488
|
+
r = @client.prepare("SELECT CAST('0139-1-1 00:00:00' AS DATETIME) as test").execute
|
|
403
489
|
expect(r.first['test']).to be_an_instance_of(Time)
|
|
404
490
|
end
|
|
405
491
|
|
|
406
492
|
it "should return DateTime when timestamp is < 0139-1-1T00:00:00" do
|
|
407
|
-
r = @client.
|
|
493
|
+
r = @client.prepare("SELECT CAST('0138-12-31 11:59:59' AS DATETIME) as test").execute
|
|
408
494
|
expect(r.first['test']).to be_an_instance_of(DateTime)
|
|
409
495
|
end
|
|
410
496
|
|
|
411
497
|
it "should return Time when timestamp is > 2038-01-19T03:14:07" do
|
|
412
|
-
r = @client.
|
|
498
|
+
r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
|
|
413
499
|
expect(r.first['test']).to be_an_instance_of(Time)
|
|
414
500
|
end
|
|
415
501
|
else
|
|
416
502
|
it "should return Time when timestamp is < 1901-12-13 20:45:52" do
|
|
417
|
-
r = @client.
|
|
503
|
+
r = @client.prepare("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test").execute
|
|
418
504
|
expect(r.first['test']).to be_an_instance_of(Time)
|
|
419
505
|
end
|
|
420
506
|
|
|
421
507
|
it "should return Time when timestamp is > 2038-01-19T03:14:07" do
|
|
422
|
-
r = @client.
|
|
508
|
+
r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
|
|
423
509
|
expect(r.first['test']).to be_an_instance_of(Time)
|
|
424
510
|
end
|
|
425
511
|
end
|
|
@@ -458,10 +544,9 @@ RSpec.describe Mysql2::Statement do
|
|
|
458
544
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
459
545
|
expect(result['enum_test'].encoding).to eql(Encoding::UTF_8)
|
|
460
546
|
|
|
461
|
-
client2 =
|
|
547
|
+
client2 = new_client(:encoding => 'ascii')
|
|
462
548
|
result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
463
549
|
expect(result['enum_test'].encoding).to eql(Encoding::US_ASCII)
|
|
464
|
-
client2.close
|
|
465
550
|
end
|
|
466
551
|
end
|
|
467
552
|
|
|
@@ -491,10 +576,9 @@ RSpec.describe Mysql2::Statement do
|
|
|
491
576
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
492
577
|
expect(result['set_test'].encoding).to eql(Encoding::UTF_8)
|
|
493
578
|
|
|
494
|
-
client2 =
|
|
579
|
+
client2 = new_client(:encoding => 'ascii')
|
|
495
580
|
result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
496
581
|
expect(result['set_test'].encoding).to eql(Encoding::US_ASCII)
|
|
497
|
-
client2.close
|
|
498
582
|
end
|
|
499
583
|
end
|
|
500
584
|
|
|
@@ -585,10 +669,9 @@ RSpec.describe Mysql2::Statement do
|
|
|
585
669
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
586
670
|
expect(result[field].encoding).to eql(Encoding::UTF_8)
|
|
587
671
|
|
|
588
|
-
client2 =
|
|
672
|
+
client2 = new_client(:encoding => 'ascii')
|
|
589
673
|
result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
|
590
674
|
expect(result[field].encoding).to eql(Encoding::US_ASCII)
|
|
591
|
-
client2.close
|
|
592
675
|
end
|
|
593
676
|
end
|
|
594
677
|
|
|
@@ -681,9 +764,7 @@ RSpec.describe Mysql2::Statement do
|
|
|
681
764
|
context 'close' do
|
|
682
765
|
it 'should free server resources' do
|
|
683
766
|
stmt = @client.prepare 'SELECT 1'
|
|
684
|
-
expect { stmt.close }.to change
|
|
685
|
-
@client.query("SHOW STATUS LIKE 'Prepared_stmt_count'").first['Value'].to_i
|
|
686
|
-
}.by(-1)
|
|
767
|
+
expect { stmt.close }.to change(&method(:stmt_count)).by(-1)
|
|
687
768
|
end
|
|
688
769
|
|
|
689
770
|
it 'should raise an error on subsequent execution' do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -23,72 +23,86 @@ RSpec.configure do |config|
|
|
|
23
23
|
$VERBOSE = old_verbose
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
def new_client(option_overrides = {})
|
|
27
|
+
client = Mysql2::Client.new(DatabaseCredentials['root'].merge(option_overrides))
|
|
28
|
+
@clients ||= []
|
|
29
|
+
@clients << client
|
|
30
|
+
return client unless block_given?
|
|
31
|
+
begin
|
|
32
|
+
yield client
|
|
33
|
+
ensure
|
|
34
|
+
client.close
|
|
35
|
+
@clients.delete(client)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
26
39
|
config.before :each do
|
|
27
|
-
@client =
|
|
40
|
+
@client = new_client
|
|
28
41
|
end
|
|
29
42
|
|
|
30
43
|
config.after :each do
|
|
31
|
-
@
|
|
44
|
+
@clients.each(&:close)
|
|
32
45
|
end
|
|
33
46
|
|
|
34
47
|
config.before(:all) do
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
48
|
+
new_client do |client|
|
|
49
|
+
client.query %[
|
|
50
|
+
CREATE TABLE IF NOT EXISTS mysql2_test (
|
|
51
|
+
id MEDIUMINT NOT NULL AUTO_INCREMENT,
|
|
52
|
+
null_test VARCHAR(10),
|
|
53
|
+
bit_test BIT(64),
|
|
54
|
+
single_bit_test BIT(1),
|
|
55
|
+
tiny_int_test TINYINT,
|
|
56
|
+
bool_cast_test TINYINT(1),
|
|
57
|
+
small_int_test SMALLINT,
|
|
58
|
+
medium_int_test MEDIUMINT,
|
|
59
|
+
int_test INT,
|
|
60
|
+
big_int_test BIGINT,
|
|
61
|
+
float_test FLOAT(10,3),
|
|
62
|
+
float_zero_test FLOAT(10,3),
|
|
63
|
+
double_test DOUBLE(10,3),
|
|
64
|
+
decimal_test DECIMAL(10,3),
|
|
65
|
+
decimal_zero_test DECIMAL(10,3),
|
|
66
|
+
date_test DATE,
|
|
67
|
+
date_time_test DATETIME,
|
|
68
|
+
timestamp_test TIMESTAMP,
|
|
69
|
+
time_test TIME,
|
|
70
|
+
year_test YEAR(4),
|
|
71
|
+
char_test CHAR(10),
|
|
72
|
+
varchar_test VARCHAR(10),
|
|
73
|
+
binary_test BINARY(10),
|
|
74
|
+
varbinary_test VARBINARY(10),
|
|
75
|
+
tiny_blob_test TINYBLOB,
|
|
76
|
+
tiny_text_test TINYTEXT,
|
|
77
|
+
blob_test BLOB,
|
|
78
|
+
text_test TEXT,
|
|
79
|
+
medium_blob_test MEDIUMBLOB,
|
|
80
|
+
medium_text_test MEDIUMTEXT,
|
|
81
|
+
long_blob_test LONGBLOB,
|
|
82
|
+
long_text_test LONGTEXT,
|
|
83
|
+
enum_test ENUM('val1', 'val2'),
|
|
84
|
+
set_test SET('val1', 'val2'),
|
|
85
|
+
PRIMARY KEY (id)
|
|
86
|
+
)
|
|
87
|
+
]
|
|
88
|
+
client.query "DELETE FROM mysql2_test;"
|
|
89
|
+
client.query %[
|
|
90
|
+
INSERT INTO mysql2_test (
|
|
91
|
+
null_test, bit_test, single_bit_test, tiny_int_test, bool_cast_test, small_int_test, medium_int_test, int_test, big_int_test,
|
|
92
|
+
float_test, float_zero_test, double_test, decimal_test, decimal_zero_test, date_test, date_time_test, timestamp_test, time_test,
|
|
93
|
+
year_test, char_test, varchar_test, binary_test, varbinary_test, tiny_blob_test,
|
|
94
|
+
tiny_text_test, blob_test, text_test, medium_blob_test, medium_text_test,
|
|
95
|
+
long_blob_test, long_text_test, enum_test, set_test
|
|
96
|
+
)
|
|
84
97
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
98
|
+
VALUES (
|
|
99
|
+
NULL, b'101', b'1', 1, 1, 10, 10, 10, 10,
|
|
100
|
+
10.3, 0, 10.3, 10.3, 0, '2010-4-4', '2010-4-4 11:44:00', '2010-4-4 11:44:00', '11:44:00',
|
|
101
|
+
2009, "test", "test", "test", "test", "test",
|
|
102
|
+
"test", "test", "test", "test", "test",
|
|
103
|
+
"test", "test", 'val1', 'val1,val2'
|
|
104
|
+
)
|
|
105
|
+
]
|
|
106
|
+
end
|
|
93
107
|
end
|
|
94
108
|
end
|