ruby-mysql 2.9.14 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|