tmtm-ruby-mysql 3.0.1 → 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.
Files changed (4) hide show
  1. data/ChangeLog +20 -0
  2. data/lib/mysql.rb +72 -19
  3. data/lib/mysql/protocol.rb +31 -39
  4. metadata +4 -3
data/ChangeLog CHANGED
@@ -1,3 +1,23 @@
1
+ 2009-07-29 TOMITA Masahiro <tommy@tmtm.org>
2
+
3
+ * lib/mysql/protocol.rb: treat M17N string correctly.
4
+
5
+ 2009-07-28 TOMITA Masahiro <tommy@tmtm.org>
6
+
7
+ * lib/mysql.rb, lib/mysql/protocol.rb: add Mysql#list_fields.
8
+
9
+ 2009-07-27 TOMITA Masahiro <tommy@tmtm.org>
10
+
11
+ * lib/mysql.rb, lib/mysql/protocol.rb: performance tuning
12
+
13
+ 2009-07-24 TOMITA Masahiro <tommy@tmtm.org>
14
+
15
+ * lib/mysql.rb: correspond to Ruby 1.9.1.
16
+
17
+ 2009-07-14 TOMITA Masahiro <tommy@tmtm.org>
18
+
19
+ * mysql.rb: Fix that Mysql#close is incorrect.
20
+
1
21
  2009-07-12 TOMITA Masahiro <tommy@tmtm.org>
2
22
 
3
23
  * version 3.0.1-alpha
data/lib/mysql.rb CHANGED
@@ -169,6 +169,7 @@ class Mysql
169
169
  def close
170
170
  if @protocol
171
171
  @protocol.synchronize do
172
+ @protocol.reset
172
173
  @protocol.send_packet Protocol::QuitPacket.new
173
174
  @protocol.close
174
175
  @protocol = nil
@@ -228,7 +229,7 @@ class Mysql
228
229
  res_packet.affected_rows, res_packet.insert_id, res_packet.server_status, res_packet.warning_count
229
230
  return nil
230
231
  else
231
- @fields = (1..res_packet.field_count).map{Field.new @protocol.read_field_packet}
232
+ @fields = Array.new(res_packet.field_count).map{Field.new @protocol.read_field_packet}
232
233
  @protocol.read_eof_packet
233
234
  return SimpleQueryResult.new self, @fields
234
235
  end
@@ -313,6 +314,28 @@ class Mysql
313
314
  return st
314
315
  end
315
316
 
317
+ # Get field(column) list
318
+ # === Argument
319
+ # table :: [String] table name.
320
+ # === Return
321
+ # Array of Mysql::Field
322
+ def list_fields(table)
323
+ @protocol.synchronize do
324
+ begin
325
+ @protocol.reset
326
+ @protocol.send_packet Protocol::FieldListPacket.new(table)
327
+ fields = []
328
+ until Protocol.eof_packet?(data = @protocol.read)
329
+ fields.push Field.new(Protocol::FieldPacket.parse(data))
330
+ end
331
+ return fields
332
+ rescue ServerError => e
333
+ @sqlstate = e.sqlstate
334
+ raise
335
+ end
336
+ end
337
+ end
338
+
316
339
  private
317
340
 
318
341
  # analyze argument and returns connection-parameter and option.
@@ -517,25 +540,49 @@ class Mysql
517
540
  ret
518
541
  end
519
542
 
