mysql-pr 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,9 +13,8 @@ require "openssl"
13
13
  class MysqlPR
14
14
  # MySQL network protocol
15
15
  class Protocol
16
-
17
16
  VERSION = 10
18
- MAX_PACKET_LENGTH = 2**24-1
17
+ MAX_PACKET_LENGTH = 2**24 - 1
19
18
 
20
19
  # Convert netdata to Ruby value
21
20
  # === Argument
@@ -27,42 +26,59 @@ class MysqlPR
27
26
  def self.net2value(pkt, type, unsigned)
28
27
  case type
29
28
  when Field::TYPE_STRING, Field::TYPE_VAR_STRING, Field::TYPE_NEWDECIMAL, Field::TYPE_BLOB
30
- return pkt.lcs
29
+ pkt.lcs
31
30
  when Field::TYPE_TINY
32
31
  v = pkt.utiny
33
- return unsigned ? v : v < 128 ? v : v-256
32
+ if unsigned
33
+ v
34
+ else
35
+ v < 128 ? v : v - 256
36
+ end
34
37
  when Field::TYPE_SHORT
35
38
  v = pkt.ushort
36
- return unsigned ? v : v < 32768 ? v : v-65536
39
+ if unsigned
40
+ v
41
+ else
42
+ v < 32_768 ? v : v - 65_536
43
+ end
37
44
  when Field::TYPE_INT24, Field::TYPE_LONG
38
45
  v = pkt.ulong
39
- return unsigned ? v : v < 2**32/2 ? v : v-2**32
46
+ if unsigned
47
+ v
48
+ else
49
+ v < 2**32 / 2 ? v : v - 2**32
50
+ end
40
51
  when Field::TYPE_LONGLONG
41
- n1, n2 = pkt.ulong, pkt.ulong
52
+ n1 = pkt.ulong
53
+ n2 = pkt.ulong
42
54
  v = (n2 << 32) | n1
43
- return unsigned ? v : v < 2**64/2 ? v : v-2**64
55
+ if unsigned
56
+ v
57
+ else
58
+ v < 2**64 / 2 ? v : v - 2**64
59
+ end
44
60
  when Field::TYPE_FLOAT
45
- return pkt.read(4).unpack('e').first
61
+ pkt.read(4).unpack1("e")
46
62
  when Field::TYPE_DOUBLE
47
- return pkt.read(8).unpack('E').first
63
+ pkt.read(8).unpack1("E")
48
64
  when Field::TYPE_DATE
49
65
  len = pkt.utiny
50
66
  y, m, d = pkt.read(len).unpack("vCC")
51
- t = MysqlPR::Time.new(y, m, d, nil, nil, nil)
52
- return t
67
+ MysqlPR::Time.new(y, m, d, nil, nil, nil)
68
+
53
69
  when Field::TYPE_DATETIME, Field::TYPE_TIMESTAMP
54
70
  len = pkt.utiny
55
71
  y, m, d, h, mi, s, sp = pkt.read(len).unpack("vCCCCCV")
56
- return MysqlPR::Time.new(y, m, d, h, mi, s, false, sp)
72
+ MysqlPR::Time.new(y, m, d, h, mi, s, false, sp)
57
73
  when Field::TYPE_TIME
58
74
  len = pkt.utiny
59
75
  sign, d, h, mi, s, sp = pkt.read(len).unpack("CVCCCV")
60
76
  h = d.to_i * 24 + h.to_i
61
- return MysqlPR::Time.new(0, 0, 0, h, mi, s, sign!=0, sp)
77
+ MysqlPR::Time.new(0, 0, 0, h, mi, s, sign != 0, sp)
62
78
  when Field::TYPE_YEAR
63
- return pkt.ushort
79
+ pkt.ushort
64
80
  when Field::TYPE_BIT
65
- return pkt.lcs
81
+ pkt.lcs
66
82
  else
67
83
  raise "not implemented: type=#{type}"
68
84
  end
@@ -94,26 +110,24 @@ class MysqlPR
94
110
  val = [v].pack("V")
95
111
  elsif v < 256**8
96
112
  type = Field::TYPE_LONGLONG | 0x8000
97
- val = [v&0xffffffff, v>>32].pack("VV")
113
+ val = [v & 0xffffffff, v >> 32].pack("VV")
98
114
  else
99
115
  raise ProtocolError, "value too large: #{v}"
100
116
  end
