tmtm-ruby-mysql 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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