543
+ MYSQL_RUBY_TYPE = {
544
+ Field::TYPE_BIT => :binary,
545
+ Field::TYPE_DECIMAL => :string,
546
+ Field::TYPE_VARCHAR => :string,
547
+ Field::TYPE_NEWDECIMAL => :string,
548
+ Field::TYPE_TINY_BLOB => :string,
549
+ Field::TYPE_MEDIUM_BLOB => :string,
550
+ Field::TYPE_LONG_BLOB => :string,
551
+ Field::TYPE_BLOB => :string,
552
+ Field::TYPE_VAR_STRING => :string,
553
+ Field::TYPE_STRING => :string,
554
+ Field::TYPE_TINY => :integer,
555
+ Field::TYPE_SHORT => :integer,
556
+ Field::TYPE_LONG => :integer,
557
+ Field::TYPE_LONGLONG => :integer,
558
+ Field::TYPE_INT24 => :integer,
559
+ Field::TYPE_YEAR => :integer,
560
+ Field::TYPE_FLOAT => :float,
561
+ Field::TYPE_DOUBLE => :float,
562
+ Field::TYPE_TIMESTAMP => :datetime,
563
+ Field::TYPE_DATE => :datetime,
564
+ Field::TYPE_DATETIME => :datetime,
565
+ Field::TYPE_NEWDATE => :datetime,
566
+ Field::TYPE_TIME => :time,
567
+ }
568
+
520
569
  def convert_str_to_ruby_value(field, value, charset)
521
570
  return nil if value.nil?
522
- case field.type
523
- when Field::TYPE_BIT, Field::TYPE_DECIMAL, Field::TYPE_VARCHAR,
524
- Field::TYPE_NEWDECIMAL, Field::TYPE_TINY_BLOB,
525
- Field::TYPE_MEDIUM_BLOB, Field::TYPE_LONG_BLOB,
526
- Field::TYPE_BLOB, Field::TYPE_VAR_STRING, Field::TYPE_STRING
571
+ case MYSQL_RUBY_TYPE[field.type]
572
+ when :binary
573
+ Charset.to_binary(value)
574
+ when :string
527
575
  field.flags & Field::BINARY_FLAG == 0 ? charset.force_encoding(value) : Charset.to_binary(value)
528
- when Field::TYPE_TINY, Field::TYPE_SHORT, Field::TYPE_LONG,
529
- Field::TYPE_LONGLONG, Field::TYPE_INT24, Field::TYPE_YEAR
576
+ when :integer
530
577
  value.to_i
531
- when Field::TYPE_FLOAT, Field::TYPE_DOUBLE
578
+ when :float
532
579
  value.to_f
533
- when Field::TYPE_TIMESTAMP, Field::TYPE_DATE, Field::TYPE_DATETIME, Field::TYPE_NEWDATE
580
+ when :datetime
534
581
  unless value =~ /\A(\d\d\d\d).(\d\d).(\d\d)(?:.(\d\d).(\d\d).(\d\d))?\z/
535
582
  raise "unsupported format date type: #{value}"
536
583
  end
537
584
  Time.new($1, $2, $3, $4, $5, $6)
538
- when Field::TYPE_TIME
585
+ when :time
539
586
  unless value =~ /\A(-?)(\d+).(\d\d).(\d\d)?\z/
540
587
  raise "unsupported format time type: #{value}"
541
588
  end
@@ -562,14 +609,20 @@ class Mysql
562
609
  def parse_data(data, fields, charset)
563
610
  return nil if Protocol.eof_packet? data
564
611
  data.slice!(0) # skip first byte
565
- null_bit_map = data.slice!(0, (fields.length+7+2)/8).unpack("C*")
566
- ret = (0...fields.length).map do |i|
567
- if null_bit_map[(i+2)/8][(i+2)%8] == 1
612
+ null_bit_map = data.slice!(0, (fields.length+7+2)/8).unpack("b*").first
613
+ ret = fields.each_with_index.map do |f, i|
614
+ if null_bit_map[i+2] == ?1
568
615
  nil
569
616
  else
570
- unsigned = fields[i].flags & Field::UNSIGNED_FLAG != 0
571
- v = Protocol.net2value(data, fields[i].type, unsigned)
572
- fields[i].flags & Field::BINARY_FLAG == 0 ? charset.force_encoding(v) : Charset.to_binary(v)
617
+ unsigned = f.flags & Field::UNSIGNED_FLAG != 0
618
+ v = Protocol.net2value(data, f.type, unsigned)
619
+ if v.is_a? Numeric or v.is_a? Mysql::Time
620
+ v
621
+ elsif f.type == Field::TYPE_BIT or f.flags & Field::BINARY_FLAG != 0
622
+ Charset.to_binary(v)
623
+ else
624
+ charset.force_encoding(v)
625
+ end
573
626
  end
