ruby-mysql 2.9.11 → 2.10.0

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.
@@ -0,0 +1,1886 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'test/unit'
3
+ require 'test/unit/rr'
4
+ begin
5
+ require 'test/unit/notify'
6
+ rescue LoadError
7
+ # ignore
8
+ end
9
+
10
+ require 'mysql'
11
+
12
+ # MYSQL_USER must have ALL privilege for MYSQL_DATABASE.* and RELOAD privilege for *.*
13
+ MYSQL_SERVER = ENV['MYSQL_SERVER']
14
+ MYSQL_USER = ENV['MYSQL_USER']
15
+ MYSQL_PASSWORD = ENV['MYSQL_PASSWORD']
16
+ MYSQL_DATABASE = ENV['MYSQL_DATABASE'] || "test_for_mysql_ruby"
17
+ MYSQL_PORT = ENV['MYSQL_PORT']
18
+ MYSQL_SOCKET = ENV['MYSQL_SOCKET']
19
+
20
+ class TestMysql < Test::Unit::TestCase
21
+ sub_test_case 'Mysql::VERSION' do
22
+ test 'returns client version' do
23
+ assert{ Mysql::VERSION == 21000 }
24
+ end
25
+ end
26
+
27
+ sub_test_case 'Mysql.init' do
28
+ test 'returns Mysql object' do
29
+ assert{ Mysql.init.kind_of? Mysql }
30
+ end
31
+ end
32
+
33
+ sub_test_case 'Mysql.real_connect' do
34
+ test 'connect to mysqld' do
35
+ @m = Mysql.real_connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
36
+ assert{ @m.kind_of? Mysql }
37
+ end
38
+
39
+ test 'flag argument affects' do
40
+ @m = Mysql.real_connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET, Mysql::CLIENT_FOUND_ROWS)
41
+ @m.query 'create temporary table t (c int)'
42
+ @m.query 'insert into t values (123)'
43
+ @m.query 'update t set c=123'
44
+ assert{ @m.affected_rows == 1 }
45
+ end
46
+
47
+ teardown do
48
+ @m.close if @m
49
+ end
50
+ end
51
+
52
+ sub_test_case 'Mysql.connect' do
53
+ test 'connect to mysqld' do
54
+ @m = Mysql.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
55
+ assert{ @m.kind_of? Mysql }
56
+ end
57
+
58
+ teardown do
59
+ @m.close if @m
60
+ end
61
+ end
62
+
63
+ sub_test_case 'Mysql.new' do
64
+ test 'connect to mysqld' do
65
+ @m = Mysql.new(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
66
+ assert{ @m.kind_of? Mysql }
67
+ end
68
+ teardown do
69
+ @m.close if @m
70
+ end
71
+ end
72
+
73
+ sub_test_case 'Mysql.escape_string' do
74
+ test 'escape special character' do
75
+ assert{ Mysql.escape_string("abc'def\"ghi\0jkl%mno") == "abc\\'def\\\"ghi\\0jkl%mno" }
76
+ end
77
+ end
78
+
79
+ sub_test_case 'Mysql.quote' do
80
+ test 'escape special character' do
81
+ assert{ Mysql.quote("abc'def\"ghi\0jkl%mno") == "abc\\'def\\\"ghi\\0jkl%mno" }
82
+ end
83
+ end
84
+
85
+ sub_test_case 'Mysql.client_info' do
86
+ test 'returns client version as string' do
87
+ assert{ Mysql.client_info == '5.0.0' }
88
+ end
89
+ end
90
+
91
+ sub_test_case 'Mysql.get_client_info' do
92
+ test 'returns client version as string' do
93
+ assert{ Mysql.get_client_info == '5.0.0' }
94
+ end
95
+ end
96
+
97
+ sub_test_case 'Mysql.client_version' do
98
+ test 'returns client version as Integer' do
99
+ assert{ Mysql.client_version == 50000 }
100
+ end
101
+ end
102
+
103
+ sub_test_case 'Mysql.get_client_version' do
104
+ test 'returns client version as Integer' do
105
+ assert{ Mysql.client_version == 50000 }
106
+ end
107
+ end
108
+
109
+ sub_test_case 'Mysql#real_connect' do
110
+ test 'connect to mysqld' do
111
+ @m = Mysql.init
112
+ assert{ @m.real_connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET) == @m }
113
+ end
114
+ teardown do
115
+ @m.close if @m
116
+ end
117
+ end
118
+
119
+ sub_test_case 'Mysql#connect' do
120
+ test 'connect to mysqld' do
121
+ @m = Mysql.init
122
+ assert{ @m.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET) == @m }
123
+ end
124
+ teardown do
125
+ @m.close if @m
126
+ end
127
+ end
128
+
129
+ sub_test_case 'Mysql#options' do
130
+ setup do
131
+ @m = Mysql.init
132
+ end
133
+ teardown do
134
+ @m.close
135
+ end
136
+ test 'INIT_COMMAND: execute query when connecting' do
137
+ assert{ @m.options(Mysql::INIT_COMMAND, "SET AUTOCOMMIT=0") == @m }
138
+ assert{ @m.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET) == @m }
139
+ assert{ @m.query('select @@AUTOCOMMIT').fetch_row == ["0"] }
140
+ end
141
+ test 'OPT_CONNECT_TIMEOUT: set timeout for connecting' do
142
+ assert{ @m.options(Mysql::OPT_CONNECT_TIMEOUT, 0.1) == @m }
143
+ stub(UNIXSocket).new{ sleep 1}
144
+ stub(TCPSocket).new{ sleep 1}
145
+ assert_raise Mysql::ClientError, 'connection timeout' do
146
+ @m.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
147
+ end
148
+ assert_raise Mysql::ClientError, 'connection timeout' do
149
+ @m.connect
150
+ end
151
+ end
152
+ test 'OPT_LOCAL_INFILE: client can execute LOAD DATA LOCAL INFILE query' do
153
+ require 'tempfile'
154
+ tmpf = Tempfile.new 'mysql_spec'
155
+ tmpf.puts "123\tabc\n"
156
+ tmpf.close
157
+ assert{ @m.options(Mysql::OPT_LOCAL_INFILE, true) == @m }
158
+ @m.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
159
+ @m.query('create temporary table t (i int, c char(10))')
160
+ @m.query("load data local infile '#{tmpf.path}' into table t")
161
+ assert{ @m.query('select * from t').fetch_row == ['123','abc'] }
162
+ end
163
+ test 'OPT_LOAD_DATA_LOCAL_DIR: client can execute LOAD DATA LOCAL INFILE query with specified directory' do
164
+ require 'tempfile'
165
+ tmpf = Tempfile.new 'mysql_spec'
166
+ tmpf.puts "123\tabc\n"
167
+ tmpf.close
168
+ assert{ @m.options(Mysql::OPT_LOAD_DATA_LOCAL_DIR, File.dirname(tmpf.path)) == @m }
169
+ @m.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
170
+ @m.query('create temporary table t (i int, c char(10))')
171
+ @m.query("load data local infile '#{tmpf.path}' into table t")
172
+ assert{ @m.query('select * from t').fetch_row == ['123','abc'] }
173
+ end
174
+ test 'OPT_LOAD_DATA_LOCAL_DIR: client cannot execute LOAD DATA LOCAL INFILE query without specified directory' do
175
+ require 'tempfile'
176
+ tmpf = Tempfile.new 'mysql_spec'
177
+ tmpf.puts "123\tabc\n"
178
+ tmpf.close
179
+ assert{ @m.options(Mysql::OPT_LOAD_DATA_LOCAL_DIR, '/hoge') == @m }
180
+ @m.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
181
+ @m.query('create temporary table t (i int, c char(10))')
182
+ assert_raise Mysql::ClientError::LoadDataLocalInfileRejected, 'LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.' do
183
+ @m.query("load data local infile '#{tmpf.path}' into table t")
184
+ end
185
+ end
186
+ test 'without OPT_LOCAL_INFILE and OPT_LOAD_DATA_LOCAL_DIR: client cannot execute LOAD DATA LOCAL INFILE query' do
187
+ require 'tempfile'
188
+ tmpf = Tempfile.new 'mysql_spec'
189
+ tmpf.puts "123\tabc\n"
190
+ tmpf.close
191
+ @m.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
192
+ @m.query('create temporary table t (i int, c char(10))')
193
+ assert_raise Mysql::ServerError::NotAllowedCommand, 'The used command is not allowed with this MySQL version' do
194
+ @m.query("load data local infile '#{tmpf.path}' into table t")
195
+ end
196
+ end
197
+ test 'OPT_READ_TIMEOUT: set timeout for reading packet' do
198
+ assert{ @m.options(Mysql::OPT_READ_TIMEOUT, 10) == @m }
199
+ end
200
+ test 'OPT_WRITE_TIMEOUT: set timeout for writing packet' do
201
+ assert{ @m.options(Mysql::OPT_WRITE_TIMEOUT, 10) == @m }
202
+ end
203
+ test 'SET_CHARSET_NAME: set charset for connection' do
204
+ assert{ @m.options(Mysql::SET_CHARSET_NAME, 'utf8') == @m }
205
+ @m.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
206
+ assert{ @m.query('select @@character_set_connection').fetch_row == ['utf8'] }
207
+ end
208
+ end
209
+
210
+ sub_test_case 'Mysql' do
211
+ setup do
212
+ @m = Mysql.new(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
213
+ end
214
+
215
+ teardown do
216
+ @m.close if @m rescue nil
217
+ end
218
+
219
+ sub_test_case '#escape_string' do
220
+ if defined? ::Encoding
221
+ test 'escape special character for charset' do
222
+ @m.charset = 'cp932'
223
+ assert{ @m.escape_string("abc'def\"ghi\0jkl%mno_表".encode('cp932')) == "abc\\'def\\\"ghi\\0jkl%mno_表".encode('cp932') }
224
+ end
225
+ else
226
+ test 'raise error if charset is multibyte' do
227
+ @m.charset = 'cp932'
228
+ assert_raise Mysql::ClientError, 'Mysql#escape_string is called for unsafe multibyte charset' do
229
+ @m.escape_string("abc'def\"ghi\0jkl%mno_\x95\\")
230
+ end
231
+ end
232
+ test 'not warn if charset is singlebyte' do
233
+ @m.charset = 'latin1'
234
+ assert{ @m.escape_string("abc'def\"ghi\0jkl%mno_\x95\\") == "abc\\'def\\\"ghi\\0jkl%mno_\x95\\\\" }
235
+ end
236
+ end
237
+ end
238
+
239
+ sub_test_case '#quote' do
240
+ test 'is alias of #escape_string' do
241
+ assert{ @m.method(:quote) == @m.method(:escape_string) }
242
+ end
243
+ end
244
+
245
+ sub_test_case '#client_info' do
246
+ test 'returns client version as string' do
247
+ assert{ @m.client_info == '5.0.0' }
248
+ end
249
+ end
250
+
251
+ sub_test_case '#get_client_info' do
252
+ test 'returns client version as string' do
253
+ assert{ @m.get_client_info == '5.0.0' }
254
+ end
255
+ end
256
+
257
+ sub_test_case '#affected_rows' do
258
+ test 'returns number of affected rows' do
259
+ @m.query 'create temporary table t (id int)'
260
+ @m.query 'insert into t values (1),(2)'
261
+ assert{ @m.affected_rows == 2 }
262
+ end
263
+ end
264
+
265
+ sub_test_case '#character_set_name' do
266
+ test 'returns charset name' do
267
+ m = Mysql.init
268
+ m.options Mysql::SET_CHARSET_NAME, 'cp932'
269
+ m.connect MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET
270
+ assert{ m.character_set_name == 'cp932' }
271
+ end
272
+ end
273
+
274
+ sub_test_case '#close' do
275
+ test 'returns self' do
276
+ assert{ @m.close == @m }
277
+ end
278
+ end
279
+
280
+ sub_test_case '#close!' do
281
+ test 'returns self' do
282
+ assert{ @m.close! == @m }
283
+ end
284
+ end
285
+
286
+ # sub_test_case '#create_db' do
287
+ # end
288
+
289
+ # sub_test_case '#drop_db' do
290
+ # end
291
+
292
+ sub_test_case '#errno' do
293
+ test 'default value is 0' do
294
+ assert{ @m.errno == 0 }
295
+ end
296
+ test 'returns error number of latest error' do
297
+ @m.query('hogehoge') rescue nil
298
+ assert{ @m.errno == 1064 }
299
+ end
300
+ end
301
+
302
+ sub_test_case '#error' do
303
+ test 'returns error message of latest error' do
304
+ @m.query('hogehoge') rescue nil
305
+ assert{ @m.error == "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'hogehoge' at line 1" }
306
+ end
307
+ end
308
+
309
+ sub_test_case '#field_count' do
310
+ test 'returns number of fields for latest query' do
311
+ @m.query 'select 1,2,3'
312
+ assert{ @m.field_count == 3 }
313
+ end
314
+ end
315
+
316
+ sub_test_case '#client_version' do
317
+ test 'returns client version as Integer' do
318
+ assert{ @m.client_version.kind_of? Integer }
319
+ end
320
+ end
321
+
322
+ sub_test_case '#get_client_version' do
323
+ test 'returns client version as Integer' do
324
+ assert{ @m.get_client_version.kind_of? Integer }
325
+ end
326
+ end
327
+
328
+ sub_test_case '#get_host_info' do
329
+ test 'returns connection type as String' do
330
+ if MYSQL_SERVER == nil or MYSQL_SERVER == 'localhost'
331
+ assert{ @m.get_host_info == 'Localhost via UNIX socket' }
332
+ else
333
+ assert{ @m.get_host_info == "#{MYSQL_SERVER} via TCP/IP" }
334
+ end
335
+ end
336
+ end
337
+
338
+ sub_test_case '#host_info' do
339
+ test 'returns connection type as String' do
340
+ if MYSQL_SERVER == nil or MYSQL_SERVER == 'localhost'
341
+ assert{ @m.host_info == 'Localhost via UNIX socket' }
342
+ else
343
+ assert{ @m.host_info == "#{MYSQL_SERVER} via TCP/IP" }
344
+ end
345
+ end
346
+ end
347
+
348
+ sub_test_case '#get_proto_info' do
349
+ test 'returns version of connection as Integer' do
350
+ assert{ @m.get_proto_info == 10 }
351
+ end
352
+ end
353
+
354
+ sub_test_case '#proto_info' do
355
+ test 'returns version of connection as Integer' do
356
+ assert{ @m.proto_info == 10 }
357
+ end
358
+ end
359
+
360
+ sub_test_case '#get_server_info' do
361
+ test 'returns server version as String' do
362
+ assert{ @m.get_server_info =~ /\A\d+\.\d+\.\d+/ }
363
+ end
364
+ end
365
+
366
+ sub_test_case '#server_info' do
367
+ test 'returns server version as String' do
368
+ assert{ @m.server_info =~ /\A\d+\.\d+\.\d+/ }
369
+ end
370
+ end
371
+
372
+ sub_test_case '#info' do
373
+ test 'returns information of latest query' do
374
+ @m.query 'create temporary table t (id int)'
375
+ @m.query 'insert into t values (1),(2),(3)'
376
+ assert{ @m.info == 'Records: 3 Duplicates: 0 Warnings: 0' }
377
+ end
378
+ end
379
+
380
+ sub_test_case '#insert_id' do
381
+ test 'returns latest auto_increment value' do
382
+ @m.query 'create temporary table t (id int auto_increment, unique (id))'
383
+ @m.query 'insert into t values (0)'
384
+ assert{ @m.insert_id == 1 }
385
+ @m.query 'alter table t auto_increment=1234'
386
+ @m.query 'insert into t values (0)'
387
+ assert{ @m.insert_id == 1234 }
388
+ end
389
+ end
390
+
391
+ sub_test_case '#kill' do
392
+ setup do
393
+ @m2 = Mysql.new(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
394
+ end
395
+ teardown do
396
+ @m2.close rescue nil
397
+ end
398
+ test 'returns self' do
399
+ assert{ @m.kill(@m2.thread_id) == @m }
400
+ end
401
+ end
402
+
403
+ sub_test_case '#list_dbs' do
404
+ test 'returns database list' do
405
+ ret = @m.list_dbs
406
+ assert{ ret.kind_of? Array }
407
+ assert{ ret.include? MYSQL_DATABASE }
408
+ end
409
+ test 'with pattern returns databases that matches pattern' do
410
+ assert{ @m.list_dbs('info%').include? 'information_schema' }
411
+ end
412
+ end
413
+
414
+ sub_test_case '#list_fields' do
415
+ setup do
416
+ @m.query 'create temporary table t (i int, c char(10), d date)'
417
+ end
418
+ test 'returns result set that contains information of fields' do
419
+ ret = @m.list_fields('t')
420
+ assert{ ret.kind_of? Mysql::Result }
421
+ assert{ ret.num_rows == 0 }
422
+ assert{ ret.fetch_fields.map{|f|f.name} == ['i','c','d'] }
423
+ end
424
+ test 'with pattern returns result set that contains information of fields that matches pattern' do
425
+ ret = @m.list_fields('t', 'i')
426
+ assert{ ret.kind_of? Mysql::Result }
427
+ assert{ ret.num_rows == 0 }
428
+ ret.fetch_fields.map{|f|f.name} == ['i']
429
+ end
430
+ end
431
+
432
+ sub_test_case '#list_processes' do
433
+ test 'returns result set that contains information of all connections' do
434
+ ret = @m.list_processes
435
+ assert{ ret.kind_of? Mysql::Result }
436
+ assert{ ret.find{|r|r[0].to_i == @m.thread_id}[4] == "Processlist" }
437
+ end
438
+ end
439
+
440
+ sub_test_case '#list_tables' do
441
+ setup do
442
+ @m.query 'create table test_mysql_list_tables (id int)'
443
+ end
444
+ teardown do
445
+ @m.query 'drop table if exists test_mysql_list_tables'
446
+ end
447
+ test 'returns table list' do
448
+ ret = @m.list_tables
449
+ assert{ ret.kind_of? Array }
450
+ assert{ ret.include? 'test_mysql_list_tables' }
451
+ end
452
+ test 'with pattern returns lists that matches pattern' do
453
+ ret = @m.list_tables '%mysql\_list\_t%'
454
+ assert{ ret.include? 'test_mysql_list_tables' }
455
+ end
456
+ end
457
+
458
+ sub_test_case '#ping' do
459
+ test 'returns self' do
460
+ assert{ @m.ping == @m }
461
+ end
462
+ end
463
+
464
+ sub_test_case '#query' do
465
+ test 'returns Mysql::Result if query returns results' do
466
+ assert{ @m.query('select 123').kind_of? Mysql::Result }
467
+ end
468
+ test 'returns nil if query returns no results' do
469
+ assert{ @m.query('set @hoge:=123') == nil }
470
+ end
471
+ test 'returns self if query_with_result is false' do
472
+ @m.query_with_result = false
473
+ assert{ @m.query('select 123') == @m }
474
+ @m.store_result
475
+ assert{ @m.query('set @hoge:=123') == @m }
476
+ end
477
+ end
478
+
479
+ sub_test_case '#real_query' do
480
+ test 'is same as #query' do
481
+ assert{ @m.real_query('select 123').kind_of? Mysql::Result }
482
+ end
483
+ end
484
+
485
+ sub_test_case '#refresh' do
486
+ test 'returns self' do
487
+ assert{ @m.refresh(Mysql::REFRESH_HOSTS) == @m }
488
+ end
489
+ end
490
+
491
+ sub_test_case '#reload' do
492
+ test 'returns self' do
493
+ assert{ @m.reload == @m }
494
+ end
495
+ end
496
+
497
+ sub_test_case '#select_db' do
498
+ test 'changes default database' do
499
+ @m.select_db 'information_schema'
500
+ assert{ @m.query('select database()').fetch_row.first == 'information_schema' }
501
+ end
502
+ end
503
+
504
+ # sub_test_case '#shutdown' do
505
+ # end
506
+
507
+ sub_test_case '#stat' do
508
+ test 'returns server status' do
509
+ assert{ @m.stat =~ /\AUptime: \d+ Threads: \d+ Questions: \d+ Slow queries: \d+ Opens: \d+ Flush tables: \d+ Open tables: \d+ Queries per second avg: \d+\.\d+\z/ }
510
+ end
511
+ end
512
+
513
+ sub_test_case '#store_result' do
514
+ test 'returns Mysql::Result' do
515
+ @m.query_with_result = false
516
+ @m.query 'select 1,2,3'
517
+ ret = @m.store_result
518
+ assert{ ret.kind_of? Mysql::Result }
519
+ assert{ ret.fetch_row == ['1','2','3'] }
520
+ end
521
+ test 'raises error when no query' do
522
+ assert_raise Mysql::ClientError, 'invalid usage' do
523
+ @m.store_result
524
+ end
525
+ end
526
+ test 'raises error when query does not return results' do
527
+ @m.query 'set @hoge:=123'
528
+ assert_raise Mysql::ClientError, 'invalid usage' do
529
+ @m.store_result
530
+ end
531
+ end
532
+ end
533
+
534
+ sub_test_case '#thread_id' do
535
+ test 'returns thread id as Integer' do
536
+ assert{ @m.thread_id.kind_of? Integer }
537
+ end
538
+ end
539
+
540
+ sub_test_case '#use_result' do
541
+ test 'returns Mysql::Result' do
542
+ @m.query_with_result = false
543
+ @m.query 'select 1,2,3'
544
+ ret = @m.use_result
545
+ assert{ ret.kind_of? Mysql::Result }
546
+ assert{ ret.fetch_row == ['1','2','3'] }
547
+ end
548
+ test 'raises error when no query' do
549
+ assert_raise Mysql::ClientError, 'invalid usage' do
550
+ @m.use_result
551
+ end
552
+ end
553
+ test 'raises error when query does not return results' do
554
+ @m.query 'set @hoge:=123'
555
+ assert_raise Mysql::ClientError, 'invalid usage' do
556
+ @m.use_result
557
+ end
558
+ end
559
+ end
560
+
561
+ sub_test_case '#get_server_version' do
562
+ test 'returns server version as Integer' do
563
+ assert{ @m.get_server_version.kind_of? Integer }
564
+ end
565
+ end
566
+
567
+ sub_test_case '#server_version' do
568
+ test 'returns server version as Integer' do
569
+ assert{ @m.server_version.kind_of? Integer }
570
+ end
571
+ end
572
+
573
+ sub_test_case '#warning_count' do
574
+ setup do
575
+ @m.query("set sql_mode=''")
576
+ @m.query("set sql_mode=''") # clear warnings on previous `set' statement.
577
+ end
578
+ test 'default values is zero' do
579
+ assert{ @m.warning_count == 0 }
580
+ end
581
+ test 'returns number of warnings' do
582
+ @m.query 'create temporary table t (i tinyint)'
583
+ @m.query 'insert into t values (1234567)'
584
+ assert{ @m.warning_count == 1 }
585
+ end
586
+ end
587
+
588
+ sub_test_case '#commit' do
589
+ test 'returns self' do
590
+ assert{ @m.commit == @m }
591
+ end
592
+ end
593
+
594
+ sub_test_case '#rollback' do
595
+ test 'returns self' do
596
+ assert{ @m.rollback == @m }
597
+ end
598
+ end
599
+
600
+ sub_test_case '#autocommit' do
601
+ test 'returns self' do
602
+ assert{ @m.autocommit(true) == @m }
603
+ end
604
+
605
+ test 'change auto-commit mode' do
606
+ @m.autocommit(true)
607
+ assert{ @m.query('select @@autocommit').fetch_row == ['1'] }
608
+ @m.autocommit(false)
609
+ assert{ @m.query('select @@autocommit').fetch_row == ['0'] }
610
+ end
611
+ end
612
+
613
+ sub_test_case '#set_server_option' do
614
+ test 'returns self' do
615
+ assert{ @m.set_server_option(Mysql::OPTION_MULTI_STATEMENTS_ON) == @m }
616
+ end
617
+ end
618
+
619
+ sub_test_case '#sqlstate' do
620
+ test 'default values is "00000"' do
621
+ assert{ @m.sqlstate == "00000" }
622
+ end
623
+ test 'returns sqlstate code' do
624
+ assert_raise do
625
+ @m.query("hoge")
626
+ end
627
+ assert{ @m.sqlstate == "42000" }
628
+ end
629
+ end
630
+
631
+ sub_test_case '#query_with_result' do
632
+ test 'default value is true' do
633
+ assert{ @m.query_with_result == true }
634
+ end
635
+ test 'can set value' do
636
+ assert{ (@m.query_with_result=true) == true }
637
+ assert{ @m.query_with_result == true }
638
+ assert{ (@m.query_with_result=false) == false }
639
+ assert{ @m.query_with_result == false }
640
+ end
641
+ end
642
+
643
+ sub_test_case '#query_with_result is false' do
644
+ test 'Mysql#query returns self and Mysql#store_result returns result set' do
645
+ @m.query_with_result = false
646
+ assert{ @m.query('select 1,2,3') == @m }
647
+ res = @m.store_result
648
+ assert{ res.fetch_row == ['1','2','3'] }
649
+ end
650
+ end
651
+
652
+ sub_test_case '#query with block' do
653
+ test 'returns self' do
654
+ assert{ @m.query('select 1'){} == @m }
655
+ end
656
+ test 'evaluate block with Mysql::Result' do
657
+ assert{ @m.query('select 1'){|res| res.kind_of? Mysql::Result} == @m }
658
+ end
659
+ test 'evaluate block multiple times if multiple query is specified' do
660
+ @m.set_server_option Mysql::OPTION_MULTI_STATEMENTS_ON
661
+ cnt = 0
662
+ expect = [["1"], ["2"]]
663
+ assert{ @m.query('select 1; select 2'){|res|
664
+ assert{ res.fetch_row == expect.shift }
665
+ cnt += 1
666
+ } == @m }
667
+ assert{ cnt == 2 }
668
+ end
669
+ test 'evaluate block only when query has result' do
670
+ @m.set_server_option Mysql::OPTION_MULTI_STATEMENTS_ON
671
+ cnt = 0
672
+ expect = [["1"], ["2"]]
673
+ assert{ @m.query('select 1; set @hoge:=1; select 2'){|res|
674
+ assert{ res.fetch_row == expect.shift }
675
+ cnt += 1
676
+ } == @m }
677
+ assert{ cnt == 2 }
678
+ end
679
+ end
680
+ end
681
+
682
+ sub_test_case 'multiple statement query:' do
683
+ setup do
684
+ @m = Mysql.new(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
685
+ @m.set_server_option(Mysql::OPTION_MULTI_STATEMENTS_ON)
686
+ @res = @m.query 'select 1,2; select 3,4,5'
687
+ end
688
+ test 'Mysql#query returns results for first query' do
689
+ assert{ @res.entries == [['1','2']] }
690
+ end
691
+ test 'Mysql#more_results is true' do
692
+ assert{ @m.more_results == true }
693
+ end
694
+ test 'Mysql#more_results? is true' do
695
+ assert{ @m.more_results? == true }
696
+ end
697
+ test 'Mysql#next_result is true' do
698
+ assert{ @m.next_result == true }
699
+ end
700
+ sub_test_case 'for next query:' do
701
+ setup do
702
+ @m.next_result
703
+ @res = @m.store_result
704
+ end
705
+ test 'Mysql#store_result returns results' do
706
+ assert{ @res.entries == [['3','4','5']] }
707
+ end
708
+ test 'Mysql#more_results is false' do
709
+ assert{ @m.more_results == false }
710
+ end
711
+ test 'Mysql#more_results? is false' do
712
+ assert{ @m.more_results? == false }
713
+ end
714
+ test 'Mysql#next_result is false' do
715
+ assert{ @m.next_result == false }
716
+ end
717
+ end
718
+ end
719
+
720
+ sub_test_case 'Mysql::Result' do
721
+ setup do
722
+ @m = Mysql.new(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
723
+ @m.charset = 'latin1'
724
+ @m.query 'create temporary table t (id int default 0, str char(10), primary key (id))'
725
+ @m.query "insert into t values (1,'abc'),(2,'defg'),(3,'hi'),(4,null)"
726
+ @res = @m.query 'select * from t'
727
+ end
728
+
729
+ teardown do
730
+ @m.close if @m
731
+ end
732
+
733
+ test '#data_seek set position of current record' do
734
+ assert{ @res.fetch_row == ['1', 'abc'] }
735
+ assert{ @res.fetch_row == ['2', 'defg'] }
736
+ assert{ @res.fetch_row == ['3', 'hi'] }
737
+ @res.data_seek 1
738
+ assert{ @res.fetch_row == ['2', 'defg'] }
739
+ end
740
+
741
+ test '#fetch_field return current field' do
742
+ f = @res.fetch_field
743
+ assert{ f.name == 'id' }
744
+ assert{ f.table == 't' }
745
+ assert{ f.def == nil }
746
+ assert{ f.type == Mysql::Field::TYPE_LONG }
747
+ assert{ f.length == 11 }
748
+ assert{ f.max_length == 1 }
749
+ assert{ f.flags == Mysql::Field::NUM_FLAG|Mysql::Field::PRI_KEY_FLAG|Mysql::Field::PART_KEY_FLAG|Mysql::Field::NOT_NULL_FLAG }
750
+ assert{ f.decimals == 0 }
751
+
752
+ f = @res.fetch_field
753
+ assert{ f.name == 'str' }
754
+ assert{ f.table == 't' }
755
+ assert{ f.def == nil }
756
+ assert{ f.type == Mysql::Field::TYPE_STRING }
757
+ assert{ f.length == 10 }
758
+ assert{ f.max_length == 4 }
759
+ assert{ f.flags == 0 }
760
+ assert{ f.decimals == 0 }
761
+
762
+ assert{ @res.fetch_field == nil }
763
+ end
764
+
765
+ test '#fetch_fields returns array of fields' do
766
+ ret = @res.fetch_fields
767
+ assert{ ret.size == 2 }
768
+ assert{ ret[0].name == 'id' }
769
+ assert{ ret[1].name == 'str' }
770
+ end
771
+
772
+ test '#fetch_field_direct returns field' do
773
+ f = @res.fetch_field_direct 0
774
+ assert{ f.name == 'id' }
775
+ f = @res.fetch_field_direct 1
776
+ assert{ f.name == 'str' }
777
+ assert_raise Mysql::ClientError, 'invalid argument: -1' do
778
+ @res.fetch_field_direct(-1)
779
+ end
780
+ assert_raise Mysql::ClientError, 'invalid argument: 2' do
781
+ @res.fetch_field_direct 2
782
+ end
783
+ end
784
+
785
+ test '#fetch_lengths returns array of length of field data' do
786
+ assert{ @res.fetch_lengths == nil }
787
+ @res.fetch_row
788
+ assert{ @res.fetch_lengths == [1, 3] }
789
+ @res.fetch_row
790
+ assert{ @res.fetch_lengths == [1, 4] }
791
+ @res.fetch_row
792
+ assert{ @res.fetch_lengths == [1, 2] }
793
+ @res.fetch_row
794
+ assert{ @res.fetch_lengths == [1, 0] }
795
+ @res.fetch_row
796
+ assert{ @res.fetch_lengths == nil }
797
+ end
798
+
799
+ test '#fetch_row returns one record as array for current record' do
800
+ assert{ @res.fetch_row == ['1', 'abc'] }
801
+ assert{ @res.fetch_row == ['2', 'defg'] }
802
+ assert{ @res.fetch_row == ['3', 'hi'] }
803
+ assert{ @res.fetch_row == ['4', nil] }
804
+ assert{ @res.fetch_row == nil }
805
+ end
806
+
807
+ test '#fetch_hash returns one record as hash for current record' do
808
+ assert{ @res.fetch_hash == {'id'=>'1', 'str'=>'abc'} }
809
+ assert{ @res.fetch_hash == {'id'=>'2', 'str'=>'defg'} }
810
+ assert{ @res.fetch_hash == {'id'=>'3', 'str'=>'hi'} }
811
+ assert{ @res.fetch_hash == {'id'=>'4', 'str'=>nil} }
812
+ assert{ @res.fetch_hash == nil }
813
+ end
814
+
815
+ test '#fetch_hash(true) returns with table name' do
816
+ assert{ @res.fetch_hash(true) == {'t.id'=>'1', 't.str'=>'abc'} }
817
+ assert{ @res.fetch_hash(true) == {'t.id'=>'2', 't.str'=>'defg'} }
818
+ assert{ @res.fetch_hash(true) == {'t.id'=>'3', 't.str'=>'hi'} }
819
+ assert{ @res.fetch_hash(true) == {'t.id'=>'4', 't.str'=>nil} }
820
+ assert{ @res.fetch_hash(true) == nil }
821
+ end
822
+
823
+ test '#num_fields returns number of fields' do
824
+ assert{ @res.num_fields == 2 }
825
+ end
826
+
827
+ test '#num_rows returns number of records' do
828
+ assert{ @res.num_rows == 4 }
829
+ end
830
+
831
+ test '#each iterate block with a record' do
832
+ expect = [["1","abc"], ["2","defg"], ["3","hi"], ["4",nil]]
833
+ @res.each do |a|
834
+ assert{ a == expect.shift }
835
+ end
836
+ end
837
+
838
+ test '#each_hash iterate block with a hash' do
839
+ expect = [{"id"=>"1","str"=>"abc"}, {"id"=>"2","str"=>"defg"}, {"id"=>"3","str"=>"hi"}, {"id"=>"4","str"=>nil}]
840
+ @res.each_hash do |a|
841
+ assert{ a == expect.shift }
842
+ end
843
+ end
844
+
845
+ test '#each_hash(true): hash key has table name' do
846
+ expect = [{"t.id"=>"1","t.str"=>"abc"}, {"t.id"=>"2","t.str"=>"defg"}, {"t.id"=>"3","t.str"=>"hi"}, {"t.id"=>"4","t.str"=>nil}]
847
+ @res.each_hash(true) do |a|
848
+ assert{ a == expect.shift }
849
+ end
850
+ end
851
+
852
+ test '#row_tell returns position of current record, #row_seek set position of current record' do
853
+ assert{ @res.fetch_row == ['1', 'abc'] }
854
+ pos = @res.row_tell
855
+ assert{ @res.fetch_row == ['2', 'defg'] }
856
+ assert{ @res.fetch_row == ['3', 'hi'] }
857
+ @res.row_seek pos
858
+ assert{ @res.fetch_row == ['2', 'defg'] }
859
+ end
860
+
861
+ test '#field_tell returns position of current field, #field_seek set position of current field' do
862
+ assert{ @res.field_tell == 0 }
863
+ @res.fetch_field
864
+ assert{ @res.field_tell == 1 }
865
+ @res.fetch_field
866
+ assert{ @res.field_tell == 2 }
867
+ @res.field_seek 1
868
+ assert{ @res.field_tell == 1 }
869
+ end
870
+
871
+ test '#free returns nil' do
872
+ assert{ @res.free == nil }
873
+ end
874
+ end
875
+
876
+ sub_test_case 'Mysql::Field' do
877
+ setup do
878
+ @m = Mysql.new(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
879
+ @m.charset = 'latin1'
880
+ @m.query 'create temporary table t (id int default 0, str char(10), primary key (id))'
881
+ @m.query "insert into t values (1,'abc'),(2,'defg'),(3,'hi'),(4,null)"
882
+ @res = @m.query 'select * from t'
883
+ end
884
+
885
+ teardown do
886
+ @m.close if @m
887
+ end
888
+
889
+ test '#name is name of field' do
890
+ assert{ @res.fetch_field.name == 'id' }
891
+ end
892
+
893
+ test '#table is name of table for field' do
894
+ assert{ @res.fetch_field.table == 't' }
895
+ end
896
+
897
+ test '#def for result set is null' do
898
+ assert{ @res.fetch_field.def == nil }
899
+ end
900
+
901
+ test '#def for field information is default value' do
902
+ assert{ @m.list_fields('t').fetch_field.def == '0' }
903
+ end
904
+
905
+ test '#type is type of field as Integer' do
906
+ assert{ @res.fetch_field.type == Mysql::Field::TYPE_LONG }
907
+ assert{ @res.fetch_field.type == Mysql::Field::TYPE_STRING }
908
+ end
909
+
910
+ test '#length is length of field' do
911
+ assert{ @res.fetch_field.length == 11 }
912
+ assert{ @res.fetch_field.length == 10 }
913
+ end
914
+
915
+ test '#max_length is maximum length of field value' do
916
+ assert{ @res.fetch_field.max_length == 1 }
917
+ assert{ @res.fetch_field.max_length == 4 }
918
+ end
919
+
920
+ test '#flags is flag of field as Integer' do
921
+ assert{ @res.fetch_field.flags == Mysql::Field::NUM_FLAG|Mysql::Field::PRI_KEY_FLAG|Mysql::Field::PART_KEY_FLAG|Mysql::Field::NOT_NULL_FLAG }
922
+ assert{ @res.fetch_field.flags == 0 }
923
+ end
924
+
925
+ test '#decimals is number of decimal digits' do
926
+ assert{ @m.query('select 1.23').fetch_field.decimals == 2 }
927
+ end
928
+
929
+ test '#hash return field as hash' do
930
+ assert{ @res.fetch_field.hash == {
931
+ 'name' => 'id',
932
+ 'table' => 't',
933
+ 'def' => nil,
934
+ 'type' => Mysql::Field::TYPE_LONG,
935
+ 'length' => 11,
936
+ 'max_length' => 1,
937
+ 'flags' => Mysql::Field::NUM_FLAG|Mysql::Field::PRI_KEY_FLAG|Mysql::Field::PART_KEY_FLAG|Mysql::Field::NOT_NULL_FLAG,
938
+ 'decimals' => 0,
939
+ }
940
+ }
941
+ assert{ @res.fetch_field.hash == {
942
+ 'name' => 'str',
943
+ 'table' => 't',
944
+ 'def' => nil,
945
+ 'type' => Mysql::Field::TYPE_STRING,
946
+ 'length' => 10,
947
+ 'max_length' => 4,
948
+ 'flags' => 0,
949
+ 'decimals' => 0,
950
+ }
951
+ }
952
+ end
953
+
954
+ test '#inspect returns "#<Mysql::Field:name>"' do
955
+ assert{ @res.fetch_field.inspect == '#<Mysql::Field:id>' }
956
+ assert{ @res.fetch_field.inspect == '#<Mysql::Field:str>' }
957
+ end
958
+
959
+ test '#is_num? returns true if the field is numeric' do
960
+ assert{ @res.fetch_field.is_num? == true }
961
+ assert{ @res.fetch_field.is_num? == false }
962
+ end
963
+
964
+ test '#is_not_null? returns true if the field is not null' do
965
+ assert{ @res.fetch_field.is_not_null? == true }
966
+ assert{ @res.fetch_field.is_not_null? == false }
967
+ end
968
+
969
+ test '#is_pri_key? returns true if the field is primary key' do
970
+ assert{ @res.fetch_field.is_pri_key? == true }
971
+ assert{ @res.fetch_field.is_pri_key? == false }
972
+ end
973
+ end
974
+
975
+ sub_test_case 'create Mysql::Stmt object:' do
976
+ setup do
977
+ @m = Mysql.new(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
978
+ end
979
+
980
+ teardown do
981
+ @m.close if @m
982
+ end
983
+
984
+ test 'Mysql#stmt_init returns Mysql::Stmt object' do
985
+ assert{ @m.stmt_init.kind_of? Mysql::Stmt }
986
+ end
987
+
988
+ test 'Mysq;#prepare returns Mysql::Stmt object' do
989
+ assert{ @m.prepare("select 1").kind_of? Mysql::Stmt }
990
+ end
991
+ end
992
+
993
+ sub_test_case 'Mysql::Stmt' do
994
+ setup do
995
+ @m = Mysql.new(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
996
+ @m.query("set sql_mode=''")
997
+ @s = @m.stmt_init
998
+ end
999
+
1000
+ teardown do
1001
+ @s.close if @s rescue nil
1002
+ @m.close if @m
1003
+ end
1004
+
1005
+ test '#affected_rows returns number of affected records' do
1006
+ @m.query 'create temporary table t (i int, c char(10))'
1007
+ @s.prepare 'insert into t values (?,?)'
1008
+ @s.execute 1, 'hoge'
1009
+ assert{ @s.affected_rows == 1 }
1010
+ @s.execute 2, 'hoge'
1011
+ @s.execute 3, 'hoge'
1012
+ @s.prepare 'update t set c=?'
1013
+ @s.execute 'fuga'
1014
+ assert{ @s.affected_rows == 3 }
1015
+ end
1016
+
1017
+ sub_test_case '#bind_result' do
1018
+ setup do
1019
+ @m.query 'create temporary table t (i int, c char(10), d double, t datetime)'
1020
+ @m.query 'insert into t values (123,"9abcdefg",1.2345,20091208100446)'
1021
+ @s.prepare 'select * from t'
1022
+ end
1023
+
1024
+ test '(nil) make result format to be standard value' do
1025
+ @s.bind_result nil, nil, nil, nil
1026
+ @s.execute
1027
+ assert{ @s.fetch == [123, '9abcdefg', 1.2345, Mysql::Time.new(2009,12,8,10,4,46)] }
1028
+ end
1029
+
1030
+ test '(Numeric) make result format to be Integer value' do
1031
+ @s.bind_result Numeric, Numeric, Numeric, Numeric
1032
+ @s.execute
1033
+ assert{ @s.fetch == [123, 9, 1, 20091208100446] }
1034
+ end
1035
+
1036
+ test '(Integer) make result format to be Integer value' do
1037
+ @s.bind_result Integer, Integer, Integer, Integer
1038
+ @s.execute
1039
+ assert{ @s.fetch == [123, 9, 1, 20091208100446] }
1040
+ end
1041
+
1042
+ test '(Fixnum) make result format to be Integer value' do
1043
+ @s.bind_result Fixnum, Fixnum, Fixnum, Fixnum
1044
+ @s.execute
1045
+ assert{ @s.fetch == [123, 9, 1, 20091208100446] }
1046
+ end
1047
+
1048
+ test '(String) make result format to be String value' do
1049
+ @s.bind_result String, String, String, String
1050
+ @s.execute
1051
+ assert{ @s.fetch == ["123", "9abcdefg", "1.2345", "2009-12-08 10:04:46"] }
1052
+ end
1053
+
1054
+ test '(Float) make result format to be Float value' do
1055
+ @s.bind_result Float, Float, Float, Float
1056
+ @s.execute
1057
+ assert{ @s.fetch == [123.0, 9.0, 1.2345 , 20091208100446.0] }
1058
+ end
1059
+
1060
+ test '(Mysql::Time) make result format to be Mysql::Time value' do
1061
+ @s.bind_result Mysql::Time, Mysql::Time, Mysql::Time, Mysql::Time
1062
+ @s.execute
1063
+ assert{ @s.fetch == [Mysql::Time.new(2000,1,23), Mysql::Time.new, Mysql::Time.new, Mysql::Time.new(2009,12,8,10,4,46)] }
1064
+ end
1065
+
1066
+ test '(invalid) raises error' do
1067
+ assert_raise TypeError do
1068
+ @s.bind_result(Time, nil, nil, nil)
1069
+ end
1070
+ end
1071
+
1072
+ test 'with mismatch argument count raise error' do
1073
+ assert_raise Mysql::ClientError, 'bind_result: result value count(4) != number of argument(1)' do
1074
+ @s.bind_result(nil)
1075
+ end
1076
+ end
1077
+ end
1078
+
1079
+ test '#close returns nil' do
1080
+ assert{ @s.close == nil }
1081
+ end
1082
+
1083
+ test '#data_seek set position of current record' do
1084
+ @m.query 'create temporary table t (i int)'
1085
+ @m.query 'insert into t values (0),(1),(2),(3),(4),(5),(6)'
1086
+ @s.prepare 'select i from t'
1087
+ @s.execute
1088
+ assert{ @s.fetch == [0] }
1089
+ assert{ @s.fetch == [1] }
1090
+ assert{ @s.fetch == [2] }
1091
+ @s.data_seek 5
1092
+ assert{ @s.fetch == [5] }
1093
+ @s.data_seek 1
1094
+ assert{ @s.fetch == [1] }
1095
+ end
1096
+
1097
+ test '#each iterate block with a record' do
1098
+ @m.query 'create temporary table t (i int, c char(255), d datetime)'
1099
+ @m.query "insert into t values (1,'abc','19701224235905'),(2,'def','21120903123456'),(3,'123',null)"
1100
+ @s.prepare 'select * from t'
1101
+ @s.execute
1102
+ expect = [
1103
+ [1, 'abc', Mysql::Time.new(1970,12,24,23,59,05)],
1104
+ [2, 'def', Mysql::Time.new(2112,9,3,12,34,56)],
1105
+ [3, '123', nil],
1106
+ ]
1107
+ @s.each do |a|
1108
+ assert{ a == expect.shift }
1109
+ end
1110
+ end
1111
+
1112
+ test '#execute returns self' do
1113
+ @s.prepare 'select 1'
1114
+ assert{ @s.execute == @s }
1115
+ end
1116
+
1117
+ test '#execute pass arguments to query' do
1118
+ @m.query 'create temporary table t (i int)'
1119
+ @s.prepare 'insert into t values (?)'
1120
+ @s.execute 123
1121
+ @s.execute '456'
1122
+ assert{ @m.query('select * from t').entries == [['123'], ['456']] }
1123
+ end
1124
+
1125
+ test '#execute with various arguments' do
1126
+ @m.query 'create temporary table t (i int, c char(255), t timestamp)'
1127
+ @s.prepare 'insert into t values (?,?,?)'
1128
+ @s.execute 123, 'hoge', Time.local(2009,12,8,19,56,21)
1129
+ assert{ @m.query('select * from t').fetch_row == ['123', 'hoge', '2009-12-08 19:56:21'] }
1130
+ end
1131
+
1132
+ test '#execute with arguments that is invalid count raise error' do
1133
+ @s.prepare 'select ?'
1134
+ assert_raise Mysql::ClientError, 'parameter count mismatch' do
1135
+ @s.execute 123, 456
1136
+ end
1137
+ end
1138
+
1139
+ test '#execute with huge value' do
1140
+ [30, 31, 32, 62, 63].each do |i|
1141
+ assert{ @m.prepare('select cast(? as signed)').execute(2**i-1).fetch == [2**i-1] }
1142
+ assert{ @m.prepare('select cast(? as signed)').execute(-(2**i)).fetch == [-2**i] }
1143
+ end
1144
+ end
1145
+
1146
+ sub_test_case '#execute with various integer value:' do
1147
+ setup do
1148
+ @m.query('create temporary table t (i bigint)')
1149
+ end
1150
+ [
1151
+ -9223372036854775808,
1152
+ -9223372036854775807,
1153
+ -4294967297,
1154
+ -4294967296,
1155
+ -4294967295,
1156
+ -2147483649,
1157
+ -2147483648,
1158
+ -2147483647,
1159
+ -65537,
1160
+ -65536,
1161
+ -65535,
1162
+ -32769,
1163
+ -32768,
1164
+ -32767,
1165
+ -257,
1166
+ -256,
1167
+ -255,
1168
+ -129,
1169
+ -128,
1170
+ -127,
1171
+ 0,
1172
+ 126,
1173
+ 127,
1174
+ 128,
1175
+ 254,
1176
+ 255,
1177
+ 256,
1178
+ 32766,
1179
+ 32767,
1180
+ 32768,
1181
+ 65534,
1182
+ 65535,
1183
+ 65536,
1184
+ 2147483646,
1185
+ 2147483647,
1186
+ 2147483648,
1187
+ 4294967294,
1188
+ 4294967295,
1189
+ 4294967296,
1190
+ 9223372036854775806,
1191
+ 9223372036854775807,
1192
+ ].each do |n|
1193
+ test "#{n} is #{n}" do
1194
+ @s.prepare 'insert into t values (?)'
1195
+ @s.execute n
1196
+ assert{ @m.query('select i from t').fetch == ["#{n}"] }
1197
+ end
1198
+ end
1199
+ end
1200
+
1201
+ sub_test_case '#execute with various unsigned integer value:' do
1202
+ setup do
1203
+ @m.query('create temporary table t (i bigint unsigned)')
1204
+ end
1205
+ [
1206
+ 0,
1207
+ 126,
1208
+ 127,
1209
+ 128,
1210
+ 254,
1211
+ 255,
1212
+ 256,
1213
+ 32766,
1214
+ 32767,
1215
+ 32768,
1216
+ 65534,
1217
+ 65535,
1218
+ 65536,
1219
+ 2147483646,
1220
+ 2147483647,
1221
+ 2147483648,
1222
+ 4294967294,
1223
+ 4294967295,
1224
+ 4294967296,
1225
+ 9223372036854775806,
1226
+ 9223372036854775807,
1227
+ 9223372036854775808,
1228
+ 18446744073709551614,
1229
+ 18446744073709551615,
1230
+ ].each do |n|
1231
+ test "#{n} is #{n}" do
1232
+ @s.prepare 'insert into t values (?)'
1233
+ @s.execute n
1234
+ assert{ @m.query('select i from t').fetch == ["#{n}"] }
1235
+ end
1236
+ end
1237
+ end
1238
+
1239
+ test '#fetch returns result-record' do
1240
+ @s.prepare 'select 123, "abc", null'
1241
+ @s.execute
1242
+ assert{ @s.fetch == [123, 'abc', nil] }
1243
+ end
1244
+
1245
+ test '#fetch bit column (8bit)' do
1246
+ @m.query 'create temporary table t (i bit(8))'
1247
+ @m.query 'insert into t values (0),(-1),(127),(-128),(255),(-255),(256)'
1248
+ @s.prepare 'select i from t'
1249
+ @s.execute
1250
+ if defined? Encoding
1251
+ assert{ @s.entries == [
1252
+ ["\x00".force_encoding('ASCII-8BIT')],
1253
+ ["\xff".force_encoding('ASCII-8BIT')],
1254
+ ["\x7f".force_encoding('ASCII-8BIT')],
1255
+ ["\xff".force_encoding('ASCII-8BIT')],
1256
+ ["\xff".force_encoding('ASCII-8BIT')],
1257
+ ["\xff".force_encoding('ASCII-8BIT')],
1258
+ ["\xff".force_encoding('ASCII-8BIT')],
1259
+ ]
1260
+ }
1261
+ else
1262
+ assert{ @s.entries == [["\x00"], ["\xff"], ["\x7f"], ["\xff"], ["\xff"], ["\xff"], ["\xff"]] }
1263
+ end
1264
+ end
1265
+
1266
+ test '#fetch bit column (64bit)' do
1267
+ @m.query 'create temporary table t (i bit(64))'
1268
+ @m.query 'insert into t values (0),(-1),(4294967296),(18446744073709551615),(18446744073709551616)'
1269
+ @s.prepare 'select i from t'
1270
+ @s.execute
1271
+ if defined? Encoding
1272
+ assert{ @s.entries == [
1273
+ ["\x00\x00\x00\x00\x00\x00\x00\x00".force_encoding('ASCII-8BIT')],
1274
+ ["\xff\xff\xff\xff\xff\xff\xff\xff".force_encoding('ASCII-8BIT')],
1275
+ ["\x00\x00\x00\x01\x00\x00\x00\x00".force_encoding('ASCII-8BIT')],
1276
+ ["\xff\xff\xff\xff\xff\xff\xff\xff".force_encoding('ASCII-8BIT')],
1277
+ ["\xff\xff\xff\xff\xff\xff\xff\xff".force_encoding('ASCII-8BIT')],
1278
+ ]
1279
+ }
1280
+ else
1281
+ assert{ @s.entries == [
1282
+ ["\x00\x00\x00\x00\x00\x00\x00\x00"],
1283
+ ["\xff\xff\xff\xff\xff\xff\xff\xff"],
1284
+ ["\x00\x00\x00\x01\x00\x00\x00\x00"],
1285
+ ["\xff\xff\xff\xff\xff\xff\xff\xff"],
1286
+ ["\xff\xff\xff\xff\xff\xff\xff\xff"],
1287
+ ]
1288
+ }
1289
+ end
1290
+ end
1291
+
1292
+ test '#fetch tinyint column' do
1293
+ @m.query 'create temporary table t (i tinyint)'
1294
+ @m.query 'insert into t values (0),(-1),(127),(-128),(255),(-255)'
1295
+ @s.prepare 'select i from t'
1296
+ @s.execute
1297
+ assert{ @s.entries == [[0], [-1], [127], [-128], [127], [-128]] }
1298
+ end
1299
+
1300
+ test '#fetch tinyint unsigned column' do
1301
+ @m.query 'create temporary table t (i tinyint unsigned)'
1302
+ @m.query 'insert into t values (0),(-1),(127),(-128),(255),(-255),(256)'
1303
+ @s.prepare 'select i from t'
1304
+ @s.execute
1305
+ assert{ @s.entries == [[0], [0], [127], [0], [255], [0], [255]] }
1306
+ end
1307
+
1308
+ test '#fetch smallint column' do
1309
+ @m.query 'create temporary table t (i smallint)'
1310
+ @m.query 'insert into t values (0),(-1),(32767),(-32768),(65535),(-65535),(65536)'
1311
+ @s.prepare 'select i from t'
1312
+ @s.execute
1313
+ assert{ @s.entries == [[0], [-1], [32767], [-32768], [32767], [-32768], [32767]] }
1314
+ end
1315
+
1316
+ test '#fetch smallint unsigned column' do
1317
+ @m.query 'create temporary table t (i smallint unsigned)'
1318
+ @m.query 'insert into t values (0),(-1),(32767),(-32768),(65535),(-65535),(65536)'
1319
+ @s.prepare 'select i from t'
1320
+ @s.execute
1321
+ assert{ @s.entries == [[0], [0], [32767], [0], [65535], [0], [65535]] }
1322
+ end
1323
+
1324
+ test '#fetch mediumint column' do
1325
+ @m.query 'create temporary table t (i mediumint)'
1326
+ @m.query 'insert into t values (0),(-1),(8388607),(-8388608),(16777215),(-16777215),(16777216)'
1327
+ @s.prepare 'select i from t'
1328
+ @s.execute
1329
+ assert{ @s.entries == [[0], [-1], [8388607], [-8388608], [8388607], [-8388608], [8388607]] }
1330
+ end
1331
+
1332
+ test '#fetch mediumint unsigned column' do
1333
+ @m.query 'create temporary table t (i mediumint unsigned)'
1334
+ @m.query 'insert into t values (0),(-1),(8388607),(-8388608),(16777215),(-16777215),(16777216)'
1335
+ @s.prepare 'select i from t'
1336
+ @s.execute
1337
+ assert{ @s.entries == [[0], [0], [8388607], [0], [16777215], [0], [16777215]] }
1338
+ end
1339
+
1340
+ test '#fetch int column' do
1341
+ @m.query 'create temporary table t (i int)'
1342
+ @m.query 'insert into t values (0),(-1),(2147483647),(-2147483648),(4294967295),(-4294967295),(4294967296)'
1343
+ @s.prepare 'select i from t'
1344
+ @s.execute
1345
+ assert{ @s.entries == [[0], [-1], [2147483647], [-2147483648], [2147483647], [-2147483648], [2147483647]] }
1346
+ end
1347
+
1348
+ test '#fetch int unsigned column' do
1349
+ @m.query 'create temporary table t (i int unsigned)'
1350
+ @m.query 'insert into t values (0),(-1),(2147483647),(-2147483648),(4294967295),(-4294967295),(4294967296)'
1351
+ @s.prepare 'select i from t'
1352
+ @s.execute
1353
+ assert{ @s.entries == [[0], [0], [2147483647], [0], [4294967295], [0], [4294967295]] }
1354
+ end
1355
+
1356
+ test '#fetch bigint column' do
1357
+ @m.query 'create temporary table t (i bigint)'
1358
+ @m.query 'insert into t values (0),(-1),(9223372036854775807),(-9223372036854775808),(18446744073709551615),(-18446744073709551615),(18446744073709551616)'
1359
+ @s.prepare 'select i from t'
1360
+ @s.execute
1361
+ assert{ @s.entries == [[0], [-1], [9223372036854775807], [-9223372036854775808], [9223372036854775807], [-9223372036854775808], [9223372036854775807]] }
1362
+ end
1363
+
1364
+ test '#fetch bigint unsigned column' do
1365
+ @m.query 'create temporary table t (i bigint unsigned)'
1366
+ @m.query 'insert into t values (0),(-1),(9223372036854775807),(-9223372036854775808),(18446744073709551615),(-18446744073709551615),(18446744073709551616)'
1367
+ @s.prepare 'select i from t'
1368
+ @s.execute
1369
+ assert{ @s.entries == [[0], [0], [9223372036854775807], [0], [18446744073709551615], [0], [18446744073709551615]] }
1370
+ end
1371
+
1372
+ test '#fetch float column' do
1373
+ @m.query 'create temporary table t (i float)'
1374
+ @m.query 'insert into t values (0),(-3.402823466E+38),(-1.175494351E-38),(1.175494351E-38),(3.402823466E+38)'
1375
+ @s.prepare 'select i from t'
1376
+ @s.execute
1377
+ assert{ @s.fetch[0] == 0.0 }
1378
+ assert{ (@s.fetch[0] - -3.402823466E+38).abs < 0.000000001E+38 }
1379
+ assert{ (@s.fetch[0] - -1.175494351E-38).abs < 0.000000001E-38 }
1380
+ assert{ (@s.fetch[0] - 1.175494351E-38).abs < 0.000000001E-38 }
1381
+ assert{ (@s.fetch[0] - 3.402823466E+38).abs < 0.000000001E+38 }
1382
+ end
1383
+
1384
+ test '#fetch float unsigned column' do
1385
+ @m.query 'create temporary table t (i float unsigned)'
1386
+ @m.query 'insert into t values (0),(-3.402823466E+38),(-1.175494351E-38),(1.175494351E-38),(3.402823466E+38)'
1387
+ @s.prepare 'select i from t'
1388
+ @s.execute
1389
+ assert{ @s.fetch[0] == 0.0 }
1390
+ assert{ @s.fetch[0] == 0.0 }
1391
+ assert{ @s.fetch[0] == 0.0 }
1392
+ assert{ (@s.fetch[0] - 1.175494351E-38).abs < 0.000000001E-38 }
1393
+ assert{ (@s.fetch[0] - 3.402823466E+38).abs < 0.000000001E+38 }
1394
+ end
1395
+
1396
+ test '#fetch double column' do
1397
+ @m.query 'create temporary table t (i double)'
1398
+ @m.query 'insert into t values (0),(-1.7976931348623157E+308),(-2.2250738585072014E-308),(2.2250738585072014E-308),(1.7976931348623157E+308)'
1399
+ @s.prepare 'select i from t'
1400
+ @s.execute
1401
+ assert{ @s.fetch[0] == 0.0 }
1402
+ assert{ (@s.fetch[0] - -Float::MAX).abs < Float::EPSILON }
1403
+ assert{ (@s.fetch[0] - -Float::MIN).abs < Float::EPSILON }
1404
+ assert{ (@s.fetch[0] - Float::MIN).abs < Float::EPSILON }
1405
+ assert{ (@s.fetch[0] - Float::MAX).abs < Float::EPSILON }
1406
+ end
1407
+
1408
+ test '#fetch double unsigned column' do
1409
+ @m.query 'create temporary table t (i double unsigned)'
1410
+ @m.query 'insert into t values (0),(-1.7976931348623157E+308),(-2.2250738585072014E-308),(2.2250738585072014E-308),(1.7976931348623157E+308)'
1411
+ @s.prepare 'select i from t'
1412
+ @s.execute
1413
+ assert{ @s.fetch[0] == 0.0 }
1414
+ assert{ @s.fetch[0] == 0.0 }
1415
+ assert{ @s.fetch[0] == 0.0 }
1416
+ assert{ (@s.fetch[0] - Float::MIN).abs < Float::EPSILON }
1417
+ assert{ (@s.fetch[0] - Float::MAX).abs < Float::EPSILON }
1418
+ end
1419
+
1420
+ test '#fetch decimal column' do
1421
+ @m.query 'create temporary table t (i decimal)'
1422
+ @m.query 'insert into t values (0),(9999999999),(-9999999999),(10000000000),(-10000000000)'
1423
+ @s.prepare 'select i from t'
1424
+ @s.execute
1425
+ assert{ @s.entries == [["0"], ["9999999999"], ["-9999999999"], ["9999999999"], ["-9999999999"]] }
1426
+ end
1427
+
1428
+ test '#fetch decimal unsigned column' do
1429
+ @m.query 'create temporary table t (i decimal unsigned)'
1430
+ @m.query 'insert into t values (0),(9999999998),(9999999999),(-9999999998),(-9999999999),(10000000000),(-10000000000)'
1431
+ @s.prepare 'select i from t'
1432
+ @s.execute
1433
+ assert{ @s.entries == [["0"], ["9999999998"], ["9999999999"], ["0"], ["0"], ["9999999999"], ["0"]] }
1434
+ end
1435
+
1436
+ test '#fetch date column' do
1437
+ @m.query 'create temporary table t (i date)'
1438
+ @m.query "insert into t values ('0000-00-00'),('1000-01-01'),('9999-12-31')"
1439
+ @s.prepare 'select i from t'
1440
+ @s.execute
1441
+ cols = @s.fetch
1442
+ assert{ cols == [Mysql::Time.new] }
1443
+ assert{ cols.first.to_s == '0000-00-00' }
1444
+ cols = @s.fetch
1445
+ assert{ cols == [Mysql::Time.new(1000,1,1)] }
1446
+ assert{ cols.first.to_s == '1000-01-01' }
1447
+ cols = @s.fetch
1448
+ assert{ cols == [Mysql::Time.new(9999,12,31)] }
1449
+ assert{ cols.first.to_s == '9999-12-31' }
1450
+ end
1451
+
1452
+ test '#fetch datetime column' do
1453
+ @m.query 'create temporary table t (i datetime)'
1454
+ @m.query "insert into t values ('0000-00-00 00:00:00'),('1000-01-01 00:00:00'),('9999-12-31 23:59:59')"
1455
+ @s.prepare 'select i from t'
1456
+ @s.execute
1457
+ assert{ @s.fetch == [Mysql::Time.new] }
1458
+ assert{ @s.fetch == [Mysql::Time.new(1000,1,1)] }
1459
+ assert{ @s.fetch == [Mysql::Time.new(9999,12,31,23,59,59)] }
1460
+ end
1461
+
1462
+ test '#fetch timestamp column' do
1463
+ @m.query 'create temporary table t (i timestamp)'
1464
+ @m.query("insert into t values ('1970-01-02 00:00:00'),('2037-12-30 23:59:59')")
1465
+ @s.prepare 'select i from t'
1466
+ @s.execute
1467
+ assert{ @s.fetch == [Mysql::Time.new(1970,1,2)] }
1468
+ assert{ @s.fetch == [Mysql::Time.new(2037,12,30,23,59,59)] }
1469
+ end
1470
+
1471
+ test '#fetch time column' do
1472
+ @m.query 'create temporary table t (i time)'
1473
+ @m.query "insert into t values ('-838:59:59'),(0),('838:59:59')"
1474
+ @s.prepare 'select i from t'
1475
+ @s.execute
1476
+ assert{ @s.fetch == [Mysql::Time.new(0,0,0,838,59,59,true)] }
1477
+ assert{ @s.fetch == [Mysql::Time.new(0,0,0,0,0,0,false)] }
1478
+ assert{ @s.fetch == [Mysql::Time.new(0,0,0,838,59,59,false)] }
1479
+ end
1480
+
1481
+ test '#fetch year column' do
1482
+ @m.query 'create temporary table t (i year)'
1483
+ @m.query 'insert into t values (0),(70),(69),(1901),(2155)'
1484
+ @s.prepare 'select i from t'
1485
+ @s.execute
1486
+ assert{ @s.entries == [[0], [1970], [2069], [1901], [2155]] }
1487
+ end
1488
+
1489
+ test '#fetch char column' do
1490
+ @m.query 'create temporary table t (i char(10))'
1491
+ @m.query "insert into t values (null),('abc')"
1492
+ @s.prepare 'select i from t'
1493
+ @s.execute
1494
+ assert{ @s.entries == [[nil], ['abc']] }
1495
+ end
1496
+
1497
+ test '#fetch varchar column' do
1498
+ @m.query 'create temporary table t (i varchar(10))'
1499
+ @m.query "insert into t values (null),('abc')"
1500
+ @s.prepare 'select i from t'
1501
+ @s.execute
1502
+ assert{ @s.entries == [[nil], ['abc']] }
1503
+ end
1504
+
1505
+ test '#fetch binary column' do
1506
+ @m.query 'create temporary table t (i binary(10))'
1507
+ @m.query "insert into t values (null),('abc')"
1508
+ @s.prepare 'select i from t'
1509
+ @s.execute
1510
+ assert{ @s.entries == [[nil], ["abc\0\0\0\0\0\0\0"]] }
1511
+ end
1512
+
1513
+ test '#fetch varbinary column' do
1514
+ @m.query 'create temporary table t (i varbinary(10))'
1515
+ @m.query "insert into t values (null),('abc')"
1516
+ @s.prepare 'select i from t'
1517
+ @s.execute
1518
+ assert{ @s.entries == [[nil], ["abc"]] }
1519
+ end
1520
+
1521
+ test '#fetch tinyblob column' do
1522
+ @m.query 'create temporary table t (i tinyblob)'
1523
+ @m.query "insert into t values (null),('#{"a"*255}')"
1524
+ @s.prepare 'select i from t'
1525
+ @s.execute
1526
+ assert{ @s.entries == [[nil], ["a"*255]] }
1527
+ end
1528
+
1529
+ test '#fetch tinytext column' do
1530
+ @m.query 'create temporary table t (i tinytext)'
1531
+ @m.query "insert into t values (null),('#{"a"*255}')"
1532
+ @s.prepare 'select i from t'
1533
+ @s.execute
1534
+ assert{ @s.entries == [[nil], ["a"*255]] }
1535
+ end
1536
+
1537
+ test '#fetch blob column' do
1538
+ @m.query 'create temporary table t (i blob)'
1539
+ @m.query "insert into t values (null),('#{"a"*65535}')"
1540
+ @s.prepare 'select i from t'
1541
+ @s.execute
1542
+ assert{ @s.entries == [[nil], ["a"*65535]] }
1543
+ end
1544
+
1545
+ test '#fetch text column' do
1546
+ @m.query 'create temporary table t (i text)'
1547
+ @m.query "insert into t values (null),('#{"a"*65535}')"
1548
+ @s.prepare 'select i from t'
1549
+ @s.execute
1550
+ assert{ @s.entries == [[nil], ["a"*65535]] }
1551
+ end
1552
+
1553
+ test '#fetch mediumblob column' do
1554
+ @m.query 'create temporary table t (i mediumblob)'
1555
+ @m.query "insert into t values (null),('#{"a"*16777215}')"
1556
+ @s.prepare 'select i from t'
1557
+ @s.execute
1558
+ assert{ @s.entries == [[nil], ['a'*16777215]] }
1559
+ end
1560
+
1561
+ test '#fetch mediumtext column' do
1562
+ @m.query 'create temporary table t (i mediumtext)'
1563
+ @m.query "insert into t values (null),('#{"a"*16777215}')"
1564
+ @s.prepare 'select i from t'
1565
+ @s.execute
1566
+ assert{ @s.entries == [[nil], ['a'*16777215]] }
1567
+ end
1568
+
1569
+ test '#fetch longblob column' do
1570
+ @m.query 'create temporary table t (i longblob)'
1571
+ @m.query "insert into t values (null),('#{"a"*16777216}')"
1572
+ @s.prepare 'select i from t'
1573
+ @s.execute
1574
+ assert{ @s.entries == [[nil], ["a"*16777216]] }
1575
+ end
1576
+
1577
+ test '#fetch longtext column' do
1578
+ @m.query 'create temporary table t (i longtext)'
1579
+ @m.query "insert into t values (null),('#{"a"*16777216}')"
1580
+ @s.prepare 'select i from t'
1581
+ @s.execute
1582
+ assert{ @s.entries == [[nil], ["a"*16777216]] }
1583
+ end
1584
+
1585
+ test '#fetch enum column' do
1586
+ @m.query "create temporary table t (i enum('abc','def'))"
1587
+ @m.query "insert into t values (null),(0),(1),(2),('abc'),('def'),('ghi')"
1588
+ @s.prepare 'select i from t'
1589
+ @s.execute
1590
+ assert{ @s.entries == [[nil], [''], ['abc'], ['def'], ['abc'], ['def'], ['']] }
1591
+ end
1592
+
1593
+ test '#fetch set column' do
1594
+ @m.query "create temporary table t (i set('abc','def'))"
1595
+ @m.query "insert into t values (null),(0),(1),(2),(3),('abc'),('def'),('abc,def'),('ghi')"
1596
+ @s.prepare 'select i from t'
1597
+ @s.execute
1598
+ assert{ @s.entries == [[nil], [''], ['abc'], ['def'], ['abc,def'], ['abc'], ['def'], ['abc,def'], ['']] }
1599
+ end
1600
+
1601
+ test '#fetch json column' do
1602
+ if @m.server_version >= 50700
1603
+ @m.query "create temporary table t (i json)"
1604
+ @m.query "insert into t values ('123'),('{\"a\":1,\"b\":2,\"c\":3}'),('[1,2,3]')"
1605
+ @s.prepare 'select i from t'
1606
+ @s.execute
1607
+ assert{ @s.entries == [['123'], ['{"a": 1, "b": 2, "c": 3}'], ['[1, 2, 3]']] }
1608
+ end
1609
+ end
1610
+
1611
+ test '#field_count' do
1612
+ @s.prepare 'select 1,2,3'
1613
+ assert{ @s.field_count == 3 }
1614
+ @s.prepare 'set @a=1'
1615
+ assert{ @s.field_count == 0 }
1616
+ end
1617
+
1618
+ test '#free_result' do
1619
+ @s.free_result
1620
+ @s.prepare 'select 1,2,3'
1621
+ @s.execute
1622
+ @s.free_result
1623
+ end
1624
+
1625
+ test '#insert_id' do
1626
+ @m.query 'create temporary table t (i int auto_increment, unique(i))'
1627
+ @s.prepare 'insert into t values (0)'
1628
+ @s.execute
1629
+ assert{ @s.insert_id == 1 }
1630
+ @s.execute
1631
+ assert{ @s.insert_id == 2 }
1632
+ end
1633
+
1634
+ test '#num_rows' do
1635
+ @m.query 'create temporary table t (i int)'
1636
+ @m.query 'insert into t values (1),(2),(3),(4)'
1637
+ @s.prepare 'select * from t'
1638
+ @s.execute
1639
+ assert{ @s.num_rows == 4 }
1640
+ end
1641
+
1642
+ test '#param_count' do
1643
+ @m.query 'create temporary table t (a int, b int, c int)'
1644
+ @s.prepare 'select * from t'
1645
+ assert{ @s.param_count == 0 }
1646
+ @s.prepare 'insert into t values (?,?,?)'
1647
+ assert{ @s.param_count == 3 }
1648
+ end
1649
+
1650
+ test '#prepare' do
1651
+ assert{ @s.prepare('select 1').kind_of? Mysql::Stmt }
1652
+ assert_raise Mysql::ParseError do
1653
+ @s.prepare 'invalid syntax'
1654
+ end
1655
+ end
1656
+
1657
+ test '#prepare returns self' do
1658
+ assert{ @s.prepare('select 1') == @s }
1659
+ end
1660
+
1661
+ test '#prepare with invalid query raises error' do
1662
+ assert_raise Mysql::ParseError do
1663
+ @s.prepare 'invalid query'
1664
+ end
1665
+ end
1666
+
1667
+ test '#result_metadata' do
1668
+ @s.prepare 'select 1 foo, 2 bar'
1669
+ f = @s.result_metadata.fetch_fields
1670
+ assert{ f[0].name == 'foo' }
1671
+ assert{ f[1].name == 'bar' }
1672
+ end
1673
+
1674
+ test '#result_metadata forn no data' do
1675
+ @s.prepare 'set @a=1'
1676
+ assert{ @s.result_metadata == nil }
1677
+ end
1678
+
1679
+ test '#row_seek and #row_tell' do
1680
+ @m.query 'create temporary table t (i int)'
1681
+ @m.query 'insert into t values (0),(1),(2),(3),(4)'
1682
+ @s.prepare 'select * from t'
1683
+ @s.execute
1684
+ row0 = @s.row_tell
1685
+ assert{ @s.fetch == [0] }
1686
+ assert{ @s.fetch == [1] }
1687
+ row2 = @s.row_seek row0
1688
+ assert{ @s.fetch == [0] }
1689
+ @s.row_seek row2
1690
+ assert{ @s.fetch == [2] }
1691
+ end
1692
+
1693
+ test '#sqlstate' do
1694
+ @s.prepare 'select 1'
1695
+ assert{ @s.sqlstate == '00000' }
1696
+ assert_raise Mysql::ParseError do
1697
+ @s.prepare 'hogehoge'
1698
+ end
1699
+ assert{ @s.sqlstate == '42000' }
1700
+ end
1701
+ end
1702
+
1703
+ sub_test_case 'Mysql::Time' do
1704
+ setup do
1705
+ @t = Mysql::Time.new
1706
+ end
1707
+
1708
+ test '.new with no arguments returns 0' do
1709
+ assert{ @t.year == 0 }
1710
+ assert{ @t.month == 0 }
1711
+ assert{ @t.day == 0 }
1712
+ assert{ @t.hour == 0 }
1713
+ assert{ @t.minute == 0 }
1714
+ assert{ @t.second == 0 }
1715
+ assert{ @t.neg == false }
1716
+ assert{ @t.second_part == 0 }
1717
+ end
1718
+
1719
+ test '#inspect' do
1720
+ assert{ Mysql::Time.new(2009,12,8,23,35,21).inspect == '#<Mysql::Time:2009-12-08 23:35:21>' }
1721
+ end
1722
+
1723
+ test '#to_s' do
1724
+ assert{ Mysql::Time.new(2009,12,8,23,35,21).to_s == '2009-12-08 23:35:21' }
1725
+ end
1726
+
1727
+ test '#to_i' do
1728
+ assert{ Mysql::Time.new(2009,12,8,23,35,21).to_i == 20091208233521 }
1729
+ end
1730
+
1731
+ test '#year' do
1732
+ assert{ (@t.year = 2009) == 2009 }
1733
+ assert{ @t.year == 2009 }
1734
+ end
1735
+
1736
+ test '#month' do
1737
+ assert{ (@t.month = 12) == 12 }
1738
+ assert{ @t.month == 12 }
1739
+ end
1740
+
1741
+ test '#day' do
1742
+ assert{ (@t.day = 8) == 8 }
1743
+ assert{ @t.day == 8 }
1744
+ end
1745
+
1746
+ test '#hour' do
1747
+ assert{ (@t.hour = 23) == 23 }
1748
+ assert{ @t.hour == 23 }
1749
+ end
1750
+
1751
+ test '#minute' do
1752
+ assert{ (@t.minute = 35) == 35 }
1753
+ assert{ @t.minute == 35 }
1754
+ end
1755
+
1756
+ test '#second' do
1757
+ assert{ (@t.second = 21) == 21 }
1758
+ assert{ @t.second == 21 }
1759
+ end
1760
+
1761
+ test '#neg' do
1762
+ assert{ @t.neg == false }
1763
+ end
1764
+
1765
+ test '#second_part' do
1766
+ assert{ @t.second_part == 0 }
1767
+ end
1768
+
1769
+ test '#==' do
1770
+ t1 = Mysql::Time.new 2009,12,8,23,35,21
1771
+ t2 = Mysql::Time.new 2009,12,8,23,35,21
1772
+ assert{ t1 == t2 }
1773
+ end
1774
+ end
1775
+
1776
+ sub_test_case 'Mysql::Error' do
1777
+ setup do
1778
+ m = Mysql.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
1779
+ begin
1780
+ m.query('hogehoge')
1781
+ rescue => @e
1782
+ end
1783
+ end
1784
+
1785
+ test '#error is error message' do
1786
+ assert{ @e.error == "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'hogehoge' at line 1" }
1787
+ end
1788
+
1789
+ test '#errno is error number' do
1790
+ assert{ @e.errno == 1064 }
1791
+ end
1792
+
1793
+ test '#sqlstate is sqlstate value as String' do
1794
+ assert{ @e.sqlstate == '42000' }
1795
+ end
1796
+ end
1797
+
1798
+ if defined? Encoding
1799
+ sub_test_case 'Connection charset is UTF-8:' do
1800
+ setup do
1801
+ @m = Mysql.connect(MYSQL_SERVER, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, MYSQL_PORT, MYSQL_SOCKET)
1802
+ @m.charset = "utf8"
1803
+ @m.query "create temporary table t (utf8 char(10) charset utf8, cp932 char(10) charset cp932, eucjp char(10) charset eucjpms, bin varbinary(10))"
1804
+ @utf8 = "いろは"
1805
+ @cp932 = @utf8.encode "CP932"
1806
+ @eucjp = @utf8.encode "EUC-JP-MS"
1807
+ @bin = "\x00\x01\x7F\x80\xFE\xFF".force_encoding("ASCII-8BIT")
1808
+ @default_internal = Encoding.default_internal
1809
+ end
1810
+
1811
+ teardown do
1812
+ Encoding.default_internal = @default_internal
1813
+ end
1814
+
1815
+ sub_test_case 'default_internal is CP932' do
1816
+ setup do
1817
+ @m.prepare("insert into t (utf8,cp932,eucjp,bin) values (?,?,?,?)").execute @utf8, @cp932, @eucjp, @bin
1818
+ Encoding.default_internal = 'CP932'
1819
+ end
1820
+ test 'is converted to CP932' do
1821
+ assert @m.query('select "あいう"').fetch == ["\x82\xA0\x82\xA2\x82\xA4".force_encoding("CP932")]
1822
+ end
1823
+ test 'data is stored as is' do
1824
+ assert @m.query('select hex(utf8),hex(cp932),hex(eucjp),hex(bin) from t').fetch == ['E38184E3828DE381AF', '82A282EB82CD', 'A4A4A4EDA4CF', '00017F80FEFF']
1825
+ end
1826
+ test 'By simple query, charset of retrieved data is connection charset' do
1827
+ assert @m.query('select utf8,cp932,eucjp,bin from t').fetch == [@cp932, @cp932, @cp932, @bin]
1828
+ end
1829
+ test 'By prepared statement, charset of retrieved data is connection charset except for binary' do
1830
+ assert @m.prepare('select utf8,cp932,eucjp,bin from t').execute.fetch == [@cp932, @cp932, @cp932, @bin]
1831
+ end
1832
+ end
1833
+
1834
+ sub_test_case 'query with CP932 encoding' do
1835
+ test 'is converted to UTF-8' do
1836
+ assert @m.query('select HEX("あいう")'.encode("CP932")).fetch == ["E38182E38184E38186"]
1837
+ end
1838
+ end
1839
+
1840
+ sub_test_case 'prepared statement with CP932 encoding' do
1841
+ test 'is converted to UTF-8' do
1842
+ assert @m.prepare('select HEX("あいう")'.encode("CP932")).execute.fetch == ["E38182E38184E38186"]
1843
+ end
1844
+ end
1845
+
1846
+ sub_test_case 'The encoding of data are correspond to charset of column:' do
1847
+ setup do
1848
+ @m.prepare("insert into t (utf8,cp932,eucjp,bin) values (?,?,?,?)").execute @utf8, @cp932, @eucjp, @bin
1849
+ end
1850
+ test 'data is stored as is' do
1851
+ assert{ @m.query('select hex(utf8),hex(cp932),hex(eucjp),hex(bin) from t').fetch == ['E38184E3828DE381AF', '82A282EB82CD', 'A4A4A4EDA4CF', '00017F80FEFF'] }
1852
+ end
1853
+ test 'By simple query, charset of retrieved data is connection charset' do
1854
+ assert{ @m.query('select utf8,cp932,eucjp,bin from t').fetch == [@utf8, @utf8, @utf8, @bin] }
1855
+ end
1856
+ test 'By prepared statement, charset of retrieved data is connection charset except for binary' do
1857
+ assert{ @m.prepare('select utf8,cp932,eucjp,bin from t').execute.fetch == [@utf8, @utf8, @utf8, @bin] }
1858
+ end
1859
+ end
1860
+
1861
+ sub_test_case 'The encoding of data are different from charset of column:' do
1862
+ setup do
1863
+ @m.prepare("insert into t (utf8,cp932,eucjp,bin) values (?,?,?,?)").execute @utf8, @utf8, @utf8, @utf8
1864
+ end
1865
+ test 'stored data is converted' do
1866
+ assert{ @m.query("select hex(utf8),hex(cp932),hex(eucjp),hex(bin) from t").fetch == ["E38184E3828DE381AF", "82A282EB82CD", "A4A4A4EDA4CF", "E38184E3828DE381AF"] }
1867
+ end
1868
+ test 'By simple query, charset of retrieved data is connection charset' do
1869
+ assert{ @m.query("select utf8,cp932,eucjp,bin from t").fetch == [@utf8, @utf8, @utf8, @utf8.dup.force_encoding('ASCII-8BIT')] }
1870
+ end
1871
+ test 'By prepared statement, charset of retrieved data is connection charset except for binary' do
1872
+ assert{ @m.prepare("select utf8,cp932,eucjp,bin from t").execute.fetch == [@utf8, @utf8, @utf8, @utf8.dup.force_encoding("ASCII-8BIT")] }
1873
+ end
1874
+ end
1875
+
1876
+ sub_test_case 'The data include invalid byte code:' do
1877
+ test 'raises Encoding::InvalidByteSequenceError' do
1878
+ cp932 = "\x01\xFF\x80".force_encoding("CP932")
1879
+ assert_raise Encoding::InvalidByteSequenceError do
1880
+ @m.prepare("insert into t (cp932) values (?)").execute cp932
1881
+ end
1882
+ end
1883
+ end
1884
+ end
1885
+ end
1886
+ end