ruby-mysql 2.9.4 → 2.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ruby-mysql might be problematic. Click here for more details.

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