574
627
  end
575
628
  ret
@@ -619,7 +672,7 @@ class Mysql
619
672
  @protocol.read_eof_packet
620
673
  end
621
674
  if res_packet.field_count > 0
622
- fields = (1..res_packet.field_count).map{Field.new @protocol.read_field_packet}
675
+ fields = Array.new(res_packet.field_count).map{Field.new @protocol.read_field_packet}
623
676
  @protocol.read_eof_packet
624
677
  else
625
678
  fields = []
@@ -656,7 +709,7 @@ class Mysql
656
709
  res_packet.affected_rows, res_packet.insert_id, res_packet.server_status, res_packet.warning_count
657
710
  return nil
658
711
  end
659
- @fields = (1..res_packet.field_count).map{Field.new @protocol.read_field_packet}
712
+ @fields = Array.new(res_packet.field_count).map{Field.new @protocol.read_field_packet}
660
713
  @protocol.read_eof_packet
661
714
  return StatementResult.new(@mysql, @fields)
662
715
  rescue ServerError => e
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2008 TOMITA Masahiro
1
+ # Copyright (C) 2008-2009 TOMITA Masahiro
2
2
  # mailto:tommy@tmtm.org
3
3
 
4
4
  require "socket"
@@ -25,6 +25,7 @@ class Mysql
25
25
 
26
26
  # convert String to LengthCodedString
27
27
  def self.lcs(str)
28
+ str = Charset.to_binary str
28
29
  lcb(str.length)+str
29
30
  end
30
31
 
@@ -35,24 +36,19 @@ class Mysql
35
36
  # Integer or nil
36
37
  def self.lcb2int!(lcb)
37
38
  return nil if lcb.empty?
38
- case ord lcb
39
- when 251
40
- ord! lcb
39
+ case v = lcb.slice!(0)
40
+ when ?\xfb
41
41
  return nil
42
- when 252
43
- _, v = lcb.unpack("Cv")
44
- lcb[0, 3] = ""
45
- return v
46
- when 253
47
- v, = lcb.unpack("V")
48
- lcb[0, 4] = ""
49
- return v >> 8
50
- when 254
51
- _, v1, v2 = lcb.unpack("CVV")
52
- lcb[0, 9] = ""
53
- return (v2 << 32) | v1
42
+ when ?\xfc
43
+ return lcb.slice!(0,2).unpack("v").first
44
+ when ?\xfd
45
+ c, v = lcb.slice!(0,3).unpack("Cv")
46
+ return (v<<8)+c
47
+ when ?\xfe
48
+ v1, v2 = lcb.slice!(0,8).unpack("VV")
49
+ return (v2<<32)+v1
54
50
  else
55
- return ord!(lcb)
51
+ return v.ord
56
52
  end
57
53
  end
58
54
 
@@ -67,7 +63,7 @@ class Mysql
67
63
  end
68
64
 
69
65
  def self.eof_packet?(data)
70
- ord(data) == 0xfe && data.length == 5
66
+ data[0] == ?\xfe && data.length == 5
71
67
  end
72
68
 
73
69
  # Convert netdata to Ruby value
@@ -82,7 +78,7 @@ class Mysql
82
78
  when Field::TYPE_STRING, Field::TYPE_VAR_STRING, Field::TYPE_NEWDECIMAL, Field::TYPE_BLOB
83
79
  return Protocol.lcs2str!(data)
84
80
  when Field::TYPE_TINY
85
- v = ord! data
81
+ v = data.slice!(0).ord
86
82
  return unsigned ? v : v < 128 ? v : v-256
87
83
  when Field::TYPE_SHORT
