mysql2 0.5.0 → 0.5.5

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.
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