Class: Mysql

Inherits:
Object
  • Object
show all
Defined in:
lib/rspider/mysql.rb

Overview

$Id: mysql.rb,v 1.24 2005/02/12 11:37:15 tommy Exp $

Copyright © 2003-2005 TOMITA Masahiro [email protected]

Defined Under Namespace

Classes: Error, Field, Net, Random, Result

Constant Summary collapse

VERSION =
"4.0-ruby-0.2.5"
MAX_PACKET_LENGTH =
256*256*256-1
MAX_ALLOWED_PACKET =
1024*1024*1024
MYSQL_UNIX_ADDR =
"/var/lib/mysql/mysql.sock"
MYSQL_PORT =

MYSQL_UNIX_ADDR = “/tmp/mysql.sock”

3306
PROTOCOL_VERSION =
10
COM_SLEEP =

Command

0
COM_QUIT =
1
COM_INIT_DB =
2
COM_QUERY =
3
COM_FIELD_LIST =
4
COM_CREATE_DB =
5
COM_DROP_DB =
6
COM_REFRESH =
7
COM_SHUTDOWN =
8
COM_STATISTICS =
9
COM_PROCESS_INFO =
10
COM_CONNECT =
11
COM_PROCESS_KILL =
12
COM_DEBUG =
13
COM_PING =
14
COM_TIME =
15
COM_DELAYED_INSERT =
16
COM_CHANGE_USER =
17
COM_BINLOG_DUMP =
18
COM_TABLE_DUMP =
19
COM_CONNECT_OUT =
20
COM_REGISTER_SLAVE =
21
CLIENT_LONG_PASSWORD =

Client flag

1
CLIENT_FOUND_ROWS =
1 << 1
CLIENT_LONG_FLAG =
1 << 2
CLIENT_CONNECT_WITH_DB =
1 << 3
CLIENT_NO_SCHEMA =
1 << 4
CLIENT_COMPRESS =
1 << 5
CLIENT_ODBC =
1 << 6
CLIENT_LOCAL_FILES =
1 << 7
CLIENT_IGNORE_SPACE =
1 << 8
CLIENT_INTERACTIVE =
1 << 10
CLIENT_SSL =
1 << 11
CLIENT_IGNORE_SIGPIPE =
1 << 12
CLIENT_TRANSACTIONS =
1 << 13
CLIENT_CAPABILITIES =
CLIENT_LONG_PASSWORD|CLIENT_LONG_FLAG|CLIENT_TRANSACTIONS
OPT_CONNECT_TIMEOUT =

Connection Option

0
OPT_COMPRESS =
1
OPT_NAMED_PIPE =
2
INIT_COMMAND =
3
READ_DEFAULT_FILE =
4
READ_DEFAULT_GROUP =
5
SET_CHARSET_DIR =
6
SET_CHARSET_NAME =
7
OPT_LOCAL_INFILE =
8
SERVER_STATUS_IN_TRANS =

Server Status

1
SERVER_STATUS_AUTOCOMMIT =
2
REFRESH_GRANT =

Refresh parameter

1
REFRESH_LOG =
2
REFRESH_TABLES =
4
REFRESH_HOSTS =
8
REFRESH_STATUS =
16
REFRESH_THREADS =
32
REFRESH_SLAVE =
64
REFRESH_MASTER =
128

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Mysql

Returns a new instance of Mysql.



86
87
88
89
90
91
92
93
94
# File 'lib/rspider/mysql.rb', line 86

def initialize(*args)
  @client_flag = 0
  @max_allowed_packet = MAX_ALLOWED_PACKET
  @query_with_result = true
  @status = :STATUS_READY
  if args[0] != :INIT then
    real_connect(*args)
  end
end

Instance Attribute Details

#affected_rowsObject (readonly)

Returns the value of attribute affected_rows.



311
312
313
# File 'lib/rspider/mysql.rb', line 311

def affected_rows
  @affected_rows
end

#field_countObject (readonly)

Returns the value of attribute field_count.



311
312
313
# File 'lib/rspider/mysql.rb', line 311

def field_count
  @field_count
end

#infoObject (readonly)

Returns the value of attribute info.



311
312
313
# File 'lib/rspider/mysql.rb', line 311

def info
  @info
end

#insert_idObject (readonly)

Returns the value of attribute insert_id.



311
312
313
# File 'lib/rspider/mysql.rb', line 311

def insert_id
  @insert_id
