ruby-mysql 2.11.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40bdb4e1eba4eca2ed1e93524260bd9407f91ee5f65b8c32b8c38524ef05ebdd
4
- data.tar.gz: 224ad0bdf2050dca6e5d7a603bd64cb44a5f414270aa06b9dd89690cd2665a32
3
+ metadata.gz: 37cc4956fc000b612b24fe104acf96abf27e0a7016cbd05c2c5e7b4ae5e0bade
4
+ data.tar.gz: b2c4ded73325a5c4aadce1d81af507e2a7d4144764150fde183f0e541e25e8b8
5
5
  SHA512:
6
- metadata.gz: a73e1ab248a44935cd4115c0d2de16f491d51b2eb7ab7a9b33185a0f478be8753cc226ea78d645a2bb1ae0b09cb15a7432f9e8d5a1dfa82af3ef016783689544
7
- data.tar.gz: 37db0a8b13b5a543cf9d552801aa0419c4ccce9fbe287d8df0335002df728e5e5ab5a9d82c873c174dec547b1077730cd265a4a6ace1714c88cb984b3d5f4134
6
+ metadata.gz: c81163849e312cb8cb861a1c5add93fba0973d1fbf01b9296513914931134230dbf7d2d6437e72097c8426d24daab316c2756621d3302d5ee91efb72ab951cc3
7
+ data.tar.gz: c4e13cea550e4659db986772663b04364c8c18f51abc9442516058cbe5ebc420dd19a95e324e149ae0966edefa1259fff9274677295849834029f827667547c2
data/CHANGELOG.md ADDED
@@ -0,0 +1,58 @@
1
+ ## [3.0.1] - 2022-06-18
2
+
3
+ - LICENSE: correct author
4
+ - FIX: correct LOAD DATA LOCAL INFILE result information.
5
+ - FIX: reset SERVER_MORE_RESULTS_EXISTS when error packet is received.
6
+ - FIX: close the socket when the connection is disconnected.
7
+ - FIX: allow multiple results by default.
8
+
9
+ ## [3.0.0] - 2021-11-16
10
+
11
+ - `Mysql.new` no longer connect. use `Mysql.connect` or `Mysql#connect`.
12
+
13
+ - `Mysql.init` is removed. use `Mysql.new` instead.
14
+
15
+ - `Mysql.new`, `Mysql.conncet` and `Mysql#connect` takes URI object or URI string or Hash object.
16
+ example:
17
+ Mysql.connect('mysql://user:password@hostname:port/dbname?charset=ascii')
18
+ Mysql.connect('mysql://user:password@%2Ftmp%2Fmysql.sock/dbname?charset=ascii') # for UNIX socket
19
+ Mysql.connect('hostname', 'user', 'password', 'dbname')
20
+ Mysql.connect(host: 'hostname', username: 'user', password: 'password', database: 'dbname')
21
+
22
+ - `Mysql.options` is removed. use `Mysql#param = value` instead.
23
+ For example:
24
+ m = Mysql.init
25
+ m.options(Mysql::OPT_LOCAL_INFILE, true)
26
+ m.connect(host, user, passwd)
27
+ change to
28
+ m = Mysql.new
29
+ m.local_infile = true
30
+ m.connect(host, user, passwd)
31
+ or
32
+ m = Mysql.connect(host, user, passwd, local_infile: true)
33
+
34
+ - `Mysql::Time` is removed.
35
+ Instead, `Time` object is returned for the DATE, DATETIME, TIMESTAMP data,
36
+ and `Integer` object is returned for the TIME data.
37
+ If DATE, DATETIME, TIMESTAMP are invalid values for Time, nil is returned.
38
+
39
+ - meaningless methods are removed:
40
+ * `bind_result`
41
+ * `client_info`
42
+ * `client_version`
43
+ * `get_proto_info`
44
+ * `get_server_info`
45
+ * `get_server_version`
46
+ * `proto_info`
47
+ * `query_with_result`
48
+
49
+ - alias method are removed:
50
+ * `get_host_info`: use `host_info`
51
+ * `real_connect`: use `connect`
52
+ * `real_query`: use `query`
53
+
54
+ - methods corresponding to deprecated APIs in MySQL are removed:
55
+ * `list_dbs`: use `SHOW DATABASES`
56
+ * `list_fields`: use `SHOW COLUMNS`
57
+ * `list_processes`: use `SHOW PROCESSLIST`
58
+ * `list_tables`: use `SHOW TABLES`
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # ruby-mysql
2
+
3
+ ## Description
4
+
5
+ MySQL connector for Ruby.
6
+
7
+ ## Installation
8
+
9
+ ```
10
+ gem install ruby-mysql
11
+ ```
12
+
13
+ ## Synopsis
14
+
15
+ ```ruby
16
+ my = Mysql.connect('mysql://username:password@hostname:port/dbname?charset=utf8mb4')
17
+ my.query("select col1, col2 from tblname").each do |col1, col2|
18
+ p col1, col2
19
+ end
20
+ stmt = my.prepare('insert into tblname (col1,col2) values (?,?)')
21
+ stmt.execute 123, 'abc'
22
+ ```
23
+
24
+ ## Copyright
25
+
26
+ * Author: TOMITA Masahiro <tommy@tmtm.org>
27
+ * Copyright: Copyright 2008 TOMITA Masahiro
28
+ * License: MIT
@@ -15,12 +15,10 @@ class Mysql
15
15
  MAX_PACKET_LENGTH = 2**24-1