88
84
  v = data.slice!(0,2).unpack("v").first
@@ -99,11 +95,11 @@ class Mysql
99
95
  when Field::TYPE_DOUBLE
100
96
  return data.slice!(0,8).unpack("E").first
101
97
  when Field::TYPE_DATE, Field::TYPE_DATETIME, Field::TYPE_TIMESTAMP
102
- len = ord! data
98
+ len = data.slice!(0).ord
103
99
  y, m, d, h, mi, s, bs = data.slice!(0,len).unpack("vCCCCCV")
104
100
  return Mysql::Time.new(y, m, d, h, mi, s, bs)
105
101
  when Field::TYPE_TIME
106
- len = ord! data
102
+ len = data.slice!(0).ord
107
103
  sign, d, h, mi, s, sp = data.slice!(0,len).unpack("CVCCCV")
108
104
  h = d.to_i * 24 + h.to_i
109
105
  return Mysql::Time.new(0, 0, 0, h, mi, s, sign!=0, sp)
@@ -177,22 +173,6 @@ class Mysql
177
173
  return type, val
178
174
  end
179
175
 
180
- if "".respond_to? :ord
181
- def self.ord(str)
182
- str.ord
183
- end
184
- def self.ord!(str)
185
- str.slice!(0).ord
186
- end
187
- else
188
- def self.ord(str)
189
- str[0]
190
- end
191
- def self.ord!(str)
192
- str.slice!(0)
193
- end
194
- end
195
-
196
176
  attr_reader :sqlstate
197
177
 
198
178
  # make socket connection to server.
@@ -262,7 +242,7 @@ class Mysql
262
242
  @sqlstate = "00000"
263
243
 
264
244
  # Error packet
265
- if Protocol.ord(ret) == 0xff
245
+ if ret[0] == ?\xff
266
246
  f, errno, marker, @sqlstate, message = ret.unpack("Cvaa5a*")
267
247
  unless marker == "#"
268
248
  f, errno, message = ret.unpack("Cva*") # Version 4.0 Error
@@ -483,7 +463,7 @@ class Mysql
483
463
  # Prepare result packet
484
464
  class PrepareResultPacket < RxPacket
485
465
  def self.parse(data)
486
- raise ProtocolError, "invalid packet" unless Protocol.ord!(data) == 0x00
466
+ raise ProtocolError, "invalid packet" unless data.slice!(0) == ?\0
487
467
  statement_id, field_count, param_count, f, warning_count = data.unpack("VvvCv")
488
468
  raise ProtocolError, "invalid packet" unless f == 0x00
489
469
  self.new statement_id, field_count, param_count, warning_count
@@ -554,5 +534,17 @@ class Mysql
554
534
  [Mysql::COM_STMT_CLOSE, statement_id].pack("CV")
555
535
  end
556
536
  end
537
+
538
+ class FieldListPacket < TxPacket
539
+ attr_accessor :table, :field
540
+
541
+ def initialize(*args)
542
+ @table, @field = args
543
+ end
544
+
545
+ def serialize
546
+ [Mysql::COM_FIELD_LIST, "#{@table}\0#{@field}"].pack("Ca*")
547
+ end
548
+ end
557
549
  end
558
550
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tmtm-ruby-mysql
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - tommy
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-12 00:00:00 -07:00
12
+ date: 2009-07-29 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -34,6 +34,7 @@ files:
34
34
  - lib/mysql.rb
35
35
  has_rdoc: true
36
36
  homepage: http://github.com/tmtm/ruby-mysql
37
+ licenses:
37
38
  post_install_message:
38
39
  rdoc_options:
39
40
  - --title
@@ -65,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
66
  requirements: []
66
67
 
67
68
  rubyforge_project: rubymysql
68
- rubygems_version: 1.2.0
69
+ rubygems_version: 1.3.5
69
70
  signing_key:
70
71
  specification_version: 2
71
72
  summary: MySQL connector for Ruby