ruby-mysql 2.11.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -0
- data/README.md +28 -0
- data/lib/mysql/protocol.rb +81 -147
- data/lib/mysql.rb +182 -359
- data/test/test_mysql.rb +217 -550
- metadata +10 -7
- data/README.rdoc +0 -69
data/lib/mysql.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
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,44 +13,76 @@
|
|
11
13
|
# end
|
12
14
|
class Mysql
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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"
|
19
21
|
|
20
|
-
VERSION =
|
22
|
+
VERSION = '3.0.0' # Version number of this library
|
21
23
|
MYSQL_UNIX_PORT = "/tmp/mysql.sock" # UNIX domain socket filename
|
22
24
|
MYSQL_TCP_PORT = 3306 # TCP socket port number
|
23
25
|
|
24
|
-
#
|
25
|
-
|
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
|
+
|
26
75
|
# @private
|
27
76
|
attr_reader :protocol
|
28
77
|
|
29
|
-
# @return [Boolean] if true, {#query} return {Mysql::Result}.
|
30
|
-
attr_accessor :query_with_result
|
31
|
-
|
32
78
|
class << self
|
33
|
-
# Make Mysql object without connecting.
|
34
|
-
# @return [Mysql]
|
35
|
-
def init
|
36
|
-
my = self.allocate
|
37
|
-
my.instance_eval{initialize}
|
38
|
-
my
|
39
|
-
end
|
40
|
-
|
41
79
|
# Make Mysql object and connect to mysqld.
|
42
|
-
#
|
80
|
+
# parameter is same as arguments for {#initialize}.
|
43
81
|
# @return [Mysql]
|
44
|
-
def
|
45
|
-
|
46
|
-
my.connect(*args)
|
82
|
+
def connect(*args, **opts)
|
83
|
+
self.new(*args, **opts).connect
|
47
84
|
end
|
48
85
|
|
49
|
-
alias real_connect new
|
50
|
-
alias connect new
|
51
|
-
|
52
86
|
# Escape special character in string.
|
53
87
|
# @param [String] str
|
54
88
|
# @return [String]
|
@@ -64,62 +98,116 @@ class Mysql
|
|
64
98
|
end
|
65
99
|
end
|
66
100
|
alias quote escape_string
|
67
|
-
|
68
|
-
# @return [String] client version. This value is dummy for MySQL/Ruby compatibility.
|
69
|
-
def client_info
|
70
|
-
"5.0.0"
|
71
|
-
end
|
72
|
-
alias get_client_info client_info
|
73
|
-
|
74
|
-
# @return [Integer] client version. This value is dummy for MySQL/Ruby compatibility.
|
75
|
-
def client_version
|
76
|
-
50000
|
77
|
-
end
|
78
|
-
alias get_client_version client_version
|
79
101
|
end
|
80
102
|
|
81
|
-
|
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)
|
82
140
|
@fields = nil
|
83
141
|
@protocol = nil
|
84
|
-
@charset = nil
|
85
|
-
@init_command = nil
|
86
142
|
@sqlstate = "00000"
|
87
|
-
@query_with_result = true
|
88
143
|
@host_info = nil
|
89
144
|
@last_error = nil
|
90
145
|
@result_exist = false
|
91
|
-
@opts =
|
92
|
-
|
93
|
-
read_timeout: nil,
|
94
|
-
write_timeout: nil,
|
95
|
-
local_infile: nil,
|
96
|
-
ssl_mode: SSL_MODE_PREFERRED,
|
97
|
-
get_server_public_key: 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,77 +229,6 @@ 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_GET_SERVER_PUBLIC_KEY,
|
148
|
-
# Mysql::OPT_LOAD_DATA_LOCAL_DIR, Mysql::OPT_LOCAL_INFILE, Mysql::OPT_READ_TIMEOUT,
|
149
|
-
# Mysql::OPT_SSL_MODE, Mysql::OPT_WRITE_TIMEOUT, Mysql::SET_CHARSET_NAME
|
150
|
-
# @param [Integer] opt option
|
151
|
-
# @param [Integer] value option value that is depend on opt
|
152
|
-
# @return [Mysql] self
|
153
|
-
def options(opt, value=nil)
|
154
|
-
case opt
|
155
|
-
# when Mysql::DEFAULT_AUTH
|
156
|
-
# when Mysql::ENABLE_CLEARTEXT_PLUGIN
|
157
|
-
when Mysql::INIT_COMMAND
|
158
|
-
@init_command = value.to_s
|
159
|
-
# when Mysql::OPT_BIND
|
160
|
-
# when Mysql::OPT_CAN_HANDLE_EXPIRED_PASSWORDS
|
161
|
-
# when Mysql::OPT_COMPRESS
|
162
|
-
# when Mysql::OPT_COMPRESSION_ALGORITHMS
|
163
|
-
# when Mysql::OPT_CONNECT_ATTR_ADD
|
164
|
-
# when Mysql::OPT_CONNECT_ATTR_DELETE
|
165
|
-
# when Mysql::OPT_CONNECT_ATTR_RESET
|
166
|
-
when Mysql::OPT_CONNECT_TIMEOUT
|
167
|
-
@opts[:connect_timeout] = value
|
168
|
-
when Mysql::OPT_GET_SERVER_PUBLIC_KEY
|
169
|
-
@opts[:get_server_public_key] = value
|
170
|
-
when Mysql::OPT_LOAD_DATA_LOCAL_DIR
|
171
|
-
@opts[:local_infile] = value
|
172
|
-
when Mysql::OPT_LOCAL_INFILE
|
173
|
-
@opts[:local_infile] = value ? '' : nil
|
174
|
-
# when Mysql::OPT_MAX_ALLOWED_PACKET
|
175
|
-
# when Mysql::OPT_NAMED_PIPE
|
176
|
-
# when Mysql::OPT_NET_BUFFER_LENGTH
|
177
|
-
# when Mysql::OPT_OPTIONAL_RESULTSET_METADATA
|
178
|
-
# when Mysql::OPT_PROTOCOL
|
179
|
-
when Mysql::OPT_READ_TIMEOUT
|
180
|
-
@opts[:read_timeout] = value
|
181
|
-
# when Mysql::OPT_RECONNECT
|
182
|
-
# when Mysql::OPT_RETRY_COUNT
|
183
|
-
# when Mysql::SET_CLIENT_IP
|
184
|
-
# when Mysql::OPT_SSL_CA
|
185
|
-
# when Mysql::OPT_SSL_CAPATH
|
186
|
-
# when Mysql::OPT_SSL_CERT
|
187
|
-
# when Mysql::OPT_SSL_CIPHER
|
188
|
-
# when Mysql::OPT_SSL_CRL
|
189
|
-
# when Mysql::OPT_SSL_CRLPATH
|
190
|
-
# when Mysql::OPT_SSL_FIPS_MODE
|
191
|
-
# when Mysql::OPT_SSL_KEY
|
192
|
-
when Mysql::OPT_SSL_MODE
|
193
|
-
@opts[:ssl_mode] = value
|
194
|
-
# when Mysql::OPT_TLS_CIPHERSUITES
|
195
|
-
# when Mysql::OPT_TLS_VERSION
|
196
|
-
# when Mysql::OPT_USE_RESULT
|
197
|
-
when Mysql::OPT_WRITE_TIMEOUT
|
198
|
-
@opts[:write_timeout] = value
|
199
|
-
# when Mysql::OPT_ZSTD_COMPRESSION_LEVEL
|
200
|
-
# when Mysql::PLUGIN_DIR
|
201
|
-
# when Mysql::READ_DEFAULT_FILE
|
202
|
-
# when Mysql::READ_DEFAULT_GROUP
|
203
|
-
# when Mysql::REPORT_DATA_TRUNCATION
|
204
|
-
# when Mysql::SERVER_PUBLIC_KEY
|
205
|
-
# when Mysql::SET_CHARSET_DIR
|
206
|
-
when Mysql::SET_CHARSET_NAME
|
207
|
-
@charset = Charset.by_name value.to_s
|
208
|
-
# when Mysql::SHARED_MEMORY_BASE_NAME
|
209
|
-
else
|
210
|
-
warn "option not implemented: #{opt}" if $VERBOSE
|
211
|
-
end
|
212
|
-
self
|
213
|
-
end
|
214
|
-
|
215
232
|
# Escape special character in MySQL.
|
216
233
|
#
|
217
234
|
# @param [String] str
|
@@ -221,33 +238,26 @@ class Mysql
|
|
221
238
|
end
|
222
239
|
alias quote escape_string
|
223
240
|
|
224
|
-
# @return [
|
225
|
-
def
|
226
|
-
|
227
|
-
end
|
228
|
-
alias get_client_info client_info
|
229
|
-
|
230
|
-
# @return [Integer] client version
|
231
|
-
def client_version
|
232
|
-
self.class.client_version
|
241
|
+
# @return [Mysql::Charset] character set of MySQL connection
|
242
|
+
def charset
|
243
|
+
@opts[:charset]
|
233
244
|
end
|
234
|
-
alias get_client_version client_version
|
235
245
|
|
236
246
|
# Set charset of MySQL connection.
|
237
|
-
# @param [String
|
247
|
+
# @param [String, Mysql::Charset] cs
|
238
248
|
def charset=(cs)
|
239
249
|
charset = cs.is_a?(Charset) ? cs : Charset.by_name(cs)
|
240
250
|
if @protocol
|
241
251
|
@protocol.charset = charset
|
242
252
|
query "SET NAMES #{charset.name}"
|
243
253
|
end
|
244
|
-
@charset = charset
|
254
|
+
@opts[:charset] = charset
|
245
255
|
cs
|
246
256
|
end
|
247
257
|
|
248
258
|
# @return [String] charset name
|
249
259
|
def character_set_name
|
250
|
-
@charset.name
|
260
|
+
@protocol.charset.name
|
251
261
|
end
|
252
262
|
|
253
263
|
# @return [Integer] last error number
|
@@ -274,27 +284,18 @@ class Mysql
|
|
274
284
|
def host_info
|
275
285
|
@host_info
|
276
286
|
end
|
277
|
-
alias get_host_info host_info
|
278
|
-
|
279
|
-
# @return [Integer] protocol version
|
280
|
-
def proto_info
|
281
|
-
Mysql::Protocol::VERSION
|
282
|
-
end
|
283
|
-
alias get_proto_info proto_info
|
284
287
|
|
285
288
|
# @return [String] server version
|
286
289
|
def server_info
|
287
290
|
check_connection
|
288
291
|
@protocol.server_info
|
289
292
|
end
|
290
|
-
alias get_server_info server_info
|
291
293
|
|
292
294
|
# @return [Integer] server version
|
293
295
|
def server_version
|
294
296
|
check_connection
|
295
297
|
@protocol.server_version
|
296
298
|
end
|
297
|
-
alias get_server_version server_version
|
298
299
|
|
299
300
|
# @return [String] information for last query
|
300
301
|
def info
|
@@ -325,22 +326,18 @@ class Mysql
|
|
325
326
|
self
|
326
327
|
end
|
327
328
|
|
328
|
-
# database list.
|
329
|
-
# @param [String] db database name that may contain wild card.
|
330
|
-
# @return [Array<String>] database list
|
331
|
-
def list_dbs(db=nil)
|
332
|
-
db &&= db.gsub(/[\\\']/){"\\#{$&}"}
|
333
|
-
query(db ? "show databases like '#{db}'" : "show databases").map(&:first)
|
334
|
-
end
|
335
|
-
|
336
329
|
# Execute query string.
|
337
|
-
# @
|
338
|
-
#
|
339
|
-
#
|
340
|
-
#
|
341
|
-
# @
|
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]
|
342
338
|
# @example
|
343
339
|
# my.query("select 1,NULL,'abc'").fetch # => [1, nil, "abc"]
|
340
|
+
# my.query("select 1,NULL,'abc'"){|res| res.fetch}
|
344
341
|
def query(str, &block)
|
345
342
|
check_connection
|
346
343
|
@fields = nil
|
@@ -357,20 +354,15 @@ class Mysql
|
|
357
354
|
end
|
358
355
|
return self
|
359
356
|
end
|
360
|
-
|
361
|
-
return @fields ? store_result : nil
|
362
|
-
else
|
363
|
-
return self
|
364
|
-
end
|
357
|
+
return @fields ? store_result : nil
|
365
358
|
rescue ServerError => e
|
366
359
|
@last_error = e
|
367
360
|
@sqlstate = e.sqlstate
|
368
361
|
raise
|
369
362
|
end
|
370
363
|
end
|
371
|
-
alias real_query query
|
372
364
|
|
373
|
-
# Get all data for last query
|
365
|
+
# Get all data for last query.
|
374
366
|
# @return [Mysql::Result]
|
375
367
|
def store_result
|
376
368
|
check_connection
|
@@ -386,12 +378,6 @@ class Mysql
|
|
386
378
|
@protocol.thread_id
|
387
379
|
end
|
388
380
|
|
389
|
-
# Use result of query. The result data is retrieved when you use Mysql::Result#fetch.
|
390
|
-
# @return [Mysql::Result]
|
391
|
-
def use_result
|
392
|
-
store_result
|
393
|
-
end
|
394
|
-
|
395
381
|
# Set server option.
|
396
382
|
# @param [Integer] opt {Mysql::OPTION_MULTI_STATEMENTS_ON} or {Mysql::OPTION_MULTI_STATEMENTS_OFF}
|
397
383
|
# @return [Mysql] self
|
@@ -425,7 +411,7 @@ class Mysql
|
|
425
411
|
# @param [String] str query string
|
426
412
|
# @return [Mysql::Stmt] Prepared-statement object
|
427
413
|
def prepare(str)
|
428
|
-
st = Stmt.new @protocol
|
414
|
+
st = Stmt.new @protocol
|
429
415
|
st.prepare str
|
430
416
|
st
|
431
417
|
end
|
@@ -433,40 +419,8 @@ class Mysql
|
|
433
419
|
# @private
|
434
420
|
# Make empty prepared-statement object.
|
435
421
|
# @return [Mysql::Stmt] If block is not specified.
|
436
|
-
def
|
437
|
-
Stmt.new @protocol
|
438
|
-
end
|
439
|
-
|
440
|
-
# Returns Mysql::Result object that is empty.
|
441
|
-
# Use fetch_fields to get list of fields.
|
442
|
-
# @param [String] table table name.
|
443
|
-
# @param [String] field field name that may contain wild card.
|
444
|
-
# @return [Mysql::Result]
|
445
|
-
def list_fields(table, field=nil)
|
446
|
-
check_connection
|
447
|
-
begin
|
448
|
-
fields = @protocol.field_list_command table, field
|
449
|
-
return Result.new fields
|
450
|
-
rescue ServerError => e
|
451
|
-
@last_error = e
|
452
|
-
@sqlstate = e.sqlstate
|
453
|
-
raise
|
454
|
-
end
|
455
|
-
end
|
456
|
-
|
457
|
-
# @return [Mysql::Result] containing process list
|
458
|
-
def list_processes
|
459
|
-
check_connection
|
460
|
-
@fields = @protocol.process_info_command
|
461
|
-
@result_exist = true
|
462
|
-
store_result
|
463
|
-
end
|
464
|
-
|
465
|
-
# @param [String] table database name that may contain wild card.
|
466
|
-
# @return [Array<String>] list of table name.
|
467
|
-
def list_tables(table=nil)
|
468
|
-
q = table ? "show tables like '#{quote table}'" : "show tables"
|
469
|
-
query(q).map(&:first)
|
422
|
+
def stmt
|
423
|
+
Stmt.new @protocol
|
470
424
|
end
|
471
425
|
|
472
426
|
# Check whether the connection is available.
|
@@ -579,7 +533,7 @@ class Mysql
|
|
579
533
|
end
|
580
534
|
|
581
535
|
# @return [Hash] field information
|
582
|
-
def
|
536
|
+
def to_hash
|
583
537
|
{
|
584
538
|
"name" => @name,
|
585
539
|
"table" => @table,
|
@@ -815,10 +769,9 @@ class Mysql
|
|
815
769
|
# @private
|
816
770
|
# @param [Array<Mysql::Field>] fields
|
817
771
|
# @param [Mysql::Protocol] protocol
|
818
|
-
|
819
|
-
def initialize(fields, protocol, charset)
|
772
|
+
def initialize(fields, protocol)
|
820
773
|
super fields
|
821
|
-
@records = protocol.stmt_retr_all_records @fields, charset
|
774
|
+
@records = protocol.stmt_retr_all_records @fields, protocol.charset
|
822
775
|
end
|
823
776
|
end
|
824
777
|
|
@@ -853,15 +806,12 @@ class Mysql
|
|
853
806
|
|
854
807
|
# @private
|
855
808
|
# @param [Mysql::Protocol] protocol
|
856
|
-
|
857
|
-
def initialize(protocol, charset)
|
809
|
+
def initialize(protocol)
|
858
810
|
@protocol = protocol
|
859
|
-
@charset = charset
|
860
811
|
@statement_id = nil
|
861
812
|
@affected_rows = @insert_id = @server_status = @warning_count = 0
|
862
813
|
@sqlstate = "00000"
|
863
814
|
@param_count = nil
|
864
|
-
@bind_result = nil
|
865
815
|
end
|
866
816
|
|
867
817
|
# @private
|
@@ -888,13 +838,13 @@ class Mysql
|
|
888
838
|
def execute(*values)
|
889
839
|
raise ClientError, "not prepared" unless @param_count
|
890
840
|
raise ClientError, "parameter count mismatch" if values.length != @param_count
|
891
|
-
values = values.map{|v| @charset.convert v}
|
841
|
+
values = values.map{|v| @protocol.charset.convert v}
|
892
842
|
begin
|
893
843
|
@sqlstate = "00000"
|
894
844
|
nfields = @protocol.stmt_execute_command @statement_id, values
|
895
845
|
if nfields
|
896
846
|
@fields = @protocol.retr_fields nfields
|
897
|
-
@result = StatementResult.new @fields, @protocol
|
847
|
+
@result = StatementResult.new @fields, @protocol
|
898
848
|
else
|
899
849
|
@affected_rows, @insert_id, @server_status, @warning_count, @info =
|
900
850
|
@protocol.affected_rows, @protocol.insert_id, @protocol.server_status, @protocol.warning_count, @protocol.message
|
@@ -917,46 +867,7 @@ class Mysql
|
|
917
867
|
|
918
868
|
# @return [Array] current record data
|
919
869
|
def fetch
|
920
|
-
|
921
|
-
return row unless @bind_result
|
922
|
-
row.zip(@bind_result).map do |col, type|
|
923
|
-
if col.nil?
|
924
|
-
nil
|
925
|
-
elsif [Numeric, Integer].include? type
|
926
|
-
col.to_i
|
927
|
-
elsif type == String
|
928
|
-
col.to_s
|
929
|
-
elsif type == Float && !col.is_a?(Float)
|
930
|
-
col.to_i.to_f
|
931
|
-
elsif type == Mysql::Time && !col.is_a?(Mysql::Time)
|
932
|
-
if col.to_s =~ /\A\d+\z/
|
933
|
-
i = col.to_s.to_i
|
934
|
-
if i < 100000000
|
935
|
-
y = i/10000
|
936
|
-
m = i/100%100
|
937
|
-
d = i%100
|
938
|
-
h, mm, s = 0
|
939
|
-
else
|
940
|
-
y = i/10000000000
|
941
|
-
m = i/100000000%100
|
942
|
-
d = i/1000000%100
|
943
|
-
h = i/10000%100
|
944
|
-
mm= i/100%100
|
945
|
-
s = i%100
|
946
|
-
end
|
947
|
-
if y < 70
|
948
|
-
y += 2000
|
949
|
-
elsif y < 100
|
950
|
-
y += 1900
|
951
|
-
end
|
952
|
-
Mysql::Time.new(y, m, d, h, mm, s)
|
953
|
-
else
|
954
|
-
Mysql::Time.new
|
955
|
-
end
|
956
|
-
else
|
957
|
-
col
|
958
|
-
end
|
959
|
-
end
|
870
|
+
@result.fetch
|
960
871
|
end
|
961
872
|
|
962
873
|
# Return data of current record as Hash.
|
@@ -967,20 +878,6 @@ class Mysql
|
|
967
878
|
@result.fetch_hash with_table
|
968
879
|
end
|
969
880
|
|
970
|
-
# Set retrieve type of value
|
971
|
-
# @param [Numeric / Fixnum / Integer / Float / String / Mysql::Time / nil] args value type
|
972
|
-
# @return [Mysql::Stmt] self
|
973
|
-
def bind_result(*args)
|
974
|
-
if @fields.length != args.length
|
975
|
-
raise ClientError, "bind_result: result value count(#{@fields.length}) != number of argument(#{args.length})"
|
976
|
-
end
|
977
|
-
args.each do |a|
|
978
|
-
raise TypeError unless [Numeric, Integer, Float, String, Mysql::Time, nil].include? a
|
979
|
-
end
|
980
|
-
@bind_result = args
|
981
|
-
self
|
982
|
-
end
|
983
|
-
|
984
881
|
# Iterate block with record.
|
985
882
|
# @yield [Array] record data
|
986
883
|
# @return [Mysql::Stmt] self
|
@@ -1049,78 +946,4 @@ class Mysql
|
|
1049
946
|
Result.new @fields
|
1050
947
|
end
|
1051
948
|
end
|
1052
|
-
|
1053
|
-
# @!visibility public
|
1054
|
-
# @!attribute [rw] year
|
1055
|
-
# @return [Integer]
|
1056
|
-
# @!attribute [rw] month
|
1057
|
-
# @return [Integer]
|
1058
|
-
# @!attribute [rw] day
|
1059
|
-
# @return [Integer]
|
1060
|
-
# @!attribute [rw] hour
|
1061
|
-
# @return [Integer]
|
1062
|
-
# @!attribute [rw] minute
|
1063
|
-
# @return [Integer]
|
1064
|
-
# @!attribute [rw] second
|
1065
|
-
# @return [Integer]
|
1066
|
-
# @!attribute [rw] neg
|
1067
|
-
# @return [Boolean] negative flag
|
1068
|
-
# @!attribute [rw] second_part
|
1069
|
-
# @return [Integer]
|
1070
|
-
class Time
|
1071
|
-
# @param [Integer] year
|
1072
|
-
# @param [Integer] month
|
1073
|
-
# @param [Integer] day
|
1074
|
-
# @param [Integer] hour
|
1075
|
-
# @param [Integer] minute
|
1076
|
-
# @param [Integer] second
|
1077
|
-
# @param [Boolean] neg negative flag
|
1078
|
-
# @param [Integer] second_part
|
1079
|
-
def initialize(year=0, month=0, day=0, hour=0, minute=0, second=0, neg=false, second_part=0)
|
1080
|
-
@date_flag = !(hour && minute && second)
|
1081
|
-
@year, @month, @day, @hour, @minute, @second, @neg, @second_part =
|
1082
|
-
year.to_i, month.to_i, day.to_i, hour.to_i, minute.to_i, second.to_i, neg, second_part.to_i
|
1083
|
-
end
|
1084
|
-
attr_accessor :year, :month, :day, :hour, :minute, :second, :neg, :second_part
|
1085
|
-
alias mon month
|
1086
|
-
alias min minute
|
1087
|
-
alias sec second
|
1088
|
-
|
1089
|
-
# @private
|
1090
|
-
def ==(other)
|
1091
|
-
other.is_a?(Mysql::Time) &&
|
1092
|
-
@year == other.year && @month == other.month && @day == other.day &&
|
1093
|
-
@hour == other.hour && @minute == other.minute && @second == other.second &&
|
1094
|
-
@neg == neg && @second_part == other.second_part
|
1095
|
-
end
|
1096
|
-
|
1097
|
-
# @private
|
1098
|
-
def eql?(other)
|
1099
|
-
self == other
|
1100
|
-
end
|
1101
|
-
|
1102
|
-
# @return [String] "yyyy-mm-dd HH:MM:SS"
|
1103
|
-
def to_s
|
1104
|
-
if @date_flag
|
1105
|
-
sprintf "%04d-%02d-%02d", year, mon, day
|
1106
|
-
elsif year == 0 and mon == 0 and day == 0
|
1107
|
-
h = neg ? hour * -1 : hour
|
1108
|
-
sprintf "%02d:%02d:%02d", h, min, sec
|
1109
|
-
else
|
1110
|
-
sprintf "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec
|
1111
|
-
end
|
1112
|
-
end
|
1113
|
-
|
1114
|
-
# @return [Integer] yyyymmddHHMMSS
|
1115
|
-
def to_i
|
1116
|
-
sprintf("%04d%02d%02d%02d%02d%02d", year, mon, day, hour, min, sec).to_i
|
1117
|
-
end
|
1118
|
-
|
1119
|
-
# @private
|
1120
|
-
def inspect
|
1121
|
-
sprintf "#<#{self.class.name}:%04d-%02d-%02d %02d:%02d:%02d>", year, mon, day, hour, min, sec
|
1122
|
-
end
|
1123
|
-
|
1124
|
-
end
|
1125
|
-
|
1126
949
|
end
|