16
16
 
17
17
  # Convert netdata to Ruby value
18
- # === Argument
19
- # data :: [Packet] packet data
20
- # type :: [Integer] field type
21
- # unsigned :: [true or false] true if value is unsigned
22
- # === Return
23
- # Object :: converted value.
18
+ # @param data [Packet] packet data
19
+ # @param type [Integer] field type
20
+ # @param unsigned [true or false] true if value is unsigned
21
+ # @return [Object] converted value.
24
22
  def self.net2value(pkt, type, unsigned)
25
23
  case type
26
24
  when Field::TYPE_STRING, Field::TYPE_VAR_STRING, Field::TYPE_NEWDECIMAL, Field::TYPE_BLOB, Field::TYPE_JSON
@@ -45,17 +43,18 @@ class Mysql
45
43
  when Field::TYPE_DATE
46
44
  len = pkt.utiny
47
45
  y, m, d = pkt.read(len).unpack("vCC")
48
- t = Mysql::Time.new(y, m, d, nil, nil, nil)
46
+ t = Time.new(y, m, d) rescue nil
49
47
  return t
50
48
  when Field::TYPE_DATETIME, Field::TYPE_TIMESTAMP
51
49
  len = pkt.utiny
52
50
  y, m, d, h, mi, s, sp = pkt.read(len).unpack("vCCCCCV")
53
- return Mysql::Time.new(y, m, d, h, mi, s, false, sp)
51
+ return Time.new(y, m, d, h, mi, Rational((s.to_i*1000000+sp.to_i)/1000000)) rescue nil
54
52
  when Field::TYPE_TIME
55
53
  len = pkt.utiny
56
54
  sign, d, h, mi, s, sp = pkt.read(len).unpack("CVCCCV")
57
- h = d.to_i * 24 + h.to_i
58
- return Mysql::Time.new(0, 0, 0, h, mi, s, sign!=0, sp)
55
+ r = d.to_i*86400 + h.to_i*3600 + mi.to_i*60 + s.to_i + sp.to_f/1000000
56
+ r *= -1 if sign != 0
57
+ return r
59
58
  when Field::TYPE_YEAR
60
59
  return pkt.ushort
61
60
  when Field::TYPE_BIT
@@ -66,13 +65,10 @@ class Mysql
66
65
  end
67
66
 
68
67
  # convert Ruby value to netdata
