mysql2 0.4.10 → 0.5.4

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 (51) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +98 -38
  3. data/ext/mysql2/client.c +223 -76
  4. data/ext/mysql2/client.h +1 -39
  5. data/ext/mysql2/extconf.rb +46 -26
  6. data/ext/mysql2/mysql2_ext.c +8 -2
  7. data/ext/mysql2/mysql2_ext.h +8 -4
  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 +242 -86
  11. data/ext/mysql2/result.h +3 -3
  12. data/ext/mysql2/statement.c +90 -73
  13. data/ext/mysql2/statement.h +0 -2
  14. data/ext/mysql2/wait_for_single_fd.h +2 -1
  15. data/lib/mysql2/client.rb +51 -28
  16. data/lib/mysql2/em.rb +2 -4
  17. data/lib/mysql2/error.rb +52 -22
  18. data/lib/mysql2/result.rb +2 -0
  19. data/lib/mysql2/statement.rb +3 -11
  20. data/lib/mysql2/version.rb +1 -1
  21. data/lib/mysql2.rb +18 -15
  22. data/support/3A79BD29.asc +49 -0
  23. data/support/5072E1F5.asc +5 -5
  24. data/support/mysql_enc_to_ruby.rb +8 -3
  25. data/support/ruby_enc_to_mysql.rb +7 -5
  26. metadata +14 -58
  27. data/examples/eventmachine.rb +0 -21
  28. data/examples/threaded.rb +0 -18
  29. data/spec/configuration.yml.example +0 -11
  30. data/spec/em/em_spec.rb +0 -136
  31. data/spec/my.cnf.example +0 -9
  32. data/spec/mysql2/client_spec.rb +0 -1039
  33. data/spec/mysql2/error_spec.rb +0 -82
  34. data/spec/mysql2/result_spec.rb +0 -545
  35. data/spec/mysql2/statement_spec.rb +0 -776
  36. data/spec/rcov.opts +0 -3
  37. data/spec/spec_helper.rb +0 -108
  38. data/spec/ssl/ca-cert.pem +0 -17
  39. data/spec/ssl/ca-key.pem +0 -27
  40. data/spec/ssl/ca.cnf +0 -22
  41. data/spec/ssl/cert.cnf +0 -22
  42. data/spec/ssl/client-cert.pem +0 -17
  43. data/spec/ssl/client-key.pem +0 -27
  44. data/spec/ssl/client-req.pem +0 -15
  45. data/spec/ssl/gen_certs.sh +0 -48
  46. data/spec/ssl/pkcs8-client-key.pem +0 -28
  47. data/spec/ssl/pkcs8-server-key.pem +0 -28
  48. data/spec/ssl/server-cert.pem +0 -17
  49. data/spec/ssl/server-key.pem +0 -27
  50. data/spec/ssl/server-req.pem +0 -15
  51. data/spec/test_data +0 -1
