mysql2 0.5.0 → 0.5.5

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