69
- # === Argument
70
- # v :: [Object] Ruby value.
71
- # === Return
72
- # Integer :: type of column. Field::TYPE_*
73
- # String :: netdata
74
- # === Exception
75
- # ProtocolError :: value too large / value is not supported
68
+ # @param v [Object] Ruby value.
69
+ # @return [Integer] type of column. Field::TYPE_*
70
+ # @return [String] netdata
71
+ # @raise [ProtocolError] value too large / value is not supported
76
72
  def self.value2net(v)
77
73
  case v
78
74
  when nil
@@ -97,12 +93,9 @@ class Mysql
97
93
  when String
98
94
  type = Field::TYPE_STRING
99
95
  val = Packet.lcs(v)
100
- when ::Time
96
+ when Time
101
97
  type = Field::TYPE_DATETIME
102
98
  val = [11, v.year, v.month, v.day, v.hour, v.min, v.sec, v.usec].pack("CvCCCCCV")
103
- when Mysql::Time
104
- type = Field::TYPE_DATETIME
105
- val = [11, v.year, v.month, v.day, v.hour, v.min, v.sec, v.second_part].pack("CvCCCCCV")
106
99
  else
107
100
  raise ProtocolError, "class #{v.class} is not supported"
108
101
  end
@@ -129,30 +122,38 @@ class Mysql
129
122
  # :RESULT :: After retr_fields(), retr_all_records() or stmt_retr_all_records() is needed.
130
123
 
131
124
  # make socket connection to server.
132
- # @param host [String] if "localhost" or "" or nil then use UNIX socket. Otherwise use TCP socket
133
- # @param port [Integer] port number using by TCP socket
134
- # @param socket [String] socket file name using by UNIX socket
135
- # @param [Hash] opts
136
- # @option opts :conn_timeout [Integer] connect timeout (sec).
137
- # @option opts :read_timeout [Integer] read timeout (sec).
138
- # @option opts :write_timeout [Integer] write timeout (sec).
139
- # @option opts :local_infile [String] local infile path
140
- # @option opts :get_server_public_key [Boolean]
125
+ # @param opts [Hash]
126
+ # @option :host [String] hostname mysqld running
127
+ # @option :username [String] username to connect to mysqld
128
+ # @option :password [String] password to connect to mysqld
129
+ # @option :database [String] initial database name
130
+ # @option :port [String] port number (used if host is not 'localhost' or nil)
131
+ # @option :socket [String] socket filename (used if host is 'localhost' or nil)
132
+ # @option :flags [Integer] connection flag. Mysql::CLIENT_* ORed
133
+ # @option :charset [Mysql::Charset] character set
134
+ # @option :connect_timeout [Numeric, nil]
135
+ # @option :read_timeout [Numeric, nil]
136
+ # @option :write_timeout [Numeric, nil]
137
+ # @option :local_infile [Boolean]
138
+ # @option :load_data_local_dir [String]
139
+ # @option :ssl_mode [Integer]
140
+ # @option :get_server_public_key [Boolean]
141
141
  # @raise [ClientError] connection timeout
142
- def initialize(host, port, socket, opts)
142
+ def initialize(opts)
143
143
  @opts = opts
144
+ @charset = Mysql::Charset.by_name("utf8mb4")
144
145
  @insert_id = 0
145
146
  @warning_count = 0
146
147
  @gc_stmt_queue = [] # stmt id list which GC destroy.
147
148
  set_state :INIT
148
149
  @get_server_public_key = @opts[:get_server_public_key]
149
150
  begin
150
- if host.nil? or host.empty? or host == "localhost"
151
- socket ||= ENV["MYSQL_UNIX_PORT"] || MYSQL_UNIX_PORT
151
+ if @opts[:host].nil? or @opts[:host].empty? or @opts[:host] == "localhost"
152
+ socket = @opts[:socket] || ENV["MYSQL_UNIX_PORT"] || MYSQL_UNIX_PORT
152
153
  @socket = Socket.unix(socket)
