ruby-mysql 2.9.14 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +50 -0
- data/README.md +28 -0
- data/lib/mysql/authenticator/caching_sha2_password.rb +62 -0
- data/lib/mysql/authenticator/mysql_native_password.rb +37 -0
- data/lib/mysql/authenticator/sha256_password.rb +40 -0
- data/lib/mysql/authenticator.rb +84 -0
- data/lib/mysql/charset.rb +379 -328
- data/lib/mysql/constants.rb +91 -44
- data/lib/mysql/error.rb +13 -7
- data/lib/mysql/protocol.rb +243 -210
- data/lib/mysql.rb +183 -338
- data/test/test_mysql.rb +264 -550
- metadata +18 -12
- data/README.rdoc +0 -68
data/lib/mysql.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# coding: ascii-8bit
|
2
|
-
# Copyright (C) 2008
|
2
|
+
# Copyright (C) 2008 TOMITA Masahiro
|
3
3
|
# mailto:tommy@tmtm.org
|
4
4
|
|
5
|
+
require 'uri'
|
6
|
+
|
5
7
|
# MySQL connection class.
|
6
8
|
# @example
|
7
9
|
# my = Mysql.connect('hostname', 'user', 'password', 'dbname')
|
@@ -11,48 +13,76 @@
|
|
11
13
|
# end
|
12
14
|
class Mysql
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
begin
|
20
|
-
require "mysql/ext.so"
|
21
|
-
rescue LoadError
|
22
|
-
end
|
16
|
+
require_relative "mysql/constants"
|
17
|
+
require_relative "mysql/error"
|
18
|
+
require_relative "mysql/charset"
|
19
|
+
require_relative "mysql/protocol"
|
20
|
+
require_relative "mysql/packet.rb"
|
23
21
|
|
24
|
-
VERSION =
|
22
|
+
VERSION = '3.0.0' # Version number of this library
|
25
23
|
MYSQL_UNIX_PORT = "/tmp/mysql.sock" # UNIX domain socket filename
|
26
24
|
MYSQL_TCP_PORT = 3306 # TCP socket port number
|
27
25
|
|
28
|
-
#
|
29
|
-
|
26
|
+
# @!attribute [rw] host
|
27
|
+
# @return [String, nil]
|
28
|
+
# @!attribute [rw] username
|
29
|
+
# @return [String, nil]
|
30
|
+
# @!attribute [rw] password
|
31
|
+
# @return [String, nil]
|
32
|
+
# @!attribute [rw] database
|
33
|
+
# @return [String, nil]
|
34
|
+
# @!attribute [rw] port
|
35
|
+
# @return [Integer, String, nil]
|
36
|
+
# @!attribute [rw] socket
|
37
|
+
# @return [String, nil] socket filename
|
38
|
+
# @!attribute [rw] flags
|
39
|
+
# @return [Integer, nil]
|
40
|
+
# @!attribute [rw] connect_timeout
|
41
|
+
# @return [Numeric, nil]
|
42
|
+
# @!attribute [rw] read_timeout
|
43
|
+
# @return [Numeric, nil]
|
44
|
+
# @!attribute [rw] write_timeout
|
45
|
+
# @return [Numeric, nil]
|
46
|
+
# @!attribute [rw] init_command
|
47
|
+
# @return [String, nil]
|
48
|
+
# @!attribute [rw] local_infile
|
49
|
+
# @return [Boolean]
|
50
|
+
# @!attribute [rw] load_data_local_dir
|
51
|
+
# @return [String, nil]
|
52
|
+
# @!attribute [rw] ssl_mode
|
53
|
+
# @return [String, Integer] 1 or "disabled" / 2 or "preferred" / 3 or "required"
|
54
|
+
# @!attribute [rw] get_server_public_key
|
55
|
+
# @return [Boolean]
|
56
|
+
DEFAULT_OPTS = {
|
57
|
+
host: nil,
|
58
|
+
username: nil,
|
59
|
+
password: nil,
|
60
|
+
database: nil,
|
61
|
+
port: nil,
|
62
|
+
socket: nil,
|
63
|
+
flags: 0,
|
64
|
+
charset: nil,
|
65
|
+
connect_timeout: nil,
|
66
|
+
read_timeout: nil,
|
67
|
+
write_timeout: nil,
|
68
|
+
init_command: nil,
|
69
|
+
local_infile: nil,
|
70
|
+
load_data_local_dir: nil,
|
71
|
+
ssl_mode: SSL_MODE_PREFERRED,
|
72
|
+
get_server_public_key: false,
|
73
|
+
}.freeze
|
74
|
+
|
30
75
|
# @private
|
31
76
|
attr_reader :protocol
|
32
77
|
|
33
|
-
# @return [Boolean] if true, {#query} return {Mysql::Result}.
|
34
|
-
attr_accessor :query_with_result
|
35
|
-
|
36
78
|
class << self
|
37
|
-
# Make Mysql object without connecting.
|
38
|
-
# @return [Mysql]
|
39
|
-
def init
|
40
|
-
my = self.allocate
|
41
|
-
my.instance_eval{initialize}
|
42
|
-
my
|
43
|
-
end
|
44
|
-
|
45
79
|
# Make Mysql object and connect to mysqld.
|
46
|
-
#
|
80
|
+
# parameter is same as arguments for {#initialize}.
|
47
81
|
# @return [Mysql]
|
48
|
-
def
|
49
|
-
|
50
|
-
my.connect(*args)
|
82
|
+
def connect(*args, **opts)
|
83
|
+
self.new(*args, **opts).connect
|
51
84
|
end
|
52
85
|
|
53
|
-
alias real_connect new
|
54
|
-
alias connect new
|
55
|
-
|
56
86
|
# Escape special character in string.
|
57
87
|
# @param [String] str
|
58
88
|
# @return [String]
|
@@ -68,58 +98,116 @@ class Mysql
|
|
68
98
|
end
|
69
99
|
end
|
70
100
|
alias quote escape_string
|
71
|
-
|
72
|
-
# @return [String] client version. This value is dummy for MySQL/Ruby compatibility.
|
73
|
-
def client_info
|
74
|
-
"5.0.0"
|
75
|
-
end
|
76
|
-
alias get_client_info client_info
|
77
|
-
|
78
|
-
# @return [Integer] client version. This value is dummy for MySQL/Ruby compatibility.
|
79
|
-
def client_version
|
80
|
-
50000
|
81
|
-
end
|
82
|
-
alias get_client_version client_version
|
83
101
|
end
|
84
102
|
|
85
|
-
|
103
|
+
# @overload initialize(uri, **opts)
|
104
|
+
# @param uri [String, URI] "mysql://username:password@host:port/database?param=value&..." / "mysql://username:password@%2Ftmp%2Fmysql.sock/database" / "mysql://username:password@/database?socket=/tmp/mysql.sock"
|
105
|
+
# @param opts [Hash] options
|
106
|
+
# @overload initialize(host, username, password, database, port, socket, flags, **opts)
|
107
|
+
# @param host [String] hostname mysqld running
|
108
|
+
# @param username [String] username to connect to mysqld
|
109
|
+
# @param password [String] password to connect to mysqld
|
110
|
+
# @param database [String] initial database name
|
111
|
+
# @param port [String] port number (used if host is not 'localhost' or nil)
|
112
|
+
# @param socket [String] socket filename (used if host is 'localhost' or nil)
|
113
|
+
# @param flags [Integer] connection flag. Mysql::CLIENT_* ORed
|
114
|
+
# @param opts [Hash] options
|
115
|
+
# @overload initialize(host: nil, username: nil, password: nil, database: nil, port: nil, socket: nil, flags: nil, **opts)
|
116
|
+
# @param host [String] hostname mysqld running
|
117
|
+
# @param username [String] username to connect to mysqld
|
118
|
+
# @param password [String] password to connect to mysqld
|
119
|
+
# @param database [String] initial database name
|
120
|
+
# @param port [String] port number (used if host is not 'localhost' or nil)
|
121
|
+
# @param socket [String] socket filename (used if host is 'localhost' or nil)
|
122
|
+
# @param flags [Integer] connection flag. Mysql::CLIENT_* ORed
|
123
|
+
# @param opts [Hash] options
|
124
|
+
# @option opts :host [String] hostname mysqld running
|
125
|
+
# @option opts :username [String] username to connect to mysqld
|
126
|
+
# @option opts :password [String] password to connect to mysqld
|
127
|
+
# @option opts :database [String] initial database name
|
128
|
+
# @option opts :port [String] port number (used if host is not 'localhost' or nil)
|
129
|
+
# @option opts :socket [String] socket filename (used if host is 'localhost' or nil)
|
130
|
+
# @option opts :flags [Integer] connection flag. Mysql::CLIENT_* ORed
|
131
|
+
# @option opts :charset [Mysql::Charset, String] character set
|
132
|
+
# @option opts :connect_timeout [Numeric, nil]
|
133
|
+
# @option opts :read_timeout [Numeric, nil]
|
134
|
+
# @option opts :write_timeout [Numeric, nil]
|
135
|
+
# @option opts :local_infile [Boolean]
|
136
|
+
# @option opts :load_data_local_dir [String]
|
137
|
+
# @option opts :ssl_mode [Integer]
|
138
|
+
# @option opts :get_server_public_key [Boolean]
|
139
|
+
def initialize(*args, **opts)
|
86
140
|
@fields = nil
|
87
141
|
@protocol = nil
|
88
|
-
@charset = nil
|
89
|
-
@connect_timeout = nil
|
90
|
-
@read_timeout = nil
|
91
|
-
@write_timeout = nil
|
92
|
-
@init_command = nil
|
93
142
|
@sqlstate = "00000"
|
94
|
-
@query_with_result = true
|
95
143
|
@host_info = nil
|
96
144
|
@last_error = nil
|
97
145
|
@result_exist = false
|
98
|
-
@
|
146
|
+
@opts = DEFAULT_OPTS.dup
|
147
|
+
parse_args(args, opts)
|
99
148
|
end
|
100
149
|
|
101
150
|
# Connect to mysqld.
|
102
|
-
#
|
103
|
-
# @
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
# @param [String / nil] socket socket file name (used if host is 'localhost' or nil)
|
108
|
-
# @param [Integer / nil] flag connection flag. Mysql::CLIENT_* ORed
|
109
|
-
# @return self
|
110
|
-
def connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, socket=nil, flag=0)
|
111
|
-
if flag & CLIENT_COMPRESS != 0
|
151
|
+
# parameter is same as arguments for {#initialize}.
|
152
|
+
# @return [Mysql] self
|
153
|
+
def connect(*args, **opts)
|
154
|
+
parse_args(args, opts)
|
155
|
+
if @opts[:flags] & CLIENT_COMPRESS != 0
|
112
156
|
warn 'unsupported flag: CLIENT_COMPRESS' if $VERBOSE
|
113
|
-
|
157
|
+
@opts[:flags] &= ~CLIENT_COMPRESS
|
114
158
|
end
|
115
|
-
@protocol = Protocol.new
|
116
|
-
@protocol.authenticate
|
117
|
-
@
|
118
|
-
@
|
119
|
-
query @init_command if @init_command
|
159
|
+
@protocol = Protocol.new(@opts)
|
160
|
+
@protocol.authenticate
|
161
|
+
@host_info = (@opts[:host].nil? || @opts[:host] == "localhost") ? 'Localhost via UNIX socket' : "#{@opts[:host]} via TCP/IP"
|
162
|
+
query @opts[:init_command] if @opts[:init_command]
|
120
163
|
return self
|
121
164
|
end
|
122
|
-
|
165
|
+
|
166
|
+
def parse_args(args, opts)
|
167
|
+
case args[0]
|
168
|
+
when URI
|
169
|
+
uri = args[0]
|
170
|
+
when /\Amysql:\/\//
|
171
|
+
uri = URI.parse(args[0])
|
172
|
+
when String
|
173
|
+
@opts[:host], user, passwd, dbname, port, socket, flags = *args
|
174
|
+
@opts[:username] = user if user
|
175
|
+
@opts[:password] = passwd if passwd
|
176
|
+
@opts[:database] = dbname if dbname
|
177
|
+
@opts[:port] = port if port
|
178
|
+
@opts[:socket] = socket if socket
|
179
|
+
@opts[:flags] = flags if flags
|
180
|
+
when Hash
|
181
|
+
# skip
|
182
|
+
when nil
|
183
|
+
# skip
|
184
|
+
end
|
185
|
+
if uri
|
186
|
+
host = uri.hostname.to_s
|
187
|
+
host = URI.decode_www_form_component(host)
|
188
|
+
if host.start_with?('/')
|
189
|
+
@opts[:socket] = host
|
190
|
+
host = ''
|
191
|
+
end
|
192
|
+
@opts[:host] = host
|
193
|
+
@opts[:username] = URI.decode_www_form_component(uri.user.to_s)
|
194
|
+
@opts[:password] = URI.decode_www_form_component(uri.password.to_s)
|
195
|
+
@opts[:database] = uri.path.sub(/\A\/+/, '')
|
196
|
+
@opts[:port] = uri.port
|
197
|
+
opts = URI.decode_www_form(uri.query).to_h.transform_keys(&:intern).merge(opts) if uri.query
|
198
|
+
opts[:flags] = opts[:flags].to_i if opts[:flags]
|
199
|
+
end
|
200
|
+
if args.last.kind_of? Hash
|
201
|
+
opts = opts.merge(args.last)
|
202
|
+
end
|
203
|
+
@opts.update(opts)
|
204
|
+
end
|
205
|
+
|
206
|
+
DEFAULT_OPTS.each_key do |var|
|
207
|
+
next if var == :charset
|
208
|
+
define_method(var){@opts[var]}
|
209
|
+
define_method("#{var}="){|val| @opts[var] = val}
|
210
|
+
end
|
123
211
|
|
124
212
|
# Disconnect from mysql.
|
125
213
|
# @return [Mysql] self
|
@@ -141,90 +229,35 @@ class Mysql
|
|
141
229
|
return self
|
142
230
|
end
|
143
231
|
|
144
|
-
# Set option for connection.
|
145
|
-
#
|
146
|
-
# Available options:
|
147
|
-
# Mysql::INIT_COMMAND, Mysql::OPT_CONNECT_TIMEOUT, Mysql::OPT_READ_TIMEOUT,
|
148
|
-
# Mysql::OPT_WRITE_TIMEOUT, Mysql::SET_CHARSET_NAME
|
149
|
-
# @param [Integer] opt option
|
150
|
-
# @param [Integer] value option value that is depend on opt
|
151
|
-
# @return [Mysql] self
|
152
|
-
def options(opt, value=nil)
|
153
|
-
case opt
|
154
|
-
when Mysql::INIT_COMMAND
|
155
|
-
@init_command = value.to_s
|
156
|
-
# when Mysql::OPT_COMPRESS
|
157
|
-
when Mysql::OPT_CONNECT_TIMEOUT
|
158
|
-
@connect_timeout = value
|
159
|
-
# when Mysql::GUESS_CONNECTION
|
160
|
-
when Mysql::OPT_LOCAL_INFILE
|
161
|
-
@local_infile = value
|
162
|
-
# when Mysql::OPT_NAMED_PIPE
|
163
|
-
# when Mysql::OPT_PROTOCOL
|
164
|
-
when Mysql::OPT_READ_TIMEOUT
|
165
|
-
@read_timeout = value.to_i
|
166
|
-
# when Mysql::OPT_RECONNECT
|
167
|
-
# when Mysql::SET_CLIENT_IP
|
168
|
-
# when Mysql::OPT_SSL_VERIFY_SERVER_CERT
|
169
|
-
# when Mysql::OPT_USE_EMBEDDED_CONNECTION
|
170
|
-
# when Mysql::OPT_USE_REMOTE_CONNECTION
|
171
|
-
when Mysql::OPT_WRITE_TIMEOUT
|
172
|
-
@write_timeout = value.to_i
|
173
|
-
# when Mysql::READ_DEFAULT_FILE
|
174
|
-
# when Mysql::READ_DEFAULT_GROUP
|
175
|
-
# when Mysql::REPORT_DATA_TRUNCATION
|
176
|
-
# when Mysql::SECURE_AUTH
|
177
|
-
# when Mysql::SET_CHARSET_DIR
|
178
|
-
when Mysql::SET_CHARSET_NAME
|
179
|
-
@charset = Charset.by_name value.to_s
|
180
|
-
# when Mysql::SHARED_MEMORY_BASE_NAME
|
181
|
-
else
|
182
|
-
warn "option not implemented: #{opt}" if $VERBOSE
|
183
|
-
end
|
184
|
-
self
|
185
|
-
end
|
186
|
-
|
187
232
|
# Escape special character in MySQL.
|
188
233
|
#
|
189
|
-
# In Ruby 1.8, this is not safe for multibyte charset such as 'SJIS'.
|
190
|
-
# You should use place-holder in prepared-statement.
|
191
234
|
# @param [String] str
|
192
235
|
# return [String]
|
193
236
|
def escape_string(str)
|
194
|
-
if not defined? Encoding and @charset.unsafe
|
195
|
-
raise ClientError, 'Mysql#escape_string is called for unsafe multibyte charset'
|
196
|
-
end
|
197
237
|
self.class.escape_string str
|
198
238
|
end
|
199
239
|
alias quote escape_string
|
200
240
|
|
201
|
-
# @return [
|
202
|
-
def
|
203
|
-
|
204
|
-
end
|
205
|
-
alias get_client_info client_info
|
206
|
-
|
207
|
-
# @return [Integer] client version
|
208
|
-
def client_version
|
209
|
-
self.class.client_version
|
241
|
+
# @return [Mysql::Charset] character set of MySQL connection
|
242
|
+
def charset
|
243
|
+
@opts[:charset]
|
210
244
|
end
|
211
|
-
alias get_client_version client_version
|
212
245
|
|
213
246
|
# Set charset of MySQL connection.
|
214
|
-
# @param [String
|
247
|
+
# @param [String, Mysql::Charset] cs
|
215
248
|
def charset=(cs)
|
216
249
|
charset = cs.is_a?(Charset) ? cs : Charset.by_name(cs)
|
217
250
|
if @protocol
|
218
251
|
@protocol.charset = charset
|
219
252
|
query "SET NAMES #{charset.name}"
|
220
253
|
end
|
221
|
-
@charset = charset
|
254
|
+
@opts[:charset] = charset
|
222
255
|
cs
|
223
256
|
end
|
224
257
|
|
225
258
|
# @return [String] charset name
|
226
259
|
def character_set_name
|
227
|
-
@charset.name
|
260
|
+
@protocol.charset.name
|
228
261
|
end
|
229
262
|
|
230
263
|
# @return [Integer] last error number
|
@@ -251,27 +284,18 @@ class Mysql
|
|
251
284
|
def host_info
|
252
285
|
@host_info
|
253
286
|
end
|
254
|
-
alias get_host_info host_info
|
255
|
-
|
256
|
-
# @return [Integer] protocol version
|
257
|
-
def proto_info
|
258
|
-
Mysql::Protocol::VERSION
|
259
|
-
end
|
260
|
-
alias get_proto_info proto_info
|
261
287
|
|
262
288
|
# @return [String] server version
|
263
289
|
def server_info
|
264
290
|
check_connection
|
265
291
|
@protocol.server_info
|
266
292
|
end
|
267
|
-
alias get_server_info server_info
|
268
293
|
|
269
294
|
# @return [Integer] server version
|
270
295
|
def server_version
|
271
296
|
check_connection
|
272
297
|
@protocol.server_version
|
273
298
|
end
|
274
|
-
alias get_server_version server_version
|
275
299
|
|
276
300
|
# @return [String] information for last query
|
277
301
|
def info
|
@@ -302,22 +326,18 @@ class Mysql
|
|
302
326
|
self
|
303
327
|
end
|
304
328
|
|
305
|
-
# database list.
|
306
|
-
# @param [String] db database name that may contain wild card.
|
307
|
-
# @return [Array<String>] database list
|
308
|
-
def list_dbs(db=nil)
|
309
|
-
db &&= db.gsub(/[\\\']/){"\\#{$&}"}
|
310
|
-
query(db ? "show databases like '#{db}'" : "show databases").map(&:first)
|
311
|
-
end
|
312
|
-
|
313
329
|
# Execute query string.
|
314
|
-
# @
|
315
|
-
#
|
316
|
-
#
|
317
|
-
#
|
318
|
-
# @
|
330
|
+
# @overload query(str)
|
331
|
+
# @param [String] str Query.
|
332
|
+
# @return [Mysql::Result]
|
333
|
+
# @return [nil] if the query does not return result set.
|
334
|
+
# @overload query(str, &block)
|
335
|
+
# @param [String] str Query.
|
336
|
+
# @yield [Mysql::Result] evaluated per query.
|
337
|
+
# @return [self]
|
319
338
|
# @example
|
320
339
|
# my.query("select 1,NULL,'abc'").fetch # => [1, nil, "abc"]
|
340
|
+
# my.query("select 1,NULL,'abc'"){|res| res.fetch}
|
321
341
|
def query(str, &block)
|
322
342
|
check_connection
|
323
343
|
@fields = nil
|
@@ -334,20 +354,15 @@ class Mysql
|
|
334
354
|
end
|
335
355
|
return self
|
336
356
|
end
|
337
|
-
|
338
|
-
return @fields ? store_result : nil
|
339
|
-
else
|
340
|
-
return self
|
341
|
-
end
|
357
|
+
return @fields ? store_result : nil
|
342
358
|
rescue ServerError => e
|
343
359
|
@last_error = e
|
344
360
|
@sqlstate = e.sqlstate
|
345
361
|
raise
|
346
362
|
end
|
347
363
|
end
|
348
|
-
alias real_query query
|
349
364
|
|
350
|
-
# Get all data for last query
|
365
|
+
# Get all data for last query.
|
351
366
|
# @return [Mysql::Result]
|
352
367
|
def store_result
|
353
368
|
check_connection
|
@@ -363,12 +378,6 @@ class Mysql
|
|
363
378
|
@protocol.thread_id
|
364
379
|
end
|
365
380
|
|
366
|
-
# Use result of query. The result data is retrieved when you use Mysql::Result#fetch.
|
367
|
-
# @return [Mysql::Result]
|
368
|
-
def use_result
|
369
|
-
store_result
|
370
|
-
end
|
371
|
-
|
372
381
|
# Set server option.
|
373
382
|
# @param [Integer] opt {Mysql::OPTION_MULTI_STATEMENTS_ON} or {Mysql::OPTION_MULTI_STATEMENTS_OFF}
|
374
383
|
# @return [Mysql] self
|
@@ -402,7 +411,7 @@ class Mysql
|
|
402
411
|
# @param [String] str query string
|
403
412
|
# @return [Mysql::Stmt] Prepared-statement object
|
404
413
|
def prepare(str)
|
405
|
-
st = Stmt.new @protocol
|
414
|
+
st = Stmt.new @protocol
|
406
415
|
st.prepare str
|
407
416
|
st
|
408
417
|
end
|
@@ -410,41 +419,8 @@ class Mysql
|
|
410
419
|
# @private
|
411
420
|
# Make empty prepared-statement object.
|
412
421
|
# @return [Mysql::Stmt] If block is not specified.
|
413
|
-
def
|
414
|
-
Stmt.new @protocol
|
415
|
-
end
|
416
|
-
|
417
|
-
# Returns Mysql::Result object that is empty.
|
418
|
-
# Use fetch_fields to get list of fields.
|
419
|
-
# @param [String] table table name.
|
420
|
-
# @param [String] field field name that may contain wild card.
|
421
|
-
# @return [Mysql::Result]
|
422
|
-
def list_fields(table, field=nil)
|
423
|
-
check_connection
|
424
|
-
begin
|
425
|
-
fields = @protocol.field_list_command table, field
|
426
|
-
return Result.new fields
|
427
|
-
rescue ServerError => e
|
428
|
-
@last_error = e
|
429
|
-
@sqlstate = e.sqlstate
|
430
|
-
raise
|
431
|
-
end
|
432
|
-
end
|
433
|
-
|
434
|
-
# @return [Mysql::Result] containing process list
|
435
|
-
def list_processes
|
436
|
-
check_connection
|
437
|
-
@fields = @protocol.process_info_command
|
438
|
-
@result_exist = true
|
439
|
-
store_result
|
440
|
-
end
|
441
|
-
|
442
|
-
# @note for Ruby 1.8: This is not multi-byte safe. Don't use for multi-byte charset such as cp932.
|
443
|
-
# @param [String] table database name that may contain wild card.
|
444
|
-
# @return [Array<String>] list of table name.
|
445
|
-
def list_tables(table=nil)
|
446
|
-
q = table ? "show tables like '#{quote table}'" : "show tables"
|
447
|
-
query(q).map(&:first)
|
422
|
+
def stmt
|
423
|
+
Stmt.new @protocol
|
448
424
|
end
|
449
425
|
|
450
426
|
# Check whether the connection is available.
|
@@ -557,7 +533,7 @@ class Mysql
|
|
557
533
|
end
|
558
534
|
|
559
535
|
# @return [Hash] field information
|
560
|
-
def
|
536
|
+
def to_hash
|
561
537
|
{
|
562
538
|
"name" => @name,
|
563
539
|
"table" => @table,
|
@@ -793,10 +769,9 @@ class Mysql
|
|
793
769
|
# @private
|
794
770
|
# @param [Array<Mysql::Field>] fields
|
795
771
|
# @param [Mysql::Protocol] protocol
|
796
|
-
|
797
|
-
def initialize(fields, protocol, charset)
|
772
|
+
def initialize(fields, protocol)
|
798
773
|
super fields
|
799
|
-
@records = protocol.stmt_retr_all_records @fields, charset
|
774
|
+
@records = protocol.stmt_retr_all_records @fields, protocol.charset
|
800
775
|
end
|
801
776
|
end
|
802
777
|
|
@@ -831,15 +806,12 @@ class Mysql
|
|
831
806
|
|
832
807
|
# @private
|
833
808
|
# @param [Mysql::Protocol] protocol
|
834
|
-
|
835
|
-
def initialize(protocol, charset)
|
809
|
+
def initialize(protocol)
|
836
810
|
@protocol = protocol
|
837
|
-
@charset = charset
|
838
811
|
@statement_id = nil
|
839
812
|
@affected_rows = @insert_id = @server_status = @warning_count = 0
|
840
813
|
@sqlstate = "00000"
|
841
814
|
@param_count = nil
|
842
|
-
@bind_result = nil
|
843
815
|
end
|
844
816
|
|
845
817
|
# @private
|
@@ -866,13 +838,13 @@ class Mysql
|
|
866
838
|
def execute(*values)
|
867
839
|
raise ClientError, "not prepared" unless @param_count
|
868
840
|
raise ClientError, "parameter count mismatch" if values.length != @param_count
|
869
|
-
values = values.map{|v| @charset.convert v}
|
841
|
+
values = values.map{|v| @protocol.charset.convert v}
|
870
842
|
begin
|
871
843
|
@sqlstate = "00000"
|
872
844
|
nfields = @protocol.stmt_execute_command @statement_id, values
|
873
845
|
if nfields
|
874
846
|
@fields = @protocol.retr_fields nfields
|
875
|
-
@result = StatementResult.new @fields, @protocol
|
847
|
+
@result = StatementResult.new @fields, @protocol
|
876
848
|
else
|
877
849
|
@affected_rows, @insert_id, @server_status, @warning_count, @info =
|
878
850
|
@protocol.affected_rows, @protocol.insert_id, @protocol.server_status, @protocol.warning_count, @protocol.message
|
@@ -895,46 +867,7 @@ class Mysql
|
|
895
867
|
|
896
868
|
# @return [Array] current record data
|
897
869
|
def fetch
|
898
|
-
|
899
|
-
return row unless @bind_result
|
900
|
-
row.zip(@bind_result).map do |col, type|
|
901
|
-
if col.nil?
|
902
|
-
nil
|
903
|
-
elsif [Numeric, Integer, Fixnum].include? type
|
904
|
-
col.to_i
|
905
|
-
elsif type == String
|
906
|
-
col.to_s
|
907
|
-
elsif type == Float && !col.is_a?(Float)
|
908
|
-
col.to_i.to_f
|
909
|
-
elsif type == Mysql::Time && !col.is_a?(Mysql::Time)
|
910
|
-
if col.to_s =~ /\A\d+\z/
|
911
|
-
i = col.to_s.to_i
|
912
|
-
if i < 100000000
|
913
|
-
y = i/10000
|
914
|
-
m = i/100%100
|
915
|
-
d = i%100
|
916
|
-
h, mm, s = 0
|
917
|
-
else
|
918
|
-
y = i/10000000000
|
919
|
-
m = i/100000000%100
|
920
|
-
d = i/1000000%100
|
921
|
-
h = i/10000%100
|
922
|
-
mm= i/100%100
|
923
|
-
s = i%100
|
924
|
-
end
|
925
|
-
if y < 70
|
926
|
-
y += 2000
|
927
|
-
elsif y < 100
|
928
|
-
y += 1900
|
929
|
-
end
|
930
|
-
Mysql::Time.new(y, m, d, h, mm, s)
|
931
|
-
else
|
932
|
-
Mysql::Time.new
|
933
|
-
end
|
934
|
-
else
|
935
|
-
col
|
936
|
-
end
|
937
|
-
end
|
870
|
+
@result.fetch
|
938
871
|
end
|
939
872
|
|
940
873
|
# Return data of current record as Hash.
|
@@ -945,20 +878,6 @@ class Mysql
|
|
945
878
|
@result.fetch_hash with_table
|
946
879
|
end
|
947
880
|
|
948
|
-
# Set retrieve type of value
|
949
|
-
# @param [Numeric / Fixnum / Integer / Float / String / Mysql::Time / nil] args value type
|
950
|
-
# @return [Mysql::Stmt] self
|
951
|
-
def bind_result(*args)
|
952
|
-
if @fields.length != args.length
|
953
|
-
raise ClientError, "bind_result: result value count(#{@fields.length}) != number of argument(#{args.length})"
|
954
|
-
end
|
955
|
-
args.each do |a|
|
956
|
-
raise TypeError unless [Numeric, Fixnum, Integer, Float, String, Mysql::Time, nil].include? a
|
957
|
-
end
|
958
|
-
@bind_result = args
|
959
|
-
self
|
960
|
-
end
|
961
|
-
|
962
881
|
# Iterate block with record.
|
963
882
|
# @yield [Array] record data
|
964
883
|
# @return [Mysql::Stmt] self
|
@@ -1027,78 +946,4 @@ class Mysql
|
|
1027
946
|
Result.new @fields
|
1028
947
|
end
|
1029
948
|
end
|
1030
|
-
|
1031
|
-
# @!visibility public
|
1032
|
-
# @!attribute [rw] year
|
1033
|
-
# @return [Integer]
|
1034
|
-
# @!attribute [rw] month
|
1035
|
-
# @return [Integer]
|
1036
|
-
# @!attribute [rw] day
|
1037
|
-
# @return [Integer]
|
1038
|
-
# @!attribute [rw] hour
|
1039
|
-
# @return [Integer]
|
1040
|
-
# @!attribute [rw] minute
|
1041
|
-
# @return [Integer]
|
1042
|
-
# @!attribute [rw] second
|
1043
|
-
# @return [Integer]
|
1044
|
-
# @!attribute [rw] neg
|
1045
|
-
# @return [Boolean] negative flag
|
1046
|
-
# @!attribute [rw] second_part
|
1047
|
-
# @return [Integer]
|
1048
|
-
class Time
|
1049
|
-
# @param [Integer] year
|
1050
|
-
# @param [Integer] month
|
1051
|
-
# @param [Integer] day
|
1052
|
-
# @param [Integer] hour
|
1053
|
-
# @param [Integer] minute
|
1054
|
-
# @param [Integer] second
|
1055
|
-
# @param [Boolean] neg negative flag
|
1056
|
-
# @param [Integer] second_part
|
1057
|
-
def initialize(year=0, month=0, day=0, hour=0, minute=0, second=0, neg=false, second_part=0)
|
1058
|
-
@date_flag = !(hour && minute && second)
|
1059
|
-
@year, @month, @day, @hour, @minute, @second, @neg, @second_part =
|
1060
|
-
year.to_i, month.to_i, day.to_i, hour.to_i, minute.to_i, second.to_i, neg, second_part.to_i
|
1061
|
-
end
|
1062
|
-
attr_accessor :year, :month, :day, :hour, :minute, :second, :neg, :second_part
|
1063
|
-
alias mon month
|
1064
|
-
alias min minute
|
1065
|
-
alias sec second
|
1066
|
-
|
1067
|
-
# @private
|
1068
|
-
def ==(other)
|
1069
|
-
other.is_a?(Mysql::Time) &&
|
1070
|
-
@year == other.year && @month == other.month && @day == other.day &&
|
1071
|
-
@hour == other.hour && @minute == other.minute && @second == other.second &&
|
1072
|
-
@neg == neg && @second_part == other.second_part
|
1073
|
-
end
|
1074
|
-
|
1075
|
-
# @private
|
1076
|
-
def eql?(other)
|
1077
|
-
self == other
|
1078
|
-
end
|
1079
|
-
|
1080
|
-
# @return [String] "yyyy-mm-dd HH:MM:SS"
|
1081
|
-
def to_s
|
1082
|
-
if @date_flag
|
1083
|
-
sprintf "%04d-%02d-%02d", year, mon, day
|
1084
|
-
elsif year == 0 and mon == 0 and day == 0
|
1085
|
-
h = neg ? hour * -1 : hour
|
1086
|
-
sprintf "%02d:%02d:%02d", h, min, sec
|
1087
|
-
else
|
1088
|
-
sprintf "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec
|
1089
|
-
end
|
1090
|
-
end
|
1091
|
-
|
1092
|
-
# @return [Integer] yyyymmddHHMMSS
|
1093
|
-
def to_i
|
1094
|
-
sprintf("%04d%02d%02d%02d%02d%02d", year, mon, day, hour, min, sec).to_i
|
1095
|
-
end
|
1096
|
-
|
1097
|
-
# @private
|
1098
|
-
def inspect
|
1099
|
-
sprintf "#<#{self.class.name}:%04d-%02d-%02d %02d:%02d:%02d>", year, mon, day, hour, min, sec
|
1100
|
-
end
|
1101
|
-
|
1102
|
-
end
|
1103
|
-
|
1104
949
|
end
|