mysql2 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,712 +0,0 @@
1
- require './spec/spec_helper.rb'
2
-
3
- RSpec.describe Mysql2::Statement do
4
- before :each do
5
- @client = new_client(encoding: "utf8")
6
- end
7
-
8
- def stmt_count
9
- # Use the performance schema in MySQL 5.7 and above
10
- @client.query("SELECT COUNT(1) AS count FROM performance_schema.prepared_statements_instances").first['count'].to_i
11
- rescue Mysql2::Error
12
- # Fall back to the global prepapred statement counter
13
- @client.query("SHOW STATUS LIKE 'Prepared_stmt_count'").first['Value'].to_i
14
- end
15
-
16
- it "should create a statement" do
17
- statement = nil
18
- expect { statement = @client.prepare 'SELECT 1' }.to change(&method(:stmt_count)).by(1)
19
- expect(statement).to be_an_instance_of(Mysql2::Statement)
20
- end
21
-
22
- it "should raise an exception when server disconnects" do
23
- @client.close
24
- expect { @client.prepare 'SELECT 1' }.to raise_error(Mysql2::Error)
25
- end
26
-
27
- it "should tell us the param count" do
28
- statement = @client.prepare 'SELECT ?, ?'
29
- expect(statement.param_count).to eq(2)
30
-
31
- statement2 = @client.prepare 'SELECT 1'
32
- expect(statement2.param_count).to eq(0)
33
- end
34
-
35
- it "should tell us the field count" do
36
- statement = @client.prepare 'SELECT ?, ?'
37
- expect(statement.field_count).to eq(2)
38
-
39
- statement2 = @client.prepare 'SELECT 1'
40
- expect(statement2.field_count).to eq(1)
41
- end
42
-
43
- it "should let us execute our statement" do
44
- statement = @client.prepare 'SELECT 1'
45
- expect(statement.execute).not_to eq(nil)
46
- end
47
-
48
- it "should raise an exception without a block" do
49
- statement = @client.prepare 'SELECT 1'
50
- expect { statement.execute.each }.to raise_error(LocalJumpError)
51
- end
52
-
53
- it "should tell us the result count" do
54
- statement = @client.prepare 'SELECT 1'
55
- result = statement.execute
56
- expect(result.count).to eq(1)
57
- end
58
-
59
- it "should let us iterate over results" do
60
- statement = @client.prepare 'SELECT 1'
61
- result = statement.execute
62
- rows = []
63
- result.each { |r| rows << r }
64
- expect(rows).to eq([{ "1" => 1 }])
65
- end
66
-
67
- it "should handle booleans" do
68
- stmt = @client.prepare('SELECT ? AS `true`, ? AS `false`')
69
- result = stmt.execute(true, false)
70
- expect(result.to_a).to eq(['true' => 1, 'false' => 0])
71
- end
72
-
73
- it "should handle bignum but in int64_t" do
74
- stmt = @client.prepare('SELECT ? AS max, ? AS min')
75
- int64_max = (1 << 63) - 1
76
- int64_min = -(1 << 63)
77
- result = stmt.execute(int64_max, int64_min)
78
- expect(result.to_a).to eq(['max' => int64_max, 'min' => int64_min])
79
- end
80
-
81
- it "should handle bignum but beyond int64_t" do
82
- stmt = @client.prepare('SELECT ? AS max1, ? AS max2, ? AS max3, ? AS min1, ? AS min2, ? AS min3')
83
- int64_max1 = (1 << 63)
84
- int64_max2 = (1 << 64) - 1
85
- int64_max3 = 1 << 64
86
- int64_min1 = -(1 << 63) - 1
87
- int64_min2 = -(1 << 64) + 1
88
- int64_min3 = -0xC000000000000000
89
- result = stmt.execute(int64_max1, int64_max2, int64_max3, int64_min1, int64_min2, int64_min3)
90
- expect(result.to_a).to eq(['max1' => int64_max1, 'max2' => int64_max2, 'max3' => int64_max3, 'min1' => int64_min1, 'min2' => int64_min2, 'min3' => int64_min3])
91
- end
92
-
93
- it "should accept keyword arguments on statement execute" do
94
- stmt = @client.prepare 'SELECT 1 AS a'
95
-
96
- expect(stmt.execute(as: :hash).first).to eq("a" => 1)
97
- expect(stmt.execute(as: :array).first).to eq([1])
98
- end
99
-
100
- it "should accept bind arguments and keyword arguments on statement execute" do
101
- stmt = @client.prepare 'SELECT ? AS a'
102
-
103
- expect(stmt.execute(1, as: :hash).first).to eq("a" => 1)
104
- expect(stmt.execute(1, as: :array).first).to eq([1])
105
- end
106
-
107
- it "should keep its result after other query" do
108
- @client.query 'USE test'
109
- @client.query 'CREATE TABLE IF NOT EXISTS mysql2_stmt_q(a int)'
110
- @client.query 'INSERT INTO mysql2_stmt_q (a) VALUES (1), (2)'
111
- stmt = @client.prepare('SELECT a FROM mysql2_stmt_q WHERE a = ?')
112
- result1 = stmt.execute(1)
113
- result2 = stmt.execute(2)
114
- expect(result2.first).to eq("a" => 2)
115
- expect(result1.first).to eq("a" => 1)
116
- @client.query 'DROP TABLE IF EXISTS mysql2_stmt_q'
117
- end
118
-
119
- it "should be reusable 1000 times" do
120
- statement = @client.prepare 'SELECT 1'
121
- 1000.times do
122
- result = statement.execute
123
- expect(result.to_a.length).to eq(1)
124
- end
125
- end
126
-
127
- it "should be reusable 10000 times" do
128
- statement = @client.prepare 'SELECT 1'
129
- 10000.times do
130
- result = statement.execute
131
- expect(result.to_a.length).to eq(1)
132
- end
133
- end
134
-
135
- it "should handle comparisons and likes" do
136
- @client.query 'USE test'
137
- @client.query 'CREATE TABLE IF NOT EXISTS mysql2_stmt_q(a int, b varchar(10))'
138
- @client.query 'INSERT INTO mysql2_stmt_q (a, b) VALUES (1, "Hello"), (2, "World")'
139
- statement = @client.prepare 'SELECT * FROM mysql2_stmt_q WHERE a < ?'
140
- results = statement.execute(2)
141
- expect(results.first).to eq("a" => 1, "b" => "Hello")
142
-
143
- statement = @client.prepare 'SELECT * FROM mysql2_stmt_q WHERE b LIKE ?'
144
- results = statement.execute('%orld')
145
- expect(results.first).to eq("a" => 2, "b" => "World")
146
-
147
- @client.query 'DROP TABLE IF EXISTS mysql2_stmt_q'
148
- end
149
-
150
- it "should select dates" do
151
- statement = @client.prepare 'SELECT NOW()'
152
- result = statement.execute
153
- expect(result.first.first[1]).to be_an_instance_of(Time)
154
- end
155
-
156
- it "should prepare Date values" do
157
- now = Date.today
158
- statement = @client.prepare('SELECT ? AS a')
159
- result = statement.execute(now)
160
- expect(result.first['a'].to_s).to eql(now.strftime('%F'))
161
- end
162
-
163
- it "should prepare Time values with microseconds" do
164
- now = Time.now
165
- statement = @client.prepare('SELECT ? AS a')
166
- result = statement.execute(now)
167
- # microseconds is six digits after the decimal, but only test on 5 significant figures
168
- expect(result.first['a'].strftime('%F %T.%5N %z')).to eql(now.strftime('%F %T.%5N %z'))
169
- end
170
-
171
- it "should prepare DateTime values with microseconds" do
172
- now = DateTime.now
173
- statement = @client.prepare('SELECT ? AS a')
174
- result = statement.execute(now)
175
- # microseconds is six digits after the decimal, but only test on 5 significant figures
176
- expect(result.first['a'].strftime('%F %T.%5N %z')).to eql(now.strftime('%F %T.%5N %z'))
177
- end
178
-
179
- it "should tell us about the fields" do
180
- statement = @client.prepare 'SELECT 1 as foo, 2'
181
- statement.execute
182
- list = statement.fields
183
- expect(list.length).to eq(2)
184
- expect(list.first).to eq('foo')
185
- expect(list[1]).to eq('2')
186
- end
187
-
188
- it "should handle as a decimal binding a BigDecimal" do
189
- stmt = @client.prepare('SELECT ? AS decimal_test')
190
- test_result = stmt.execute(BigDecimal("123.45")).first
191
- expect(test_result['decimal_test']).to be_an_instance_of(BigDecimal)
192
- expect(test_result['decimal_test']).to eql(123.45)
193
- end
194
-
195
- it "should update a DECIMAL value passing a BigDecimal" do
196
- @client.query 'USE test'
197
- @client.query 'DROP TABLE IF EXISTS mysql2_stmt_decimal_test'
198
- @client.query 'CREATE TABLE mysql2_stmt_decimal_test (decimal_test DECIMAL(10,3))'
199
-
200
- @client.prepare("INSERT INTO mysql2_stmt_decimal_test VALUES (?)").execute(BigDecimal("123.45"))
201
-
202
- test_result = @client.query("SELECT * FROM mysql2_stmt_decimal_test").first
203
- expect(test_result['decimal_test']).to eql(123.45)
204
- end
205
-
206
- it "should warn but still work if cache_rows is set to false" do
207
- statement = @client.prepare 'SELECT 1'
208
- result = nil
209
- expect { result = statement.execute(cache_rows: false).to_a }.to output(/:cache_rows is forced for prepared statements/).to_stderr
210
- expect(result.length).to eq(1)
211
- end
212
-
213
- context "utf8_db" do
214
- before(:each) do
215
- @client.query("DROP DATABASE IF EXISTS test_mysql2_stmt_utf8")
216
- @client.query("CREATE DATABASE test_mysql2_stmt_utf8")
217
- @client.query("USE test_mysql2_stmt_utf8")
218
- @client.query("CREATE TABLE テーブル (整数 int, 文字列 varchar(32)) charset=utf8")
219
- @client.query("INSERT INTO テーブル (整数, 文字列) VALUES (1, 'イチ'), (2, '弐'), (3, 'さん')")
220
- end
221
-
222
- after(:each) do
223
- @client.query("DROP DATABASE test_mysql2_stmt_utf8")
224
- end
225
-
226
- it "should be able to retrieve utf8 field names correctly" do
227
- stmt = @client.prepare 'SELECT * FROM `テーブル`'
228
- expect(stmt.fields).to eq(%w[整数 文字列])
229
- result = stmt.execute
230
-
231
- expect(result.to_a).to eq([{ "整数" => 1, "文字列" => "イチ" }, { "整数" => 2, "文字列" => "弐" }, { "整数" => 3, "文字列" => "さん" }])
232
- end
233
-
234
- it "should be able to retrieve utf8 param query correctly" do
235
- stmt = @client.prepare 'SELECT 整数 FROM テーブル WHERE 文字列 = ?'
236
- expect(stmt.param_count).to eq(1)
237
-
238
- result = stmt.execute 'イチ'
239
-
240
- expect(result.to_a).to eq([{ "整数" => 1 }])
241
- end
242
-
243
- it "should be able to retrieve query with param in different encoding correctly" do
244
- stmt = @client.prepare 'SELECT 整数 FROM テーブル WHERE 文字列 = ?'
245
- expect(stmt.param_count).to eq(1)
246
-
247
- param = 'イチ'.encode("EUC-JP")
248
- result = stmt.execute param
249
-
250
- expect(result.to_a).to eq([{ "整数" => 1 }])
251
- end
252
- end
253
-
254
- context "streaming result" do
255
- it "should be able to stream query result" do
256
- n = 1
257
- stmt = @client.prepare("SELECT 1 UNION SELECT 2")
258
- stmt.execute(stream: true, cache_rows: false, as: :array).each do |r|
259
- case n
260
- when 1
261
- expect(r).to eq([1])
262
- when 2
263
- expect(r).to eq([2])
264
- else
265
- violated "returned more than two rows"
266
- end
267
- n += 1
268
- end
269
- end
270
- end
271
-
272
- context "#each" do
273
- # note: The current impl. of prepared statement requires results to be cached on #execute except for streaming queries
274
- # The drawback of this is that args of Result#each is ignored...
275
-
276
- it "should yield rows as hash's" do
277
- @result = @client.prepare("SELECT 1").execute
278
- @result.each do |row|
279
- expect(row).to be_an_instance_of(Hash)
280
- end
281
- end
282
-
283
- it "should yield rows as hash's with symbol keys if :symbolize_keys was set to true" do
284
- @result = @client.prepare("SELECT 1").execute(symbolize_keys: true)
285
- @result.each do |row|
286
- expect(row.keys.first).to be_an_instance_of(Symbol)
287
- end
288
- end
289
-
290
- it "should be able to return results as an array" do
291
- @result = @client.prepare("SELECT 1").execute(as: :array)
292
- @result.each do |row|
293
- expect(row).to be_an_instance_of(Array)
294
- end
295
- end
296
-
297
- it "should cache previously yielded results by default" do
298
- @result = @client.prepare("SELECT 1").execute
299
- expect(@result.first.object_id).to eql(@result.first.object_id)
300
- end
301
-
302
- it "should yield different value for #first if streaming" do
303
- result = @client.prepare("SELECT 1 UNION SELECT 2").execute(stream: true, cache_rows: true)
304
- expect(result.first).not_to eql(result.first)
305
- end
306
-
307
- it "should yield the same value for #first if streaming is disabled" do
308
- result = @client.prepare("SELECT 1 UNION SELECT 2").execute(stream: false)
309
- expect(result.first).to eql(result.first)
310
- end
311
-
312
- it "should throw an exception if we try to iterate twice when streaming is enabled" do
313
- result = @client.prepare("SELECT 1 UNION SELECT 2").execute(stream: true, cache_rows: false)
314
- expect do
315
- result.each {}
316
- result.each {}
317
- end.to raise_exception(Mysql2::Error)
318
- end
319
- end
320
-
321
- context "#fields" do
322
- it "method should exist" do
323
- stmt = @client.prepare("SELECT 1")
324
- expect(stmt).to respond_to(:fields)
325
- end
326
-
327
- it "should return an array of field names in proper order" do
328
- stmt = @client.prepare("SELECT 'a', 'b', 'c'")
329
- expect(stmt.fields).to eql(%w[a b c])
330
- end
331
-
332
- it "should return nil for statement with no result fields" do
333
- stmt = @client.prepare("INSERT INTO mysql2_test () VALUES ()")
334
- expect(stmt.fields).to eql(nil)
335
- end
336
- end
337
-
338
- context "row data type mapping" do
339
- let(:test_result) { @client.prepare("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").execute.first }
340
-
341
- it "should return nil for a NULL value" do
342
- expect(test_result['null_test']).to be_an_instance_of(NilClass)
343
- expect(test_result['null_test']).to eql(nil)
344
- end
345
-
346
- it "should return String for a BIT(64) value" do
347
- expect(test_result['bit_test']).to be_an_instance_of(String)
348
- expect(test_result['bit_test']).to eql("\000\000\000\000\000\000\000\005")
349
- end
350
-
351
- it "should return String for a BIT(1) value" do
352
- expect(test_result['single_bit_test']).to be_an_instance_of(String)
353
- expect(test_result['single_bit_test']).to eql("\001")
354
- end
355
-
356
- it "should return Fixnum for a TINYINT value" do
357
- expect(num_classes).to include(test_result['tiny_int_test'].class)
358
- expect(test_result['tiny_int_test']).to eql(1)
359
- end
360
-
361
- context "cast booleans for TINYINT if :cast_booleans is enabled" do
362
- # rubocop:disable Style/Semicolon
363
- let(:id1) { @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 1)'; @client.last_id }
364
- let(:id2) { @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 0)'; @client.last_id }
365
- let(:id3) { @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (-1)'; @client.last_id }
366
- # rubocop:enable Style/Semicolon
367
-
368
- after do
369
- @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})"
370
- end
371
-
372
- it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do
373
- query = @client.prepare 'SELECT bool_cast_test FROM mysql2_test WHERE id = ?'
374
- result1 = query.execute id1, cast_booleans: true
375
- result2 = query.execute id2, cast_booleans: true
376
- result3 = query.execute id3, cast_booleans: true
377
- expect(result1.first['bool_cast_test']).to be true
378
- expect(result2.first['bool_cast_test']).to be false
379
- expect(result3.first['bool_cast_test']).to be true
380
- end
381
- end
382
-
383
- context "cast booleans for BIT(1) if :cast_booleans is enabled" do
384
- # rubocop:disable Style/Semicolon
385
- let(:id1) { @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (1)'; @client.last_id }
386
- let(:id2) { @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'; @client.last_id }
387
- # rubocop:enable Style/Semicolon
388
-
389
- after do
390
- @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
391
- end
392
-
393
- it "should return TrueClass or FalseClass for a BIT(1) value if :cast_booleans is enabled" do
394
- query = @client.prepare 'SELECT single_bit_test FROM mysql2_test WHERE id = ?'
395
- result1 = query.execute id1, cast_booleans: true
396
- result2 = query.execute id2, cast_booleans: true
397
- expect(result1.first['single_bit_test']).to be true
398
- expect(result2.first['single_bit_test']).to be false
399
- end
400
- end
401
-
402
- it "should return Fixnum for a SMALLINT value" do
403
- expect(num_classes).to include(test_result['small_int_test'].class)
404
- expect(test_result['small_int_test']).to eql(10)
405
- end
406
-
407
- it "should return Fixnum for a MEDIUMINT value" do
408
- expect(num_classes).to include(test_result['medium_int_test'].class)
409
- expect(test_result['medium_int_test']).to eql(10)
410
- end
411
-
412
- it "should return Fixnum for an INT value" do
413
- expect(num_classes).to include(test_result['int_test'].class)
414
- expect(test_result['int_test']).to eql(10)
415
- end
416
-
417
- it "should return Fixnum for a BIGINT value" do
418
- expect(num_classes).to include(test_result['big_int_test'].class)
419
- expect(test_result['big_int_test']).to eql(10)
420
- end
421
-
422
- it "should return Fixnum for a YEAR value" do
423
- expect(num_classes).to include(test_result['year_test'].class)
424
- expect(test_result['year_test']).to eql(2009)
425
- end
426
-
427
- it "should return BigDecimal for a DECIMAL value" do
428
- expect(test_result['decimal_test']).to be_an_instance_of(BigDecimal)
429
- expect(test_result['decimal_test']).to eql(10.3)
430
- end
431
-
432
- it "should return Float for a FLOAT value" do
433
- expect(test_result['float_test']).to be_an_instance_of(Float)
434
- expect(test_result['float_test']).to be_within(1e-5).of(10.3)
435
- end
436
-
437
- it "should return Float for a DOUBLE value" do
438
- expect(test_result['double_test']).to be_an_instance_of(Float)
439
- expect(test_result['double_test']).to eql(10.3)
440
- end
441
-
442
- it "should return Time for a DATETIME value when within the supported range" do
443
- expect(test_result['date_time_test']).to be_an_instance_of(Time)
444
- expect(test_result['date_time_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2010-04-04 11:44:00')
445
- end
446
-
447
- it "should return Time when timestamp is < 1901-12-13 20:45:52" do
448
- r = @client.prepare("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test").execute
449
- expect(r.first['test']).to be_an_instance_of(Time)
450
- end
451
-
452
- it "should return Time when timestamp is > 2038-01-19T03:14:07" do
453
- r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
454
- expect(r.first['test']).to be_an_instance_of(Time)
455
- end
456
-
457
- it "should return Time for a TIMESTAMP value when within the supported range" do
458
- expect(test_result['timestamp_test']).to be_an_instance_of(Time)
459
- expect(test_result['timestamp_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2010-04-04 11:44:00')
460
- end
461
-
462
- it "should return Time for a TIME value" do
463
- expect(test_result['time_test']).to be_an_instance_of(Time)
464
- expect(test_result['time_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2000-01-01 11:44:00')
465
- end
466
-
467
- it "should return Date for a DATE value" do
468
- expect(test_result['date_test']).to be_an_instance_of(Date)
469
- expect(test_result['date_test'].strftime("%Y-%m-%d")).to eql('2010-04-04')
470
- end
471
-
472
- it "should return String for an ENUM value" do
473
- expect(test_result['enum_test']).to be_an_instance_of(String)
474
- expect(test_result['enum_test']).to eql('val1')
475
- end
476
-
477
- it "should raise an error given an invalid DATETIME" do
478
- expect { @client.query("SELECT CAST('1972-00-27 00:00:00' AS DATETIME) as bad_datetime").each }.to \
479
- raise_error(Mysql2::Error, "Invalid date in field 'bad_datetime': 1972-00-27 00:00:00")
480
- end
481
-
482
- context "string encoding for ENUM values" do
483
- it "should default to the connection's encoding if Encoding.default_internal is nil" do
484
- with_internal_encoding nil do
485
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
486
- expect(result['enum_test'].encoding).to eql(Encoding::UTF_8)
487
-
488
- client2 = new_client(encoding: 'ascii')
489
- result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
490
- expect(result['enum_test'].encoding).to eql(Encoding::US_ASCII)
491
- end
492
- end
493
-
494
- it "should use Encoding.default_internal" do
495
- with_internal_encoding Encoding::UTF_8 do
496
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
497
- expect(result['enum_test'].encoding).to eql(Encoding.default_internal)
498
- end
499
-
500
- with_internal_encoding Encoding::ASCII do
501
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
502
- expect(result['enum_test'].encoding).to eql(Encoding.default_internal)
503
- end
504
- end
505
- end
506
-
507
- it "should return String for a SET value" do
508
- expect(test_result['set_test']).to be_an_instance_of(String)
509
- expect(test_result['set_test']).to eql('val1,val2')
510
- end
511
-
512
- context "string encoding for SET values" do
513
- it "should default to the connection's encoding if Encoding.default_internal is nil" do
514
- with_internal_encoding nil do
515
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
516
- expect(result['set_test'].encoding).to eql(Encoding::UTF_8)
517
-
518
- client2 = new_client(encoding: 'ascii')
519
- result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
520
- expect(result['set_test'].encoding).to eql(Encoding::US_ASCII)
521
- end
522
- end
523
-
524
- it "should use Encoding.default_internal" do
525
- with_internal_encoding Encoding::UTF_8 do
526
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
527
- expect(result['set_test'].encoding).to eql(Encoding.default_internal)
528
- end
529
-
530
- with_internal_encoding Encoding::ASCII do
531
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
532
- expect(result['set_test'].encoding).to eql(Encoding.default_internal)
533
- end
534
- end
535
- end
536
-
537
- it "should return String for a BINARY value" do
538
- expect(test_result['binary_test']).to be_an_instance_of(String)
539
- expect(test_result['binary_test']).to eql("test#{"\000" * 6}")
540
- end
541
-
542
- context "string encoding for BINARY values" do
543
- it "should default to binary if Encoding.default_internal is nil" do
544
- with_internal_encoding nil do
545
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
546
- expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
547
- end
548
- end
549
-
550
- it "should not use Encoding.default_internal" do
551
- with_internal_encoding Encoding::UTF_8 do
552
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
553
- expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
554
- end
555
-
556
- with_internal_encoding Encoding::ASCII do
557
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
558
- expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
559
- end
560
- end
561
- end
562
-
563
- {
564
- 'char_test' => 'CHAR',
565
- 'varchar_test' => 'VARCHAR',
566
- 'varbinary_test' => 'VARBINARY',
567
- 'tiny_blob_test' => 'TINYBLOB',
568
- 'tiny_text_test' => 'TINYTEXT',
569
- 'blob_test' => 'BLOB',
570
- 'text_test' => 'TEXT',
571
- 'medium_blob_test' => 'MEDIUMBLOB',
572
- 'medium_text_test' => 'MEDIUMTEXT',
573
- 'long_blob_test' => 'LONGBLOB',
574
- 'long_text_test' => 'LONGTEXT',
575
- }.each do |field, type|
576
- it "should return a String for #{type}" do
577
- expect(test_result[field]).to be_an_instance_of(String)
578
- expect(test_result[field]).to eql("test")
579
- end
580
-
581
- context "string encoding for #{type} values" do
582
- if %w[VARBINARY TINYBLOB BLOB MEDIUMBLOB LONGBLOB].include?(type)
583
- it "should default to binary if Encoding.default_internal is nil" do
584
- with_internal_encoding nil do
585
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
586
- expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
587
- end
588
- end
589
-
590
- it "should not use Encoding.default_internal" do
591
- with_internal_encoding Encoding::UTF_8 do
592
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
593
- expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
594
- end
595
-
596
- with_internal_encoding Encoding::ASCII do
597
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
598
- expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
599
- end
600
- end
601
- else
602
- it "should default to utf-8 if Encoding.default_internal is nil" do
603
- with_internal_encoding nil do
604
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
605
- expect(result[field].encoding).to eql(Encoding::UTF_8)
606
-
607
- client2 = new_client(encoding: 'ascii')
608
- result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
609
- expect(result[field].encoding).to eql(Encoding::US_ASCII)
610
- end
611
- end
612
-
613
- it "should use Encoding.default_internal" do
614
- with_internal_encoding Encoding::UTF_8 do
615
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
616
- expect(result[field].encoding).to eql(Encoding.default_internal)
617
- end
618
-
619
- with_internal_encoding Encoding::ASCII do
620
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
621
- expect(result[field].encoding).to eql(Encoding.default_internal)
622
- end
623
- end
624
- end
625
- end
626
- end
627
- end
628
-
629
- context 'last_id' do
630
- before(:each) do
631
- @client.query 'USE test'
632
- @client.query 'CREATE TABLE IF NOT EXISTS lastIdTest (`id` BIGINT NOT NULL AUTO_INCREMENT, blah INT(11), PRIMARY KEY (`id`))'
633
- end
634
-
635
- after(:each) do
636
- @client.query 'DROP TABLE lastIdTest'
637
- end
638
-
639
- it 'should return last insert id' do
640
- stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
641
- expect(stmt.last_id).to eq 0
642
- stmt.execute 1
643
- expect(stmt.last_id).to eq 1
644
- end
645
-
646
- it 'should handle bigint ids' do
647
- stmt = @client.prepare 'INSERT INTO lastIdTest (id, blah) VALUES (?, ?)'
648
- stmt.execute 5000000000, 5000
649
- expect(stmt.last_id).to eql(5000000000)
650
-
651
- stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
652
- stmt.execute 5001
653
- expect(stmt.last_id).to eql(5000000001)
654
- end
655
- end
656
-
657
- context 'affected_rows' do
658
- before :each do
659
- @client.query 'USE test'
660
- @client.query 'CREATE TABLE IF NOT EXISTS lastIdTest (`id` BIGINT NOT NULL AUTO_INCREMENT, blah INT(11), PRIMARY KEY (`id`))'
661
- end
662
-
663
- after :each do
664
- @client.query 'DROP TABLE lastIdTest'
665
- end
666
-
667
- it 'should return number of rows affected by an insert' do
668
- stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
669
- stmt.execute 1
670
- expect(stmt.affected_rows).to eq 1
671
- end
672
-
673
- it 'should return number of rows affected by an update' do
674
- stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
675
- stmt.execute 1
676
- expect(stmt.affected_rows).to eq 1
677
- stmt.execute 2
678
- expect(stmt.affected_rows).to eq 1
679
-
680
- stmt = @client.prepare 'UPDATE lastIdTest SET blah=? WHERE blah=?'
681
- stmt.execute 0, 1
682
- expect(stmt.affected_rows).to eq 1
683
- end
684
-
685
- it 'should return number of rows affected by a delete' do
686
- stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
687
- stmt.execute 1
688
- expect(stmt.affected_rows).to eq 1
689
- stmt.execute 2
690
- expect(stmt.affected_rows).to eq 1
691
-
692
- stmt = @client.prepare 'DELETE FROM lastIdTest WHERE blah=?'
693
- stmt.execute 1
694
- expect(stmt.affected_rows).to eq 1
695
- end
696
- end
697
-
698
- context 'close' do
699
- it 'should free server resources' do
700
- stmt = @client.prepare 'SELECT 1'
701
- GC.disable
702
- expect { stmt.close }.to change(&method(:stmt_count)).by(-1)
703
- GC.enable
704
- end
705
-
706
- it 'should raise an error on subsequent execution' do
707
- stmt = @client.prepare 'SELECT 1'
708
- stmt.close
709
- expect { stmt.execute }.to raise_error(Mysql2::Error, /Invalid statement handle/)
710
- end
711
- end
712
- end