153
154
  else
154
- port ||= ENV["MYSQL_TCP_PORT"] || (Socket.getservbyname("mysql","tcp") rescue MYSQL_TCP_PORT)
155
- @socket = Socket.tcp(host, port, connect_timeout: @opts[:connect_timeout])
155
+ port = @opts[:port] || ENV["MYSQL_TCP_PORT"] || (Socket.getservbyname("mysql","tcp") rescue MYSQL_TCP_PORT)
156
+ @socket = Socket.tcp(@opts[:host], port, connect_timeout: @opts[:connect_timeout])
156
157
  end
157
158
  rescue Errno::ETIMEDOUT
158
159
  raise ClientError, "connection timeout"
@@ -164,45 +165,39 @@ class Mysql
164
165
  end
165
166
 
166
167
  # initial negotiate and authenticate.
167
- # === Argument
168
- # user :: [String / nil] username
169
- # passwd :: [String / nil] password
170
- # db :: [String / nil] default database name. nil: no default.
171
- # flag :: [Integer] client flag
172
- # charset :: [Mysql::Charset / nil] charset for connection. nil: use server's charset
173
- # === Exception
174
- # ProtocolError :: The old style password is not supported
175
- def authenticate(user, passwd, db, flag, charset)
168
+ # @param charset [Mysql::Charset, nil] charset for connection. nil: use server's charset
169
+ # @raise [ProtocolError] The old style password is not supported
170
+ def authenticate
176
171
  check_state :INIT
177
- @authinfo = [user, passwd, db, flag, charset]
178
172
  reset
179
173
  init_packet = InitialPacket.parse read
180
174
  @server_info = init_packet.server_version
181
175
  @server_version = init_packet.server_version.split(/\D/)[0,3].inject{|a,b|a.to_i*100+b.to_i}
182
176
  @server_capabilities = init_packet.server_capabilities
183
177
  @thread_id = init_packet.thread_id
184
- @client_flags = CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | CLIENT_PLUGIN_AUTH
185
- @client_flags |= CLIENT_LOCAL_FILES if @opts[:local_infile]
186
- @client_flags |= CLIENT_CONNECT_WITH_DB if db
187
- @client_flags |= flag
188
- @charset = charset
189
- unless @charset
178
+ @client_flags = CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS | CLIENT_PLUGIN_AUTH
179
+ @client_flags |= CLIENT_LOCAL_FILES if @opts[:local_infile] || @opts[:load_data_local_dir]
180
+ @client_flags |= CLIENT_CONNECT_WITH_DB if @opts[:database]
181
+ @client_flags |= @opts[:flags]
182
+ if @opts[:charset]
183
+ @charset = @opts[:charset].is_a?(Charset) ? @opts[:charset] : Charset.by_name(@opts[:charset])
184
+ else
190
185
  @charset = Charset.by_number(init_packet.server_charset)
191
186
  @charset.encoding # raise error if unsupported charset
192
187
  end
193
188
  enable_ssl
194
- Authenticator.new(self).authenticate(user, passwd, db, init_packet.scramble_buff, init_packet.auth_plugin)
189
+ Authenticator.new(self).authenticate(@opts[:username], @opts[:password].to_s, @opts[:database], init_packet.scramble_buff, init_packet.auth_plugin)
195
190
  set_state :READY
196
191
  end
197
192
 
198
193
  def enable_ssl
199
194
  case @opts[:ssl_mode]
200
- when SSL_MODE_DISABLED
195
+ when SSL_MODE_DISABLED, '1', 'disabled'
201
196
  return
202
- when SSL_MODE_PREFERRED
197
+ when SSL_MODE_PREFERRED, '2', 'preferred'
203
198
  return if @socket.local_address.unix?
204
199
  return if @server_capabilities & CLIENT_SSL == 0
