mysql2 0.4.2 → 0.5.2
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.
- checksums.yaml +4 -4
- data/README.md +103 -59
- data/examples/eventmachine.rb +0 -2
- data/examples/threaded.rb +2 -4
- data/ext/mysql2/client.c +334 -94
- data/ext/mysql2/client.h +3 -51
- data/ext/mysql2/extconf.rb +45 -18
- data/ext/mysql2/mysql2_ext.c +2 -1
- data/ext/mysql2/mysql2_ext.h +8 -8
- data/ext/mysql2/mysql_enc_to_ruby.h +10 -0
- data/ext/mysql2/result.c +53 -94
- data/ext/mysql2/statement.c +191 -83
- data/ext/mysql2/statement.h +0 -2
- data/ext/mysql2/wait_for_single_fd.h +2 -1
- data/lib/mysql2/client.rb +50 -31
- data/lib/mysql2/em.rb +2 -4
- data/lib/mysql2/error.rb +49 -20
- data/lib/mysql2/result.rb +2 -0
- data/lib/mysql2/statement.rb +3 -9
- data/lib/mysql2/version.rb +1 -1
- data/lib/mysql2.rb +14 -15
- data/spec/configuration.yml.example +0 -6
- data/spec/em/em_spec.rb +6 -6
- data/spec/mysql2/client_spec.rb +372 -239
- data/spec/mysql2/error_spec.rb +4 -10
- data/spec/mysql2/result_spec.rb +132 -157
- data/spec/mysql2/statement_spec.rb +205 -177
- data/spec/spec_helper.rb +79 -61
- data/spec/ssl/gen_certs.sh +1 -1
- data/support/5072E1F5.asc +432 -0
- data/support/mysql_enc_to_ruby.rb +2 -2
- data/support/ruby_enc_to_mysql.rb +5 -5
- metadata +16 -14
@@ -1,16 +1,21 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
require './spec/spec_helper.rb'
|
3
2
|
|
4
3
|
RSpec.describe Mysql2::Statement do
|
5
4
|
before :each do
|
6
|
-
@client =
|
5
|
+
@client = new_client(encoding: "utf8")
|
6
|
+
end
|
7
|
+
|
8
|
+
def stmt_count
|
9
|
+
# Use the performance schema in MySQL 5.7 and above
|
10
|
+
@client.query("SELECT COUNT(1) AS count FROM performance_schema.prepared_statements_instances").first['count'].to_i
|
11
|
+
rescue Mysql2::Error
|
12
|
+
# Fall back to the global prepapred statement counter
|
13
|
+
@client.query("SHOW STATUS LIKE 'Prepared_stmt_count'").first['Value'].to_i
|
7
14
|
end
|
8
15
|
|
9
16
|
it "should create a statement" do
|
10
17
|
statement = nil
|
11
|
-
expect { statement = @client.prepare 'SELECT 1' }.to change
|
12
|
-
@client.query("SHOW STATUS LIKE 'Prepared_stmt_count'").first['Value'].to_i
|
13
|
-
}.by(1)
|
18
|
+
expect { statement = @client.prepare 'SELECT 1' }.to change(&method(:stmt_count)).by(1)
|
14
19
|
expect(statement).to be_an_instance_of(Mysql2::Statement)
|
15
20
|
end
|
16
21
|
|
@@ -59,6 +64,46 @@ RSpec.describe Mysql2::Statement do
|
|
59
64
|
expect(rows).to eq([{ "1" => 1 }])
|
60
65
|
end
|
61
66
|
|
67
|
+
it "should handle booleans" do
|
68
|
+
stmt = @client.prepare('SELECT ? AS `true`, ? AS `false`')
|
69
|
+
result = stmt.execute(true, false)
|
70
|
+
expect(result.to_a).to eq(['true' => 1, 'false' => 0])
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should handle bignum but in int64_t" do
|
74
|
+
stmt = @client.prepare('SELECT ? AS max, ? AS min')
|
75
|
+
int64_max = (1 << 63) - 1
|
76
|
+
int64_min = -(1 << 63)
|
77
|
+
result = stmt.execute(int64_max, int64_min)
|
78
|
+
expect(result.to_a).to eq(['max' => int64_max, 'min' => int64_min])
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should handle bignum but beyond int64_t" do
|
82
|
+
stmt = @client.prepare('SELECT ? AS max1, ? AS max2, ? AS max3, ? AS min1, ? AS min2, ? AS min3')
|
83
|
+
int64_max1 = (1 << 63)
|
84
|
+
int64_max2 = (1 << 64) - 1
|
85
|
+
int64_max3 = 1 << 64
|
86
|
+
int64_min1 = -(1 << 63) - 1
|
87
|
+
int64_min2 = -(1 << 64) + 1
|
88
|
+
int64_min3 = -0xC000000000000000
|
89
|
+
result = stmt.execute(int64_max1, int64_max2, int64_max3, int64_min1, int64_min2, int64_min3)
|
90
|
+
expect(result.to_a).to eq(['max1' => int64_max1, 'max2' => int64_max2, 'max3' => int64_max3, 'min1' => int64_min1, 'min2' => int64_min2, 'min3' => int64_min3])
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should accept keyword arguments on statement execute" do
|
94
|
+
stmt = @client.prepare 'SELECT 1 AS a'
|
95
|
+
|
96
|
+
expect(stmt.execute(as: :hash).first).to eq("a" => 1)
|
97
|
+
expect(stmt.execute(as: :array).first).to eq([1])
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should accept bind arguments and keyword arguments on statement execute" do
|
101
|
+
stmt = @client.prepare 'SELECT ? AS a'
|
102
|
+
|
103
|
+
expect(stmt.execute(1, as: :hash).first).to eq("a" => 1)
|
104
|
+
expect(stmt.execute(1, as: :array).first).to eq([1])
|
105
|
+
end
|
106
|
+
|
62
107
|
it "should keep its result after other query" do
|
63
108
|
@client.query 'USE test'
|
64
109
|
@client.query 'CREATE TABLE IF NOT EXISTS mysql2_stmt_q(a int)'
|
@@ -108,6 +153,29 @@ RSpec.describe Mysql2::Statement do
|
|
108
153
|
expect(result.first.first[1]).to be_an_instance_of(Time)
|
109
154
|
end
|
110
155
|
|
156
|
+
it "should prepare Date values" do
|
157
|
+
now = Date.today
|
158
|
+
statement = @client.prepare('SELECT ? AS a')
|
159
|
+
result = statement.execute(now)
|
160
|
+
expect(result.first['a'].to_s).to eql(now.strftime('%F'))
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should prepare Time values with microseconds" do
|
164
|
+
now = Time.now
|
165
|
+
statement = @client.prepare('SELECT ? AS a')
|
166
|
+
result = statement.execute(now)
|
167
|
+
# microseconds is six digits after the decimal, but only test on 5 significant figures
|
168
|
+
expect(result.first['a'].strftime('%F %T.%5N %z')).to eql(now.strftime('%F %T.%5N %z'))
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should prepare DateTime values with microseconds" do
|
172
|
+
now = DateTime.now
|
173
|
+
statement = @client.prepare('SELECT ? AS a')
|
174
|
+
result = statement.execute(now)
|
175
|
+
# microseconds is six digits after the decimal, but only test on 5 significant figures
|
176
|
+
expect(result.first['a'].strftime('%F %T.%5N %z')).to eql(now.strftime('%F %T.%5N %z'))
|
177
|
+
end
|
178
|
+
|
111
179
|
it "should tell us about the fields" do
|
112
180
|
statement = @client.prepare 'SELECT 1 as foo, 2'
|
113
181
|
statement.execute
|
@@ -117,6 +185,31 @@ RSpec.describe Mysql2::Statement do
|
|
117
185
|
expect(list[1]).to eq('2')
|
118
186
|
end
|
119
187
|
|
188
|
+
it "should handle as a decimal binding a BigDecimal" do
|
189
|
+
stmt = @client.prepare('SELECT ? AS decimal_test')
|
190
|
+
test_result = stmt.execute(BigDecimal("123.45")).first
|
191
|
+
expect(test_result['decimal_test']).to be_an_instance_of(BigDecimal)
|
192
|
+
expect(test_result['decimal_test']).to eql(123.45)
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should update a DECIMAL value passing a BigDecimal" do
|
196
|
+
@client.query 'USE test'
|
197
|
+
@client.query 'DROP TABLE IF EXISTS mysql2_stmt_decimal_test'
|
198
|
+
@client.query 'CREATE TABLE mysql2_stmt_decimal_test (decimal_test DECIMAL(10,3))'
|
199
|
+
|
200
|
+
@client.prepare("INSERT INTO mysql2_stmt_decimal_test VALUES (?)").execute(BigDecimal("123.45"))
|
201
|
+
|
202
|
+
test_result = @client.query("SELECT * FROM mysql2_stmt_decimal_test").first
|
203
|
+
expect(test_result['decimal_test']).to eql(123.45)
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should warn but still work if cache_rows is set to false" do
|
207
|
+
statement = @client.prepare 'SELECT 1'
|
208
|
+
result = nil
|
209
|
+
expect { result = statement.execute(cache_rows: false).to_a }.to output(/:cache_rows is forced for prepared statements/).to_stderr
|
210
|
+
expect(result.length).to eq(1)
|
211
|
+
end
|
212
|
+
|
120
213
|
context "utf8_db" do
|
121
214
|
before(:each) do
|
122
215
|
@client.query("DROP DATABASE IF EXISTS test_mysql2_stmt_utf8")
|
@@ -132,7 +225,7 @@ RSpec.describe Mysql2::Statement do
|
|
132
225
|
|
133
226
|
it "should be able to retrieve utf8 field names correctly" do
|
134
227
|
stmt = @client.prepare 'SELECT * FROM `テーブル`'
|
135
|
-
expect(stmt.fields).to eq(%w
|
228
|
+
expect(stmt.fields).to eq(%w[整数 文字列])
|
136
229
|
result = stmt.execute
|
137
230
|
|
138
231
|
expect(result.to_a).to eq([{ "整数" => 1, "文字列" => "イチ" }, { "整数" => 2, "文字列" => "弐" }, { "整数" => 3, "文字列" => "さん" }])
|
@@ -156,16 +249,13 @@ RSpec.describe Mysql2::Statement do
|
|
156
249
|
|
157
250
|
expect(result.to_a).to eq([{ "整数" => 1 }])
|
158
251
|
end
|
159
|
-
end
|
252
|
+
end
|
160
253
|
|
161
254
|
context "streaming result" do
|
162
255
|
it "should be able to stream query result" do
|
163
256
|
n = 1
|
164
257
|
stmt = @client.prepare("SELECT 1 UNION SELECT 2")
|
165
|
-
|
166
|
-
@client.query_options.merge!(:stream => true, :cache_rows => false, :as => :array)
|
167
|
-
|
168
|
-
stmt.execute.each do |r|
|
258
|
+
stmt.execute(stream: true, cache_rows: false, as: :array).each do |r|
|
169
259
|
case n
|
170
260
|
when 1
|
171
261
|
expect(r).to eq([1])
|
@@ -191,23 +281,17 @@ RSpec.describe Mysql2::Statement do
|
|
191
281
|
end
|
192
282
|
|
193
283
|
it "should yield rows as hash's with symbol keys if :symbolize_keys was set to true" do
|
194
|
-
@client.
|
195
|
-
@result = @client.prepare("SELECT 1").execute
|
284
|
+
@result = @client.prepare("SELECT 1").execute(symbolize_keys: true)
|
196
285
|
@result.each do |row|
|
197
286
|
expect(row.keys.first).to be_an_instance_of(Symbol)
|
198
287
|
end
|
199
|
-
@client.query_options[:symbolize_keys] = false
|
200
288
|
end
|
201
289
|
|
202
290
|
it "should be able to return results as an array" do
|
203
|
-
@client.
|
204
|
-
|
205
|
-
@result = @client.prepare("SELECT 1").execute
|
291
|
+
@result = @client.prepare("SELECT 1").execute(as: :array)
|
206
292
|
@result.each do |row|
|
207
293
|
expect(row).to be_an_instance_of(Array)
|
208
294
|
end
|
209
|
-
|
210
|
-
@client.query_options[:as] = :hash
|
211
295
|
end
|
212
296
|
|
213
297
|
it "should cache previously yielded results by default" do
|
@@ -216,222 +300,178 @@ RSpec.describe Mysql2::Statement do
|
|
216
300
|
end
|
217
301
|
|
218
302
|
it "should yield different value for #first if streaming" do
|
219
|
-
@client.
|
220
|
-
@client.query_options[:cache_rows] = false
|
221
|
-
|
222
|
-
result = @client.prepare("SELECT 1 UNION SELECT 2").execute
|
303
|
+
result = @client.prepare("SELECT 1 UNION SELECT 2").execute(stream: true, cache_rows: true)
|
223
304
|
expect(result.first).not_to eql(result.first)
|
224
|
-
|
225
|
-
@client.query_options[:stream] = false
|
226
|
-
@client.query_options[:cache_rows] = true
|
227
305
|
end
|
228
306
|
|
229
307
|
it "should yield the same value for #first if streaming is disabled" do
|
230
|
-
@client.
|
231
|
-
result = @client.prepare("SELECT 1 UNION SELECT 2").execute
|
308
|
+
result = @client.prepare("SELECT 1 UNION SELECT 2").execute(stream: false)
|
232
309
|
expect(result.first).to eql(result.first)
|
233
310
|
end
|
234
311
|
|
235
312
|
it "should throw an exception if we try to iterate twice when streaming is enabled" do
|
236
|
-
@client.
|
237
|
-
|
238
|
-
|
239
|
-
result = @client.prepare("SELECT 1 UNION SELECT 2").execute
|
240
|
-
|
241
|
-
expect {
|
313
|
+
result = @client.prepare("SELECT 1 UNION SELECT 2").execute(stream: true, cache_rows: false)
|
314
|
+
expect do
|
242
315
|
result.each {}
|
243
316
|
result.each {}
|
244
|
-
|
245
|
-
|
246
|
-
@client.query_options[:stream] = false
|
247
|
-
@client.query_options[:cache_rows] = true
|
317
|
+
end.to raise_exception(Mysql2::Error)
|
248
318
|
end
|
249
319
|
end
|
250
320
|
|
251
321
|
context "#fields" do
|
252
|
-
before(:each) do
|
253
|
-
@client.query "USE test"
|
254
|
-
@test_result = @client.prepare("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").execute
|
255
|
-
end
|
256
|
-
|
257
322
|
it "method should exist" do
|
258
|
-
|
323
|
+
stmt = @client.prepare("SELECT 1")
|
324
|
+
expect(stmt).to respond_to(:fields)
|
259
325
|
end
|
260
326
|
|
261
327
|
it "should return an array of field names in proper order" do
|
262
|
-
|
263
|
-
expect(
|
328
|
+
stmt = @client.prepare("SELECT 'a', 'b', 'c'")
|
329
|
+
expect(stmt.fields).to eql(%w[a b c])
|
330
|
+
end
|
331
|
+
|
332
|
+
it "should return nil for statement with no result fields" do
|
333
|
+
stmt = @client.prepare("INSERT INTO mysql2_test () VALUES ()")
|
334
|
+
expect(stmt.fields).to eql(nil)
|
264
335
|
end
|
265
336
|
end
|
266
337
|
|
267
338
|
context "row data type mapping" do
|
268
|
-
|
269
|
-
@client.query "USE test"
|
270
|
-
@test_result = @client.prepare("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").execute.first
|
271
|
-
end
|
339
|
+
let(:test_result) { @client.prepare("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").execute.first }
|
272
340
|
|
273
341
|
it "should return nil for a NULL value" do
|
274
|
-
expect(
|
275
|
-
expect(
|
342
|
+
expect(test_result['null_test']).to be_an_instance_of(NilClass)
|
343
|
+
expect(test_result['null_test']).to eql(nil)
|
276
344
|
end
|
277
345
|
|
278
346
|
it "should return String for a BIT(64) value" do
|
279
|
-
expect(
|
280
|
-
expect(
|
347
|
+
expect(test_result['bit_test']).to be_an_instance_of(String)
|
348
|
+
expect(test_result['bit_test']).to eql("\000\000\000\000\000\000\000\005")
|
281
349
|
end
|
282
350
|
|
283
351
|
it "should return String for a BIT(1) value" do
|
284
|
-
expect(
|
285
|
-
expect(
|
352
|
+
expect(test_result['single_bit_test']).to be_an_instance_of(String)
|
353
|
+
expect(test_result['single_bit_test']).to eql("\001")
|
286
354
|
end
|
287
355
|
|
288
356
|
it "should return Fixnum for a TINYINT value" do
|
289
|
-
expect(
|
290
|
-
expect(
|
357
|
+
expect(num_classes).to include(test_result['tiny_int_test'].class)
|
358
|
+
expect(test_result['tiny_int_test']).to eql(1)
|
291
359
|
end
|
292
360
|
|
293
|
-
|
294
|
-
|
295
|
-
id1
|
296
|
-
@client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (0)'
|
297
|
-
|
298
|
-
|
299
|
-
id3 = @client.last_id
|
361
|
+
context "cast booleans for TINYINT if :cast_booleans is enabled" do
|
362
|
+
# rubocop:disable Style/Semicolon
|
363
|
+
let(:id1) { @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 1)'; @client.last_id }
|
364
|
+
let(:id2) { @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES ( 0)'; @client.last_id }
|
365
|
+
let(:id3) { @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (-1)'; @client.last_id }
|
366
|
+
# rubocop:enable Style/Semicolon
|
300
367
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
expect(result1.first['bool_cast_test']).to be true
|
305
|
-
expect(result2.first['bool_cast_test']).to be false
|
306
|
-
expect(result3.first['bool_cast_test']).to be true
|
368
|
+
after do
|
369
|
+
@client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2},#{id3})"
|
370
|
+
end
|
307
371
|
|
308
|
-
|
372
|
+
it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do
|
373
|
+
query = @client.prepare 'SELECT bool_cast_test FROM mysql2_test WHERE id = ?'
|
374
|
+
result1 = query.execute id1, cast_booleans: true
|
375
|
+
result2 = query.execute id2, cast_booleans: true
|
376
|
+
result3 = query.execute id3, cast_booleans: true
|
377
|
+
expect(result1.first['bool_cast_test']).to be true
|
378
|
+
expect(result2.first['bool_cast_test']).to be false
|
379
|
+
expect(result3.first['bool_cast_test']).to be true
|
380
|
+
end
|
309
381
|
end
|
310
382
|
|
311
|
-
|
312
|
-
|
313
|
-
id1
|
314
|
-
@client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'
|
315
|
-
|
383
|
+
context "cast booleans for BIT(1) if :cast_booleans is enabled" do
|
384
|
+
# rubocop:disable Style/Semicolon
|
385
|
+
let(:id1) { @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (1)'; @client.last_id }
|
386
|
+
let(:id2) { @client.query 'INSERT INTO mysql2_test (single_bit_test) VALUES (0)'; @client.last_id }
|
387
|
+
# rubocop:enable Style/Semicolon
|
316
388
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
expect(result2.first['single_bit_test']).to be false
|
389
|
+
after do
|
390
|
+
@client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
|
391
|
+
end
|
321
392
|
|
322
|
-
|
393
|
+
it "should return TrueClass or FalseClass for a BIT(1) value if :cast_booleans is enabled" do
|
394
|
+
query = @client.prepare 'SELECT single_bit_test FROM mysql2_test WHERE id = ?'
|
395
|
+
result1 = query.execute id1, cast_booleans: true
|
396
|
+
result2 = query.execute id2, cast_booleans: true
|
397
|
+
expect(result1.first['single_bit_test']).to be true
|
398
|
+
expect(result2.first['single_bit_test']).to be false
|
399
|
+
end
|
323
400
|
end
|
324
401
|
|
325
402
|
it "should return Fixnum for a SMALLINT value" do
|
326
|
-
expect(
|
327
|
-
expect(
|
403
|
+
expect(num_classes).to include(test_result['small_int_test'].class)
|
404
|
+
expect(test_result['small_int_test']).to eql(10)
|
328
405
|
end
|
329
406
|
|
330
407
|
it "should return Fixnum for a MEDIUMINT value" do
|
331
|
-
expect(
|
332
|
-
expect(
|
408
|
+
expect(num_classes).to include(test_result['medium_int_test'].class)
|
409
|
+
expect(test_result['medium_int_test']).to eql(10)
|
333
410
|
end
|
334
411
|
|
335
412
|
it "should return Fixnum for an INT value" do
|
336
|
-
expect(
|
337
|
-
expect(
|
413
|
+
expect(num_classes).to include(test_result['int_test'].class)
|
414
|
+
expect(test_result['int_test']).to eql(10)
|
338
415
|
end
|
339
416
|
|
340
417
|
it "should return Fixnum for a BIGINT value" do
|
341
|
-
expect(
|
342
|
-
expect(
|
418
|
+
expect(num_classes).to include(test_result['big_int_test'].class)
|
419
|
+
expect(test_result['big_int_test']).to eql(10)
|
343
420
|
end
|
344
421
|
|
345
422
|
it "should return Fixnum for a YEAR value" do
|
346
|
-
expect(
|
347
|
-
expect(
|
423
|
+
expect(num_classes).to include(test_result['year_test'].class)
|
424
|
+
expect(test_result['year_test']).to eql(2009)
|
348
425
|
end
|
349
426
|
|
350
427
|
it "should return BigDecimal for a DECIMAL value" do
|
351
|
-
expect(
|
352
|
-
expect(
|
428
|
+
expect(test_result['decimal_test']).to be_an_instance_of(BigDecimal)
|
429
|
+
expect(test_result['decimal_test']).to eql(10.3)
|
353
430
|
end
|
354
431
|
|
355
432
|
it "should return Float for a FLOAT value" do
|
356
|
-
expect(
|
357
|
-
expect(
|
433
|
+
expect(test_result['float_test']).to be_an_instance_of(Float)
|
434
|
+
expect(test_result['float_test']).to be_within(1e-5).of(10.3)
|
358
435
|
end
|
359
436
|
|
360
437
|
it "should return Float for a DOUBLE value" do
|
361
|
-
expect(
|
362
|
-
expect(
|
438
|
+
expect(test_result['double_test']).to be_an_instance_of(Float)
|
439
|
+
expect(test_result['double_test']).to eql(10.3)
|
363
440
|
end
|
364
441
|
|
365
442
|
it "should return Time for a DATETIME value when within the supported range" do
|
366
|
-
expect(
|
367
|
-
expect(
|
443
|
+
expect(test_result['date_time_test']).to be_an_instance_of(Time)
|
444
|
+
expect(test_result['date_time_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2010-04-04 11:44:00')
|
368
445
|
end
|
369
446
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
Time
|
375
|
-
end
|
376
|
-
|
377
|
-
it "should return DateTime when timestamp is < 1901-12-13 20:45:52" do
|
378
|
-
# 1901-12-13T20:45:52 is the min for 32bit Ruby 1.8
|
379
|
-
r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
|
380
|
-
expect(r.first['test']).to be_an_instance_of(klass)
|
381
|
-
end
|
382
|
-
|
383
|
-
it "should return DateTime when timestamp is > 2038-01-19T03:14:07" do
|
384
|
-
# 2038-01-19T03:14:07 is the max for 32bit Ruby 1.8
|
385
|
-
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
|
386
|
-
expect(r.first['test']).to be_an_instance_of(klass)
|
387
|
-
end
|
388
|
-
elsif 1.size == 8 # 64bit
|
389
|
-
if RUBY_VERSION =~ /1.8/
|
390
|
-
it "should return Time when timestamp is > 0138-12-31 11:59:59" do
|
391
|
-
r = @client.query("SELECT CAST('0139-1-1 00:00:00' AS DATETIME) as test")
|
392
|
-
expect(r.first['test']).to be_an_instance_of(Time)
|
393
|
-
end
|
394
|
-
|
395
|
-
it "should return DateTime when timestamp is < 0139-1-1T00:00:00" do
|
396
|
-
r = @client.query("SELECT CAST('0138-12-31 11:59:59' AS DATETIME) as test")
|
397
|
-
expect(r.first['test']).to be_an_instance_of(DateTime)
|
398
|
-
end
|
399
|
-
|
400
|
-
it "should return Time when timestamp is > 2038-01-19T03:14:07" do
|
401
|
-
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
|
402
|
-
expect(r.first['test']).to be_an_instance_of(Time)
|
403
|
-
end
|
404
|
-
else
|
405
|
-
it "should return Time when timestamp is < 1901-12-13 20:45:52" do
|
406
|
-
r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
|
407
|
-
expect(r.first['test']).to be_an_instance_of(Time)
|
408
|
-
end
|
447
|
+
it "should return Time when timestamp is < 1901-12-13 20:45:52" do
|
448
|
+
r = @client.prepare("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test").execute
|
449
|
+
expect(r.first['test']).to be_an_instance_of(Time)
|
450
|
+
end
|
409
451
|
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
end
|
414
|
-
end
|
452
|
+
it "should return Time when timestamp is > 2038-01-19T03:14:07" do
|
453
|
+
r = @client.prepare("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test").execute
|
454
|
+
expect(r.first['test']).to be_an_instance_of(Time)
|
415
455
|
end
|
416
456
|
|
417
457
|
it "should return Time for a TIMESTAMP value when within the supported range" do
|
418
|
-
expect(
|
419
|
-
expect(
|
458
|
+
expect(test_result['timestamp_test']).to be_an_instance_of(Time)
|
459
|
+
expect(test_result['timestamp_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2010-04-04 11:44:00')
|
420
460
|
end
|
421
461
|
|
422
462
|
it "should return Time for a TIME value" do
|
423
|
-
expect(
|
424
|
-
expect(
|
463
|
+
expect(test_result['time_test']).to be_an_instance_of(Time)
|
464
|
+
expect(test_result['time_test'].strftime("%Y-%m-%d %H:%M:%S")).to eql('2000-01-01 11:44:00')
|
425
465
|
end
|
426
466
|
|
427
467
|
it "should return Date for a DATE value" do
|
428
|
-
expect(
|
429
|
-
expect(
|
468
|
+
expect(test_result['date_test']).to be_an_instance_of(Date)
|
469
|
+
expect(test_result['date_test'].strftime("%Y-%m-%d")).to eql('2010-04-04')
|
430
470
|
end
|
431
471
|
|
432
472
|
it "should return String for an ENUM value" do
|
433
|
-
expect(
|
434
|
-
expect(
|
473
|
+
expect(test_result['enum_test']).to be_an_instance_of(String)
|
474
|
+
expect(test_result['enum_test']).to eql('val1')
|
435
475
|
end
|
436
476
|
|
437
477
|
it "should raise an error given an invalid DATETIME" do
|
@@ -440,17 +480,14 @@ RSpec.describe Mysql2::Statement do
|
|
440
480
|
end
|
441
481
|
|
442
482
|
context "string encoding for ENUM values" do
|
443
|
-
before { pending('Encoding is undefined') unless defined?(Encoding) }
|
444
|
-
|
445
483
|
it "should default to the connection's encoding if Encoding.default_internal is nil" do
|
446
484
|
with_internal_encoding nil do
|
447
485
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
448
486
|
expect(result['enum_test'].encoding).to eql(Encoding::UTF_8)
|
449
487
|
|
450
|
-
client2 =
|
488
|
+
client2 = new_client(encoding: 'ascii')
|
451
489
|
result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
452
490
|
expect(result['enum_test'].encoding).to eql(Encoding::US_ASCII)
|
453
|
-
client2.close
|
454
491
|
end
|
455
492
|
end
|
456
493
|
|
@@ -468,22 +505,19 @@ RSpec.describe Mysql2::Statement do
|
|
468
505
|
end
|
469
506
|
|
470
507
|
it "should return String for a SET value" do
|
471
|
-
expect(
|
472
|
-
expect(
|
508
|
+
expect(test_result['set_test']).to be_an_instance_of(String)
|
509
|
+
expect(test_result['set_test']).to eql('val1,val2')
|
473
510
|
end
|
474
511
|
|
475
512
|
context "string encoding for SET values" do
|
476
|
-
before { pending('Encoding is undefined') unless defined?(Encoding) }
|
477
|
-
|
478
513
|
it "should default to the connection's encoding if Encoding.default_internal is nil" do
|
479
514
|
with_internal_encoding nil do
|
480
515
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
481
516
|
expect(result['set_test'].encoding).to eql(Encoding::UTF_8)
|
482
517
|
|
483
|
-
client2 =
|
518
|
+
client2 = new_client(encoding: 'ascii')
|
484
519
|
result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
485
520
|
expect(result['set_test'].encoding).to eql(Encoding::US_ASCII)
|
486
|
-
client2.close
|
487
521
|
end
|
488
522
|
end
|
489
523
|
|
@@ -501,13 +535,11 @@ RSpec.describe Mysql2::Statement do
|
|
501
535
|
end
|
502
536
|
|
503
537
|
it "should return String for a BINARY value" do
|
504
|
-
expect(
|
505
|
-
expect(
|
538
|
+
expect(test_result['binary_test']).to be_an_instance_of(String)
|
539
|
+
expect(test_result['binary_test']).to eql("test#{"\000" * 6}")
|
506
540
|
end
|
507
541
|
|
508
542
|
context "string encoding for BINARY values" do
|
509
|
-
before { pending('Encoding is undefined') unless defined?(Encoding) }
|
510
|
-
|
511
543
|
it "should default to binary if Encoding.default_internal is nil" do
|
512
544
|
with_internal_encoding nil do
|
513
545
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
@@ -542,14 +574,12 @@ RSpec.describe Mysql2::Statement do
|
|
542
574
|
'long_text_test' => 'LONGTEXT',
|
543
575
|
}.each do |field, type|
|
544
576
|
it "should return a String for #{type}" do
|
545
|
-
expect(
|
546
|
-
expect(
|
577
|
+
expect(test_result[field]).to be_an_instance_of(String)
|
578
|
+
expect(test_result[field]).to eql("test")
|
547
579
|
end
|
548
580
|
|
549
581
|
context "string encoding for #{type} values" do
|
550
|
-
|
551
|
-
|
552
|
-
if %w(VARBINARY TINYBLOB BLOB MEDIUMBLOB LONGBLOB).include?(type)
|
582
|
+
if %w[VARBINARY TINYBLOB BLOB MEDIUMBLOB LONGBLOB].include?(type)
|
553
583
|
it "should default to binary if Encoding.default_internal is nil" do
|
554
584
|
with_internal_encoding nil do
|
555
585
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
@@ -574,10 +604,9 @@ RSpec.describe Mysql2::Statement do
|
|
574
604
|
result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
575
605
|
expect(result[field].encoding).to eql(Encoding::UTF_8)
|
576
606
|
|
577
|
-
client2 =
|
607
|
+
client2 = new_client(encoding: 'ascii')
|
578
608
|
result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
|
579
609
|
expect(result[field].encoding).to eql(Encoding::US_ASCII)
|
580
|
-
client2.close
|
581
610
|
end
|
582
611
|
end
|
583
612
|
|
@@ -637,7 +666,6 @@ RSpec.describe Mysql2::Statement do
|
|
637
666
|
|
638
667
|
it 'should return number of rows affected by an insert' do
|
639
668
|
stmt = @client.prepare 'INSERT INTO lastIdTest (blah) VALUES (?)'
|
640
|
-
expect(stmt.affected_rows).to eq 0
|
641
669
|
stmt.execute 1
|
642
670
|
expect(stmt.affected_rows).to eq 1
|
643
671
|
end
|
@@ -670,9 +698,9 @@ RSpec.describe Mysql2::Statement do
|
|
670
698
|
context 'close' do
|
671
699
|
it 'should free server resources' do
|
672
700
|
stmt = @client.prepare 'SELECT 1'
|
673
|
-
|
674
|
-
|
675
|
-
|
701
|
+
GC.disable
|
702
|
+
expect { stmt.close }.to change(&method(:stmt_count)).by(-1)
|
703
|
+
GC.enable
|
676
704
|
end
|
677
705
|
|
678
706
|
it 'should raise an error on subsequent execution' do
|