rsql 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rsql/mysql.rb ADDED
@@ -0,0 +1,1127 @@
1
+ module RSQL
2
+ # $Id: mysql.rb,v 1.24 2005/02/12 11:37:15 tommy Exp $
3
+ #
4
+ # Copyright (C) 2003-2005 TOMITA Masahiro
5
+ # tommy@tmtm.org
6
+ #
7
+
8
+ class Mysql
9
+
10
+ VERSION = "4.0-ruby-0.2.5"
11
+
12
+ require "socket"
13
+
14
+ MAX_PACKET_LENGTH = 256*256*256-1
15
+ MAX_ALLOWED_PACKET = 1024*1024*1024
16
+
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 Error::new(@errno, @error)
455
+ end
456
+ a
457
+ end
458
+
459
+ def write(arg)
460
+ unless @net then
461
+ error Error::CR_SERVER_GONE_ERROR
462
+ end
463
+ @net.write arg
464
+ end
465
+
466
+ def hash_password(password)
467
+ nr = 1345345333
468
+ add = 7
469
+ nr2 = 0x12345671
470
+ password.each_byte do |i|
471
+ next if i == 0x20 or i == 9
472
+ nr ^= (((nr & 63) + add) * i) + (nr << 8)
473
+ nr2 += (nr2 << 8) ^ nr
474
+ add += i
475
+ end
476
+ [nr & ((1 << 31) - 1), nr2 & ((1 << 31) - 1)]
477
+ end
478
+
479
+ def scramble(password, message, old_ver)
480
+ return "" if password == nil or password == ""
481
+ raise "old version password is not implemented" if old_ver
482
+ hash_pass = hash_password password
483
+ hash_message = hash_password message
484
+ rnd = Random::new hash_pass[0] ^ hash_message[0], hash_pass[1] ^ hash_message[1]
485
+ to = []
486
+ 1.upto(message.length) do
487
+ to << ((rnd.rnd*31)+64).floor
488
+ end
489
+ extra = (rnd.rnd*31).floor
490
+ to.map! do |t| (t ^ extra).chr end
491
+ to.join
492
+ end
493
+
494
+ def error(errno)
495
+ @errno = errno
496
+ @error = Error::err errno
497
+ raise Error::new(@errno, @error)
498
+ end
499
+
500
+ class Result
501
+ def initialize(mysql, fields, field_count, data=nil)
502
+ @handle = mysql
503
+ @fields = fields
504
+ @field_count = field_count
505
+ @data = data
506
+ @current_field = 0
507
+ @current_row = 0
508
+ @eof = false
509
+ @row_count = 0
510
+ end
511
+ attr_accessor :eof
512
+
513
+ def data_seek(n)
514
+ @current_row = n
515
+ end
516
+
517
+ def fetch_field()
518
+ return if @current_field >= @field_count
519
+ f = @fields[@current_field]
520
+ @current_field += 1
521
+ f
522
+ end
523
+
524
+ def fetch_fields()
525
+ @fields
526
+ end
527
+
528
+ def fetch_field_direct(n)
529
+ @fields[n]
530
+ end
531
+
532
+ def fetch_lengths()
533
+ @data ? @data[@current_row].map{|i| i ? i.length : 0} : @lengths
534
+ end
535
+
536
+ def fetch_row()
537
+ if @data then
538
+ if @current_row >= @data.length then
539
+ @handle.status = :STATUS_READY
540
+ return
541
+ end
542
+ ret = @data[@current_row]
543
+ @current_row += 1
544
+ else
545
+ return if @eof
546
+ ret = @handle.read_one_row @field_count
547
+ if ret == nil then
548
+ @eof = true
549
+ return
550
+ end
551
+ @lengths = ret.map{|i| i ? i.length : 0}
552
+ @row_count += 1
553
+ end
554
+ ret
555
+ end
556
+
557
+ def fetch_hash(with_table=nil)
558
+ row = fetch_row
559
+ return if row == nil
560
+ hash = {}
561
+ @fields.each_index do |i|
562
+ f = with_table ? @fields[i].table+"."+@fields[i].name : @fields[i].name
563
+ hash[f] = row[i]
564
+ end
565
+ hash
566
+ end
567
+
568
+ def field_seek(n)
569
+ @current_field = n
570
+ end
571
+
572
+ def field_tell()
573
+ @current_field
574
+ end
575
+
576
+ def free()
577
+ @handle.skip_result
578
+ @handle = @fields = @data = nil
579
+ GC::start
580
+ end
581
+
582
+ def num_fields()
583
+ @field_count
584
+ end
585
+
586
+ def num_rows()
587
+ @data ? @data.length : @row_count
588
+ end
589
+
590
+ def row_seek(n)
591
+ @current_row = n
592
+ end
593
+
594
+ def row_tell()
595
+ @current_row
596
+ end
597
+
598
+ def each()
599
+ while row = fetch_row do
600
+ yield row
601
+ end
602
+ end
603
+
604
+ def each_hash(with_table=nil)
605
+ while hash = fetch_hash(with_table) do
606
+ yield hash
607
+ end
608
+ end
609
+
610
+ def inspect()
611
+ "#<#{self.class}>"
612
+ end
613
+
614
+ end
615
+
616
+ class Field
617
+ # Field type
618
+ TYPE_DECIMAL = 0
619
+ TYPE_TINY = 1
620
+ TYPE_SHORT = 2
621
+ TYPE_LONG = 3
622
+ TYPE_FLOAT = 4
623
+ TYPE_DOUBLE = 5
624
+ TYPE_NULL = 6
625
+ TYPE_TIMESTAMP = 7
626
+ TYPE_LONGLONG = 8
627
+ TYPE_INT24 = 9
628
+ TYPE_DATE = 10
629
+ TYPE_TIME = 11
630
+ TYPE_DATETIME = 12
631
+ TYPE_YEAR = 13
632
+ TYPE_NEWDATE = 14
633
+ TYPE_ENUM = 247
634
+ TYPE_SET = 248
635
+ TYPE_TINY_BLOB = 249
636
+ TYPE_MEDIUM_BLOB = 250
637
+ TYPE_LONG_BLOB = 251
638
+ TYPE_BLOB = 252
639
+ TYPE_VAR_STRING = 253
640
+ TYPE_STRING = 254
641
+ TYPE_GEOMETRY = 255
642
+ TYPE_CHAR = TYPE_TINY
643
+ TYPE_INTERVAL = TYPE_ENUM
644
+
645
+ # Flag
646
+ NOT_NULL_FLAG = 1
647
+ PRI_KEY_FLAG = 2
648
+ UNIQUE_KEY_FLAG = 4
649
+ MULTIPLE_KEY_FLAG = 8
650
+ BLOB_FLAG = 16
651
+ UNSIGNED_FLAG = 32
652
+ ZEROFILL_FLAG = 64
653
+ BINARY_FLAG = 128
654
+ ENUM_FLAG = 256
655
+ AUTO_INCREMENT_FLAG = 512
656
+ TIMESTAMP_FLAG = 1024
657
+ SET_FLAG = 2048
658
+ NUM_FLAG = 32768
659
+ PART_KEY_FLAG = 16384
660
+ GROUP_FLAG = 32768
661
+ UNIQUE_FLAG = 65536
662
+
663
+ def initialize(table, org_table, name, length, type, flags, decimals, def_value, max_length)
664
+ @table = table
665
+ @org_table = org_table
666
+ @name = name
667
+ @length = length
668
+ @type = type
669
+ @flags = flags
670
+ @decimals = decimals
671
+ @def = def_value
672
+ @max_length = max_length
673
+ if (type <= TYPE_INT24 and (type != TYPE_TIMESTAMP or length == 14 or length == 8)) or type == TYPE_YEAR then
674
+ @flags |= NUM_FLAG
675
+ end
676
+ end
677
+ attr_reader :table, :org_table, :name, :length, :type, :flags, :decimals, :def, :max_length
678
+
679
+ def inspect()
680
+ "#<#{self.class}:#{@name}>"
681
+ end
682
+ end
683
+
684
+ class Error < StandardError
685
+ # Server Error
686
+ ER_HASHCHK = 1000
687
+ ER_NISAMCHK = 1001
688
+ ER_NO = 1002
689
+ ER_YES = 1003
690
+ ER_CANT_CREATE_FILE = 1004
691
+ ER_CANT_CREATE_TABLE = 1005
692
+ ER_CANT_CREATE_DB = 1006
693
+ ER_DB_CREATE_EXISTS = 1007
694
+ ER_DB_DROP_EXISTS = 1008
695
+ ER_DB_DROP_DELETE = 1009
696
+ ER_DB_DROP_RMDIR = 1010
697
+ ER_CANT_DELETE_FILE = 1011
698
+ ER_CANT_FIND_SYSTEM_REC = 1012
699
+ ER_CANT_GET_STAT = 1013
700
+ ER_CANT_GET_WD = 1014
701
+ ER_CANT_LOCK = 1015
702
+ ER_CANT_OPEN_FILE = 1016
703
+ ER_FILE_NOT_FOUND = 1017
704
+ ER_CANT_READ_DIR = 1018
705
+ ER_CANT_SET_WD = 1019
706
+ ER_CHECKREAD = 1020
707
+ ER_DISK_FULL = 1021
708
+ ER_DUP_KEY = 1022
709
+ ER_ERROR_ON_CLOSE = 1023
710
+ ER_ERROR_ON_READ = 1024
711
+ ER_ERROR_ON_RENAME = 1025
712
+ ER_ERROR_ON_WRITE = 1026
713
+ ER_FILE_USED = 1027
714
+ ER_FILSORT_ABORT = 1028
715
+ ER_FORM_NOT_FOUND = 1029
716
+ ER_GET_ERRNO = 1030
717
+ ER_ILLEGAL_HA = 1031
718
+ ER_KEY_NOT_FOUND = 1032
719
+ ER_NOT_FORM_FILE = 1033
720
+ ER_NOT_KEYFILE = 1034
721
+ ER_OLD_KEYFILE = 1035
722
+ ER_OPEN_AS_READONLY = 1036
723
+ ER_OUTOFMEMORY = 1037
724
+ ER_OUT_OF_SORTMEMORY = 1038
725
+ ER_UNEXPECTED_EOF = 1039
726
+ ER_CON_COUNT_ERROR = 1040
727
+ ER_OUT_OF_RESOURCES = 1041
728
+ ER_BAD_HOST_ERROR = 1042
729
+ ER_HANDSHAKE_ERROR = 1043
730
+ ER_DBACCESS_DENIED_ERROR = 1044
731
+ ER_ACCESS_DENIED_ERROR = 1045
732
+ ER_NO_DB_ERROR = 1046
733
+ ER_UNKNOWN_COM_ERROR = 1047
734
+ ER_BAD_NULL_ERROR = 1048
735
+ ER_BAD_DB_ERROR = 1049
736
+ ER_TABLE_EXISTS_ERROR = 1050
737
+ ER_BAD_TABLE_ERROR = 1051
738
+ ER_NON_UNIQ_ERROR = 1052
739
+ ER_SERVER_SHUTDOWN = 1053
740
+ ER_BAD_FIELD_ERROR = 1054
741
+ ER_WRONG_FIELD_WITH_GROUP = 1055
742
+ ER_WRONG_GROUP_FIELD = 1056
743
+ ER_WRONG_SUM_SELECT = 1057
744
+ ER_WRONG_VALUE_COUNT = 1058
745
+ ER_TOO_LONG_IDENT = 1059
746
+ ER_DUP_FIELDNAME = 1060
747
+ ER_DUP_KEYNAME = 1061
748
+ ER_DUP_ENTRY = 1062
749
+ ER_WRONG_FIELD_SPEC = 1063
750
+ ER_PARSE_ERROR = 1064
751
+ ER_EMPTY_QUERY = 1065
752
+ ER_NONUNIQ_TABLE = 1066
753
+ ER_INVALID_DEFAULT = 1067
754
+ ER_MULTIPLE_PRI_KEY = 1068
755
+ ER_TOO_MANY_KEYS = 1069
756
+ ER_TOO_MANY_KEY_PARTS = 1070
757
+ ER_TOO_LONG_KEY = 1071
758
+ ER_KEY_COLUMN_DOES_NOT_EXITS = 1072
759
+ ER_BLOB_USED_AS_KEY = 1073
760
+ ER_TOO_BIG_FIELDLENGTH = 1074
761
+ ER_WRONG_AUTO_KEY = 1075
762
+ ER_READY = 1076
763
+ ER_NORMAL_SHUTDOWN = 1077
764
+ ER_GOT_SIGNAL = 1078
765
+ ER_SHUTDOWN_COMPLETE = 1079
766
+ ER_FORCING_CLOSE = 1080
767
+ ER_IPSOCK_ERROR = 1081
768
+ ER_NO_SUCH_INDEX = 1082
769
+ ER_WRONG_FIELD_TERMINATORS = 1083
770
+ ER_BLOBS_AND_NO_TERMINATED = 1084
771
+ ER_TEXTFILE_NOT_READABLE = 1085
772
+ ER_FILE_EXISTS_ERROR = 1086
773
+ ER_LOAD_INFO = 1087
774
+ ER_ALTER_INFO = 1088
775
+ ER_WRONG_SUB_KEY = 1089
776
+ ER_CANT_REMOVE_ALL_FIELDS = 1090
777
+ ER_CANT_DROP_FIELD_OR_KEY = 1091
778
+ ER_INSERT_INFO = 1092
779
+ ER_INSERT_TABLE_USED = 1093
780
+ ER_NO_SUCH_THREAD = 1094
781
+ ER_KILL_DENIED_ERROR = 1095
782
+ ER_NO_TABLES_USED = 1096
783
+ ER_TOO_BIG_SET = 1097
784
+ ER_NO_UNIQUE_LOGFILE = 1098
785
+ ER_TABLE_NOT_LOCKED_FOR_WRITE = 1099
786
+ ER_TABLE_NOT_LOCKED = 1100
787
+ ER_BLOB_CANT_HAVE_DEFAULT = 1101
788
+ ER_WRONG_DB_NAME = 1102
789
+ ER_WRONG_TABLE_NAME = 1103
790
+ ER_TOO_BIG_SELECT = 1104
791
+ ER_UNKNOWN_ERROR = 1105
792
+ ER_UNKNOWN_PROCEDURE = 1106
793
+ ER_WRONG_PARAMCOUNT_TO_PROCEDURE = 1107
794
+ ER_WRONG_PARAMETERS_TO_PROCEDURE = 1108
795
+ ER_UNKNOWN_TABLE = 1109
796
+ ER_FIELD_SPECIFIED_TWICE = 1110
797
+ ER_INVALID_GROUP_FUNC_USE = 1111
798
+ ER_UNSUPPORTED_EXTENSION = 1112
799
+ ER_TABLE_MUST_HAVE_COLUMNS = 1113
800
+ ER_RECORD_FILE_FULL = 1114
801
+ ER_UNKNOWN_CHARACTER_SET = 1115
802
+ ER_TOO_MANY_TABLES = 1116
803
+ ER_TOO_MANY_FIELDS = 1117
804
+ ER_TOO_BIG_ROWSIZE = 1118
805
+ ER_STACK_OVERRUN = 1119
806
+ ER_WRONG_OUTER_JOIN = 1120
807
+ ER_NULL_COLUMN_IN_INDEX = 1121
808
+ ER_CANT_FIND_UDF = 1122
809
+ ER_CANT_INITIALIZE_UDF = 1123
810
+ ER_UDF_NO_PATHS = 1124
811
+ ER_UDF_EXISTS = 1125
812
+ ER_CANT_OPEN_LIBRARY = 1126
813
+ ER_CANT_FIND_DL_ENTRY = 1127
814
+ ER_FUNCTION_NOT_DEFINED = 1128
815
+ ER_HOST_IS_BLOCKED = 1129
816
+ ER_HOST_NOT_PRIVILEGED = 1130
817
+ ER_PASSWORD_ANONYMOUS_USER = 1131
818
+ ER_PASSWORD_NOT_ALLOWED = 1132
819
+ ER_PASSWORD_NO_MATCH = 1133
820
+ ER_UPDATE_INFO = 1134
821
+ ER_CANT_CREATE_THREAD = 1135
822
+ ER_WRONG_VALUE_COUNT_ON_ROW = 1136
823
+ ER_CANT_REOPEN_TABLE = 1137
824
+ ER_INVALID_USE_OF_NULL = 1138
825
+ ER_REGEXP_ERROR = 1139
826
+ ER_MIX_OF_GROUP_FUNC_AND_FIELDS = 1140
827
+ ER_NONEXISTING_GRANT = 1141
828
+ ER_TABLEACCESS_DENIED_ERROR = 1142
829
+ ER_COLUMNACCESS_DENIED_ERROR = 1143
830
+ ER_ILLEGAL_GRANT_FOR_TABLE = 1144
831
+ ER_GRANT_WRONG_HOST_OR_USER = 1145
832
+ ER_NO_SUCH_TABLE = 1146
833
+ ER_NONEXISTING_TABLE_GRANT = 1147
834
+ ER_NOT_ALLOWED_COMMAND = 1148
835
+ ER_SYNTAX_ERROR = 1149
836
+ ER_DELAYED_CANT_CHANGE_LOCK = 1150
837
+ ER_TOO_MANY_DELAYED_THREADS = 1151
838
+ ER_ABORTING_CONNECTION = 1152
839
+ ER_NET_PACKET_TOO_LARGE = 1153
840
+ ER_NET_READ_ERROR_FROM_PIPE = 1154
841
+ ER_NET_FCNTL_ERROR = 1155
842
+ ER_NET_PACKETS_OUT_OF_ORDER = 1156
843
+ ER_NET_UNCOMPRESS_ERROR = 1157
844
+ ER_NET_READ_ERROR = 1158
845
+ ER_NET_READ_INTERRUPTED = 1159
846
+ ER_NET_ERROR_ON_WRITE = 1160
847
+ ER_NET_WRITE_INTERRUPTED = 1161
848
+ ER_TOO_LONG_STRING = 1162
849
+ ER_TABLE_CANT_HANDLE_BLOB = 1163
850
+ ER_TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164
851
+ ER_DELAYED_INSERT_TABLE_LOCKED = 1165
852
+ ER_WRONG_COLUMN_NAME = 1166
853
+ ER_WRONG_KEY_COLUMN = 1167
854
+ ER_WRONG_MRG_TABLE = 1168
855
+ ER_DUP_UNIQUE = 1169
856
+ ER_BLOB_KEY_WITHOUT_LENGTH = 1170
857
+ ER_PRIMARY_CANT_HAVE_NULL = 1171
858
+ ER_TOO_MANY_ROWS = 1172
859
+ ER_REQUIRES_PRIMARY_KEY = 1173
860
+ ER_NO_RAID_COMPILED = 1174
861
+ ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175
862
+ ER_KEY_DOES_NOT_EXITS = 1176
863
+ ER_CHECK_NO_SUCH_TABLE = 1177
864
+ ER_CHECK_NOT_IMPLEMENTED = 1178
865
+ ER_CANT_DO_THIS_DURING_AN_TRANSACTION = 1179
866
+ ER_ERROR_DURING_COMMIT = 1180
867
+ ER_ERROR_DURING_ROLLBACK = 1181
868
+ ER_ERROR_DURING_FLUSH_LOGS = 1182
869
+ ER_ERROR_DURING_CHECKPOINT = 1183
870
+ ER_NEW_ABORTING_CONNECTION = 1184
871
+ ER_DUMP_NOT_IMPLEMENTED = 1185
872
+ ER_FLUSH_MASTER_BINLOG_CLOSED = 1186
873
+ ER_INDEX_REBUILD = 1187
874
+ ER_MASTER = 1188
875
+ ER_MASTER_NET_READ = 1189
876
+ ER_MASTER_NET_WRITE = 1190
877
+ ER_FT_MATCHING_KEY_NOT_FOUND = 1191
878
+ ER_LOCK_OR_ACTIVE_TRANSACTION = 1192
879
+ ER_UNKNOWN_SYSTEM_VARIABLE = 1193
880
+ ER_CRASHED_ON_USAGE = 1194
881
+ ER_CRASHED_ON_REPAIR = 1195
882
+ ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196
883
+ ER_TRANS_CACHE_FULL = 1197
884
+ ER_SLAVE_MUST_STOP = 1198
885
+ ER_SLAVE_NOT_RUNNING = 1199
886
+ ER_BAD_SLAVE = 1200
887
+ ER_MASTER_INFO = 1201
888
+ ER_SLAVE_THREAD = 1202
889
+ ER_TOO_MANY_USER_CONNECTIONS = 1203
890
+ ER_SET_CONSTANTS_ONLY = 1204
891
+ ER_LOCK_WAIT_TIMEOUT = 1205
892
+ ER_LOCK_TABLE_FULL = 1206
893
+ ER_READ_ONLY_TRANSACTION = 1207
894
+ ER_DROP_DB_WITH_READ_LOCK = 1208
895
+ ER_CREATE_DB_WITH_READ_LOCK = 1209
896
+ ER_WRONG_ARGUMENTS = 1210
897
+ ER_NO_PERMISSION_TO_CREATE_USER = 1211
898
+ ER_UNION_TABLES_IN_DIFFERENT_DIR = 1212
899
+ ER_LOCK_DEADLOCK = 1213
900
+ ER_TABLE_CANT_HANDLE_FULLTEXT = 1214
901
+ ER_CANNOT_ADD_FOREIGN = 1215
902
+ ER_NO_REFERENCED_ROW = 1216
903
+ ER_ROW_IS_REFERENCED = 1217
904
+ ER_CONNECT_TO_MASTER = 1218
905
+ ER_QUERY_ON_MASTER = 1219
906
+ ER_ERROR_WHEN_EXECUTING_COMMAND = 1220
907
+ ER_WRONG_USAGE = 1221
908
+ ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222
909
+ ER_CANT_UPDATE_WITH_READLOCK = 1223
910
+ ER_MIXING_NOT_ALLOWED = 1224
911
+ ER_DUP_ARGUMENT = 1225
912
+ ER_USER_LIMIT_REACHED = 1226
913
+ ER_SPECIFIC_ACCESS_DENIED_ERROR = 1227
914
+ ER_LOCAL_VARIABLE = 1228
915
+ ER_GLOBAL_VARIABLE = 1229
916
+ ER_NO_DEFAULT = 1230
917
+ ER_WRONG_VALUE_FOR_VAR = 1231
918
+ ER_WRONG_TYPE_FOR_VAR = 1232
919
+ ER_VAR_CANT_BE_READ = 1233
920
+ ER_CANT_USE_OPTION_HERE = 1234
921
+ ER_NOT_SUPPORTED_YET = 1235
922
+ ER_MASTER_FATAL_ERROR_READING_BINLOG = 1236
923
+ ER_SLAVE_IGNORED_TABLE = 1237
924
+ ER_ERROR_MESSAGES = 238
925
+
926
+ # Client Error
927
+ CR_MIN_ERROR = 2000
928
+ CR_MAX_ERROR = 2999
929
+ CR_UNKNOWN_ERROR = 2000
930
+ CR_SOCKET_CREATE_ERROR = 2001
931
+ CR_CONNECTION_ERROR = 2002
932
+ CR_CONN_HOST_ERROR = 2003
933
+ CR_IPSOCK_ERROR = 2004
934
+ CR_UNKNOWN_HOST = 2005
935
+ CR_SERVER_GONE_ERROR = 2006
936
+ CR_VERSION_ERROR = 2007
937
+ CR_OUT_OF_MEMORY = 2008
938
+ CR_WRONG_HOST_INFO = 2009
939
+ CR_LOCALHOST_CONNECTION = 2010
940
+ CR_TCP_CONNECTION = 2011
941
+ CR_SERVER_HANDSHAKE_ERR = 2012
942
+ CR_SERVER_LOST = 2013
943
+ CR_COMMANDS_OUT_OF_SYNC = 2014
944
+ CR_NAMEDPIPE_CONNECTION = 2015
945
+ CR_NAMEDPIPEWAIT_ERROR = 2016
946
+ CR_NAMEDPIPEOPEN_ERROR = 2017
947
+ CR_NAMEDPIPESETSTATE_ERROR = 2018
948
+ CR_CANT_READ_CHARSET = 2019
949
+ CR_NET_PACKET_TOO_LARGE = 2020
950
+ CR_EMBEDDED_CONNECTION = 2021
951
+ CR_PROBE_SLAVE_STATUS = 2022
952
+ CR_PROBE_SLAVE_HOSTS = 2023
953
+ CR_PROBE_SLAVE_CONNECT = 2024
954
+ CR_PROBE_MASTER_CONNECT = 2025
955
+ CR_SSL_CONNECTION_ERROR = 2026
956
+ CR_MALFORMED_PACKET = 2027
957
+
958
+ CLIENT_ERRORS = [
959
+ "Unknown MySQL error",
960
+ "Can't create UNIX socket (%d)",
961
+ "Can't connect to local MySQL server through socket '%-.64s' (%d)",
962
+ "Can't connect to MySQL server on '%-.64s' (%d)",
963
+ "Can't create TCP/IP socket (%d)",
964
+ "Unknown MySQL Server Host '%-.64s' (%d)",
965
+ "MySQL server has gone away",
966
+ "Protocol mismatch. Server Version = %d Client Version = %d",
967
+ "MySQL client run out of memory",
968
+ "Wrong host info",
969
+ "Localhost via UNIX socket",
970
+ "%-.64s via TCP/IP",
971
+ "Error in server handshake",
972
+ "Lost connection to MySQL server during query",
973
+ "Commands out of sync; You can't run this command now",
974
+ "%-.64s via named pipe",
975
+ "Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu)",
976
+ "Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)",
977
+ "Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)",
978
+ "Can't initialize character set %-.64s (path: %-.64s)",
979
+ "Got packet bigger than 'max_allowed_packet'",
980
+ "Embedded server",
981
+ "Error on SHOW SLAVE STATUS:",
982
+ "Error on SHOW SLAVE HOSTS:",
983
+ "Error connecting to slave:",
984
+ "Error connecting to master:",
985
+ "SSL connection error",
986
+ "Malformed packet"
987
+ ]
988
+
989
+ def initialize(errno, error)
990
+ @errno = errno
991
+ @error = error
992
+ super error
993
+ end
994
+ attr_reader :errno, :error
995
+
996
+ def Error::err(errno)
997
+ CLIENT_ERRORS[errno - Error::CR_MIN_ERROR]
998
+ end
999
+ end
1000
+
1001
+ class Net
1002
+ def initialize(sock)
1003
+ @sock = sock
1004
+ @pkt_nr = 0
1005
+ end
1006
+
1007
+ def clear()
1008
+ @pkt_nr = 0
1009
+ end
1010
+
1011
+ def read()
1012
+ buf = []
1013
+ len = nil
1014
+ @sock.sync = false
1015
+ while len == nil or len == MAX_PACKET_LENGTH do
1016
+ a = @sock.read(4)
1017
+ len = a[0]+a[1]*256+a[2]*256*256
1018
+ pkt_nr = a[3]
1019
+ if @pkt_nr != pkt_nr then
1020
+ raise "Packets out of order: #{@pkt_nr}<>#{pkt_nr}"
1021
+ end
1022
+ @pkt_nr = @pkt_nr + 1 & 0xff
1023
+ buf << @sock.read(len)
1024
+ end
1025
+ @sock.sync = true
1026
+ buf.join
1027
+ end
1028
+
1029
+ def write(data)
1030
+ if data.is_a? Array then
1031
+ data = data.join
1032
+ end
1033
+ @sock.sync = false
1034
+ ptr = 0
1035
+ while data.length >= MAX_PACKET_LENGTH do
1036
+ @sock.write Net::int3str(MAX_PACKET_LENGTH)+@pkt_nr.chr+data[ptr, MAX_PACKET_LENGTH]
1037
+ @pkt_nr = @pkt_nr + 1 & 0xff
1038
+ ptr += MAX_PACKET_LENGTH
1039
+ end
1040
+ @sock.write Net::int3str(data.length-ptr)+@pkt_nr.chr+data[ptr .. -1]
1041
+ @pkt_nr = @pkt_nr + 1 & 0xff
1042
+ @sock.sync = true
1043
+ @sock.flush
1044
+ end
1045
+
1046
+ def close()
1047
+ @sock.close
1048
+ end
1049
+
1050
+ def Net::int2str(n)
1051
+ [n].pack("v")
1052
+ end
1053
+
1054
+ def Net::int3str(n)
1055
+ [n%256, n>>8].pack("cv")
1056
+ end
1057
+
1058
+ def Net::int4str(n)
1059
+ [n].pack("V")
1060
+ end
1061
+
1062
+ end
1063
+
1064
+ class Random
1065
+ def initialize(seed1, seed2)
1066
+ @max_value = 0x3FFFFFFF
1067
+ @seed1 = seed1 % @max_value
1068
+ @seed2 = seed2 % @max_value
1069
+ end
1070
+
1071
+ def rnd()
1072
+ @seed1 = (@seed1*3+@seed2) % @max_value
1073
+ @seed2 = (@seed1+@seed2+33) % @max_value
1074
+ @seed1.to_f / @max_value
1075
+ end
1076
+ end
1077
+
1078
+ end
1079
+
1080
+ class << Mysql
1081
+ def init()
1082
+ Mysql::new :INIT
1083
+ end
1084
+
1085
+ def real_connect(*args)
1086
+ Mysql::new(*args)
1087
+ end
1088
+ alias :connect :real_connect
1089
+
1090
+ def finalizer(net)
1091
+ proc {
1092
+ net.clear
1093
+ net.write Mysql::COM_QUIT.chr
1094
+ }
1095
+ end
1096
+
1097
+ def escape_string(str)
1098
+ str.gsub(/([\0\n\r\032\'\"\\])/) do
1099
+ case $1
1100
+ when "\0" then "\\0"
1101
+ when "\n" then "\\n"
1102
+ when "\r" then "\\r"
1103
+ when "\032" then "\\Z"
1104
+ else "\\"+$1
1105
+ end
1106
+ end
1107
+ end
1108
+ alias :quote :escape_string
1109
+
1110
+ def get_client_info()
1111
+ Mysql::VERSION
1112
+ end
1113
+ alias :client_info :get_client_info
1114
+
1115
+ def debug(str)
1116
+ raise "not implemented"
1117
+ end
1118
+ end
1119
+
1120
+ #
1121
+ # for compatibility
1122
+ #
1123
+
1124
+ MysqlRes = Mysql::Result
1125
+ MysqlField = Mysql::Field
1126
+ MysqlError = Mysql::Error
1127
+ end # module RSQL