tmtm-ruby-mysql 0.0.0

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.
@@ -0,0 +1,26 @@
1
+ # Copyright (C) 2008 TOMITA Masahiro
2
+ # mailto:tommy@tmtm.org
3
+
4
+ class Mysql
5
+ class Cache
6
+ def initialize(size)
7
+ @size = size || 0
8
+ @cache = {}
9
+ @timestamp = {}
10
+ end
11
+ def get(key)
12
+ if @size <= 0
13
+ return yield key
14
+ end
15
+ if @cache.key? key
16
+ @timestamp[key] = ::Time.now
17
+ return @cache[key]
18
+ end
19
+ if @cache.size >= @size
20
+ oldest_key = @timestamp.min_by{|k,v| v}.first
21
+ @cache.delete oldest_key
22
+ end
23
+ @cache[key] = yield key
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,255 @@
1
+ # Copyright (C) 2008 TOMITA Masahiro
2
+ # mailto:tommy@tmtm.org
3
+
4
+ require "mysql/error"
5
+
6
+ class Mysql
7
+ class Charset
8
+ def initialize(number, name, csname)
9
+ @number, @name, @csname = number, name, csname
10
+ end
11
+ attr_reader :number, :name, :csname
12
+
13
+ # [[charset_number, charset_name, collation_name, default], ...]
14
+ CHARSETS = [
15
+ [ 1, "big5", "big5_chinese_ci", true ],
16
+ [ 2, "latin2", "latin2_czech_cs", false],
17
+ [ 3, "dec8", "dec8_swedish_ci", true ],
18
+ [ 4, "cp850", "cp850_general_ci", true ],
19
+ [ 5, "latin1", "latin1_german1_ci", false],
20
+ [ 6, "hp8", "hp8_english_ci", true ],
21
+ [ 7, "koi8r", "koi8r_general_ci", true ],
22
+ [ 8, "latin1", "latin1_swedish_ci", true ],
23
+ [ 9, "latin2", "latin2_general_ci", true ],
24
+ [ 10, "swe7", "swe7_swedish_ci", true ],
25
+ [ 11, "ascii", "ascii_general_ci", true ],
26
+ [ 12, "ujis", "ujis_japanese_ci", true ],
27
+ [ 13, "sjis", "sjis_japanese_ci", true ],
28
+ [ 14, "cp1251", "cp1251_bulgarian_ci", false],
29
+ [ 15, "latin1", "latin1_danish_ci", false],
30
+ [ 16, "hebrew", "hebrew_general_ci", true ],
31
+ [ 18, "tis620", "tis620_thai_ci", true ],
32
+ [ 19, "euckr", "euckr_korean_ci", true ],
33
+ [ 20, "latin7", "latin7_estonian_cs", false],
34
+ [ 21, "latin2", "latin2_hungarian_ci", false],
35
+ [ 22, "koi8u", "koi8u_general_ci", true ],
36
+ [ 23, "cp1251", "cp1251_ukrainian_ci", false],
37
+ [ 24, "gb2312", "gb2312_chinese_ci", true ],
38
+ [ 25, "greek", "greek_general_ci", true ],
39
+ [ 26, "cp1250", "cp1250_general_ci", true ],
40
+ [ 27, "latin2", "latin2_croatian_ci", false],
41
+ [ 28, "gbk", "gbk_chinese_ci", true ],
42
+ [ 29, "cp1257", "cp1257_lithuanian_ci", false],
43
+ [ 30, "latin5", "latin5_turkish_ci", true ],
44
+ [ 31, "latin1", "latin1_german2_ci", false],
45
+ [ 32, "armscii8", "armscii8_general_ci", true ],
46
+ [ 33, "utf8", "utf8_general_ci", true ],
47
+ [ 34, "cp1250", "cp1250_czech_cs", false],
48
+ [ 35, "ucs2", "ucs2_general_ci", true ],
49
+ [ 36, "cp866", "cp866_general_ci", true ],
50
+ [ 37, "keybcs2", "keybcs2_general_ci", true ],
51
+ [ 38, "macce", "macce_general_ci", true ],
52
+ [ 39, "macroman", "macroman_general_ci", true ],
53
+ [ 40, "cp852", "cp852_general_ci", true ],
54
+ [ 41, "latin7", "latin7_general_ci", true ],
55
+ [ 42, "latin7", "latin7_general_cs", false],
56
+ [ 43, "macce", "macce_bin", false],
57
+ [ 44, "cp1250", "cp1250_croatian_ci", false],
58
+ [ 47, "latin1", "latin1_bin", false],
59
+ [ 48, "latin1", "latin1_general_ci", false],
60
+ [ 49, "latin1", "latin1_general_cs", false],
61
+ [ 50, "cp1251", "cp1251_bin", false],
62
+ [ 51, "cp1251", "cp1251_general_ci", true ],
63
+ [ 52, "cp1251", "cp1251_general_cs", false],
64
+ [ 53, "macroman", "macroman_bin", false],
65
+ [ 57, "cp1256", "cp1256_general_ci", true ],
66
+ [ 58, "cp1257", "cp1257_bin", false],
67
+ [ 59, "cp1257", "cp1257_general_ci", true ],
68
+ [ 63, "binary", "binary", true ],
69
+ [ 64, "armscii8", "armscii8_bin", false],
70
+ [ 65, "ascii", "ascii_bin", false],
71
+ [ 66, "cp1250", "cp1250_bin", false],
72
+ [ 67, "cp1256", "cp1256_bin", false],
73
+ [ 68, "cp866", "cp866_bin", false],
74
+ [ 69, "dec8", "dec8_bin", false],
75
+ [ 70, "greek", "greek_bin", false],
76
+ [ 71, "hebrew", "hebrew_bin", false],
77
+ [ 72, "hp8", "hp8_bin", false],
78
+ [ 73, "keybcs2", "keybcs2_bin", false],
79
+ [ 74, "koi8r", "koi8r_bin", false],
80
+ [ 75, "koi8u", "koi8u_bin", false],
81
+ [ 77, "latin2", "latin2_bin", false],
82
+ [ 78, "latin5", "latin5_bin", false],
83
+ [ 79, "latin7", "latin7_bin", false],
84
+ [ 80, "cp850", "cp850_bin", false],
85
+ [ 81, "cp852", "cp852_bin", false],
86
+ [ 82, "swe7", "swe7_bin", false],
87
+ [ 83, "utf8", "utf8_bin", false],
88
+ [ 84, "big5", "big5_bin", false],
89
+ [ 85, "euckr", "euckr_bin", false],
90
+ [ 86, "gb2312", "gb2312_bin", false],
91
+ [ 87, "gbk", "gbk_bin", false],
92
+ [ 88, "sjis", "sjis_bin", false],
93
+ [ 89, "tis620", "tis620_bin", false],
94
+ [ 90, "ucs2", "ucs2_bin", false],
95
+ [ 91, "ujis", "ujis_bin", false],
96
+ [ 92, "geostd8", "geostd8_general_ci", true ],
97
+ [ 93, "geostd8", "geostd8_bin", false],
98
+ [ 94, "latin1", "latin1_spanish_ci", false],
99
+ [ 95, "cp932", "cp932_japanese_ci" , true ],
100
+ [ 96, "cp932", "cp932_bin" , false],
101
+ [ 97, "eucjpms", "eucjpms_japanese_ci", true ],
102
+ [ 98, "eucjpms", "eucjpms_bin", false],
103
+ [128, "ucs2", "ucs2_unicode_ci", false],
104
+ [129, "ucs2", "ucs2_icelandic_ci", false],
105
+ [130, "ucs2", "ucs2_latvian_ci", false],
106
+ [131, "ucs2", "ucs2_romanian_ci", false],
107
+ [132, "ucs2", "ucs2_slovenian_ci", false],
108
+ [133, "ucs2", "ucs2_polish_ci", false],
109
+ [134, "ucs2", "ucs2_estonian_ci", false],
110
+ [135, "ucs2", "ucs2_spanish_ci", false],
111
+ [136, "ucs2", "ucs2_swedish_ci", false],
112
+ [137, "ucs2", "ucs2_turkish_ci", false],
113
+ [138, "ucs2", "ucs2_czech_ci", false],
114
+ [139, "ucs2", "ucs2_danish_ci", false],
115
+ [140, "ucs2", "ucs2_lithuanian_ci", false],
116
+ [141, "ucs2", "ucs2_slovak_ci", false],
117
+ [142, "ucs2", "ucs2_spanish2_ci", false],
118
+ [143, "ucs2", "ucs2_roman_ci", false],
119
+ [144, "ucs2", "ucs2_persian_ci", false],
120
+ [145, "ucs2", "ucs2_esperanto_ci", false],
121
+ [146, "ucs2", "ucs2_hungarian_ci", false],
122
+ [192, "utf8", "utf8_unicode_ci", false],
123
+ [193, "utf8", "utf8_icelandic_ci", false],
124
+ [194, "utf8", "utf8_latvian_ci", false],
125
+ [195, "utf8", "utf8_romanian_ci", false],
126
+ [196, "utf8", "utf8_slovenian_ci", false],
127
+ [197, "utf8", "utf8_polish_ci", false],
128
+ [198, "utf8", "utf8_estonian_ci", false],
129
+ [199, "utf8", "utf8_spanish_ci", false],
130
+ [200, "utf8", "utf8_swedish_ci", false],
131
+ [201, "utf8", "utf8_turkish_ci", false],
132
+ [202, "utf8", "utf8_czech_ci", false],
133
+ [203, "utf8", "utf8_danish_ci", false],
134
+ [204, "utf8", "utf8_lithuanian_ci", false],
135
+ [205, "utf8", "utf8_slovak_ci", false],
136
+ [206, "utf8", "utf8_spanish2_ci", false],
137
+ [207, "utf8", "utf8_roman_ci", false],
138
+ [208, "utf8", "utf8_persian_ci", false],
139
+ [209, "utf8", "utf8_esperanto_ci", false],
140
+ [210, "utf8", "utf8_hungarian_ci", false],
141
+ ]
142
+
143
+ NUMBER_TO_CHARSET = {}
144
+ COLLATION_TO_CHARSET = {}
145
+ CHARSET_DEFAULT = {}
146
+ CHARSETS.each do |number, csname, clname, default|
147
+ cs = Charset.new number, csname, clname
148
+ NUMBER_TO_CHARSET[number] = cs
149
+ COLLATION_TO_CHARSET[clname] = cs
150
+ CHARSET_DEFAULT[csname] = cs if default
151
+ end
152
+
153
+ def self.by_number(n)
154
+ raise ClientError, "unknown charset number: #{n}" unless NUMBER_TO_CHARSET.key? n
155
+ NUMBER_TO_CHARSET[n]
156
+ end
157
+
158
+ def self.by_name(str)
159
+ ret = COLLATION_TO_CHARSET[str] || CHARSET_DEFAULT[str]
160
+ raise ClientError, "unknown charset: #{str}" unless ret
161
+ ret
162
+ end
163
+
164
+ if defined? Encoding
165
+
166
+ # MySQL Charset -> Ruby's Encodeing
167
+ CHARSET_ENCODING = {
168
+ "armscii8" => nil,
169
+ "ascii" => Encoding::US_ASCII,
170
+ "big5" => Encoding::Big5,
171
+ "binary" => Encoding::ASCII_8BIT,
172
+ "cp1250" => Encoding::Windows_1250,
173
+ "cp1251" => Encoding::Windows_1251,
174
+ "cp1256" => Encoding::Windows_1256,
175
+ "cp1257" => Encoding::Windows_1257,
176
+ "cp850" => Encoding::CP850,
177
+ "cp852" => Encoding::CP852,
178
+ "cp866" => Encoding::IBM866,
179
+ "cp932" => Encoding::Windows_31J,
180
+ "dec8" => nil,
181
+ "eucjpms" => Encoding::EucJP_ms,
182
+ "euckr" => Encoding::EUC_KR,
183
+ "gb2312" => Encoding::EUC_CN,
184
+ "gbk" => Encoding::GBK,
185
+ "geostd8" => nil,
186
+ "greek" => Encoding::ISO_8859_7,
187
+ "hebrew" => Encoding::ISO_8859_8,
188
+ "hp8" => nil,
189
+ "keybcs2" => nil,
190
+ "koi8r" => Encoding::KOI8_R,
191
+ "koi8u" => Encoding::KOI8_U,
192
+ "latin1" => Encoding::ISO_8859_1,
193
+ "latin2" => Encoding::ISO_8859_2,
194
+ "latin5" => Encoding::ISO_8859_9,
195
+ "latin7" => Encoding::ISO_8859_13,
196
+ "macce" => Encoding::MacCentEuro,
197
+ "macroman" => Encoding::MacRoman,
198
+ "sjis" => Encoding::SHIFT_JIS,
199
+ "swe7" => nil,
200
+ "tis620" => nil,
201
+ "ucs2" => Encoding::UTF_16BE,
202
+ "ujis" => Encoding::EucJP_ms,
203
+ "utf8" => Encoding::UTF_8,
204
+ }
205
+
206
+ def self.to_binary(value)
207
+ value.dup.force_encoding Encoding::ASCII_8BIT
208
+ end
209
+
210
+ # retrun corresponding Ruby encoding
211
+ # === Return
212
+ # encoding [Encoding]
213
+ def encoding
214
+ enc = CHARSET_ENCODING[@name.downcase]
215
+ raise Mysql::ClientError, "unsupported charset: #{@name}" unless enc
216
+ enc
217
+ end
218
+
219
+ # convert encoding to corrensponding to MySQL charset
220
+ def convert(value)
221
+ if value.is_a? String and value.encoding != Encoding::ASCII_8BIT
222
+ value = value.encode encoding
223
+ end
224
+ value
225
+ end
226
+
227
+ # convert encoding from MySQL charset to Ruby
228
+ def force_encoding(value)
229
+ if value.is_a? String
230
+ value = value.dup.force_encoding encoding
231
+ end
232
+ value
233
+ end
234
+
235
+ else
236
+ # for Ruby 1.8
237
+
238
+ def self.to_binary(value)
239
+ value
240
+ end
241
+
242
+ def encoding
243
+ nil
244
+ end
245
+
246
+ def convert(value)
247
+ value
248
+ end
249
+
250
+ def force_encoding(value)
251
+ value
252
+ end
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,209 @@
1
+ # Copyright (C) 2008 TOMITA Masahiro
2
+ # mailto:tommy@tmtm.org
3
+
4
+ # for compatibility
5
+
6
+ class Mysql
7
+ class << self
8
+ alias connect new
9
+ alias real_connect new
10
+
11
+ def init
12
+ self.allocate
13
+ end
14
+
15
+ def client_version
16
+ 50067
17
+ end
18
+
19
+ def client_info
20
+ "5.0.67"
21
+ end
22
+ alias get_client_info client_info
23
+
24
+ def escape_string(str)
25
+ str.gsub(/[\0\n\r\\\'\"\x1a]/) do |s|
26
+ case s
27
+ when "\0" then "\\0"
28
+ when "\n" then "\\n"
29
+ when "\r" then "\\r"
30
+ when "\x1a" then "\\Z"
31
+ else "\\#{s}"
32
+ end
33
+ end
34
+ end
35
+ alias quote escape_string
36
+ end
37
+
38
+ alias orig_initialize initialize
39
+ alias stmt_init stmt
40
+ alias query simple_query
41
+
42
+ def initialize(*args)
43
+ if args.first.is_a? Hash || defined?(URI) && args.first.is_a?(URI) || args.first =~ /\Amysql:\/\//
44
+ orig_initialize *args
45
+ else
46
+ host, user, password, db, port, socket, flag = args
47
+ orig_initialize :host=>host, :user=>user, :password=>password, :db=>db, :port=>port, :socket=>socket, :flag=>flag
48
+ end
49
+ end
50
+
51
+ def connect(host, user, password, db, port, socket, flag)
52
+ initialize :host=>host, :user=>user, :password=>password, :db=>db, :port=>port, :socket=>socket, :flag=>flag
53
+ self
54
+ end
55
+ alias real_connect connect
56
+
57
+ def client_version
58
+ self.class.client_version
59
+ end
60
+
61
+ def options(opt, val=nil)
62
+ case opt
63
+ when INIT_COMMAND
64
+ @init_command = val
65
+ when OPT_COMPRESS
66
+ raise ClientError, "not implemented"
67
+ when OPT_CONNECT_TIMEOUT
68
+ @connect_timeout = val
69
+ when OPT_GUESS_CONNECTION
70
+ raise ClientError, "not implemented"
71
+ when OPT_LOCAL_INFILE
72
+ @local_infile = val
73
+ when OPT_NAMED_PIPE
74
+ raise ClientError, "not implemented"
75
+ when OPT_PROTOCOL
76
+ raise ClientError, "not implemented"
77
+ when OPT_READ_TIMEOUT
78
+ @read_timeout = val
79
+ when OPT_USE_EMBEDDED_CONNECTION
80
+ raise ClientError, "not implemented"
81
+ when OPT_USE_REMOTE_CONNECTION
82
+ raise ClientError, "not implemented"
83
+ when OPT_WRITE_TIMEOUT
84
+ @write_timeout = val
85
+ when READ_DEFAULT_FILE
86
+ raise ClientError, "not implemented"
87
+ when READ_DEFAULT_GROUP
88
+ raise ClientError, "not implemented"
89
+ when SECURE_AUTH
90
+ raise ClientError, "not implemented"
91
+ when SET_CHARSET_DIR
92
+ raise ClientError, "not implemented"
93
+ when SET_CHARSET_NAME
94
+ self.charset = val
95
+ when SET_CLIENT_IP
96
+ raise ClientError, "not implemented"
97
+ when SHARED_MEMORY_BASE_NAME
98
+ raise ClientError, "not implemented"
99
+ else
100
+ raise ClientError, "unknown option: #{opt}"
101
+ end
102
+ self
103
+ end
104
+
105
+ def sqlstate
106
+ @stream ? @stream.sqlstate : "00000"
107
+ end
108
+
109
+ def store_result
110
+ raise ClientError, "no result set" unless @fields
111
+ Result.new @fields, @stream
112
+ end
113
+
114
+ def use_result
115
+ raise ClientError, "no result set" unless @fields
116
+ Result.new @fields, @stream, false
117
+ end
118
+
119
+ class Result
120
+ def num_rows
121
+ @records.length
122
+ end
123
+
124
+ def data_seek(n)
125
+ @index = n
126
+ end
127
+
128
+ def row_tell
129
+ @index
130
+ end
131
+
132
+ def row_seek(n)
133
+ ret = @index
134
+ @index = n
135
+ ret
136
+ end
137
+
138
+ def free
139
+ # do nothing
140
+ end
141
+
142
+ def fetch_field
143
+ return nil if @field_index >= @fields.length
144
+ ret = @fields[@field_index]
145
+ @field_index += 1
146
+ ret
147
+ end
148
+
149
+ def field_tell
150
+ @field_index
151
+ end
152
+
153
+ def field_seek(n)
154
+ @field_index = n
155
+ end
156
+
157
+ def fetch_field_direct(n)
158
+ raise ClientError, "invalid argument: #{n}" if n < 0 or n >= @fields.length
159
+ @fields[n]
160
+ end
161
+
162
+ def fetch_fields
163
+ @fields
164
+ end
165
+
166
+ def fetch_lengths
167
+ return nil unless @fetched_record
168
+ @fetched_record.map{|c|c.nil? ? 0 : c.length}
169
+ end
170
+
171
+ def num_fields
172
+ @fields.length
173
+ end
174
+ end
175
+
176
+ class Statement
177
+ def num_rows
178
+ @records.length
179
+ end
180
+
181
+ def data_seek(n)
182
+ @index = n
183
+ end
184
+
185
+ def row_tell
186
+ @index
187
+ end
188
+
189
+ def row_seek(n)
190
+ ret = @index
191
+ @index = n
192
+ ret
193
+ end
194
+
195
+ def field_count
196
+ @fields.length
197
+ end
198
+
199
+ def free_result
200
+ # do nothing
201
+ end
202
+
203
+ def result_metadata
204
+ return nil if @fields.empty?
205
+ Result.new @fields, nil, false
206
+ end
207
+ end
208
+ Stmt = Statement
209
+ end