205
- when SSL_MODE_REQUIRED
200
+ when SSL_MODE_REQUIRED, '3', 'required'
206
201
  if @server_capabilities & CLIENT_SSL == 0
207
202
  raise ClientError::SslConnectionError, "SSL is required but the server doesn't support it"
208
203
  end
@@ -232,10 +227,8 @@ class Mysql
232
227
  end
233
228
 
234
229
  # Query command
235
- # === Argument
236
- # query :: [String] query string
237
- # === Return
238
- # [Integer / nil] number of fields of results. nil if no results.
230
+ # @param query [String] query string
231
+ # @return [Integer, nil] number of fields of results. nil if no results.
239
232
  def query_command(query)
240
233
  check_state :READY
241
234
  begin
@@ -249,8 +242,7 @@ class Mysql
249
242
  end
250
243
 
251
244
  # get result of query.
252
- # === Return
253
- # [integer / nil] number of fields of results. nil if no results.
245
+ # @return [integer, nil] number of fields of results. nil if no results.
254
246
  def get_result
255
247
  begin
256
248
  res_packet = ResultPacket.parse read
@@ -260,6 +252,7 @@ class Mysql
260
252
  end
261
253
  if res_packet.field_count.nil? # LOAD DATA LOCAL INFILE
262
254
  send_local_file(res_packet.message)
255
+ res_packet = ResultPacket.parse read
263
256
  end
264
257
  @affected_rows, @insert_id, @server_status, @warning_count, @message =
265
258
  res_packet.affected_rows, res_packet.insert_id, res_packet.server_status, res_packet.warning_count, res_packet.message
@@ -274,21 +267,18 @@ class Mysql
274
267
  # send local file to server
275
268
  def send_local_file(filename)
276
269
  filename = File.absolute_path(filename)
277
- if filename.start_with? @opts[:local_infile]
270
+ if @opts[:local_infile] || @opts[:load_data_local_dir] && filename.start_with?(@opts[:load_data_local_dir])
278
271
  File.open(filename){|f| write f}
279
272
  else
280
273
  raise ClientError::LoadDataLocalInfileRejected, 'LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.'
281
274
  end
282
275
  ensure
283
276
  write nil # EOF mark
284
- read
285
277
  end
286
278
 
287
279
  # Retrieve n fields
288
- # === Argument
289
- # n :: [Integer] number of fields
290
- # === Return
291
- # [Array of Mysql::Field] field list
280
+ # @param n [Integer] number of fields
281
+ # @return [Array<Mysql::Field>] field list
292
282
  def retr_fields(n)
293
283
  check_state :FIELD
294
284
  begin
@@ -303,10 +293,8 @@ class Mysql
303
293
  end
304
294
 
305
295
  # Retrieve all records for simple query
306
- # === Argument
307
- # fields :: [Array<Mysql::Field>] number of fields
308
- # === Return
309
- # [Array of Array of String] all records
296
+ # @param fields [Array<Mysql::Field>] number of fields
297
+ # @return [Array<Array<String>>] all records
310
298
  def retr_all_records(fields)
311
299
  check_state :RESULT
312
300
  enc = charset.encoding
@@ -323,43 +311,6 @@ class Mysql
323
311
  end
324
312
  end
325
313
 
326
- # Field list command
327
- # === Argument
328
- # table :: [String] table name.
329
- # field :: [String / nil] field name that may contain wild card.
330
- # === Return
331
- # [Array of Field] field list
332
- def field_list_command(table, field)
333
- synchronize do
334
- reset
335
- write [COM_FIELD_LIST, table, 0, field].pack("Ca*Ca*")
336
- fields = []
337
- until (data = read).eof?
338
- fields.push Field.new(FieldPacket.parse(data))
339
- end
340
- return fields
341
- end
342
- end
343
-
344
- # Process info command
345
- # === Return
346
- # [Array of Field] field list
347
- def process_info_command
348
- check_state :READY
349
- begin
350
- reset
351
- write [COM_PROCESS_INFO].pack("C")
352
- field_count = read.lcb
353
- fields = field_count.times.map{Field.new FieldPacket.parse(read)}
354
- read_eof_packet
355
- set_state :RESULT
356
- return fields
357
- rescue
358
- set_state :READY
359
- raise
360
- end
361
- end
362
-
363
314
  # Ping command
