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.
- 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
|