117
+ elsif -v <= 256 / 2
118
+ type = Field::TYPE_TINY
119
+ val = [v].pack("C")
120
+ elsif -v <= 256**2 / 2
121
+ type = Field::TYPE_SHORT
122
+ val = [v].pack("v")
123
+ elsif -v <= 256**4 / 2
124
+ type = Field::TYPE_LONG
125
+ val = [v].pack("V")
126
+ elsif -v <= 256**8 / 2
127
+ type = Field::TYPE_LONGLONG
128
+ val = [v & 0xffffffff, v >> 32].pack("VV")
101
129
  else
102
- if -v <= 256/2
103
- type = Field::TYPE_TINY
104
- val = [v].pack("C")
105
- elsif -v <= 256**2/2
106
- type = Field::TYPE_SHORT
107
- val = [v].pack("v")
108
- elsif -v <= 256**4/2
109
- type = Field::TYPE_LONG
110
- val = [v].pack("V")
111
- elsif -v <= 256**8/2
112
- type = Field::TYPE_LONGLONG
113
- val = [v&0xffffffff, v>>32].pack("VV")
114
- else
115
- raise ProtocolError, "value too large: #{v}"
116
- end
130
+ raise ProtocolError, "value too large: #{v}"
117
131
  end
118
132
  when Float
119
133
  type = Field::TYPE_DOUBLE
@@ -127,18 +141,11 @@ class MysqlPR
127
141
  else
128
142
  raise ProtocolError, "class #{v.class} is not supported"
129
143
  end
130
- return type, val
144
+ [type, val]
131
145
  end
132
146
 
133
- attr_reader :server_info
134
- attr_reader :server_version
135
- attr_reader :thread_id
136
- attr_reader :sqlstate
137
- attr_reader :affected_rows
138
- attr_reader :insert_id
139
- attr_reader :server_status
140
- attr_reader :warning_count
141
- attr_reader :message
147
+ attr_reader :server_info, :server_version, :thread_id, :sqlstate, :affected_rows, :insert_id, :server_status,
148
+ :warning_count, :message
142
149
  attr_accessor :charset
143
150
 
144
151
  # @state variable keep state for connection.
@@ -161,7 +168,7 @@ class MysqlPR
161
168
  def initialize(host, port, socket, conn_timeout, read_timeout, write_timeout, ssl_options = nil)
162
169
  @insert_id = 0
163
170
  @warning_count = 0
164
- @gc_stmt_queue = [] # stmt id list which GC destroy.
171
+ @gc_stmt_queue = [] # stmt id list which GC destroy.
165
172
  set_state :INIT
166
173
  @read_timeout = read_timeout
167
174
  @write_timeout = write_timeout
@@ -169,11 +176,15 @@ class MysqlPR
169
176
  @ssl_enabled = false
170
177
  begin
171
178
  Timeout.timeout conn_timeout do
172
- if host.nil? or host.empty? or host == "localhost"
179
+ if host.nil? || host.empty? || (host == "localhost")
173
180
  socket ||= ENV["MYSQL_UNIX_PORT"] || MYSQL_UNIX_PORT
174
181
  @sock = UNIXSocket.new socket
175
182
  else
176
- port ||= ENV["MYSQL_TCP_PORT"] || (Socket.getservbyname("mysql","tcp") rescue MYSQL_TCP_PORT)
183
+ port ||= ENV["MYSQL_TCP_PORT"] || begin
184
+ Socket.getservbyname("mysql", "tcp")
185
+ rescue StandardError
186
+ MYSQL_TCP_PORT
187
+ end
177
188
  @sock = TCPSocket.new host, port
178
189
  end
179
190
  end
@@ -213,16 +224,17 @@ class MysqlPR
213
224
  reset
214
225
  init_packet = InitialPacket.parse read
215
226
  @server_info = init_packet.server_version
216
- @server_version = init_packet.server_version.split(/\D/)[0,3].inject{|a,b|a.to_i*100+b.to_i}
227
+ @server_version = init_packet.server_version.split(/\D/)[0, 3].inject { |a, b| a.to_i * 100 + b.to_i }
217
228
  @thread_id = init_packet.thread_id
218
- client_flags = CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION
229
+ client_flags = CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS |
230
+ CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION
219
231
  client_flags |= CLIENT_PLUGIN_AUTH
220
232
  client_flags |= CLIENT_CONNECT_WITH_DB if db
221
233
  client_flags |= flag
222
234
  @charset = charset
223
235
  unless @charset
224
236
  @charset = Charset.by_number(init_packet.server_charset)
