rspider 0.8.4

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,111 @@
1
+ R_links_regexps=[/href\s*=\s*[\'\"]?([+:%\/\?~=&;\\\(\),._a-zA-Z0-9-]*)(#[.a-zA-Z0-9-]*)?[\'\" ]?(\s*rel\s*=\s*[\'\"]?(nofollow)[\'\"]?)?/i,
2
+ /(frame[^>]*src[[:blank:]]*)=[[:blank:]]*[\'\"]?(([[a-z]{3,5}:\/\/(([.a-zA-Z0-9-])+(:[0-9]+)*))*([+:%\/?=&;\\\(\),._ a-zA-Z0-9-]*))(#[.a-zA-Z0-9-]*)?[\'\" ]?/i,
3
+ /(window[.]location)[[:blank:]]*=[[:blank:]]*[\'\"]?(([[a-z]{3,5}:\/\/(([.a-zA-Z0-9-])+(:[0-9]+)*))*([+:%\/?=&;\\\(\),._ a-zA-Z0-9-]*))(#[.a-zA-Z0-9-]*)?[\'\" ]?/i,
4
+ /(http-equiv=['\"]refresh['\"] *content=['\"][0-9]+;url)[[:blank:]]*=[[:blank:]]*[\'\"]?(([[a-z]{3,5}:\/\/(([.a-zA-Z0-9-])+(:[0-9]+)*))*([+:%\/?=&;\\\(\),._ a-zA-Z0-9-]*))(#[.a-zA-Z0-9-]*)?[\'\" ]?/i,
5
+ /(window[.]open[[:blank:]]*[(])[[:blank:]]*[\'\"]+(([[a-z]{3,5}:\/\/(([.a-zA-Z0-9-])+(:[0-9]+)*))*([+:%\/?=&;\\\(\),._ a-zA-Z0-9-]*))(#[.a-zA-Z0-9-]*)?[\'\" ]?/i ]
6
+
7
+ def scan_html_relative_links(html,base_url)
8
+ links=[]
9
+ R_links_regexps.each{ |r|
10
+ matches=html.scan(r)
11
+ matches.each{ |m|
12
+ links.push m[0] if m[3].nil? and m[0] != ""
13
+ }
14
+ }
15
+ links
16
+ end
17
+ def scan_html_simple_links(html,base_url)
18
+ r=Regexp.compile('href=[\'\"]([^\'^\"^\s]*)[\'\"]')
19
+ links=[]
20
+ matches=html.scan(r)
21
+ matches.each{ |m|
22
+ links.push m[0]
23
+ }
24
+ links
25
+ end
26
+ def get_head_data(html)
27
+ r=Regexp.compile('<head[^>]*>(.*?)<\/head>',Regexp::IGNORECASE|Regexp::MULTILINE)
28
+ m=html.scan(r)
29
+ return nil if m.nil?
30
+ return nil if m[0].nil?
31
+ head={}
32
+ head[:title]=""
33
+ head[:keywords]=""
34
+ head[:robots]=""
35
+ head[:description]=""
36
+ head[:nofollow]=false
37
+ head[:noindex]=false
38
+ head[:base]=""
39
+
40
+
41
+ h=m[0][0]
42
+ begin
43
+ r_robots=/<meta +name *=[\"']?robots[\"']? *content=[\"']?([^<>'\"]+)[\"']?/im
44
+ robots=h.scan(r_robots)[0][0]
45
+ head[:robots]=robots
46
+ rescue
47
+ end
48
+ begin
49
+ r_desc=/<meta +name *=[\"']?description[\"']? *content=[\"']?([^<>'\"]+)[\"']?/im
50
+ head[:description]=h.scan(r_desc)[0][0]
51
+ rescue
52
+ end
53
+ begin
54
+ r_keys=/<meta +name *=[\"']?keywords[\"']? *content=[\"']?([^<>'\"]+)[\"']?/im
55
+ head[:keywords]=h.scan(r_keys)[0][0]
56
+ rescue
57
+ end
58
+
59
+ #<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
60
+ begin
61
+ r_charset=/<meta +http\-equiv*=[\"']?Content-Type[\"']? *content=[\"']?([^<>'\"]+)[\"']?/im
62
+ head[:charset]=h.scan(r_charset)[0][0].split("=").pop
63
+ rescue
64
+ end
65
+
66
+ begin
67
+ r_base=/<base +href *= *[\"']?([^<>'\"]+)[\"']?/im
68
+ head[:base]=h.scan(r_base)[0][0]
69
+ rescue
70
+ end
71
+ begin
72
+ r_title=/<title *>(.*?)<\/title*>/im
73
+ head[:title]=h.scan(r_title)[0][0].gsub("\n","")
74
+ rescue
75
+ end
76
+
77
+ begin
78
+ archives=[]
79
+ r_archives=/<link +rel*=[\"']?archives[\"']? *[^\>]+href=[\"']?([^<>'\"]+)[\"']?/im
80
+ h.scan(r_archives).each{ |l|
81
+ archives.push l[0]
82
+ }
83
+ head[:archives]=archives
84
+ rescue
85
+ end
86
+ begin
87
+ links=[]
88
+ r_alternates=/<link +rel*=[\"']?alternate[\"']? *[^\>]+href=[\"']?([^<>'\"]+)[\"']?/im
89
+ h.scan(r_alternates).each{ |l|
90
+ links.push l[0]
91
+ }
92
+ head[:rss_links]=links
93
+ rescue
94
+ end
95
+ robots.downcase.split(",").each{ |j|
96
+ head[:noindex]=true if j=="noindex"
97
+ head[:nofollow]=true if j=="nofollow"
98
+ } unless robots.nil?
99
+ head
100
+ end
101
+ html=open("3.html").read
102
+ lnks=scan_html_relative_links(html,"http://localhost/search_doc/")
103
+ lnks2=scan_html_simple_links(html,"http://localhost/search_doc/")
104
+ puts lnks2-lnks
105
+ get_head_data(html).each{|k,v|
106
+ if v.class==Array
107
+ puts "#{k}:Array:#{v.length},#{v.join("\narch:")}"
108
+ else
109
+ puts "#{k}:#{v}"
110
+ end
111
+ }
@@ -0,0 +1,1131 @@
1
+ # $Id: mysql.rb,v 1.24 2005/02/12 11:37:15 tommy Exp $
2
+ #
3
+ # Copyright (C) 2003-2005 TOMITA Masahiro
4
+ # tommy@tmtm.org
5
+ #
6
+
7
+ class Mysql
8
+
9
+ VERSION = "4.0-ruby-0.2.5"
10
+
11
+ require "socket"
12
+
13
+ MAX_PACKET_LENGTH = 256*256*256-1
14
+ MAX_ALLOWED_PACKET = 1024*1024*1024
15
+
16
+ MYSQL_UNIX_ADDR = "/var/lib/mysql/mysql.sock"
17
+ #MYSQL_UNIX_ADDR = "/tmp/mysql.sock"
18
+ MYSQL_PORT = 3306
19
+ PROTOCOL_VERSION = 10
20
+
21
+ # Command
22
+ COM_SLEEP = 0
23
+ COM_QUIT = 1
24
+ COM_INIT_DB = 2
25
+ COM_QUERY = 3
26
+ COM_FIELD_LIST = 4
27
+ COM_CREATE_DB = 5
28
+ COM_DROP_DB = 6
29
+ COM_REFRESH = 7
30
+ COM_SHUTDOWN = 8
31
+ COM_STATISTICS = 9
32
+ COM_PROCESS_INFO = 10
33
+ COM_CONNECT = 11
34
+ COM_PROCESS_KILL = 12
35
+ COM_DEBUG = 13
36
+ COM_PING = 14
37
+ COM_TIME = 15
38
+ COM_DELAYED_INSERT = 16
39
+ COM_CHANGE_USER = 17
40
+ COM_BINLOG_DUMP = 18
41
+ COM_TABLE_DUMP = 19
42
+ COM_CONNECT_OUT = 20
43
+ COM_REGISTER_SLAVE = 21
44
+
45
+ # Client flag
46
+ CLIENT_LONG_PASSWORD = 1
47
+ CLIENT_FOUND_ROWS = 1 << 1
48
+ CLIENT_LONG_FLAG = 1 << 2
49
+ CLIENT_CONNECT_WITH_DB= 1 << 3
50
+ CLIENT_NO_SCHEMA = 1 << 4
51
+ CLIENT_COMPRESS = 1 << 5
52
+ CLIENT_ODBC = 1 << 6
53
+ CLIENT_LOCAL_FILES = 1 << 7
54
+ CLIENT_IGNORE_SPACE = 1 << 8
55
+ CLIENT_INTERACTIVE = 1 << 10
56
+ CLIENT_SSL = 1 << 11
57
+ CLIENT_IGNORE_SIGPIPE = 1 << 12
58
+ CLIENT_TRANSACTIONS = 1 << 13
59
+ CLIENT_CAPABILITIES = CLIENT_LONG_PASSWORD|CLIENT_LONG_FLAG|CLIENT_TRANSACTIONS
60
+
61
+ # Connection Option
62
+ OPT_CONNECT_TIMEOUT = 0
63
+ OPT_COMPRESS = 1
64
+ OPT_NAMED_PIPE = 2
65
+ INIT_COMMAND = 3
66
+ READ_DEFAULT_FILE = 4
67
+ READ_DEFAULT_GROUP = 5
68
+ SET_CHARSET_DIR = 6
69
+ SET_CHARSET_NAME = 7
70
+ OPT_LOCAL_INFILE = 8
71
+
72
+ # Server Status
73
+ SERVER_STATUS_IN_TRANS = 1
74
+ SERVER_STATUS_AUTOCOMMIT = 2
75
+
76
+ # Refresh parameter
77
+ REFRESH_GRANT = 1
78
+ REFRESH_LOG = 2
79
+ REFRESH_TABLES = 4
80
+ REFRESH_HOSTS = 8
81
+ REFRESH_STATUS = 16
82
+ REFRESH_THREADS = 32
83
+ REFRESH_SLAVE = 64
84
+ REFRESH_MASTER = 128
85
+
86
+ def initialize(*args)
87
+ @client_flag = 0
88
+ @max_allowed_packet = MAX_ALLOWED_PACKET
89
+ @query_with_result = true
90
+ @status = :STATUS_READY
91
+ if args[0] != :INIT then
92
+ real_connect(*args)
93
+ end
94
+ end
95
+
96
+ def real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, socket=nil, flag=nil)
97
+ @server_status = SERVER_STATUS_AUTOCOMMIT
98
+ if (host == nil or host == "localhost") and defined? UNIXSocket then
99
+ unix_socket = socket || ENV["MYSQL_UNIX_PORT"] || MYSQL_UNIX_ADDR
100
+ sock = UNIXSocket::new(unix_socket)
101
+ @host_info = Error::err(Error::CR_LOCALHOST_CONNECTION)
102
+ @unix_socket = unix_socket
103
+ else
104
+ sock = TCPSocket::new(host, port||ENV["MYSQL_TCP_PORT"]||(Socket::getservbyname("mysql","tcp") rescue MYSQL_PORT))
105
+ @host_info = sprintf Error::err(Error::CR_TCP_CONNECTION), host
106
+ end
107
+ @host = host ? host.dup : nil
108
+ sock.setsockopt Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true
109
+ @net = Net::new sock
110
+
111
+ a = read
112
+ @protocol_version = a.slice!(0)
113
+ @server_version, a = a.split(/\0/,2)
114
+ @thread_id, @scramble_buff = a.slice!(0,13).unpack("La8")
115
+ if a.size >= 2 then
116
+ @server_capabilities, = a.slice!(0,2).unpack("v")
117
+ end
118
+ if a.size >= 16 then
119
+ @server_language, @server_status = a.unpack("cv")
120
+ end
121
+
122
+ flag = 0 if flag == nil
123
+ flag |= @client_flag | CLIENT_CAPABILITIES
124
+ flag |= CLIENT_CONNECT_WITH_DB if db
125
+ data = Net::int2str(flag)+Net::int3str(@max_allowed_packet)+(user||"")+"\0"+scramble(passwd, @scramble_buff, @protocol_version==9)
126
+ if db and @server_capabilities & CLIENT_CONNECT_WITH_DB != 0 then
127
+ data << "\0"+db
128
+ @db = db.dup
129
+ end
130
+ write data
131
+ read
132
+ ObjectSpace.define_finalizer(self, Mysql.finalizer(@net))
133
+ self
134
+ end
135
+ alias :connect :real_connect
136
+
137
+ def escape_string(str)
138
+ Mysql::escape_string str
139
+ end
140
+ alias :quote :escape_string
141
+
142
+ def get_client_info()
143
+ VERSION
144
+ end
145
+ alias :client_info :get_client_info
146
+
147
+ def options(option, arg=nil)
148
+ if option == OPT_LOCAL_INFILE then
149
+ if arg == false or arg == 0 then
150
+ @client_flag &= ~CLIENT_LOCAL_FILES
151
+ else
152
+ @client_flag |= CLIENT_LOCAL_FILES
153
+ end
154
+ else
155
+ raise "not implemented"
156
+ end
157
+ end
158
+
159
+ def real_query(query)
160
+ command COM_QUERY, query, true
161
+ read_query_result
162
+ self
163
+ end
164
+
165
+ def use_result()
166
+ if @status != :STATUS_GET_RESULT then
167
+ error Error::CR_COMMANDS_OUT_OF_SYNC
168
+ end
169
+ res = Result::new self, @fields, @field_count
170
+ @status = :STATUS_USE_RESULT
171
+ res
172
+ end
173
+
174
+ def store_result()
175
+ if @status != :STATUS_GET_RESULT then
176
+ error Error::CR_COMMANDS_OUT_OF_SYNC
177
+ end
178
+ @status = :STATUS_READY
179
+ data = read_rows @field_count
180
+ res = Result::new self, @fields, @field_count, data
181
+ @fields = nil
182
+ @affected_rows = data.length
183
+ res
184
+ end
185
+
186
+ def change_user(user="", passwd="", db="")
187
+ data = user+"\0"+scramble(passwd, @scramble_buff, @protocol_version==9)+"\0"+db
188
+ command COM_CHANGE_USER, data
189
+ @user = user
190
+ @passwd = passwd
191
+ @db = db
192
+ end
193
+
194
+ def character_set_name()
195
+ raise "not implemented"
196
+ end
197
+
198
+ def close()
199
+ @status = :STATUS_READY
200
+ command COM_QUIT, nil, true
201
+ @net.close
202
+ self
203
+ end
204
+
205
+ def create_db(db)
206
+ command COM_CREATE_DB, db
207
+ self
208
+ end
209
+
210
+ def drop_db(db)
211
+ command COM_DROP_DB, db
212
+ self
213
+ end
214
+
215
+ def dump_debug_info()
216
+ command COM_DEBUG
217
+ self
218
+ end
219
+
220
+ def get_host_info()
221
+ @host_info
222
+ end
223
+ alias :host_info :get_host_info
224
+
225
+ def get_proto_info()
226
+ @protocol_version
227
+ end
228
+ alias :proto_info :get_proto_info
229
+
230
+ def get_server_info()
231
+ @server_version
232
+ end
233
+ alias :server_info :get_server_info
234
+
235
+ def kill(id)
236
+ command COM_PROCESS_KILL, Net::int4str(id)
237
+ self
238
+ end
239
+
240
+ def list_dbs(db=nil)
241
+ real_query "show databases #{db}"
242
+ @status = :STATUS_READY
243
+ read_rows(1).flatten
244
+ end
245
+
246
+ def list_fields(table, field=nil)
247
+ command COM_FIELD_LIST, "#{table}\0#{field}", true
248
+ f = read_rows 6
249
+ fields = unpack_fields(f, @server_capabilities & CLIENT_LONG_FLAG != 0)
250
+ res = Result::new self, fields, f.length
251
+ res.eof = true
252
+ res
253
+ end
254
+
255
+ def list_processes()
256
+ data = command COM_PROCESS_INFO
257
+ @field_count = get_length data
258
+ fields = read_rows 5
259
+ @fields = unpack_fields(fields, @server_capabilities & CLIENT_LONG_FLAG != 0)
260
+ @status = :STATUS_GET_RESULT
261
+ store_result
262
+ end
263
+
264
+ def list_tables(table=nil)
265
+ real_query "show tables #{table}"
266
+ @status = :STATUS_READY
267
+ read_rows(1).flatten
268
+ end
269
+
270
+ def ping()
271
+ command COM_PING
272
+ self
273
+ end
274
+
275
+ def query(query)
276
+ real_query query
277
+ if not @query_with_result then
278
+ return self
279
+ end
280
+ if @field_count == 0 then
281
+ return nil
282
+ end
283
+ store_result
284
+ end
285
+
286
+ def refresh(r)
287
+ command COM_REFRESH, r.chr
288
+ self
289
+ end
290
+
291
+ def reload()
292
+ refresh REFRESH_GRANT
293
+ self
294
+ end
295
+
296
+ def select_db(db)
297
+ command COM_INIT_DB, db
298
+ @db = db
299
+ self
300
+ end
301
+
302
+ def shutdown()
303
+ command COM_SHUTDOWN
304
+ self
305
+ end
306
+
307
+ def stat()
308
+ command COM_STATISTICS
309
+ end
310
+
311
+ attr_reader :info, :insert_id, :affected_rows, :field_count, :thread_id
312
+ attr_accessor :query_with_result, :status
313
+
314
+ def read_one_row(field_count)
315
+ data = read
316
+ return if data[0] == 254 and data.length == 1
317
+ rec = []
318
+ field_count.times do
319
+ len = get_length data
320
+ if len == nil then
321
+ rec << len
322
+ else
323
+ rec << data.slice!(0,len)
324
+ end
325
+ end
326
+ rec
327
+ end
328
+
329
+ def skip_result()
330
+ if @status == :STATUS_USE_RESULT then
331
+ loop do
332
+ data = read
333
+ break if data[0] == 254 and data.length == 1
334
+ end
335
+ @status = :STATUS_READY
336
+ end
337
+ end
338
+
339
+ def inspect()
340
+ "#<#{self.class}>"
341
+ end
342
+
343
+ private
344
+
345
+ def read_query_result()
346
+ data = read
347
+ @field_count = get_length(data)
348
+ if @field_count == nil then # LOAD DATA LOCAL INFILE
349
+ File::open(data) do |f|
350
+ write f.read
351
+ end
352
+ write "" # mark EOF
353
+ data = read
354
+ @field_count = get_length(data)
355
+ end
356
+ if @field_count == 0 then
357
+ @affected_rows = get_length(data, true)
358
+ @insert_id = get_length(data, true)
359
+ if @server_capabilities & CLIENT_TRANSACTIONS != 0 then
360
+ a = data.slice!(0,2)
361
+ @server_status = a[0]+a[1]*256
362
+ end
363
+ if data.size > 0 and get_length(data) then
364
+ @info = data
365
+ end
366
+ else
367
+ @extra_info = get_length(data, true)
368
+ fields = read_rows 5
369
+ @fields = unpack_fields(fields, @server_capabilities & CLIENT_LONG_FLAG != 0)
370
+ @status = :STATUS_GET_RESULT
371
+ end
372
+ self
373
+ end
374
+
375
+ def unpack_fields(data, long_flag_protocol)
376
+ ret = []
377
+ data.each do |f|
378
+ table = org_table = f[0]
379
+ name = f[1]
380
+ length = f[2][0]+f[2][1]*256+f[2][2]*256*256
381
+ type = f[3][0]
382
+ if long_flag_protocol then
383
+ flags = f[4][0]+f[4][1]*256
384
+ decimals = f[4][2]
385
+ else
386
+ flags = f[4][0]
387
+ decimals = f[4][1]
388
+ end
389
+ def_value = f[5]
390
+ max_length = 0
391
+ ret << Field::new(table, org_table, name, length, type, flags, decimals, def_value, max_length)
392
+ end
393
+ ret
394
+ end
395
+
396
+ def read_rows(field_count)
397
+ ret = []
398
+ while rec = read_one_row(field_count) do
399
+ ret << rec
400
+ end
401
+ ret
402
+ end
403
+
404
+ def get_length(data, longlong=nil)
405
+ return if data.length == 0
406
+ c = data.slice!(0)
407
+ case c
408
+ when 251
409
+ return nil
410
+ when 252
411
+ a = data.slice!(0,2)
412
+ return a[0]+a[1]*256
413
+ when 253
414
+ a = data.slice!(0,3)
415
+ return a[0]+a[1]*256+a[2]*256**2
416
+ when 254
417
+ a = data.slice!(0,8)
418
+ if longlong then
419
+ return a[0]+a[1]*256+a[2]*256**2+a[3]*256**3+
420
+ a[4]*256**4+a[5]*256**5+a[6]*256**6+a[7]*256**7
421
+ else
422
+ return a[0]+a[1]*256+a[2]*256**2+a[3]*256**3
423
+ end
424
+ else
425
+ c
426
+ end
427
+ end
428
+
429
+ def command(cmd, arg=nil, skip_check=nil)
430
+ unless @net then
431
+ error Error::CR_SERVER_GONE_ERROR
432
+ end
433
+ if @status != :STATUS_READY then
434
+ error Error::CR_COMMANDS_OUT_OF_SYNC
435
+ end
436
+ @net.clear
437
+ write cmd.chr+(arg||"")
438
+ read unless skip_check
439
+ end
440
+
441
+ def read()
442
+ unless @net then
443
+ error Error::CR_SERVER_GONE_ERROR
444
+ end
445
+ a = @net.read
446
+ if a[0] == 255 then
447
+ if a.length > 3 then
448
+ @errno = a[1]+a[2]*256
449
+ @error = a[3 .. -1]
450
+ else
451
+ @errno = Error::CR_UNKNOWN_ERROR
452
+ @error = Error::err @errno
453
+ end
454
+ raise Mysql::Error::new(@errno, @error)
455
+ #raise "#{@errno}:#{@error}"
456
+ #raise @error
457
+ #hack by renlu
458
+ end
459
+ a
460
+ end
461
+
462
+ def write(arg)
463
+ unless @net then
464
+ error Error::CR_SERVER_GONE_ERROR
465
+ end
466
+ @net.write arg
467
+ end
468
+
469
+ def hash_password(password)
470
+ nr = 1345345333
471
+ add = 7
472
+ nr2 = 0x12345671
473
+ password.each_byte do |i|
474
+ next if i == 0x20 or i == 9
475
+ nr ^= (((nr & 63) + add) * i) + (nr << 8)
476
+ nr2 += (nr2 << 8) ^ nr
477
+ add += i
478
+ end
479
+ [nr & ((1 << 31) - 1), nr2 & ((1 << 31) - 1)]
480
+ end
481
+
482
+ def scramble(password, message, old_ver)
483
+ return "" if password == nil or password == ""
484
+ raise "old version password is not implemented" if old_ver
485
+ hash_pass = hash_password password
486
+ hash_message = hash_password message
487
+ rnd = Random::new hash_pass[0] ^ hash_message[0], hash_pass[1] ^ hash_message[1]
488
+ to = []
489
+ 1.upto(message.length) do
490
+ to << ((rnd.rnd*31)+64).floor
491
+ end
492
+ extra = (rnd.rnd*31).floor
493
+ to.map! do |t| (t ^ extra).chr end
494
+ to.join
495
+ end
496
+
497
+ def error(errno)
498
+ @errno = errno
499
+ @error = Error::err errno
500
+ raise Error::new(@errno, @error)
501
+ end
502
+
503
+ class Result
504
+ def initialize(mysql, fields, field_count, data=nil)
505
+ @handle = mysql
506
+ @fields = fields
507
+ @field_count = field_count
508
+ @data = data
509
+ @current_field = 0
510
+ @current_row = 0
511
+ @eof = false
512
+ @row_count = 0
513
+ end
514
+ attr_accessor :eof
515
+
516
+ def data_seek(n)
517
+ @current_row = n
518
+ end
519
+
520
+ def fetch_field()
521
+ return if @current_field >= @field_count
522
+ f = @fields[@current_field]
523
+ @current_field += 1
524
+ f
525
+ end
526
+
527
+ def fetch_fields()
528
+ @fields
529
+ end
530
+
531
+ def fetch_field_direct(n)
532
+ @fields[n]
533
+ end
534
+
535
+ def fetch_lengths()
536
+ @data ? @data[@current_row].map{|i| i ? i.length : 0} : @lengths
537
+ end
538
+
539
+ def fetch_row()
540
+ if @data then
541
+ if @current_row >= @data.length then
542
+ @handle.status = :STATUS_READY
543
+ return
544
+ end
545
+ ret = @data[@current_row]
546
+ @current_row += 1
547
+ else
548
+ return if @eof
549
+ ret = @handle.read_one_row @field_count
550
+ if ret == nil then
551
+ @eof = true
552
+ return
553
+ end
554
+ @lengths = ret.map{|i| i ? i.length : 0}
555
+ @row_count += 1
556
+ end
557
+ ret
558
+ end
559
+
560
+ def fetch_hash(with_table=nil)
561
+ row = fetch_row
562
+ return if row == nil
563
+ hash = {}
564
+ @fields.each_index do |i|
565
+ f = with_table ? @fields[i].table+"."+@fields[i].name : @fields[i].name
566
+ hash[f] = row[i]
567
+ end
568
+ hash
569
+ end
570
+
571
+ def field_seek(n)
572
+ @current_field = n
573
+ end
574
+
575
+ def field_tell()
576
+ @current_field
577
+ end
578
+
579
+ def free()
580
+ @handle.skip_result
581
+ @handle = @fields = @data = nil
582
+ GC::start
583
+ end
584
+
585
+ def num_fields()
586
+ @field_count
587
+ end
588
+
589
+ def num_rows()
590
+ @data ? @data.length : @row_count
591
+ end
592
+
593
+ def row_seek(n)
594
+ @current_row = n
595
+ end
596
+
597
+ def row_tell()
598
+ @current_row
599
+ end
600
+
601
+ def each()
602
+ while row = fetch_row do
603
+ yield row
604
+ end
605
+ end
606
+
607
+ def each_hash(with_table=nil)
608
+ while hash = fetch_hash(with_table) do
609
+ yield hash
610
+ end
611
+ end
612
+
613
+ def inspect()
614
+ "#<#{self.class}>"
615
+ end
616
+
617
+ end
618
+
619
+ class Field
620
+ # Field type
621
+ TYPE_DECIMAL = 0
622
+ TYPE_TINY = 1
623
+ TYPE_SHORT = 2
624
+ TYPE_LONG = 3
625
+ TYPE_FLOAT = 4
626
+ TYPE_DOUBLE = 5
627
+ TYPE_NULL = 6
628
+ TYPE_TIMESTAMP = 7
629
+ TYPE_LONGLONG = 8
630
+ TYPE_INT24 = 9
631
+ TYPE_DATE = 10
632
+ TYPE_TIME = 11
633
+ TYPE_DATETIME = 12
634
+ TYPE_YEAR = 13
635
+ TYPE_NEWDATE = 14
636
+ TYPE_ENUM = 247
637
+ TYPE_SET = 248
638
+ TYPE_TINY_BLOB = 249
639
+ TYPE_MEDIUM_BLOB = 250
640
+ TYPE_LONG_BLOB = 251
641
+ TYPE_BLOB = 252
642
+ TYPE_VAR_STRING = 253
643
+ TYPE_STRING = 254
644
+ TYPE_GEOMETRY = 255
645
+ TYPE_CHAR = TYPE_TINY
646
+ TYPE_INTERVAL = TYPE_ENUM
647
+
648
+ # Flag
649
+ NOT_NULL_FLAG = 1
650
+ PRI_KEY_FLAG = 2
651
+ UNIQUE_KEY_FLAG = 4
652
+ MULTIPLE_KEY_FLAG = 8
653
+ BLOB_FLAG = 16
654
+ UNSIGNED_FLAG = 32
655
+ ZEROFILL_FLAG = 64
656
+ BINARY_FLAG = 128
657
+ ENUM_FLAG = 256
658
+ AUTO_INCREMENT_FLAG = 512
659
+ TIMESTAMP_FLAG = 1024
660
+ SET_FLAG = 2048
661
+ NUM_FLAG = 32768
662
+ PART_KEY_FLAG = 16384
663
+ GROUP_FLAG = 32768
664
+ UNIQUE_FLAG = 65536
665
+
666
+ def initialize(table, org_table, name, length, type, flags, decimals, def_value, max_length)
667
+ @table = table
668
+ @org_table = org_table
669
+ @name = name
670
+ @length = length
671
+ @type = type
672
+ @flags = flags
673
+ @decimals = decimals
674
+ @def = def_value
675
+ @max_length = max_length
676
+ if (type <= TYPE_INT24 and (type != TYPE_TIMESTAMP or length == 14 or length == 8)) or type == TYPE_YEAR then
677
+ @flags |= NUM_FLAG
678
+ end
679
+ end
680
+ attr_reader :table, :org_table, :name, :length, :type, :flags, :decimals, :def, :max_length
681
+
682
+ def inspect()
683
+ "#<#{self.class}:#{@name}>"
684
+ end
685
+ end
686
+
687
+ #class Error < StandardError
688
+ #Hack by renlu
689
+ class Error < StandardError
690
+ # Server Error
691
+ ER_HASHCHK = 1000
692
+ ER_NISAMCHK = 1001
693
+ ER_NO = 1002
694
+ ER_YES = 1003
695
+ ER_CANT_CREATE_FILE = 1004
696
+ ER_CANT_CREATE_TABLE = 1005
697
+ ER_CANT_CREATE_DB = 1006
698
+ ER_DB_CREATE_EXISTS = 1007
699
+ ER_DB_DROP_EXISTS = 1008
700
+ ER_DB_DROP_DELETE = 1009
701
+ ER_DB_DROP_RMDIR = 1010
702
+ ER_CANT_DELETE_FILE = 1011
703
+ ER_CANT_FIND_SYSTEM_REC = 1012
704
+ ER_CANT_GET_STAT = 1013
705
+ ER_CANT_GET_WD = 1014
706
+ ER_CANT_LOCK = 1015
707
+ ER_CANT_OPEN_FILE = 1016
708
+ ER_FILE_NOT_FOUND = 1017
709
+ ER_CANT_READ_DIR = 1018
710
+ ER_CANT_SET_WD = 1019
711
+ ER_CHECKREAD = 1020
712
+ ER_DISK_FULL = 1021
713
+ ER_DUP_KEY = 1022
714
+ ER_ERROR_ON_CLOSE = 1023
715
+ ER_ERROR_ON_READ = 1024
716
+ ER_ERROR_ON_RENAME = 1025
717
+ ER_ERROR_ON_WRITE = 1026
718
+ ER_FILE_USED = 1027
719
+ ER_FILSORT_ABORT = 1028
720
+ ER_FORM_NOT_FOUND = 1029
721
+ ER_GET_ERRNO = 1030
722
+ ER_ILLEGAL_HA = 1031
723
+ ER_KEY_NOT_FOUND = 1032
724
+ ER_NOT_FORM_FILE = 1033
725
+ ER_NOT_KEYFILE = 1034
726
+ ER_OLD_KEYFILE = 1035
727
+ ER_OPEN_AS_READONLY = 1036
728
+ ER_OUTOFMEMORY = 1037
729
+ ER_OUT_OF_SORTMEMORY = 1038
730
+ ER_UNEXPECTED_EOF = 1039
731
+ ER_CON_COUNT_ERROR = 1040
732
+ ER_OUT_OF_RESOURCES = 1041
733
+ ER_BAD_HOST_ERROR = 1042
734
+ ER_HANDSHAKE_ERROR = 1043
735
+ ER_DBACCESS_DENIED_ERROR = 1044
736
+ ER_ACCESS_DENIED_ERROR = 1045
737
+ ER_NO_DB_ERROR = 1046
738
+ ER_UNKNOWN_COM_ERROR = 1047
739
+ ER_BAD_NULL_ERROR = 1048
740
+ ER_BAD_DB_ERROR = 1049
741
+ ER_TABLE_EXISTS_ERROR = 1050
742
+ ER_BAD_TABLE_ERROR = 1051
743
+ ER_NON_UNIQ_ERROR = 1052
744
+ ER_SERVER_SHUTDOWN = 1053
745
+ ER_BAD_FIELD_ERROR = 1054
746
+ ER_WRONG_FIELD_WITH_GROUP = 1055
747
+ ER_WRONG_GROUP_FIELD = 1056
748
+ ER_WRONG_SUM_SELECT = 1057
749
+ ER_WRONG_VALUE_COUNT = 1058
750
+ ER_TOO_LONG_IDENT = 1059
751
+ ER_DUP_FIELDNAME = 1060
752
+ ER_DUP_KEYNAME = 1061
753
+ ER_DUP_ENTRY = 1062
754
+ ER_WRONG_FIELD_SPEC = 1063
755
+ ER_PARSE_ERROR = 1064
756
+ ER_EMPTY_QUERY = 1065
757
+ ER_NONUNIQ_TABLE = 1066
758
+ ER_INVALID_DEFAULT = 1067
759
+ ER_MULTIPLE_PRI_KEY = 1068
760
+ ER_TOO_MANY_KEYS = 1069
761
+ ER_TOO_MANY_KEY_PARTS = 1070
762
+ ER_TOO_LONG_KEY = 1071
763
+ ER_KEY_COLUMN_DOES_NOT_EXITS = 1072
764
+ ER_BLOB_USED_AS_KEY = 1073
765
+ ER_TOO_BIG_FIELDLENGTH = 1074
766
+ ER_WRONG_AUTO_KEY = 1075
767
+ ER_READY = 1076
768
+ ER_NORMAL_SHUTDOWN = 1077
769
+ ER_GOT_SIGNAL = 1078
770
+ ER_SHUTDOWN_COMPLETE = 1079
771
+ ER_FORCING_CLOSE = 1080
772
+ ER_IPSOCK_ERROR = 1081
773
+ ER_NO_SUCH_INDEX = 1082
774
+ ER_WRONG_FIELD_TERMINATORS = 1083
775
+ ER_BLOBS_AND_NO_TERMINATED = 1084
776
+ ER_TEXTFILE_NOT_READABLE = 1085
777
+ ER_FILE_EXISTS_ERROR = 1086
778
+ ER_LOAD_INFO = 1087
779
+ ER_ALTER_INFO = 1088
780
+ ER_WRONG_SUB_KEY = 1089
781
+ ER_CANT_REMOVE_ALL_FIELDS = 1090
782
+ ER_CANT_DROP_FIELD_OR_KEY = 1091
783
+ ER_INSERT_INFO = 1092
784
+ ER_INSERT_TABLE_USED = 1093
785
+ ER_NO_SUCH_THREAD = 1094
786
+ ER_KILL_DENIED_ERROR = 1095
787
+ ER_NO_TABLES_USED = 1096
788
+ ER_TOO_BIG_SET = 1097
789
+ ER_NO_UNIQUE_LOGFILE = 1098
790
+ ER_TABLE_NOT_LOCKED_FOR_WRITE = 1099
791
+ ER_TABLE_NOT_LOCKED = 1100
792
+ ER_BLOB_CANT_HAVE_DEFAULT = 1101
793
+ ER_WRONG_DB_NAME = 1102
794
+ ER_WRONG_TABLE_NAME = 1103
795
+ ER_TOO_BIG_SELECT = 1104
796
+ ER_UNKNOWN_ERROR = 1105
797
+ ER_UNKNOWN_PROCEDURE = 1106
798
+ ER_WRONG_PARAMCOUNT_TO_PROCEDURE = 1107
799
+ ER_WRONG_PARAMETERS_TO_PROCEDURE = 1108
800
+ ER_UNKNOWN_TABLE = 1109
801
+ ER_FIELD_SPECIFIED_TWICE = 1110
802
+ ER_INVALID_GROUP_FUNC_USE = 1111
803
+ ER_UNSUPPORTED_EXTENSION = 1112
804
+ ER_TABLE_MUST_HAVE_COLUMNS = 1113
805
+ ER_RECORD_FILE_FULL = 1114
806
+ ER_UNKNOWN_CHARACTER_SET = 1115
807
+ ER_TOO_MANY_TABLES = 1116
808
+ ER_TOO_MANY_FIELDS = 1117
809
+ ER_TOO_BIG_ROWSIZE = 1118
810
+ ER_STACK_OVERRUN = 1119
811
+ ER_WRONG_OUTER_JOIN = 1120
812
+ ER_NULL_COLUMN_IN_INDEX = 1121
813
+ ER_CANT_FIND_UDF = 1122
814
+ ER_CANT_INITIALIZE_UDF = 1123
815
+ ER_UDF_NO_PATHS = 1124
816
+ ER_UDF_EXISTS = 1125
817
+ ER_CANT_OPEN_LIBRARY = 1126
818
+ ER_CANT_FIND_DL_ENTRY = 1127
819
+ ER_FUNCTION_NOT_DEFINED = 1128
820
+ ER_HOST_IS_BLOCKED = 1129
821
+ ER_HOST_NOT_PRIVILEGED = 1130
822
+ ER_PASSWORD_ANONYMOUS_USER = 1131
823
+ ER_PASSWORD_NOT_ALLOWED = 1132
824
+ ER_PASSWORD_NO_MATCH = 1133
825
+ ER_UPDATE_INFO = 1134
826
+ ER_CANT_CREATE_THREAD = 1135
827
+ ER_WRONG_VALUE_COUNT_ON_ROW = 1136
828
+ ER_CANT_REOPEN_TABLE = 1137
829
+ ER_INVALID_USE_OF_NULL = 1138
830
+ ER_REGEXP_ERROR = 1139
831
+ ER_MIX_OF_GROUP_FUNC_AND_FIELDS = 1140
832
+ ER_NONEXISTING_GRANT = 1141
833
+ ER_TABLEACCESS_DENIED_ERROR = 1142
834
+ ER_COLUMNACCESS_DENIED_ERROR = 1143
835
+ ER_ILLEGAL_GRANT_FOR_TABLE = 1144
836
+ ER_GRANT_WRONG_HOST_OR_USER = 1145
837
+ ER_NO_SUCH_TABLE = 1146
838
+ ER_NONEXISTING_TABLE_GRANT = 1147
839
+ ER_NOT_ALLOWED_COMMAND = 1148
840
+ ER_SYNTAX_ERROR = 1149
841
+ ER_DELAYED_CANT_CHANGE_LOCK = 1150
842
+ ER_TOO_MANY_DELAYED_THREADS = 1151
843
+ ER_ABORTING_CONNECTION = 1152
844
+ ER_NET_PACKET_TOO_LARGE = 1153
845
+ ER_NET_READ_ERROR_FROM_PIPE = 1154
846
+ ER_NET_FCNTL_ERROR = 1155
847
+ ER_NET_PACKETS_OUT_OF_ORDER = 1156
848
+ ER_NET_UNCOMPRESS_ERROR = 1157
849
+ ER_NET_READ_ERROR = 1158
850
+ ER_NET_READ_INTERRUPTED = 1159
851
+ ER_NET_ERROR_ON_WRITE = 1160
852
+ ER_NET_WRITE_INTERRUPTED = 1161
853
+ ER_TOO_LONG_STRING = 1162
854
+ ER_TABLE_CANT_HANDLE_BLOB = 1163
855
+ ER_TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164
856
+ ER_DELAYED_INSERT_TABLE_LOCKED = 1165
857
+ ER_WRONG_COLUMN_NAME = 1166
858
+ ER_WRONG_KEY_COLUMN = 1167
859
+ ER_WRONG_MRG_TABLE = 1168
860
+ ER_DUP_UNIQUE = 1169
861
+ ER_BLOB_KEY_WITHOUT_LENGTH = 1170
862
+ ER_PRIMARY_CANT_HAVE_NULL = 1171
863
+ ER_TOO_MANY_ROWS = 1172
864
+ ER_REQUIRES_PRIMARY_KEY = 1173
865
+ ER_NO_RAID_COMPILED = 1174
866
+ ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175
867
+ ER_KEY_DOES_NOT_EXITS = 1176
868
+ ER_CHECK_NO_SUCH_TABLE = 1177
869
+ ER_CHECK_NOT_IMPLEMENTED = 1178
870
+ ER_CANT_DO_THIS_DURING_AN_TRANSACTION = 1179
871
+ ER_ERROR_DURING_COMMIT = 1180
872
+ ER_ERROR_DURING_ROLLBACK = 1181
873
+ ER_ERROR_DURING_FLUSH_LOGS = 1182
874
+ ER_ERROR_DURING_CHECKPOINT = 1183
875
+ ER_NEW_ABORTING_CONNECTION = 1184
876
+ ER_DUMP_NOT_IMPLEMENTED = 1185
877
+ ER_FLUSH_MASTER_BINLOG_CLOSED = 1186
878
+ ER_INDEX_REBUILD = 1187
879
+ ER_MASTER = 1188
880
+ ER_MASTER_NET_READ = 1189
881
+ ER_MASTER_NET_WRITE = 1190
882
+ ER_FT_MATCHING_KEY_NOT_FOUND = 1191
883
+ ER_LOCK_OR_ACTIVE_TRANSACTION = 1192
884
+ ER_UNKNOWN_SYSTEM_VARIABLE = 1193
885
+ ER_CRASHED_ON_USAGE = 1194
886
+ ER_CRASHED_ON_REPAIR = 1195
887
+ ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196
888
+ ER_TRANS_CACHE_FULL = 1197
889
+ ER_SLAVE_MUST_STOP = 1198
890
+ ER_SLAVE_NOT_RUNNING = 1199
891
+ ER_BAD_SLAVE = 1200
892
+ ER_MASTER_INFO = 1201
893
+ ER_SLAVE_THREAD = 1202
894
+ ER_TOO_MANY_USER_CONNECTIONS = 1203
895
+ ER_SET_CONSTANTS_ONLY = 1204
896
+ ER_LOCK_WAIT_TIMEOUT = 1205
897
+ ER_LOCK_TABLE_FULL = 1206
898
+ ER_READ_ONLY_TRANSACTION = 1207
899
+ ER_DROP_DB_WITH_READ_LOCK = 1208
900
+ ER_CREATE_DB_WITH_READ_LOCK = 1209
901
+ ER_WRONG_ARGUMENTS = 1210
902
+ ER_NO_PERMISSION_TO_CREATE_USER = 1211
903
+ ER_UNION_TABLES_IN_DIFFERENT_DIR = 1212
904
+ ER_LOCK_DEADLOCK = 1213
905
+ ER_TABLE_CANT_HANDLE_FULLTEXT = 1214
906
+ ER_CANNOT_ADD_FOREIGN = 1215
907
+ ER_NO_REFERENCED_ROW = 1216
908
+ ER_ROW_IS_REFERENCED = 1217
909
+ ER_CONNECT_TO_MASTER = 1218
910
+ ER_QUERY_ON_MASTER = 1219
911
+ ER_ERROR_WHEN_EXECUTING_COMMAND = 1220
912
+ ER_WRONG_USAGE = 1221
913
+ ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222
914
+ ER_CANT_UPDATE_WITH_READLOCK = 1223
915
+ ER_MIXING_NOT_ALLOWED = 1224
916
+ ER_DUP_ARGUMENT = 1225
917
+ ER_USER_LIMIT_REACHED = 1226
918
+ ER_SPECIFIC_ACCESS_DENIED_ERROR = 1227
919
+ ER_LOCAL_VARIABLE = 1228
920
+ ER_GLOBAL_VARIABLE = 1229
921
+ ER_NO_DEFAULT = 1230
922
+ ER_WRONG_VALUE_FOR_VAR = 1231
923
+ ER_WRONG_TYPE_FOR_VAR = 1232
924
+ ER_VAR_CANT_BE_READ = 1233
925
+ ER_CANT_USE_OPTION_HERE = 1234
926
+ ER_NOT_SUPPORTED_YET = 1235
927
+ ER_MASTER_FATAL_ERROR_READING_BINLOG = 1236
928
+ ER_SLAVE_IGNORED_TABLE = 1237
929
+ ER_ERROR_MESSAGES = 238
930
+
931
+ # Client Error
932
+ CR_MIN_ERROR = 2000
933
+ CR_MAX_ERROR = 2999
934
+ CR_UNKNOWN_ERROR = 2000
935
+ CR_SOCKET_CREATE_ERROR = 2001
936
+ CR_CONNECTION_ERROR = 2002
937
+ CR_CONN_HOST_ERROR = 2003
938
+ CR_IPSOCK_ERROR = 2004
939
+ CR_UNKNOWN_HOST = 2005
940
+ CR_SERVER_GONE_ERROR = 2006
941
+ CR_VERSION_ERROR = 2007
942
+ CR_OUT_OF_MEMORY = 2008
943
+ CR_WRONG_HOST_INFO = 2009
944
+ CR_LOCALHOST_CONNECTION = 2010
945
+ CR_TCP_CONNECTION = 2011
946
+ CR_SERVER_HANDSHAKE_ERR = 2012
947
+ CR_SERVER_LOST = 2013
948
+ CR_COMMANDS_OUT_OF_SYNC = 2014
949
+ CR_NAMEDPIPE_CONNECTION = 2015
950
+ CR_NAMEDPIPEWAIT_ERROR = 2016
951
+ CR_NAMEDPIPEOPEN_ERROR = 2017
952
+ CR_NAMEDPIPESETSTATE_ERROR = 2018
953
+ CR_CANT_READ_CHARSET = 2019
954
+ CR_NET_PACKET_TOO_LARGE = 2020
955
+ CR_EMBEDDED_CONNECTION = 2021
956
+ CR_PROBE_SLAVE_STATUS = 2022
957
+ CR_PROBE_SLAVE_HOSTS = 2023
958
+ CR_PROBE_SLAVE_CONNECT = 2024
959
+ CR_PROBE_MASTER_CONNECT = 2025
960
+ CR_SSL_CONNECTION_ERROR = 2026
961
+ CR_MALFORMED_PACKET = 2027
962
+
963
+ CLIENT_ERRORS = [
964
+ "Unknown MySQL error",
965
+ "Can't create UNIX socket (%d)",
966
+ "Can't connect to local MySQL server through socket '%-.64s' (%d)",
967
+ "Can't connect to MySQL server on '%-.64s' (%d)",
968
+ "Can't create TCP/IP socket (%d)",
969
+ "Unknown MySQL Server Host '%-.64s' (%d)",
970
+ "MySQL server has gone away",
971
+ "Protocol mismatch. Server Version = %d Client Version = %d",
972
+ "MySQL client run out of memory",
973
+ "Wrong host info",
974
+ "Localhost via UNIX socket",
975
+ "%-.64s via TCP/IP",
976
+ "Error in server handshake",
977
+ "Lost connection to MySQL server during query",
978
+ "Commands out of sync; You can't run this command now",
979
+ "%-.64s via named pipe",
980
+ "Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu)",
981
+ "Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)",
982
+ "Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)",
983
+ "Can't initialize character set %-.64s (path: %-.64s)",
984
+ "Got packet bigger than 'max_allowed_packet'",
985
+ "Embedded server",
986
+ "Error on SHOW SLAVE STATUS:",
987
+ "Error on SHOW SLAVE HOSTS:",
988
+ "Error connecting to slave:",
989
+ "Error connecting to master:",
990
+ "SSL connection error",
991
+ "Malformed packet"
992
+ ]
993
+
994
+ def initialize(errno, error)
995
+ @errno = errno
996
+ @error = error
997
+ super error
998
+ end
999
+ attr_reader :errno, :error
1000
+
1001
+ def Error::err(errno)
1002
+ CLIENT_ERRORS[errno - Error::CR_MIN_ERROR]
1003
+ end
1004
+ end
1005
+
1006
+ class Net
1007
+ def initialize(sock)
1008
+ @sock = sock
1009
+ @pkt_nr = 0
1010
+ end
1011
+
1012
+ def clear()
1013
+ @pkt_nr = 0
1014
+ end
1015
+
1016
+ def read()
1017
+ buf = []
1018
+ len = nil
1019
+ @sock.sync = false
1020
+ while len == nil or len == MAX_PACKET_LENGTH do
1021
+ a = @sock.read(4)
1022
+ len = a[0]+a[1]*256+a[2]*256*256
1023
+ pkt_nr = a[3]
1024
+ if @pkt_nr != pkt_nr then
1025
+ raise "Packets out of order: #{@pkt_nr}<>#{pkt_nr}"
1026
+ end
1027
+ @pkt_nr = @pkt_nr + 1 & 0xff
1028
+ buf << @sock.read(len)
1029
+ end
1030
+ @sock.sync = true
1031
+ buf.join
1032
+ end
1033
+
1034
+ def write(data)
1035
+ if data.is_a? Array then
1036
+ data = data.join
1037
+ end
1038
+ @sock.sync = false
1039
+ ptr = 0
1040
+ while data.length >= MAX_PACKET_LENGTH do
1041
+ @sock.write Net::int3str(MAX_PACKET_LENGTH)+@pkt_nr.chr+data[ptr, MAX_PACKET_LENGTH]
1042
+ @pkt_nr = @pkt_nr + 1 & 0xff
1043
+ ptr += MAX_PACKET_LENGTH
1044
+ end
1045
+ @sock.write Net::int3str(data.length-ptr)+@pkt_nr.chr+data[ptr .. -1]
1046
+ @pkt_nr = @pkt_nr + 1 & 0xff
1047
+ @sock.sync = true
1048
+ @sock.flush
1049
+ end
1050
+
1051
+ def close()
1052
+ @sock.close
1053
+ end
1054
+
1055
+ def Net::int2str(n)
1056
+ [n].pack("v")
1057
+ end
1058
+
1059
+ def Net::int3str(n)
1060
+ [n%256, n>>8].pack("cv")
1061
+ end
1062
+
1063
+ def Net::int4str(n)
1064
+ [n].pack("V")
1065
+ end
1066
+
1067
+ end
1068
+
1069
+ class Random
1070
+ def initialize(seed1, seed2)
1071
+ @max_value = 0x3FFFFFFF
1072
+ @seed1 = seed1 % @max_value
1073
+ @seed2 = seed2 % @max_value
1074
+ end
1075
+
1076
+ def rnd()
1077
+ @seed1 = (@seed1*3+@seed2) % @max_value
1078
+ @seed2 = (@seed1+@seed2+33) % @max_value
1079
+ @seed1.to_f / @max_value
1080
+ end
1081
+ end
1082
+
1083
+ end
1084
+
1085
+ class << Mysql
1086
+ def init()
1087
+ Mysql::new :INIT
1088
+ end
1089
+
1090
+ def real_connect(*args)
1091
+ Mysql::new(*args)
1092
+ end
1093
+ alias :connect :real_connect
1094
+
1095
+ def finalizer(net)
1096
+ proc {
1097
+ net.clear
1098
+ net.write Mysql::COM_QUIT.chr
1099
+ }
1100
+ end
1101
+
1102
+ def escape_string(str)
1103
+ str.gsub(/([\0\n\r\032\'\"\\])/) do
1104
+ case $1
1105
+ when "\0" then "\\0"
1106
+ when "\n" then "\\n"
1107
+ when "\r" then "\\r"
1108
+ when "\032" then "\\Z"
1109
+ else "\\"+$1
1110
+ end
1111
+ end
1112
+ end
1113
+ alias :quote :escape_string
1114
+
1115
+ def get_client_info()
1116
+ Mysql::VERSION
1117
+ end
1118
+ alias :client_info :get_client_info
1119
+
1120
+ def debug(str)
1121
+ raise "not implemented"
1122
+ end
1123
+ end
1124
+
1125
+ #
1126
+ # for compatibility
1127
+ #
1128
+
1129
+ MysqlRes = Mysql::Result
1130
+ MysqlField = Mysql::Field
1131
+ MysqlError = Mysql::Error