end

#query_with_resultObject

Returns the value of attribute query_with_result.



312
313
314
# File 'lib/rspider/mysql.rb', line 312

def query_with_result
  @query_with_result
end

#statusObject

Returns the value of attribute status.



312
313
314
# File 'lib/rspider/mysql.rb', line 312

def status
  @status
end

#thread_idObject (readonly)

Returns the value of attribute thread_id.



311
312
313
# File 'lib/rspider/mysql.rb', line 311

def thread_id
  @thread_id
end

Class Method Details

.debug(str) ⇒ Object



1120
1121
1122
# File 'lib/rspider/mysql.rb', line 1120

def debug(str)
  raise "not implemented"
end

.escape_string(str) ⇒ Object Also known as: quote



1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
# File 'lib/rspider/mysql.rb', line 1102

def escape_string(str)
  str.gsub(/([\0\n\r\032\'\"\\])/) do
    case $1
    when "\0" then "\\0"
    when "\n" then "\\n"
    when "\r" then "\\r"
    when "\032" then "\\Z"
    else "\\"+$1
    end
  end
end

.finalizer(net) ⇒ Object



1095
1096
1097
1098
1099
1100
# File 'lib/rspider/mysql.rb', line 1095

def finalizer(net)
  proc {
    net.clear
    net.write Mysql::COM_QUIT.chr
  }
end

.get_client_infoObject Also known as: client_info



1115
1116
1117
# File 'lib/rspider/mysql.rb', line 1115

def get_client_info()
  Mysql::VERSION
end

.initObject



1086
1087
1088
# File 'lib/rspider/mysql.rb', line 1086

def init()
  Mysql::new :INIT
end

.real_connect(*args) ⇒ Object Also known as: connect



1090
1091
1092
# File 'lib/rspider/mysql.rb', line 1090

def real_connect(*args)
  Mysql::new(*args)
end

Instance Method Details

#change_user(user = "", passwd = "", db = "") ⇒ Object



186
187
188
189
190
191
192
# File 'lib/rspider/mysql.rb', line 186

def change_user(user="", passwd="", db="")
  data = user+"\0"+scramble(passwd, @scramble_buff, @protocol_version==9)+"\0"+db
  command COM_CHANGE_USER, data
  @user = user
  @passwd = passwd
  @db = db
end

#character_set_nameObject



194
195
196
# File 'lib/rspider/mysql.rb', line 194

def character_set_name()
  raise "not implemented"
end

#client_infoObject



145
146
147
# File 'lib/rspider/mysql.rb', line 145

def get_client_info()
  VERSION
end

#closeObject



198
199
200
201
202
203
# File 'lib/rspider/mysql.rb', line 198

def close()
  @status = :STATUS_READY
  command COM_QUIT, nil, true
  @net.close
  self
end

#connectObject



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/rspider/mysql.rb', line 135

def real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, socket=nil, flag=nil)
  @server_status = SERVER_STATUS_AUTOCOMMIT
  if (host == nil or host == "localhost") and defined? UNIXSocket then
    unix_socket = socket || ENV["MYSQL_UNIX_PORT"] || MYSQL_UNIX_ADDR
    sock = UNIXSocket::new(unix_socket)
    @host_info = Error::err(Error::CR_LOCALHOST_CONNECTION)
    @unix_socket = unix_socket
  else      
    sock = TCPSocket::new(host, port||ENV["MYSQL_TCP_PORT"]||(Socket::getservbyname("mysql","tcp") rescue MYSQL_PORT))
    @host_info = sprintf Error::err(Error::CR_TCP_CONNECTION), host
  end
  @host = host ? host.dup : nil
  sock.setsockopt Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true
  @net = Net::new sock

  a = read
  @protocol_version = a.slice!(0)
  @server_version, a = a.split(/\0/,2)
  @thread_id, @scramble_buff = a.slice!(0,13).unpack("La8")
  if a.size >= 2 then
    @server_capabilities, = a.slice!(0,2).unpack("v")
  end
  if a.size >= 16 then
    @server_language, @server_status = a.unpack("cv")
  end

  flag = 0 if flag == nil
  flag |= @client_flag | CLIENT_CAPABILITIES
  flag |= CLIENT_CONNECT_WITH_DB if db
  data = Net::int2str(flag)+Net::int3str(@max_allowed_packet)+(user||"")+"\0"+scramble(passwd, @scramble_buff, @protocol_version==9)
  if db and @server_capabilities & CLIENT_CONNECT_WITH_DB != 0 then
    data << "\0"+db
    @db = db.dup
  end
  write data
  read
  ObjectSpace.define_finalizer(self, Mysql.finalizer(@net))
  self
end

#create_db(db) ⇒ Object



205
206
207
208
# File 'lib/rspider/mysql.rb', line 205

def create_db(db)
  command COM_CREATE_DB, db
  self
end

#drop_db(db) ⇒ Object



210
211
212
213
# File 'lib/rspider/mysql.rb', line 210

def drop_db(db)
  command COM_DROP_DB, db
  self
end

#dump_debug_infoObject



215
216
217
218
# File 'lib/rspider/mysql.rb', line 215

def dump_debug_info()
  command COM_DEBUG
  self
end

#escape_string(str) ⇒ Object



137
138
139
# File 'lib/rspider/mysql.rb', line 137

def escape_string(str)
  Mysql::escape_string str
end

#get_client_infoObject



142
143
144
# File 'lib/rspider/mysql.rb', line 142

def get_client_info()
  VERSION
end

#get_host_infoObject Also known as: host_info



220
221
222
# File 'lib/rspider/mysql.rb', line 220

def get_host_info()
  @host_info
end

#get_proto_infoObject Also known as: proto_info



225
226
227
# File 'lib/rspider/mysql.rb', line 225

def get_proto_info()
  @protocol_version
end

#get_server_infoObject Also known as: server_info



230
231
232
# File 'lib/rspider/mysql.rb', line 230

def get_server_info()
  @server_version
end

#inspectObject



339
340
341
# File 'lib/rspider/mysql.rb', line 339

def inspect()
  "#<#{self.class}>"
end

#kill(id) ⇒ Object



235
236
237
238
# File 'lib/rspider/mysql.rb', line 235

def kill(id)
  command COM_PROCESS_KILL, Net::int4str(id)
  self
end

#list_dbs(db = nil) ⇒ Object



240
241
242
243
244
# File 'lib/rspider/mysql.rb', line 240

def list_dbs(db=nil)
  real_query "show databases #{db}"
  @status = :STATUS_READY
  read_rows(1).flatten
end

#list_fields(table, field = nil) ⇒ Object



246
247
248
249
250
251
252
253
# File 'lib/rspider/mysql.rb', line 246

def list_fields(table, field=nil)
  command COM_FIELD_LIST, "#{table}\0#{field}", true
  f = read_rows 6
  fields = unpack_fields(f, @server_capabilities & CLIENT_LONG_FLAG != 0)
  res = Result::new self, fields, f.length
  res.eof = true
  res
end

#list_processesObject



255
256
257
258
259
260
261
262
# File 'lib/rspider/mysql.rb', line 255

def list_processes()
  data = command COM_PROCESS_INFO
  @field_count = get_length data
  fields = read_rows 5
  @fields = unpack_fields(fields, @server_capabilities & CLIENT_LONG_FLAG != 0)
  @status = :STATUS_GET_RESULT
  store_result
end

#list_tables(table = nil) ⇒ Object



264
265
266
267
268
# File 'lib/rspider/mysql.rb', line 264

def list_tables(table=nil)
  real_query "show tables #{table}"
  @status = :STATUS_READY
  read_rows(1).flatten
end

#options(option, arg = nil) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
# File 'lib/rspider/mysql.rb', line 147

def options(option, arg=nil)
  if option == OPT_LOCAL_INFILE then
    if arg == false or arg == 0 then
	@client_flag &= ~CLIENT_LOCAL_FILES
    else
	@client_flag |= CLIENT_LOCAL_FILES
    end
  else
    raise "not implemented"
  end
end

#pingObject



270
271
272
273
# File 'lib/rspider/mysql.rb', line 270

def ping()
  command COM_PING
  self
end

#query(query) ⇒ Object



275
276
277
278
279
280
281
282
283
284
# File 'lib/rspider/mysql.rb', line 275

def query(query)
  real_query query
  if not @query_with_result then
    return self
  end
  if @field_count == 0 then
    return nil
  end
  store_result
end

#quoteObject



140
141
142
# File 'lib/rspider/mysql.rb', line 140

def escape_string(str)
  Mysql::escape_string str
end

#read_one_row(field_count) ⇒ Object



314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/rspider/mysql.rb', line 314

def read_one_row(field_count)
  data = read
  return if data[0] == 254 and data.length == 1
  rec = []
  field_count.times do
    len = get_length data
    if len == nil then
	rec << len
    else
	rec << data.slice!(0,len)
    end
  end
  rec
end

#real_connect(host = nil, user = nil, passwd = nil, db = nil, port = nil, socket = nil, flag = nil) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/rspider/mysql.rb', line 96

def real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, socket=nil, flag=nil)
  @server_status = SERVER_STATUS_AUTOCOMMIT
  if (host == nil or host == "localhost") and defined? UNIXSocket then
    unix_socket = socket || ENV["MYSQL_UNIX_PORT"] || MYSQL_UNIX_ADDR
    sock = UNIXSocket::new(unix_socket)
    @host_info = Error::err(Error::CR_LOCALHOST_CONNECTION)
    @unix_socket = unix_socket
  else      
    sock = TCPSocket::new(host, port||ENV["MYSQL_TCP_PORT"]||(Socket::getservbyname("mysql","tcp") rescue MYSQL_PORT))
    @host_info = sprintf Error::err(Error::CR_TCP_CONNECTION), host
  end
  @host = host ? host.dup : nil
  sock.setsockopt Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true
  @net = Net::new sock

  a = read
  @protocol_version = a.slice!(0)
  @server_version, a = a.split(/\0/,2)
  @thread_id, @scramble_buff = a.slice!(0,13).unpack("La8")
  if a.size >= 2 then
    @server_capabilities, = a.slice!(0,2).unpack("v")
  end
  if a.size >= 16 then
    @server_language, @server_status = a.unpack("cv")
  end

  flag = 0 if flag == nil
  flag |= @client_flag | CLIENT_CAPABILITIES
  flag |= CLIENT_CONNECT_WITH_DB if db
  data = Net::int2str(flag)+Net::int3str(@max_allowed_packet)+(user||"")+"\0"+scramble(passwd, @scramble_buff, @protocol_version==9)
  if db and @server_capabilities & CLIENT_CONNECT_WITH_DB != 0 then
    data << "\0"+db
    @db = db.dup
  end
  write data
  read
  ObjectSpace.define_finalizer(self, Mysql.finalizer(@net))
  self
end

#real_query(query) ⇒ Object



159
160
161
162
163
# File 'lib/rspider/mysql.rb', line 159

def real_query(query)
  command COM_QUERY, query, true
  read_query_result
  self
end

#refresh(r) ⇒ Object



286
287
288
289
# File 'lib/rspider/mysql.rb', line 286

def refresh(r)
  command COM_REFRESH, r.chr
  self
end

#reloadObject



291
292
293
294
# File 'lib/rspider/mysql.rb', line 291

def reload()
  refresh REFRESH_GRANT
  self
end

#select_db(db) ⇒ Object



296
297
298
299
300
# File 'lib/rspider/mysql.rb', line 296

def select_db(db)
  command COM_INIT_DB, db
  @db = db
  self
end

#shutdownObject



302
303
304
305
# File 'lib/rspider/mysql.rb', line 302

def shutdown()
  command COM_SHUTDOWN
  self
end

#skip_resultObject



329
330
331
332
333
334
335
336
337
# File 'lib/rspider/mysql.rb', line 329

def skip_result()
  if @status == :STATUS_USE_RESULT then
    loop do
	data = read
	break if data[0] == 254 and data.length == 1
    end
    @status = :STATUS_READY
  end
end

#statObject



307
308
309
# File 'lib/rspider/mysql.rb', line 307

def stat()
  command COM_STATISTICS
end

#store_resultObject



174
175
176
177
178
179
180
181
182
183
184
# File 'lib/rspider/mysql.rb', line 174

def store_result()
  if @status != :STATUS_GET_RESULT then
    error Error::CR_COMMANDS_OUT_OF_SYNC
  end
  @status = :STATUS_READY
  data = read_rows @field_count
  res = Result::new self, @fields, @field_count, data
  @fields = nil
  @affected_rows = data.length
  res
end

#use_resultObject



165
166
167
168
169
170
171
172
# File 'lib/rspider/mysql.rb', line 165

def use_result()
  if @status != :STATUS_GET_RESULT then
    error Error::CR_COMMANDS_OUT_OF_SYNC
  end
  res = Result::new self, @fields, @field_count
  @status = :STATUS_USE_RESULT
  res
end