225
- @charset.encoding # raise error if unsupported charset
237
+ @charset.encoding # raise error if unsupported charset
226
238
  end
227
239
 
228
240
  # SSL handshake if requested and server supports it
@@ -240,11 +252,11 @@ class MysqlPR
240
252
  scramble = init_packet.scramble_buff
241
253
 
242
254
  # Choose password encryption based on auth plugin
243
- if auth_plugin == "caching_sha2_password"
244
- netpw = encrypt_password_sha256(passwd, scramble)
245
- else
246
- netpw = encrypt_password(passwd, scramble)
247
- end
255
+ netpw = if auth_plugin == "caching_sha2_password"
256
+ encrypt_password_sha256(passwd, scramble)
257
+ else
258
+ encrypt_password(passwd, scramble)
259
+ end
248
260
 
249
261
  write AuthenticationPacket.serialize(client_flags, 1024**3, @charset.number, user, netpw, db, auth_plugin)
250
262
 
@@ -309,25 +321,22 @@ class MysqlPR
309
321
  if @ssl_enabled
310
322
  # Send plaintext password over SSL
311
323
  write "#{passwd}\x00"
312
- read # OK or error
313
- set_state :READY
314
324
  else
315
325
  # Need RSA encryption - request public key
316
326
  write "\x02" # Request public key
317
327
  pubkey_response = read
318
328
  pubkey_data = pubkey_response.to_s
319
329
 
320
- if pubkey_data.getbyte(0) == 0x01
321
- # Got public key
322
- public_key = pubkey_data[1..]
323
- encrypted_password = rsa_encrypt_password(passwd, scramble, public_key)
324
- write encrypted_password
325
- read # OK or error
326
- set_state :READY
327
- else
328
- raise ProtocolError, "Failed to get server public key"
329
- end
330
+ raise ProtocolError, "Failed to get server public key" unless pubkey_data.getbyte(0) == 0x01
331
+
332
+ # Got public key
333
+ public_key = pubkey_data[1..]
334
+ encrypted_password = rsa_encrypt_password(passwd, scramble, public_key)
335
+ write encrypted_password
336
+
330
337
  end
338
+ read
339
+ set_state :READY
331
340
  else
332
341
  raise ProtocolError, "Unknown caching_sha2_password status: #{status}"
333
342
  end
@@ -352,30 +361,20 @@ class MysqlPR
352
361
  ssl_context = OpenSSL::SSL::SSLContext.new
353
362
 
354
363
  # Configure SSL context based on options
355
- if @ssl_options[:ca]
356
- ssl_context.ca_file = @ssl_options[:ca]
357
- end
358
- if @ssl_options[:cert]
359
- ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(@ssl_options[:cert]))
360
- end
361
- if @ssl_options[:key]
362
- ssl_context.key = OpenSSL::PKey::RSA.new(File.read(@ssl_options[:key]))
363
- end
364
- if @ssl_options[:ca_path]
365
- ssl_context.ca_path = @ssl_options[:ca_path]
366
- end
364
+ ssl_context.ca_file = @ssl_options[:ca] if @ssl_options[:ca]
365
+ ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(@ssl_options[:cert])) if @ssl_options[:cert]
366
+ ssl_context.key = OpenSSL::PKey::RSA.new(File.read(@ssl_options[:key])) if @ssl_options[:key]
367
+ ssl_context.ca_path = @ssl_options[:ca_path] if @ssl_options[:ca_path]
367
368
 
368
369
  # Set verification mode
369
- if @ssl_options[:verify] == false
370
- ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
371
- else
372
- ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
373
- end
370
+ ssl_context.verify_mode = if @ssl_options[:verify] == false
371
+ OpenSSL::SSL::VERIFY_NONE
372
+ else
373
+ OpenSSL::SSL::VERIFY_PEER
374
+ end
374
375
 
375
376
  # Set minimum TLS version if specified
376
- if @ssl_options[:min_version]
377
- ssl_context.min_version = @ssl_options[:min_version]
378
- end
377
+ ssl_context.min_version = @ssl_options[:min_version] if @ssl_options[:min_version]
379
378
 
380
379
  # Wrap socket in SSL
381
380
  ssl_socket = OpenSSL::SSL::SSLSocket.new(@sock, ssl_context)
@@ -409,7 +408,7 @@ class MysqlPR
409
408
  reset
410
409
  write [COM_QUERY, @charset.convert(query)].pack("Ca*")