364
315
  def ping_command
365
316
  simple_command [COM_PING].pack("C")
@@ -391,12 +342,8 @@ class Mysql
391
342
  end
392
343
 
393
344
  # Stmt prepare command
394
- # === Argument
395
- # stmt :: [String] prepared statement
396
- # === Return
397
- # [Integer] statement id
398
- # [Integer] number of parameters
399
- # [Array of Field] field list
345
+ # @param stmt [String] prepared statement
346
+ # @return [Array<Integer, Integer, Array<Field>>] statement id, number of parameters, field list
400
347
  def stmt_prepare_command(stmt)
401
348
  synchronize do
402
349
  reset
@@ -417,11 +364,9 @@ class Mysql
417
364
  end
418
365
 
419
366
  # Stmt execute command
420
- # === Argument
421
- # stmt_id :: [Integer] statement id
422
- # values :: [Array] parameters
423
- # === Return
424
- # [Integer] number of fields
367
+ # @param stmt_id [Integer] statement id
368
+ # @param values [Array] parameters
369
+ # @return [Integer] number of fields
425
370
  def stmt_execute_command(stmt_id, values)
426
371
  check_state :READY
427
372
  begin
@@ -435,11 +380,9 @@ class Mysql
435
380
  end
436
381
 
437
382
  # Retrieve all records for prepared statement
438
- # === Argument
439
- # fields :: [Array of Mysql::Fields] field list
440
- # charset :: [Mysql::Charset]
441
- # === Return
442
- # [Array of Array of Object] all records
383
+ # @param fields [Array of Mysql::Fields] field list
384
+ # @param charset [Mysql::Charset]
385
+ # @return [Array<Array<Object>>] all records
443
386
  def stmt_retr_all_records(fields, charset)
444
387
  check_state :RESULT
445
388
  enc = charset.encoding
@@ -455,8 +398,7 @@ class Mysql
455
398
  end
456
399
 
457
400
  # Stmt close command
458
- # === Argument
459
- # stmt_id :: [Integer] statement id
401
+ # @param stmt_id [Integer] statement id
460
402
  def stmt_close_command(stmt_id)
461
403
  synchronize do
462
404
  reset
@@ -502,10 +444,8 @@ class Mysql
502
444
  end
503
445
 
504
446
  # Read one packet data
505
- # === Return
506
- # [Packet] packet data
507
- # === Exception
508
- # [ProtocolError] invalid packet sequence number
447
+ # @return [Packet] packet data
448
+ # @rails [ProtocolError] invalid packet sequence number
509
449
  def read
510
450
  data = ''
511
451
  len = nil
@@ -520,6 +460,7 @@ class Mysql
520
460
  raise EOFError unless ret && ret.length == len
521
461
  data.concat ret
522
462
  rescue EOFError
463
+ @socket.close rescue nil
523
464
  raise ClientError::ServerGoneError, 'MySQL server has gone away'
524
465
  rescue Errno::ETIMEDOUT
525
466
  raise ClientError, "read timeout"
@@ -534,6 +475,7 @@ class Mysql
534
475
  _, errno, message = data.unpack("Cva*") # Version 4.0 Error
535
476
  @sqlstate = ""
536
477
  end
478
+ @server_status &= ~SERVER_MORE_RESULTS_EXISTS
537
479
  message.force_encoding(@charset.encoding)
538
480
  if Mysql::ServerError::ERROR_MAP.key? errno
539
481
  raise Mysql::ServerError::ERROR_MAP[errno].new(message, @sqlstate)
@@ -546,9 +488,9 @@ class Mysql
546
488
  def read_timeout(len, timeout)
