mysql2 0.4.10 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +167 -48
  3. data/ext/mysql2/client.c +335 -108
  4. data/ext/mysql2/client.h +10 -41
  5. data/ext/mysql2/extconf.rb +84 -26
  6. data/ext/mysql2/mysql2_ext.c +8 -2
  7. data/ext/mysql2/mysql2_ext.h +21 -4
  8. data/ext/mysql2/mysql_enc_name_to_ruby.h +60 -55
  9. data/ext/mysql2/mysql_enc_to_ruby.h +79 -3
  10. data/ext/mysql2/result.c +298 -92
  11. data/ext/mysql2/result.h +3 -3
  12. data/ext/mysql2/statement.c +137 -81
  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 +55 -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 +19 -15
  22. data/support/3A79BD29.asc +49 -0
  23. data/support/5072E1F5.asc +5 -5
  24. data/support/C74CD1D8.asc +104 -0
  25. data/support/mysql_enc_to_ruby.rb +9 -3
  26. data/support/ruby_enc_to_mysql.rb +8 -5
  27. metadata +19 -62
  28. data/examples/eventmachine.rb +0 -21
  29. data/examples/threaded.rb +0 -18
  30. data/spec/configuration.yml.example +0 -11
  31. data/spec/em/em_spec.rb +0 -136
  32. data/spec/my.cnf.example +0 -9
  33. data/spec/mysql2/client_spec.rb +0 -1039
  34. data/spec/mysql2/error_spec.rb +0 -82
  35. data/spec/mysql2/result_spec.rb +0 -545
  36. data/spec/mysql2/statement_spec.rb +0 -776
  37. data/spec/rcov.opts +0 -3
  38. data/spec/spec_helper.rb +0 -108
  39. data/spec/ssl/ca-cert.pem +0 -17
  40. data/spec/ssl/ca-key.pem +0 -27
  41. data/spec/ssl/ca.cnf +0 -22
  42. data/spec/ssl/cert.cnf +0 -22
  43. data/spec/ssl/client-cert.pem +0 -17
  44. data/spec/ssl/client-key.pem +0 -27
  45. data/spec/ssl/client-req.pem +0 -15
  46. data/spec/ssl/gen_certs.sh +0 -48
  47. data/spec/ssl/pkcs8-client-key.pem +0 -28
  48. data/spec/ssl/pkcs8-server-key.pem +0 -28
  49. data/spec/ssl/server-cert.pem +0 -17
  50. data/spec/ssl/server-key.pem +0 -27
  51. data/spec/ssl/server-req.pem +0 -15
  52. 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