411
410
  get_result
412
- rescue
411
+ rescue StandardError
413
412
  set_state :READY
414
413
  raise
415
414
  end
@@ -419,26 +418,27 @@ class MysqlPR
419
418
  # === Return
420
419
  # [integer / nil] number of fields of results. nil if no results.
421
420
  def get_result
422
- begin
423
- res_packet = ResultPacket.parse read
424
- if res_packet.field_count.to_i > 0 # result data exists
425
- set_state :FIELD
426
- return res_packet.field_count
427
- end
428
- if res_packet.field_count.nil? # LOAD DATA LOCAL INFILE
429
- filename = res_packet.message
430
- File.open(filename){|f| write f}
431
- write nil # EOF mark
432
- read
433
- end
434
- @affected_rows, @insert_id, @server_status, @warning_count, @message =
435
- res_packet.affected_rows, res_packet.insert_id, res_packet.server_status, res_packet.warning_count, res_packet.message
436
- set_state :READY
437
- return nil
438
- rescue
439
- set_state :READY
440
- raise
441
- end
421
+ res_packet = ResultPacket.parse read
422
+ if res_packet.field_count.to_i.positive? # result data exists
423
+ set_state :FIELD
424
+ return res_packet.field_count
425
+ end
426
+ if res_packet.field_count.nil? # LOAD DATA LOCAL INFILE
427
+ filename = res_packet.message
428
+ File.open(filename) { |f| write f }
429
+ write nil # EOF mark
430
+ read
431
+ end
432
+ @affected_rows = res_packet.affected_rows
433
+ @insert_id = res_packet.insert_id
434
+ @server_status = res_packet.server_status
435
+ @warning_count = res_packet.warning_count
436
+ @message = res_packet.message
437
+ set_state :READY
438
+ nil
439
+ rescue StandardError
440
+ set_state :READY
441
+ raise
442
442
  end
443
443
 
444
444
  # Retrieve n fields
@@ -449,11 +449,11 @@ class MysqlPR
449
449
  def retr_fields(n)
450
450
  check_state :FIELD
451
451
  begin
452
- fields = n.times.map{Field.new FieldPacket.parse(read)}
452
+ fields = n.times.map { Field.new FieldPacket.parse(read) }
453
453
  read_eof_packet
454
454
  set_state :RESULT
455
455
  fields
456
- rescue
456
+ rescue StandardError
457
457
  set_state :READY
458
458
  raise
459
459
  end
@@ -507,11 +507,11 @@ class MysqlPR
507
507
  reset
508
508
  write [COM_PROCESS_INFO].pack("C")
509
509
  field_count = read.lcb
510
- fields = field_count.times.map{Field.new FieldPacket.parse(read)}
510
+ fields = field_count.times.map { Field.new FieldPacket.parse(read) }
511
511
  read_eof_packet
512
512
  set_state :RESULT
513
- return fields
514
- rescue
513
+ fields
514
+ rescue StandardError
515
515
  set_state :READY
516
516
  raise
517
517
  end
@@ -559,12 +559,12 @@ class MysqlPR
559
559
  reset
560
560
  write [COM_STMT_PREPARE, charset.convert(stmt)].pack("Ca*")
561
561
  res_packet = PrepareResultPacket.parse read
562
- if res_packet.param_count > 0
563
- res_packet.param_count.times{read} # skip parameter packet
562
+ if res_packet.param_count.positive?
563
+ res_packet.param_count.times { read } # skip parameter packet
564
564
  read_eof_packet
565
565
  end
566
- if res_packet.field_count > 0
567
- fields = res_packet.field_count.times.map{Field.new FieldPacket.parse(read)}
566
+ if res_packet.field_count.positive?
567
+ fields = res_packet.field_count.times.map { Field.new FieldPacket.parse(read) }
568
568
  read_eof_packet
569
569
  else
570
570
  fields = []
@@ -585,7 +585,7 @@ class MysqlPR
585
585
  reset
586
586
  write ExecutePacket.serialize(stmt_id, MysqlPR::Stmt::CURSOR_TYPE_NO_CURSOR, values)
587
587
  get_result
588
- rescue
588
+ rescue StandardError
589
589
  set_state :READY
590
590
  raise
591
591
  end
@@ -628,36 +628,34 @@ class MysqlPR
628
628
  private
629
629
 
630
630
  def check_state(st)
631
- raise 'command out of sync' unless @state == st
631
+ raise "command out of sync" unless @state == st
632
632
  end
