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.
- data/ChangeLog +20 -0
- data/lib/mysql.rb +72 -19
- data/lib/mysql/protocol.rb +31 -39
- 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 = (
|
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
|
524
|
-
|
525
|
-
|
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
|
529
|
-
Field::TYPE_LONGLONG, Field::TYPE_INT24, Field::TYPE_YEAR
|
576
|
+
when :integer
|
530
577
|
value.to_i
|
531
|
-
when
|
578
|
+
when :float
|
532
579
|
value.to_f
|
533
|
-
when
|
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
|
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("
|
566
|
-
ret =
|
567
|
-
if null_bit_map[
|
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 =
|
571
|
-
v = Protocol.net2value(data,
|
572
|
-
|
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 = (
|
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 = (
|
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
|
data/lib/mysql/protocol.rb
CHANGED
@@ -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
|
39
|
-
when
|
40
|
-
ord! lcb
|
39
|
+
case v = lcb.slice!(0)
|
40
|
+
when ?\xfb
|
41
41
|
return nil
|
42
|
-
when
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
return
|
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
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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.
|
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
|
+
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.
|
69
|
+
rubygems_version: 1.3.5
|
69
70
|
signing_key:
|
70
71
|
specification_version: 2
|
71
72
|
summary: MySQL connector for Ruby
|