tmtm-ruby-mysql 0.0.0

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