633
633
 
634
634
  def set_state(st)
635
635
  @state = st
636
- if st == :READY
637
- gc_disabled = GC.disable unless RUBY_PLATFORM == 'java'
638
- begin
639
- while st = @gc_stmt_queue.shift
640
- reset
641
- write [COM_STMT_CLOSE, st].pack("CV")
642
- end
643
- ensure
644
- GC.enable unless gc_disabled unless RUBY_PLATFORM == 'java'
636
+ return unless st == :READY
637
+
638
+ gc_disabled = GC.disable unless RUBY_PLATFORM == "java"
639
+ begin
640
+ while (st = @gc_stmt_queue.shift)
641
+ reset
642
+ write [COM_STMT_CLOSE, st].pack("CV")
645
643
  end
644
+ ensure
645
+ GC.enable if RUBY_PLATFORM != "java" && !gc_disabled
646
646
  end
647
647
  end
648
648
 
649
649
  def synchronize
650
- begin
651
- check_state :READY
652
- return yield
653
- ensure
654
- set_state :READY
655
- end
650
+ check_state :READY
651
+ yield
652
+ ensure
653
+ set_state :READY
656
654
  end
657
655
 
658
656
  # Reset sequence number
659
657
  def reset
660
- @seq = 0 # packet counter. reset by each command
658
+ @seq = 0 # packet counter. reset by each command
661
659
  end
662
660
 
663
661
  # Read one packet data
@@ -668,35 +666,39 @@ class MysqlPR
668
666
  def read
669
667
  ret = ""
670
668
  len = nil
671
- begin
669
+ loop do
672
670
  Timeout.timeout @read_timeout do
673
671
  header = @sock.read(4)
674
672
  raise EOFError unless header && header.length == 4
673
+
675
674
  len1, len2, seq = header.unpack("CvC")
676
675
  len = (len2 << 8) + len1
677
676
  raise ProtocolError, "invalid packet: sequence number mismatch(#{seq} != #{@seq}(expected))" if @seq != seq
677
+
678
678
  @seq = (@seq + 1) % 256
679
679
  ret = @sock.read(len)
680
680
  raise EOFError unless ret && ret.length == len
681
681
  end
682
682
  rescue EOFError
683
- raise ClientError::ServerGoneError, 'The MySQL server has gone away'
683
+ raise ClientError::ServerGoneError, "The MySQL server has gone away"
684
684
  rescue Timeout::Error
685
685
  raise ClientError, "read timeout"
686
- end while len == MAX_PACKET_LENGTH
686
+ break unless len == MAX_PACKET_LENGTH
687
+ end
687
688
 
688
689
  @sqlstate = "00000"
689
690
 
690
691
  # Error packet (use getbyte for encoding-safe comparison)
691
692
  if ret.getbyte(0) == 0xff
692
- f, errno, marker, @sqlstate, message = ret.unpack("Cvaa5a*")
693
+ _, errno, marker, @sqlstate, message = ret.unpack("Cvaa5a*")
693
694
  unless marker == "#"
694
- f, errno, message = ret.unpack("Cva*") # Version 4.0 Error
695
+ _, errno, message = ret.unpack("Cva*") # Version 4.0 Error
695
696
  @sqlstate = ""
696
697
  end
697
698
  if MysqlPR::ServerError::ERROR_MAP.key? errno
698
699
  raise MysqlPR::ServerError::ERROR_MAP[errno].new(message, @sqlstate)
699
700
  end
701
+
700
702
  raise MysqlPR::ServerError.new(message, @sqlstate)
701
703
  end
702
704
  Packet.new(ret)
@@ -706,32 +708,30 @@ class MysqlPR
706
708
  # === Argument
707
709
  # data :: [String / IO] packet data. If data is nil, write empty packet.
708
710
  def write(data)
709
- begin
710
- @sock.sync = false
711
- if data.nil?
711
+ @sock.sync = false
712
+ if data.nil?
713
+ Timeout.timeout @write_timeout do
714
+ @sock.write [0, 0, @seq].pack("CvC")
715
+ end
716
+ @seq = (@seq + 1) % 256
717
+ else
718
+ data = StringIO.new data if data.is_a? String
719
+ while (d = data.read(MAX_PACKET_LENGTH))
712
720
  Timeout.timeout @write_timeout do
713
- @sock.write [0, 0, @seq].pack("CvC")
721
+ @sock.write [d.length % 256, d.length / 256, @seq].pack("CvC")
722
+ @sock.write d
714
723
  end
