og 0.19.0 → 0.20.0

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