547
489
  return @socket.read(len) if timeout.nil? || timeout == 0
548
490
  result = ''
549
- e = ::Time.now + timeout
491
+ e = Time.now + timeout
550
492
  while result.size < len
551
- now = ::Time.now
493
+ now = Time.now
552
494
  raise Errno::ETIMEDOUT if now > e
553
495
  r = @socket.read_nonblock(len - result.size, exception: false)
554
496
  case r
@@ -566,8 +508,7 @@ class Mysql
566
508
  end
567
509
 
568
510
  # Write one packet data
569
- # === Argument
570
- # data :: [String / IO] packet data. If data is nil, write empty packet.
511
+ # @param data [String, IO, nil] packet data. If data is nil, write empty packet.
571
512
  def write(data)
572
513
  begin
573
514
  @socket.sync = false
@@ -584,6 +525,7 @@ class Mysql
584
525
  @socket.sync = true
585
526
  @socket.flush
586
527
  rescue Errno::EPIPE
528
+ @socket.close rescue nil
587
529
  raise ClientError::ServerGoneError, 'MySQL server has gone away'
588
530
  rescue Errno::ETIMEDOUT
589
531
  raise ClientError, "write timeout"
@@ -593,9 +535,9 @@ class Mysql
593
535
  def write_timeout(data, timeout)
594
536
  return @socket.write(data) if timeout.nil? || timeout == 0
595
537
  len = 0
596
- e = ::Time.now + timeout
538
+ e = Time.now + timeout
597
539
  while len < data.size
598
- now = ::Time.now
540
+ now = Time.now
599
541
  raise Errno::ETIMEDOUT if now > e
600
542
  l = @socket.write_nonblock(data[len..-1], exception: false)
601
543
  case l
@@ -611,17 +553,14 @@ class Mysql
611
553
  end
612
554
 
613
555
  # Read EOF packet
614
- # === Exception
615
- # [ProtocolError] packet is not EOF
556
+ # @raise [ProtocolError] packet is not EOF
616
557
  def read_eof_packet
617
558
  raise ProtocolError, "packet is not EOF" unless read.eof?
618
559
  end
619
560
 
620
561
  # Send simple command
621
- # === Argument
622
- # packet :: [String] packet data
623
- # === Return
624
- # [String] received data
562
+ # @param packet :: [String] packet data
563
+ # @return [String] received data
625
564
  def simple_command(packet)
626
565
  synchronize do
627
566
  reset
@@ -831,17 +770,15 @@ class Mysql
831
770
  end
832
771
 
833
772
  class StmtRawRecord
834
- # === Argument
835
- # pkt :: [Packet]
836
- # fields :: [Array of Fields]
837
- # encoding:: [Encoding]
773
+ # @param pkt [Packet]
774
+ # @param fields [Array of Fields]
775
+ # @param encoding [Encoding]
838
776
  def initialize(packet, fields, encoding)
839
777
  @packet, @fields, @encoding = packet, fields, encoding
840
778
  end
841
779
 
842
780
  # Parse statement result packet
843
- # === Return
844
- # [Array of Object] one record
781
+ # @return [Array<Object>] one record
845
782
  def parse_record_packet
846
783
  @packet.utiny # skip first byte
847
784
  null_bit_map = @packet.read((@fields.length+7+2)/8).unpack("b*").first
@@ -851,7 +788,7 @@ class Mysql
851
788
  else
852
789
  unsigned = f.flags & Field::UNSIGNED_FLAG != 0
853
790
  v = Protocol.net2value(@packet, f.type, unsigned)
854
- if v.is_a? Numeric or v.is_a? Mysql::Time
791
+ if v.nil? or v.is_a? Numeric or v.is_a? Time
855
792
  v
856
793
  elsif f.type == Field::TYPE_BIT or f.charsetnr == Charset::BINARY_CHARSET_NUMBER
857
794
  Charset.to_binary(v)