715
724
  @seq = (@seq + 1) % 256
716
- else
717
- data = StringIO.new data if data.is_a? String
718
- while d = data.read(MAX_PACKET_LENGTH)
719
- Timeout.timeout @write_timeout do
720
- @sock.write [d.length%256, d.length/256, @seq].pack("CvC")
721
- @sock.write d
722
- end
723
- @seq = (@seq + 1) % 256
724
- end
725
725
  end
726
- @sock.sync = true
727
- Timeout.timeout @write_timeout do
728
- @sock.flush
729
- end
730
- rescue Errno::EPIPE
731
- raise ClientError::ServerGoneError, 'The MySQL server has gone away'
732
- rescue Timeout::Error
733
- raise ClientError, "write timeout"
734
726
  end
727
+ @sock.sync = true
728
+ Timeout.timeout @write_timeout do
729
+ @sock.flush
730
+ end
731
+ rescue Errno::EPIPE
732
+ raise ClientError::ServerGoneError, "The MySQL server has gone away"
733
+ rescue Timeout::Error
734
+ raise ClientError, "write timeout"
735
735
  end
736
736
 
737
737
  # Read EOF packet
@@ -761,10 +761,13 @@ class MysqlPR
761
761
  # === Return
762
762
  # [String] encrypted password
763
763
  def encrypt_password(plain, scramble)
764
- return "" if plain.nil? or plain.empty?
764
+ return "" if plain.nil? || plain.empty?
765
+
765
766
  hash_stage1 = Digest::SHA1.digest plain
766
767
  hash_stage2 = Digest::SHA1.digest hash_stage1
767
- return hash_stage1.unpack("C*").zip(Digest::SHA1.digest(scramble+hash_stage2).unpack("C*")).map{|a,b| a^b}.pack("C*")
768
+ hash_stage1.unpack("C*").zip(Digest::SHA1.digest(scramble + hash_stage2).unpack("C*")).map do |a, b|
769
+ a ^ b
770
+ end.pack("C*")
768
771
  end
769
772
 
770
773
  # Encrypt password for caching_sha2_password (SHA256)
@@ -774,10 +777,13 @@ class MysqlPR
774
777
  # === Return
775
778
  # [String] encrypted password
776
779
  def encrypt_password_sha256(plain, scramble)
777
- return "" if plain.nil? or plain.empty?
780
+ return "" if plain.nil? || plain.empty?
781
+
778
782
  hash_stage1 = Digest::SHA256.digest(plain)
779
783
  hash_stage2 = Digest::SHA256.digest(hash_stage1)
780
- hash_stage1.unpack("C*").zip(Digest::SHA256.digest(hash_stage2 + scramble).unpack("C*")).map { |a, b| a ^ b }.pack("C*")
784
+ hash_stage1.unpack("C*").zip(Digest::SHA256.digest(hash_stage2 + scramble).unpack("C*")).map do |a, b|
785
+ a ^ b
786
+ end.pack("C*")
781
787
  end
782
788
 
783
789
  # Initial packet
@@ -799,18 +805,26 @@ class MysqlPR
799
805
  rest_scramble_buff = pkt.read(rest_scramble_len)
800
806
  # Remove trailing null if present
801
807
  rest_scramble_buff = rest_scramble_buff.sub(/\x00+\z/, "")
802
- auth_plugin_name = pkt.string rescue "mysql_native_password"
808
+ auth_plugin_name = begin
809
+ pkt.string
810
+ rescue StandardError
811
+ "mysql_native_password"
812
+ end
803
813
  raise ProtocolError, "unsupported version: #{protocol_version}" unless protocol_version == VERSION
804
- raise ProtocolError, "invalid packet: f0=#{f0}" unless f0 == 0
814
+ raise ProtocolError, "invalid packet: f0=#{f0}" unless f0.zero?
815
+
805
816
  scramble_buff.concat rest_scramble_buff
806
817
  server_capabilities |= (server_capabilities_upper << 16)
807
- self.new protocol_version, server_version, thread_id, server_capabilities, server_charset, server_status, scramble_buff, auth_plugin_name
818
+ new protocol_version, server_version, thread_id, server_capabilities, server_charset, server_status,
819
+ scramble_buff, auth_plugin_name
808
820
  end
809
821
 