@@ -1,776 +0,0 @@
1
- # encoding: UTF-8
2
- require './spec/spec_helper.rb'
3
-
4
- RSpec.describe Mysql2::Statement do
5
- before :each do
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
11
- end
12
-
13
- it "should create a statement" do
14
- statement = nil
15
- expect { statement = @client.prepare 'SELECT 1' }.to change(&method(:stmt_count)).by(1)
16
- expect(statement).to be_an_instance_of(Mysql2::Statement)
17
- end
18
-
19
- it "should raise an exception when server disconnects" do
20
- @client.close
21
- expect { @client.prepare 'SELECT 1' }.to raise_error(Mysql2::Error)
22
- end
23
-
24
- it "should tell us the param count" do
25
- statement = @client.prepare 'SELECT ?, ?'
26
- expect(statement.param_count).to eq(2)
27
-
28
- statement2 = @client.prepare 'SELECT 1'
29
- expect(statement2.param_count).to eq(0)
30
- end
31
-
32
- it "should tell us the field count" do
33
- statement = @client.prepare 'SELECT ?, ?'
34
- expect(statement.field_count).to eq(2)
35
-
36
- statement2 = @client.prepare 'SELECT 1'
37
- expect(statement2.field_count).to eq(1)
38
- end
39
-
40
- it "should let us execute our statement" do
41
- statement = @client.prepare 'SELECT 1'
42
- expect(statement.execute).not_to eq(nil)
43
- end
44
-
45
- it "should raise an exception without a block" do
46
- statement = @client.prepare 'SELECT 1'
47
- expect { statement.execute.each }.to raise_error(LocalJumpError)
48
- end
49
-
50
- it "should tell us the result count" do
51
- statement = @client.prepare 'SELECT 1'
52
- result = statement.execute
53
- expect(result.count).to eq(1)
54
- end
55
-
56
- it "should let us iterate over results" do
57
- statement = @client.prepare 'SELECT 1'
58
- result = statement.execute
59
- rows = []
60
- result.each { |r| rows << r }
61
- expect(rows).to eq([{ "1" => 1 }])
62
- end
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
-
90
- it "should keep its result after other query" do
91
- @client.query 'USE test'
92
- @client.query 'CREATE TABLE IF NOT EXISTS mysql2_stmt_q(a int)'
93
- @client.query 'INSERT INTO mysql2_stmt_q (a) VALUES (1), (2)'
94
- stmt = @client.prepare('SELECT a FROM mysql2_stmt_q WHERE a = ?')
95
- result1 = stmt.execute(1)
96
- result2 = stmt.execute(2)
97
- expect(result2.first).to eq("a" => 2)
98
- expect(result1.first).to eq("a" => 1)
99
- @client.query 'DROP TABLE IF EXISTS mysql2_stmt_q'
100
- end
101
-
102
- it "should be reusable 1000 times" do
103
- statement = @client.prepare 'SELECT 1'
104
- 1000.times do
105
- result = statement.execute
106
- expect(result.to_a.length).to eq(1)
107
- end
108
- end
109
-
110
- it "should be reusable 10000 times" do
111
- statement = @client.prepare 'SELECT 1'
112
- 10000.times do
113
- result = statement.execute
114
- expect(result.to_a.length).to eq(1)
115
- end
116
- end
117
-
118
- it "should handle comparisons and likes" do
119
- @client.query 'USE test'
120
- @client.query 'CREATE TABLE IF NOT EXISTS mysql2_stmt_q(a int, b varchar(10))'
121
- @client.query 'INSERT INTO mysql2_stmt_q (a, b) VALUES (1, "Hello"), (2, "World")'
122
- statement = @client.prepare 'SELECT * FROM mysql2_stmt_q WHERE a < ?'
123
- results = statement.execute(2)
124
- expect(results.first).to eq("a" => 1, "b" => "Hello")
125
-
126
- statement = @client.prepare 'SELECT * FROM mysql2_stmt_q WHERE b LIKE ?'
127
- results = statement.execute('%orld')
128
- expect(results.first).to eq("a" => 2, "b" => "World")
129
-
130
- @client.query 'DROP TABLE IF EXISTS mysql2_stmt_q'
131
- end
132
-
133
- it "should select dates" do
134
- statement = @client.prepare 'SELECT NOW()'
135
- result = statement.execute
136
- expect(result.first.first[1]).to be_an_instance_of(Time)
137
- end
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
-
170
- it "should tell us about the fields" do
171
- statement = @client.prepare 'SELECT 1 as foo, 2'
172
- statement.execute
173
- list = statement.fields
174
- expect(list.length).to eq(2)
175
- expect(list.first).to eq('foo')
176
- expect(list[1]).to eq('2')
177
- end
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
-
186
- it "should update a DECIMAL value passing a BigDecimal" do
187
- @client.query 'USE test'
188
- @client.query 'DROP TABLE IF EXISTS mysql2_stmt_decimal_test'
189
- @client.query 'CREATE TABLE mysql2_stmt_decimal_test (decimal_test DECIMAL(10,3))'
190
-
191
- @client.prepare("INSERT INTO mysql2_stmt_decimal_test VALUES (?)").execute(BigDecimal.new("123.45"))
192
-
193
- test_result = @client.query("SELECT * FROM mysql2_stmt_decimal_test").first
194
- expect(test_result['decimal_test']).to eql(123.45)
195
- end
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
-
205
- context "utf8_db" do
206
- before(:each) do
207
- @client.query("DROP DATABASE IF EXISTS test_mysql2_stmt_utf8")
208
- @client.query("CREATE DATABASE test_mysql2_stmt_utf8")
209
- @client.query("USE test_mysql2_stmt_utf8")
210
- @client.query("CREATE TABLE テーブル (整数 int, 文字列 varchar(32)) charset=utf8")
211
- @client.query("INSERT INTO テーブル (整数, 文字列) VALUES (1, 'イチ'), (2, '弐'), (3, 'さん')")
212
- end
213
-
214
- after(:each) do
215
- @client.query("DROP DATABASE test_mysql2_stmt_utf8")
216
- end
217
-
218
- it "should be able to retrieve utf8 field names correctly" do
219
- stmt = @client.prepare 'SELECT * FROM `テーブル`'
220
- expect(stmt.fields).to eq(%w(整数 文字列))
221
- result = stmt.execute
222
-
223
- expect(result.to_a).to eq([{ "整数" => 1, "文字列" => "イチ" }, { "整数" => 2, "文字列" => "弐" }, { "整数" => 3, "文字列" => "さん" }])
224
- end
225
-
226
- it "should be able to retrieve utf8 param query correctly" do
227
- stmt = @client.prepare 'SELECT 整数 FROM テーブル WHERE 文字列 = ?'
228
- expect(stmt.param_count).to eq(1)
229
-
230
- result = stmt.execute 'イチ'
231
-
232
- expect(result.to_a).to eq([{ "整数" => 1 }])
233
- end
234
-
235
- it "should be able to retrieve query with param in different encoding correctly" do
236
- stmt = @client.prepare 'SELECT 整数 FROM テーブル WHERE 文字列 = ?'
237
- expect(stmt.param_count).to eq(1)
238
-
239
- param = 'イチ'.encode("EUC-JP")
240
- result = stmt.execute param
241
-
242
- expect(result.to_a).to eq([{ "整数" => 1 }])
243
- end
244
- end if defined? Encoding
245
-
246
- context "streaming result" do
247
- it "should be able to stream query result" do
248
- n = 1
249
- stmt = @client.prepare("SELECT 1 UNION SELECT 2")
250
-
251
- @client.query_options.merge!(:stream => true, :cache_rows => false, :as => :array)
252
-
253
- stmt.execute.each do |r|
254
- case n
255
- when 1
256
- expect(r).to eq([1])
257
- when 2
258
- expect(r).to eq([2])
259
- else
260
- violated "returned more than two rows"
261
- end
262
- n += 1
263
- end
264
- end
265
- end
266
-
267
- context "#each" do
268
- # note: The current impl. of prepared statement requires results to be cached on #execute except for streaming queries
269
- # The drawback of this is that args of Result#each is ignored...
270
-
271
- it "should yield rows as hash's" do
272
- @result = @client.prepare("SELECT 1").execute
273
- @result.each do |row|
274
- expect(row).to be_an_instance_of(Hash)
275
- end
276
- end
277
-
278
- it "should yield rows as hash's with symbol keys if :symbolize_keys was set to true" do
279
- @client.query_options[:symbolize_keys] = true
280
- @result = @client.prepare("SELECT 1").execute
281
- @result.each do |row|
282
- expect(row.keys.first).to be_an_instance_of(Symbol)
283
- end
284
- @client.query_options[:symbolize_keys] = false
285
- end
286
-
287
- it "should be able to return results as an array" do
288
- @client.query_options[:as] = :array
289
-
290
- @result = @client.prepare("SELECT 1").execute
291
- @result.each do |row|
292
- expect(row).to be_an_instance_of(Array)
293
- end
294
-
295
- @client.query_options[:as] = :hash
296
- end
297
-
298
- it "should cache previously yielded results by default" do
299
- @result = @client.prepare("SELECT 1").execute
300
- expect(@result.first.object_id).to eql(@result.first.object_id)
301
- end
302
-
303
- it "should yield different value for #first if streaming" do
304
- @client.query_options[:stream] = true
305
- @client.query_options[:cache_rows] = false
306
-
307
- result = @client.prepare("SELECT 1 UNION SELECT 2").execute
308
- expect(result.first).not_to eql(result.first)
309
-
310
- @client.query_options[:stream] = false
311
- @client.query_options[:cache_rows] = true
312
- end
313
-
314
- it "should yield the same value for #first if streaming is disabled" do
315
- @client.query_options[:stream] = false
316
- result = @client.prepare("SELECT 1 UNION SELECT 2").execute
317
- expect(result.first).to eql(result.first)
318
- end
319
-
320
- it "should throw an exception if we try to iterate twice when streaming is enabled" do
321
- @client.query_options[:stream] = true
322
- @client.query_options[:cache_rows] = false
323
-
324
- result = @client.prepare("SELECT 1 UNION SELECT 2").execute
325
-
326
- expect {
327
- result.each {}
328
- result.each {}
329
- }.to raise_exception(Mysql2::Error)
330
-
331
- @client.query_options[:stream] = false
332
- @client.query_options[:cache_rows] = true
333
- end
334
- end
335
-
336
- context "#fields" do
337
- it "method should exist" do
338
- stmt = @client.prepare("SELECT 1")
339
- expect(stmt).to respond_to(:fields)
340
- end
341
-
342
- it "should return an array of field names in proper order" do
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)
350
- end
351
- end
352
-
353
- context "row data type mapping" do
354
- before(:each) do
355
- @client.query "USE test"
356
- @test_result = @client.prepare("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").execute.first
357
- end
358
-
359
- it "should return nil for a NULL value" do
360
- expect(@test_result['null_test']).to be_an_instance_of(NilClass)
361
- expect(@test_result['null_test']).to eql(nil)
362
- end
363
-
364
- it "should return String for a BIT(64) value" do
365
- expect(@test_result['bit_test']).to be_an_instance_of(String)
366
- expect(@test_result['bit_test']).to eql("\000\000\000\000\000\000\000\005")
367
- end
368
-
369
- it "should return String for a BIT(1) value" do
370
- expect(@test_result['single_bit_test']).to be_an_instance_of(String)
371
- expect(@test_result['single_bit_test']).to eql("\001")
372
- end
373
-
374
- it "should return Fixnum for a TINYINT value" do
375
- expect([Fixnum, Bignum]).to include(@test_result['tiny_int_test'].class)
376
- expect(@test_result['tiny_int_test']).to eql(1)
377
- end
378
-
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
386
-
387
- after do
388
- client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})"
389
- end
390
-
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
400
- end
401
-
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
408
-
409
- after do
410
- client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
411
- end
412
-
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
420
- end
421
-
422
- it "should return Fixnum for a SMALLINT value" do
423
- expect([Fixnum, Bignum]).to include(@test_result['small_int_test'].class)
424
- expect(@test_result['small_int_test']).to eql(10)
425
- end
426
-
427
- it "should return Fixnum for a MEDIUMINT value" do
428
- expect([Fixnum, Bignum]).to include(@test_result['medium_int_test'].class)
429
- expect(@test_result['medium_int_test']).to eql(10)
430
- end
431
-
432
- it "should return Fixnum for an INT value" do
433
- expect([Fixnum, Bignum]).to include(@test_result['int_test'].class)
434
- expect(@test_result['int_test']).to eql(10)
435
- end
436
-
437
- it "should return Fixnum for a BIGINT value" do
438
- expect([Fixnum, Bignum]).to include(@test_result['big_int_test'].class)
439
- expect(@test_result['big_int_test']).to eql(10)
440
- end
441
-
442
- it "should return Fixnum for a YEAR value" do
443
- expect([Fixnum, Bignum]).to include(@test_result['year_test'].class)
444
- expect(@test_result['year_test']).to eql(2009)
445
- end
446
-
447
- it "should return BigDecimal for a DECIMAL value" do
448
- expect(@test_result['decimal_test']).to be_an_instance_of(BigDecimal)
449
- expect(@test_result['decimal_test']).to eql(10.3)
450
- end
451
-
452
- it "should return Float for a FLOAT value" do
453
- expect(@test_result['float_test']).to be_an_instance_of(Float)
454
- expect(@test_result['float_test']).to be_within(1e-5).of(10.3)
455
- end
456
-
457
- it "should return Float for a DOUBLE value" do
458
- expect(@test_result['double_test']).to be_an_instance_of(Float)
459
- expect(@test_result['double_test']).to eql(10.3)
460
- end
461
-
462
- it "should return Time for a DATETIME value when within the supported range" do
463
- expect(@test_result['date_time_test']).to be_an_instance_of(Time)
464
- expect(@test_result['date_time_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2010-04-04 11:44:00')
465
- end
466
-
467
- if 1.size == 4 # 32bit
468
- klass = if RUBY_VERSION =~ /1.8/
469
- DateTime
470
- else
471
- Time
472
- end
473
-
474
- it "should return DateTime when timestamp is < 1901-12-13 20:45:52" do
475
- # 1901-12-13T20:45:52 is the min for 32bit Ruby 1.8
476
- r = @client.prepare("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test").execute
477
- expect(r.first['test']).to be_an_instance_of(klass)
478
- end
479
-
480
- it "should return DateTime when timestamp is > 2038-01-19T03:14:07" do
481
- # 2038-01-19T03:14:07 is the max for 32bit Ruby 1.8
482
- r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
483
- expect(r.first['test']).to be_an_instance_of(klass)
484
- end
485
- elsif 1.size == 8 # 64bit
486
- if RUBY_VERSION =~ /1.8/
487
- it "should return Time when timestamp is > 0138-12-31 11:59:59" do
488
- r = @client.prepare("SELECT CAST('0139-1-1 00:00:00' AS DATETIME) as test").execute
489
- expect(r.first['test']).to be_an_instance_of(Time)
490
- end
491
-
492
- it "should return DateTime when timestamp is < 0139-1-1T00:00:00" do
493
- r = @client.prepare("SELECT CAST('0138-12-31 11:59:59' AS DATETIME) as test").execute
494
- expect(r.first['test']).to be_an_instance_of(DateTime)
495
- end
496
-
497
- it "should return Time when timestamp is > 2038-01-19T03:14:07" do
498
- r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
499
- expect(r.first['test']).to be_an_instance_of(Time)
500
- end
501
- else
502
- it "should return Time when timestamp is < 1901-12-13 20:45:52" do
503
- r = @client.prepare("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test").execute
504
- expect(r.first['test']).to be_an_instance_of(Time)
505
- end
506
-
507
- it "should return Time when timestamp is > 2038-01-19T03:14:07" do
508
- r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
509
- expect(r.first['test']).to be_an_instance_of(Time)
510
- end
511
- end
512
- end
513
-
514
- it "should return Time for a TIMESTAMP value when within the supported range" do
515
- expect(@test_result['timestamp_test']).to be_an_instance_of(Time)
516
- expect(@test_result['timestamp_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2010-04-04 11:44:00')
517
- end
518
-
519
- it "should return Time for a TIME value" do
520
- expect(@test_result['time_test']).to be_an_instance_of(Time)
521
- expect(@test_result['time_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2000-01-01 11:44:00')
522
- end
523
-
524
- it "should return Date for a DATE value" do
525
- expect(@test_result['date_test']).to be_an_instance_of(Date)
526
- expect(@test_result['date_test'].strftime("%Y-%m-%d")).to eql('2010-04-04')
527
- end
528
-
529
- it "should return String for an ENUM value" do
530
- expect(@test_result['enum_test']).to be_an_instance_of(String)
531
- expect(@test_result['enum_test']).to eql('val1')
532
- end
533
-
534
- it "should raise an error given an invalid DATETIME" do
535
- expect { @client.query("SELECT CAST('1972-00-27 00:00:00' AS DATETIME) as bad_datetime").each }.to \
536
- raise_error(Mysql2::Error, "Invalid date in field 'bad_datetime': 1972-00-27 00:00:00")
537
- end
538
-
539
- context "string encoding for ENUM values" do
540
- before { pending('Encoding is undefined') unless defined?(Encoding) }
541
-
542
- it "should default to the connection's encoding if Encoding.default_internal is nil" do
543
- with_internal_encoding nil do
544
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
545
- expect(result['enum_test'].encoding).to eql(Encoding::UTF_8)
546
-
547
- client2 = new_client(:encoding => 'ascii')
548
- result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
549
- expect(result['enum_test'].encoding).to eql(Encoding::US_ASCII)
550
- end
551
- end
552
-
553
- it "should use Encoding.default_internal" do
554
- with_internal_encoding Encoding::UTF_8 do
555
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
556
- expect(result['enum_test'].encoding).to eql(Encoding.default_internal)
557
- end
558
-
559
- with_internal_encoding Encoding::ASCII do
560
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
561
- expect(result['enum_test'].encoding).to eql(Encoding.default_internal)
562
- end
563
- end
564
- end
565
-
566
- it "should return String for a SET value" do
567
- expect(@test_result['set_test']).to be_an_instance_of(String)
568
- expect(@test_result['set_test']).to eql('val1,val2')
569
- end
570
-
571
- context "string encoding for SET values" do
572
- before { pending('Encoding is undefined') unless defined?(Encoding) }
573
-
574
- it "should default to the connection's encoding if Encoding.default_internal is nil" do
575
- with_internal_encoding nil do
576
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
577
- expect(result['set_test'].encoding).to eql(Encoding::UTF_8)
578
-
579
- client2 = new_client(:encoding => 'ascii')
580
- result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
581
- expect(result['set_test'].encoding).to eql(Encoding::US_ASCII)
582
- end
583
- end
584
-
585
- it "should use Encoding.default_internal" do
586
- with_internal_encoding Encoding::UTF_8 do
587
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
588
- expect(result['set_test'].encoding).to eql(Encoding.default_internal)
589
- end
590
-
591
- with_internal_encoding Encoding::ASCII do
592
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
593
- expect(result['set_test'].encoding).to eql(Encoding.default_internal)
594
- end
595
- end
596
- end
597
-
598
- it "should return String for a BINARY value" do
599
- expect(@test_result['binary_test']).to be_an_instance_of(String)
600
- expect(@test_result['binary_test']).to eql("test#{"\000" * 6}")
601
- end
602
-
603
- context "string encoding for BINARY values" do
604
- before { pending('Encoding is undefined') unless defined?(Encoding) }
605
-
606
- it "should default to binary if Encoding.default_internal is nil" do
607
- with_internal_encoding nil do
608
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
609
- expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
610
- end
611
- end
612
-
613
- it "should not 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['binary_test'].encoding).to eql(Encoding::BINARY)
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['binary_test'].encoding).to eql(Encoding::BINARY)
622
- end
623
- end
624
- end
625
-
626
- {
627
- 'char_test' => 'CHAR',
628
- 'varchar_test' => 'VARCHAR',
629
- 'varbinary_test' => 'VARBINARY',
630
- 'tiny_blob_test' => 'TINYBLOB',
631
- 'tiny_text_test' => 'TINYTEXT',
632
- 'blob_test' => 'BLOB',
633
- 'text_test' => 'TEXT',
634
- 'medium_blob_test' => 'MEDIUMBLOB',
635
- 'medium_text_test' => 'MEDIUMTEXT',
636
- 'long_blob_test' => 'LONGBLOB',
637
- 'long_text_test' => 'LONGTEXT',
638
- }.each do |field, type|
639
- it "should return a String for #{type}" do
640
- expect(@test_result[field]).to be_an_instance_of(String)
641
- expect(@test_result[field]).to eql("test")
642
- end
643
-
644
- context "string encoding for #{type} values" do
645
- before { pending('Encoding is undefined') unless defined?(Encoding) }
646
-
647
- if %w(VARBINARY TINYBLOB BLOB MEDIUMBLOB LONGBLOB).include?(type)
648
- it "should default to binary if Encoding.default_internal is nil" do
649
- with_internal_encoding nil do
650
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
651
- expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
652
- end
653
- end
654
-
655
- it "should not use Encoding.default_internal" do
656
- with_internal_encoding Encoding::UTF_8 do
657
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
658
- expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
659
- end
660
-
661
- with_internal_encoding Encoding::ASCII do
662
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
663
- expect(result['binary_test'].encoding).to eql(Encoding::BINARY)
664
- end
665
- end
666
- else
667
- it "should default to utf-8 if Encoding.default_internal is nil" do
668
- with_internal_encoding nil do
669
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
670
- expect(result[field].encoding).to eql(Encoding::UTF_8)
671
-
672
- client2 = new_client(:encoding => 'ascii')
673
- result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
674
- expect(result[field].encoding).to eql(Encoding::US_ASCII)
675
- end
676
- end
677
-
678
- it "should use Encoding.default_internal" do
679
- with_internal_encoding Encoding::UTF_8 do
680
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
681
- expect(result[field].encoding).to eql(Encoding.default_internal)
682
- end
683
-
684
- with_internal_encoding Encoding::ASCII do
685
- result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
686
- expect(result[field].encoding).to eql(Encoding.default_internal)
687
- end
688
- end
689
- end
690
- end
691
- end
692
- end
693
-
694
- context 'last_id' do
695
- before(:each) do
696
- @client.query 'USE test'
697
- @client.query 'CREATE TABLE IF NOT EXISTS lastIdTest (`id` BIGINT NOT NULL AUTO_INCREMENT, blah INT(11), PRIMARY KEY (`id`))'
698
- end
699
-
700
- after(:each) do
701
- @client.query 'DROP TABLE lastIdTest'
702
- end
703
-
704
- it 'should return last insert id' do
705
- stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
706
- expect(stmt.last_id).to eq 0
707
- stmt.execute 1
708
- expect(stmt.last_id).to eq 1
709
- end
710
-
711
- it 'should handle bigint ids' do
712
- stmt = @client.prepare 'INSERT INTO lastIdTest (id, blah) VALUES (?, ?)'
713
- stmt.execute 5000000000, 5000
714
- expect(stmt.last_id).to eql(5000000000)
715
-
716
- stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
717
- stmt.execute 5001
718
- expect(stmt.last_id).to eql(5000000001)
719
- end
720
- end
721
-
722
- context 'affected_rows' do
723
- before :each do
724
- @client.query 'USE test'
725
- @client.query 'CREATE TABLE IF NOT EXISTS lastIdTest (`id` BIGINT NOT NULL AUTO_INCREMENT, blah INT(11), PRIMARY KEY (`id`))'
726
- end
727
-
728
- after :each do
729
- @client.query 'DROP TABLE lastIdTest'
730
- end
731
-
732
- it 'should return number of rows affected by an insert' do
733
- stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
734
- expect(stmt.affected_rows).to eq 0
735
- stmt.execute 1
736
- expect(stmt.affected_rows).to eq 1
737
- end
738
-
739
- it 'should return number of rows affected by an update' do
740
- stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
741
- stmt.execute 1
742
- expect(stmt.affected_rows).to eq 1
743
- stmt.execute 2
744
- expect(stmt.affected_rows).to eq 1
745
-
746
- stmt = @client.prepare 'UPDATE lastIdTest SET blah=? WHERE blah=?'
747
- stmt.execute 0, 1
748
- expect(stmt.affected_rows).to eq 1
749
- end
750
-
751
- it 'should return number of rows affected by a delete' do
752
- stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
753
- stmt.execute 1
754
- expect(stmt.affected_rows).to eq 1
755
- stmt.execute 2
756
- expect(stmt.affected_rows).to eq 1
757
-
758
- stmt = @client.prepare 'DELETE FROM lastIdTest WHERE blah=?'
759
- stmt.execute 1
760
- expect(stmt.affected_rows).to eq 1
761
- end
762
- end
763
-
764
- context 'close' do
765
- it 'should free server resources' do
766
- stmt = @client.prepare 'SELECT 1'
767
- expect { stmt.close }.to change(&method(:stmt_count)).by(-1)
768
- end
769
-
770
- it 'should raise an error on subsequent execution' do
771
- stmt = @client.prepare 'SELECT 1'
772
- stmt.close
773
- expect { stmt.execute }.to raise_error(Mysql2::Error, /Invalid statement handle/)
774
- end
775
- end
776
- end