810
- attr_reader :protocol_version, :server_version, :thread_id, :server_capabilities, :server_charset, :server_status, :scramble_buff, :auth_plugin_name
822
+ attr_reader :protocol_version, :server_version, :thread_id, :server_capabilities, :server_charset,
823
+ :server_status, :scramble_buff, :auth_plugin_name
811
824
 
812
825
  def initialize(*args)
813
- @protocol_version, @server_version, @thread_id, @server_capabilities, @server_charset, @server_status, @scramble_buff, @auth_plugin_name = args
826
+ @protocol_version, @server_version, @thread_id, @server_capabilities,
827
+ @server_charset, @server_status, @scramble_buff, @auth_plugin_name = args
814
828
  end
815
829
  end
816
830
 
@@ -818,17 +832,17 @@ class MysqlPR
818
832
  class ResultPacket
819
833
  def self.parse(pkt)
820
834
  field_count = pkt.lcb
821
- if field_count == 0
835
+ if field_count.zero?
822
836
  affected_rows = pkt.lcb
823
837
  insert_id = pkt.lcb
824
838
  server_status = pkt.ushort
825
839
  warning_count = pkt.ushort
826
840
  message = pkt.lcs
827
- return self.new(field_count, affected_rows, insert_id, server_status, warning_count, message)
828
- elsif field_count.nil? # LOAD DATA LOCAL INFILE
829
- return self.new(nil, nil, nil, nil, nil, pkt.to_s)
841
+ new(field_count, affected_rows, insert_id, server_status, warning_count, message)
842
+ elsif field_count.nil? # LOAD DATA LOCAL INFILE
843
+ new(nil, nil, nil, nil, nil, pkt.to_s)
830
844
  else
831
- return self.new(field_count)
845
+ new(field_count)
832
846
  end
833
847
  end
834
848
 
@@ -842,13 +856,13 @@ class MysqlPR
842
856
  # Field packet
843
857
  class FieldPacket
844
858
  def self.parse(pkt)
845
- first = pkt.lcs
859
+ pkt.lcs
846
860
  db = pkt.lcs
847
861
  table = pkt.lcs
848
862
  org_table = pkt.lcs
849
863
  name = pkt.lcs
850
864
  org_name = pkt.lcs
851
- f0 = pkt.utiny
865
+ pkt.utiny
852
866
  charsetnr = pkt.ushort
853
867
  length = pkt.ulong
854
868
  type = pkt.utiny
@@ -856,9 +870,10 @@ class MysqlPR
856
870
  decimals = pkt.utiny
857
871
  f1 = pkt.ushort
858
872
 
859
- raise ProtocolError, "invalid packet: f1=#{f1}" unless f1 == 0
873
+ raise ProtocolError, "invalid packet: f1=#{f1}" unless f1.zero?
874
+
860
875
  default = pkt.lcs
861
- return self.new(db, table, org_table, name, org_name, charsetnr, length, type, flags, decimals, default)
876
+ new(db, table, org_table, name, org_name, charsetnr, length, type, flags, decimals, default)
862
877
  end
863
878
 
864
879
  attr_reader :db, :table, :org_table, :name, :org_name, :charsetnr, :length, :type, :flags, :decimals, :default
@@ -871,14 +886,16 @@ class MysqlPR
871
886
  # Prepare result packet
872
887
  class PrepareResultPacket
873
888
  def self.parse(pkt)
874
- raise ProtocolError, "invalid packet" unless pkt.utiny == 0
889
+ raise ProtocolError, "invalid packet" unless pkt.utiny.zero?
890
+
875
891
  statement_id = pkt.ulong
876
892
  field_count = pkt.ushort
877
893
  param_count = pkt.ushort
878
894
  f = pkt.utiny
879
895
  warning_count = pkt.ushort
880
- raise ProtocolError, "invalid packet" unless f == 0x00
881
- self.new statement_id, field_count, param_count, warning_count
896
+ raise ProtocolError, "invalid packet" unless f.zero?
897
+
898
+ new statement_id, field_count, param_count, warning_count
882
899
  end
883
900
 
884
901
  attr_reader :statement_id, :field_count, :param_count, :warning_count
@@ -895,19 +912,20 @@ class MysqlPR
895
912
  client_flags,
896
913
  max_packet_size,
897
914
  charset_number,
898
- "" # filler: 23 bytes of 0x00
915
+ "" # filler: 23 bytes of 0x00
899
916
  ].pack("VVCa23")
900
917
  end
901
918
  end
902
919
 
903
920
  # Authentication packet
904
921
  class AuthenticationPacket
905
- def self.serialize(client_flags, max_packet_size, charset_number, username, scrambled_password, databasename, auth_plugin_name = nil)
922
+ def self.serialize(client_flags, max_packet_size, charset_number, username, scrambled_password, databasename,
923
+ auth_plugin_name = nil)
906
924
  packet = [
907
925
  client_flags,
908
926
  max_packet_size,
909
927
  charset_number,
910
- "" # reserved 23 bytes
928
+ "" # reserved 23 bytes
911
929
  ].pack("VVCa23")
912
930
 
913
931
  packet << "#{username}\x00"
@@ -929,30 +947,32 @@ class MysqlPR
929
947
  netvalues.concat n if v
930
948
  t
931
949
  end
932
- [MysqlPR::COM_STMT_EXECUTE, statement_id, cursor_type, 1, nbm, 1, types.pack("v*"), netvalues].pack("CVCVa*Ca*a*")
950
+ [MysqlPR::COM_STMT_EXECUTE, statement_id, cursor_type, 1, nbm, 1, types.pack("v*"),
951
+ netvalues].pack("CVCVa*Ca*a*")
933
952
  end
934
953
 
935
954
  # make null bitmap
936
955
  #
937
956
  # If values is [1, nil, 2, 3, nil] then returns "\x12"(0b10010).
938
957
  def self.null_bitmap(values)
939
- bitmap = values.enum_for(:each_slice,8).map do |vals|
940
- vals.reverse.inject(0){|b, v|(b << 1 | (v ? 0 : 1))}
958
+ bitmap = values.enum_for(:each_slice, 8).map do |vals|
959
+ vals.reverse.inject(0) { |b, v| (b << 1 | (v ? 0 : 1)) }
941
960
  end
942
- return bitmap.pack("C*")
961
+ bitmap.pack("C*")
943
962
  end
944
-
945
963
  end
946
964
  end
947
965
 
948
966
  class RawRecord
949
967
  def initialize(packet, nfields, encoding)
950
- @packet, @nfields, @encoding = packet, nfields, encoding
968
+ @packet = packet
969
+ @nfields = nfields
970
+ @encoding = encoding
951
971
  end
952
972
 
953
973
  def to_a
954
974
  @nfields.times.map do
955
- if s = @packet.lcs
975
+ if (s = @packet.lcs)
956
976
  s = Charset.convert_encoding(s, @encoding)
957
977
  end
958
978
  s
@@ -966,34 +986,34 @@ class MysqlPR
966
986
  # fields :: [Array of Fields]
967
987
  # encoding:: [Encoding]
968
988
  def initialize(packet, fields, encoding)
969
- @packet, @fields, @encoding = packet, fields, encoding
989
+ @packet = packet
990
+ @fields = fields
991
+ @encoding = encoding
970
992
  end
971
993
 
972
994
  # Parse statement result packet
973
995
  # === Return
974
996
  # [Array of Object] one record
975
997
  def parse_record_packet
976
- @packet.utiny # skip first byte
977
- null_bit_map = @packet.read((@fields.length+7+2)/8).unpack("b*").first
978
- rec = @fields.each_with_index.map do |f, i|
979
- if null_bit_map[i+2] == ?1
998
+ @packet.utiny # skip first byte
999
+ null_bit_map = @packet.read((@fields.length + 7 + 2) / 8).unpack1("b*")
1000
+ @fields.each_with_index.map do |f, i|
1001
+ if null_bit_map[i + 2] == "1"
980
1002
  nil
981
1003
  else
982
1004
  unsigned = f.flags & Field::UNSIGNED_FLAG != 0
983
1005
  v = Protocol.net2value(@packet, f.type, unsigned)
984
- if v.is_a? Numeric or v.is_a? MysqlPR::Time
1006
+ if v.is_a?(Numeric) || v.is_a?(MysqlPR::Time)
985
1007
  v
986
- elsif f.type == Field::TYPE_BIT or f.charsetnr == Charset::BINARY_CHARSET_NUMBER
1008
+ elsif (f.type == Field::TYPE_BIT) || (f.charsetnr == Charset::BINARY_CHARSET_NUMBER)
987
1009
  Charset.to_binary(v)
988
1010
  else
989
1011
  Charset.convert_encoding(v, @encoding)
990
1012
  end
991
1013
  end
992
1014
  end
993
- rec
994
1015
  end
995
1016
 
996
1017
  alias to_a parse_record_packet
997
-
998
1018
  end
999
1019
  end