mysql2wrapper 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile.lock +1 -5
- data/README.md +5 -1
- data/example/sample.rb +32 -18
- data/example/sample_table_information.rb +40 -0
- data/lib/mysql2wrapper.rb +1 -0
- data/lib/mysql2wrapper/client.rb +136 -21
- data/lib/mysql2wrapper/core_ext.rb +17 -0
- data/lib/mysql2wrapper/version.rb +1 -1
- data/test/sample_datas/image.jpeg +0 -0
- data/test/test.rb +268 -20
- metadata +6 -2
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,17 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
mysql2wrapper (0.0.
|
5
|
-
batchbase (= 0.0.2)
|
4
|
+
mysql2wrapper (0.0.2)
|
6
5
|
mysql2 (= 0.3.11)
|
7
6
|
|
8
7
|
GEM
|
9
8
|
remote: http://rubygems.org/
|
10
9
|
specs:
|
11
|
-
batchbase (0.0.2)
|
12
|
-
sys-proctable (= 0.9.1)
|
13
10
|
mysql2 (0.3.11)
|
14
|
-
sys-proctable (0.9.1)
|
15
11
|
|
16
12
|
PLATFORMS
|
17
13
|
ruby
|
data/README.md
CHANGED
data/example/sample.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'mysql2wrapper'
|
3
3
|
require 'logger'
|
4
|
+
require 'pp'
|
4
5
|
|
5
6
|
#
|
6
7
|
# HACKME サンプルをちょっとはマシに書く、、、、
|
@@ -21,10 +22,19 @@ client = Mysql2wrapper::Client.new(db_config,logger)
|
|
21
22
|
#client = Mysql2wrapper::Client.new(db_config,nil)
|
22
23
|
|
23
24
|
query = '
|
24
|
-
DROP TABLE IF EXISTS `
|
25
|
+
DROP TABLE IF EXISTS `test01`'
|
25
26
|
client.query query
|
26
27
|
query = '
|
27
|
-
CREATE TABLE IF NOT EXISTS `
|
28
|
+
CREATE TABLE IF NOT EXISTS `test01` (
|
29
|
+
`id` int(11) NOT NULL auto_increment,
|
30
|
+
`value1` int(11) NOT NULL,
|
31
|
+
`created_at` datetime NOT NULL,
|
32
|
+
`updated_at` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
|
33
|
+
PRIMARY KEY (`id`)
|
34
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;'
|
35
|
+
client.query query
|
36
|
+
query = '
|
37
|
+
CREATE TABLE IF NOT EXISTS `test02` (
|
28
38
|
`id` int(11) NOT NULL auto_increment,
|
29
39
|
`value1` int(11) NOT NULL,
|
30
40
|
`created_at` datetime NOT NULL,
|
@@ -33,22 +43,24 @@ CREATE TABLE IF NOT EXISTS `hoges` (
|
|
33
43
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;'
|
34
44
|
client.query query
|
35
45
|
|
36
|
-
|
37
|
-
|
38
|
-
logger.info "
|
46
|
+
p client.tables
|
47
|
+
|
48
|
+
logger.info "test01 has #{client.count 'test01'}rows"
|
49
|
+
client.query "INSERT INTO test01 (value1,created_at)VALUES(#{Time.now.to_i},NOW())"
|
50
|
+
logger.info "test01 has #{client.count 'test01'}rows"
|
39
51
|
|
40
52
|
begin
|
41
53
|
# トランザクションはブロックを渡す(ARと同じく)
|
42
54
|
client.transaction do
|
43
|
-
logger.info "
|
44
|
-
client.query "INSERT INTO
|
55
|
+
logger.info "test01 has #{client.count 'test01'}rows"
|
56
|
+
client.query "INSERT INTO test01 (value1,created_at)VALUES(#{Time.now.to_i},NOW())"
|
45
57
|
client.query query
|
46
|
-
logger.info "
|
58
|
+
logger.info "test01 has #{client.count 'test01'}rows"
|
47
59
|
raise 'error' # call ROLLBACK
|
48
60
|
end
|
49
61
|
rescue
|
50
62
|
end
|
51
|
-
logger.info "
|
63
|
+
logger.info "test01 has #{client.count 'test01'}rows"
|
52
64
|
|
53
65
|
# ハッシュを引数にしたインサートの発行
|
54
66
|
@i = 0
|
@@ -56,22 +68,24 @@ hash = {
|
|
56
68
|
:value1=>proc{@i+=1}, # procを引数にもできる
|
57
69
|
:created_at=>'now()'.to_func
|
58
70
|
}
|
59
|
-
client.insert('
|
71
|
+
client.insert('test01',hash)
|
60
72
|
logger.info "affected_rows:#{client.affected_rows}"
|
61
|
-
logger.info "
|
73
|
+
logger.info "test01 has #{client.count 'test01'}rows"
|
62
74
|
|
63
75
|
# 配列を引数にしたインサートの発行
|
64
76
|
ar = []
|
65
77
|
20.times{ar << hash}
|
66
|
-
client.insert('
|
78
|
+
client.insert('test01',ar)
|
67
79
|
logger.info "affected_rows:#{client.affected_rows}" # Client#affected_rowsでマルチプルインサートのトータルインサート数が取れる
|
68
|
-
logger.info "
|
80
|
+
logger.info "test01 has #{client.count 'test01'}rows"
|
69
81
|
|
70
82
|
# ハッシュを引数にしたアップデート
|
71
|
-
client.update '
|
72
|
-
logger.info "
|
83
|
+
client.update 'test01',{:value1=>3},'id = 1'
|
84
|
+
logger.info "test01 has #{client.count 'test01'}rows"
|
73
85
|
# 全行アップデートをしたなら第三引数でMysql2wrapper::Client::UpdateAllClassを引数にしないとダメ
|
74
|
-
client.update '
|
86
|
+
client.update 'test01',{:value1=>3},Mysql2wrapper::Client::UpdateAllClass
|
75
87
|
# clientインスタンスにショートカットあり
|
76
|
-
client.update '
|
77
|
-
logger.info "
|
88
|
+
client.update 'test01',{:value1=>4},client.update_all_flag
|
89
|
+
logger.info "test01 has #{client.count 'test01'}rows"
|
90
|
+
|
91
|
+
pp client.table_informations
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mysql2wrapper'
|
3
|
+
require 'logger'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
#
|
7
|
+
# データベース内のテーブル情報を所定の書式で出力サンプル
|
8
|
+
#
|
9
|
+
|
10
|
+
logger = Logger.new(STDOUT)
|
11
|
+
# フォーマッターを変える
|
12
|
+
#logger.formatter = Kanamei::LogFormatter.formatter
|
13
|
+
db_yml_path = File::dirname(__FILE__) + '/../config/database.yml'
|
14
|
+
logger.info db_yml_path
|
15
|
+
|
16
|
+
# 第3引数は複数DB接続が無いならば指定不要
|
17
|
+
db_config = Mysql2wrapper::Client.config_from_yml(db_yml_path,'test')
|
18
|
+
|
19
|
+
client = Mysql2wrapper::Client.new(db_config,logger)
|
20
|
+
# ログ出力しないなら第二引数をnilで
|
21
|
+
#client = Mysql2wrapper::Client.new(db_config,nil)
|
22
|
+
|
23
|
+
client.table_informations.each do |table|
|
24
|
+
puts "/*"
|
25
|
+
puts "[table]"
|
26
|
+
puts table['TABLE_NAME']
|
27
|
+
puts table['TABLE_COMMENT']
|
28
|
+
puts "[columns]"
|
29
|
+
table['COLUMNS'].each do |col|
|
30
|
+
puts "#{col['COLUMN_NAME']}:#{col['COLUMN_COMMENT']}"
|
31
|
+
end
|
32
|
+
puts "[indexes]"
|
33
|
+
table['INDEXES'].each do |col|
|
34
|
+
puts "#{col['INDEX_NAME']}:#{col['INDEX_COMMENT']}"
|
35
|
+
end
|
36
|
+
puts "[history]"
|
37
|
+
puts "*/"
|
38
|
+
puts table['CREATE TABLE']
|
39
|
+
end
|
40
|
+
|
data/lib/mysql2wrapper.rb
CHANGED
data/lib/mysql2wrapper/client.rb
CHANGED
@@ -4,7 +4,7 @@ require 'yaml'
|
|
4
4
|
require 'mysql2'
|
5
5
|
|
6
6
|
class Mysql2wrapper::Client
|
7
|
-
attr_accessor :config, :client, :logger
|
7
|
+
attr_accessor :config, :client, :logger, :last_query
|
8
8
|
attr_reader :affected_rows
|
9
9
|
|
10
10
|
# 全行更新用のフラグ表現クラス
|
@@ -19,7 +19,12 @@ class Mysql2wrapper::Client
|
|
19
19
|
def initialize(config,_logger=Logger.new(STDOUT))
|
20
20
|
self.logger = _logger
|
21
21
|
if self.logger
|
22
|
-
|
22
|
+
# TODO パスワードの隠し
|
23
|
+
config_c = config.clone
|
24
|
+
if config_c[:password].present?
|
25
|
+
config_c[:password] = '****'
|
26
|
+
end
|
27
|
+
self.logger.info "mysql2 client created with #{config_c.inspect}"
|
23
28
|
end
|
24
29
|
self.client = Mysql2::Client.new(config)
|
25
30
|
self.config = config
|
@@ -52,15 +57,36 @@ class Mysql2wrapper::Client
|
|
52
57
|
"#{self.config.inspect}\n#{self.client.pretty_inspect}"
|
53
58
|
end
|
54
59
|
|
55
|
-
def query(
|
56
|
-
|
60
|
+
def query(str_query,color=QUERY_BASE_COLOR)
|
61
|
+
begin
|
62
|
+
case str_query
|
63
|
+
when /^SET /,'COMMIT','ROLLBACK'
|
64
|
+
else
|
65
|
+
self.last_query = str_query
|
66
|
+
end
|
67
|
+
rescue ArgumentError => e
|
68
|
+
# バイナリが絡むとstr_queryに正規表現とかかけられない
|
69
|
+
# invalid sequence エラーになる
|
70
|
+
self.last_query = str_query
|
71
|
+
end
|
72
|
+
res = self.class.query(self.client,str_query,self.logger,color)
|
57
73
|
@affected_rows = self.client.affected_rows
|
58
74
|
res
|
59
75
|
end
|
60
76
|
|
77
|
+
# HACKME
|
78
|
+
# トランザクションのネストをどう考えるか
|
79
|
+
# このライブラリを使うシチュエーションってのは
|
80
|
+
# トランザクションのネストを許さない場合ってな気がするので
|
81
|
+
# 一応エラーを上げるようにしてますが、、、、
|
61
82
|
def transaction(&proc)
|
62
83
|
raise ArgumentError, "No block was given" unless block_given?
|
63
84
|
#query "SET AUTOCOMMIT=0;",QUERY_SPECIAL_COLOR
|
85
|
+
if @__inside_transaction
|
86
|
+
# HACHME エラーの種別の検討
|
87
|
+
raise StandardError, 'can not nest transaction!!!!'
|
88
|
+
end
|
89
|
+
@__inside_transaction = true
|
64
90
|
query "BEGIN",QUERY_SPECIAL_COLOR
|
65
91
|
begin
|
66
92
|
yield
|
@@ -68,6 +94,8 @@ class Mysql2wrapper::Client
|
|
68
94
|
rescue => e
|
69
95
|
query "ROLLBACK",QUERY_SPECIAL_COLOR
|
70
96
|
raise e
|
97
|
+
ensure
|
98
|
+
@__inside_transaction = false
|
71
99
|
end
|
72
100
|
end
|
73
101
|
|
@@ -79,8 +107,12 @@ class Mysql2wrapper::Client
|
|
79
107
|
config = new_config
|
80
108
|
end
|
81
109
|
|
82
|
-
def count(table_name,key_name='*')
|
83
|
-
query
|
110
|
+
def count(table_name,where=nil,key_name='*')
|
111
|
+
query = "SELECT COUNT(#{escape(key_name)}) AS cnt FROM #{escape(table_name)}"
|
112
|
+
if where
|
113
|
+
query = "#{query} #{parse_where where}"
|
114
|
+
end
|
115
|
+
query(query).first['cnt']
|
84
116
|
end
|
85
117
|
|
86
118
|
def close
|
@@ -104,10 +136,11 @@ class Mysql2wrapper::Client
|
|
104
136
|
#
|
105
137
|
def update(table_name,hash,where)
|
106
138
|
case where
|
107
|
-
when
|
108
|
-
where
|
139
|
+
when '',nil
|
140
|
+
raise ArgumentError, 'can not set blank or nil on where with update(you shoule use UpdateAllClass with where)'
|
109
141
|
when UpdateAllClass.class
|
110
|
-
where =
|
142
|
+
where = nil
|
143
|
+
when String,Hash
|
111
144
|
else
|
112
145
|
raise ArgumentError, "where must be String or UpdateAll"
|
113
146
|
end
|
@@ -115,10 +148,50 @@ class Mysql2wrapper::Client
|
|
115
148
|
hash.map do |key,value|
|
116
149
|
"`#{escape(key.to_s)}` = #{proceed_value(value)}"
|
117
150
|
end.join(',')
|
118
|
-
}"
|
151
|
+
}"
|
152
|
+
if where
|
153
|
+
query = "#{query} #{parse_where where}"
|
154
|
+
end
|
119
155
|
self.query(query)
|
120
156
|
end
|
121
157
|
|
158
|
+
def select(table_name,select,where=nil)
|
159
|
+
query = "SELECT #{select} FROM `#{escape table_name}`"
|
160
|
+
if where
|
161
|
+
query = "#{query} #{parse_where(where)}"
|
162
|
+
end
|
163
|
+
query query
|
164
|
+
end
|
165
|
+
|
166
|
+
def parse_where(v)
|
167
|
+
case v
|
168
|
+
when String
|
169
|
+
if v.size > 0
|
170
|
+
"WHERE #{v}"
|
171
|
+
else
|
172
|
+
''
|
173
|
+
end
|
174
|
+
when Hash
|
175
|
+
"WHERE #{
|
176
|
+
v.map do |key,value|
|
177
|
+
case value
|
178
|
+
when nil
|
179
|
+
"`#{escape(key.to_s)}` IS NULL"
|
180
|
+
when Array
|
181
|
+
# ここ、、、自動で条件を抜くってのもできるけど、、、、まぁそれで意図しない結果になるより
|
182
|
+
# エラーを上げるほうが妥当だろうて
|
183
|
+
raise "at least one value needs for #{key.to_s} (can not call in statement with no value)" if value.size == 0
|
184
|
+
"`#{escape(key.to_s)}` in (#{value.map{|o|proceed_value(o)}.join(',')})"
|
185
|
+
else
|
186
|
+
"`#{escape(key.to_s)}` = #{proceed_value(value)}"
|
187
|
+
end
|
188
|
+
end.join(' AND ')
|
189
|
+
}"
|
190
|
+
else
|
191
|
+
raise 'can set String or Hash on where'
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
122
195
|
def update_all_flag
|
123
196
|
self.class::UPDATE_ALL
|
124
197
|
end
|
@@ -139,19 +212,21 @@ class Mysql2wrapper::Client
|
|
139
212
|
"'#{value.strftime("%Y-%m-%d %H:%M:%S")}'"
|
140
213
|
when Date
|
141
214
|
"'#{value.strftime("%Y-%m-%d")}'"
|
142
|
-
|
143
|
-
|
144
|
-
s = s.to_s unless s.kind_of?(String)
|
145
|
-
if s.respond_to?(:function_sql?) && s.function_sql?
|
215
|
+
when String
|
216
|
+
if value.respond_to?(:function_sql?) && value.function_sql?
|
146
217
|
"#{value.to_s}"
|
147
218
|
else
|
148
|
-
|
219
|
+
value = escape(value)
|
220
|
+
#value = value.encode('utf-8', {:invalid => :replace, :undef => :replace})
|
221
|
+
"'#{value}'"
|
149
222
|
end
|
223
|
+
else
|
224
|
+
"'#{escape(value.to_s)}'"
|
150
225
|
end
|
151
226
|
end
|
152
227
|
|
153
228
|
def insert(table_name,data,multiple_insert_by=MULTIPLE_INSERT_DEFAULT)
|
154
|
-
@affected_rows = 0 #
|
229
|
+
@affected_rows = 0 # 一応リセット
|
155
230
|
affected_rows_total = 0
|
156
231
|
query = "INSERT INTO `#{escape(table_name)}`"
|
157
232
|
_datas = data.clone
|
@@ -166,7 +241,6 @@ class Mysql2wrapper::Client
|
|
166
241
|
|
167
242
|
return nil if _datas.size == 0
|
168
243
|
|
169
|
-
# TODO affected_rows by multiple
|
170
244
|
_datas.each_slice(multiple_insert_by).each do |rows|
|
171
245
|
query = <<"EOS"
|
172
246
|
INSERT INTO `#{escape(table_name)}`
|
@@ -182,6 +256,7 @@ VALUES
|
|
182
256
|
end.join(',')
|
183
257
|
}
|
184
258
|
EOS
|
259
|
+
|
185
260
|
self.query(query.chomp)
|
186
261
|
affected_rows_total += self.client.affected_rows
|
187
262
|
end
|
@@ -192,12 +267,52 @@ EOS
|
|
192
267
|
# db_server_nameはDB名そのもの(複数DB対応)
|
193
268
|
#
|
194
269
|
def self.config_from_yml(yml_path,environment,db_server_name=nil)
|
270
|
+
raise "yaml not found(#{yml_path})" unless File.exists?(yml_path)
|
195
271
|
db_config = YAML.load_file(yml_path)[environment]
|
196
272
|
if db_server_name
|
197
|
-
db_config =
|
198
|
-
|
199
|
-
|
273
|
+
db_config = db_config[db_server_name]
|
274
|
+
end
|
275
|
+
unless db_config
|
276
|
+
raise "can not get db_config with env:#{environment}#{db_server_name ? "/db_server:#{db_server_name}":''}"
|
277
|
+
end
|
278
|
+
self.make_config_key_symbol(db_config)
|
279
|
+
end
|
280
|
+
|
281
|
+
def tables
|
282
|
+
table_informations.map{|o|o['TABLE_NAME']}
|
283
|
+
end
|
284
|
+
|
285
|
+
def table_names
|
286
|
+
table_informations.map{|o|o['TABLE_NAME']}
|
287
|
+
end
|
288
|
+
|
289
|
+
def databases
|
290
|
+
query = 'show databases'
|
291
|
+
self.client.query(query).map{|ar|ar['Database']}
|
292
|
+
end
|
293
|
+
|
294
|
+
def table_informations
|
295
|
+
query = "select * from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '#{escape(self.config[:database])}' AND TABLE_TYPE = 'BASE TABLE'"
|
296
|
+
tables = self.client.query(query).to_a
|
297
|
+
tables.each do |table|
|
298
|
+
table['COLUMNS'] = table_information_schema('COLUMNS',table['TABLE_NAME'])
|
299
|
+
table['INDEXES'] = table_information_schema('STATISTICS',table['TABLE_NAME'])
|
300
|
+
query = "SHOW CREATE TABLE `#{escape(table['TABLE_NAME'])}`"
|
301
|
+
table['CREATE TABLE'] = self.client.query(query).first['Create Table']
|
200
302
|
end
|
201
|
-
|
303
|
+
tables
|
304
|
+
end
|
305
|
+
|
306
|
+
def table_information_schema(type,table_name)
|
307
|
+
query = "
|
308
|
+
SELECT
|
309
|
+
*
|
310
|
+
FROM
|
311
|
+
INFORMATION_SCHEMA.#{type}
|
312
|
+
WHERE
|
313
|
+
table_name = '#{escape(table_name)}' AND
|
314
|
+
table_schema = '#{escape(self.config[:database])}'
|
315
|
+
"
|
316
|
+
query(query).to_a
|
202
317
|
end
|
203
318
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
class Array
|
3
|
+
def select_one_must(&proc)
|
4
|
+
result = self.select(&proc)
|
5
|
+
raise StandardError, 'no data selected' if result.size == 0
|
6
|
+
raise StandardError, "multiple data selected(#{result.size} datas)" if result.size > 1
|
7
|
+
result.first
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module Mysql2
|
12
|
+
class Result
|
13
|
+
def select_one_must(&proc)
|
14
|
+
self.to_a.select_one_must(&proc)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
Binary file
|
data/test/test.rb
CHANGED
@@ -6,6 +6,7 @@ require 'test/unit'
|
|
6
6
|
require 'Fileutils'
|
7
7
|
require 'logger'
|
8
8
|
|
9
|
+
TEST_IMAGE = File.expand_path(File.dirname(__FILE__))+ '/sample_datas/image.jpeg'
|
9
10
|
#
|
10
11
|
# localhostに以下のデータベースを作成しrootのパスワード無しでアクセスできるようにしておいてください
|
11
12
|
#
|
@@ -31,7 +32,7 @@ class TestMysql2wrapper < Test::Unit::TestCase
|
|
31
32
|
query = '
|
32
33
|
CREATE TABLE IF NOT EXISTS `test02` (
|
33
34
|
`id` int(11) NOT NULL auto_increment,
|
34
|
-
`v_int1` int(11) NOT NULL,
|
35
|
+
`v_int1` int(11) NOT NULL COMMENT \'v_int1だよん\',
|
35
36
|
`v_int2` int(11) NOT NULL,
|
36
37
|
`v_int3` int(11),
|
37
38
|
`v_int4` int(11),
|
@@ -52,13 +53,14 @@ CREATE TABLE IF NOT EXISTS `test02` (
|
|
52
53
|
`v_time1` datetime NOT NULL,
|
53
54
|
`v_time2` datetime,
|
54
55
|
`v_time3` datetime,
|
56
|
+
`v_blob1` mediumblob,
|
55
57
|
`created_at` datetime NOT NULL,
|
56
58
|
`updated_at` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
|
57
|
-
PRIMARY KEY (`id`)
|
59
|
+
PRIMARY KEY (`id`),
|
60
|
+
KEY `idx_01` (`v_int1`) USING BTREE COMMENT \'idx_01 ダヨン\'
|
58
61
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
59
62
|
'
|
60
63
|
client.query query
|
61
|
-
|
62
64
|
client.close
|
63
65
|
end
|
64
66
|
|
@@ -112,16 +114,40 @@ CREATE TABLE IF NOT EXISTS `#{table}` (
|
|
112
114
|
|
113
115
|
def test_count
|
114
116
|
client = get_client
|
115
|
-
assert_equal 0,client.count('test01','id')
|
116
|
-
|
117
|
-
client.
|
118
|
-
assert_equal 1,client.count('test01'
|
119
|
-
|
120
|
-
client.
|
121
|
-
assert_equal 2,client.count('test01','
|
117
|
+
assert_equal 0,client.count('test01',nil,'id')
|
118
|
+
assert_equal 0,client.count('test01')
|
119
|
+
client.insert('test01',{:v_int1=>11,:created_at=>'NOW()'.to_func})
|
120
|
+
assert_equal 1,client.count('test01')
|
121
|
+
client.insert('test01',{:v_int1=>11,:created_at=>'NOW()'.to_func})
|
122
|
+
assert_equal 2,client.count('test01',nil,'id')
|
123
|
+
assert_equal 2,client.count('test01',nil,'*')
|
124
|
+
assert_equal 2,client.count('test01')
|
125
|
+
client.insert('test01',{:v_int1=>11,:v_int2=>22,:created_at=>'NOW()'.to_func})
|
126
|
+
assert_equal 3,client.count('test01',{:v_int1=>11},'id')
|
127
|
+
assert_equal 3,client.count('test01',"v_int1 = 11",'id')
|
128
|
+
assert_equal 1,client.count('test01',{:v_int2=>22},'id')
|
129
|
+
assert_equal 1,client.count('test01',{:v_int1=>11,:v_int2=>22},'id')
|
130
|
+
assert_equal 1,client.count('test01',{:v_int1=>11,:v_int2=>22})
|
131
|
+
assert_equal 1,client.count('test01',"v_int1 = 11 AND v_int2 = 22",'id')
|
122
132
|
client.close
|
123
133
|
end
|
124
134
|
|
135
|
+
def test_last_query
|
136
|
+
client = get_client
|
137
|
+
query = "INSERT INTO test01 (v_int1,created_at)VALUES(123,NOW())"
|
138
|
+
client.query query
|
139
|
+
assert_equal query,client.last_query
|
140
|
+
begin
|
141
|
+
client.transaction do
|
142
|
+
client.query query
|
143
|
+
assert_equal query,client.last_query
|
144
|
+
raise 'hoho'
|
145
|
+
end
|
146
|
+
rescue => e
|
147
|
+
assert_equal query,client.last_query
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
125
151
|
def test_select
|
126
152
|
client = get_client
|
127
153
|
assert_equal 0,client.count('test01','id')
|
@@ -135,8 +161,38 @@ CREATE TABLE IF NOT EXISTS `#{table}` (
|
|
135
161
|
client.query query
|
136
162
|
res = client.query "SELECT * FROM test01 WHERE id = 1"
|
137
163
|
assert_equal 1, client.affected_rows
|
164
|
+
res = client.select "test01",'*',{:id=>1}
|
165
|
+
assert_equal 1, client.affected_rows
|
138
166
|
res = client.query "SELECT * FROM test01"
|
139
167
|
assert_equal 2, client.affected_rows
|
168
|
+
|
169
|
+
query = "INSERT INTO test01 (v_int1,v_int2,created_at)VALUES(123,234,NOW())"
|
170
|
+
client.query query
|
171
|
+
res = client.select "test01",'id',{:v_int1=>123,:v_int2=>234}
|
172
|
+
assert_equal 1, client.affected_rows
|
173
|
+
assert_equal 1, res.size
|
174
|
+
res = client.select "test01",'*',"v_int1 =123 AND v_int2 = 234"
|
175
|
+
assert_equal 1, client.affected_rows
|
176
|
+
assert_equal 1, res.size
|
177
|
+
res = client.select "test01",'id',{:v_int1=>123,:v_int2=>nil}
|
178
|
+
assert_equal 2, client.affected_rows
|
179
|
+
res = client.select "test01",'*',"v_int1=123 AND v_int2 IS NULL"
|
180
|
+
assert_equal 2, client.affected_rows
|
181
|
+
|
182
|
+
|
183
|
+
res = client.select "test01",'*',{:id=>[1]}
|
184
|
+
assert_equal 1, client.affected_rows
|
185
|
+
res = client.select "test01",'*',{:id=>[1,2]}
|
186
|
+
assert_equal 2, client.affected_rows
|
187
|
+
res = client.select "test01",'*',{:id=>[1,2,999]}
|
188
|
+
assert_equal 2, client.affected_rows
|
189
|
+
res = client.select "test01",'*',{:id=>[1,2,nil]}
|
190
|
+
assert_equal 2, client.affected_rows
|
191
|
+
res = client.select "test01",'*',{:id=>[1,2,'NOW()'.to_func]}
|
192
|
+
assert_equal 2, client.affected_rows
|
193
|
+
res = client.select "test01",'*',{:id=>[1,2,Time.now]}
|
194
|
+
assert_equal 2, client.affected_rows
|
195
|
+
|
140
196
|
client.close
|
141
197
|
end
|
142
198
|
|
@@ -147,16 +203,8 @@ CREATE TABLE IF NOT EXISTS `#{table}` (
|
|
147
203
|
client.query query
|
148
204
|
client.query query
|
149
205
|
|
150
|
-
res = client.query "SELECT * FROM test01 WHERE id = 1"
|
151
|
-
assert_equal 1, res.first['v_int1']
|
152
|
-
assert_equal nil, res.first['v_int2']
|
153
|
-
res = client.query "SELECT * FROM test01 WHERE id = 2"
|
154
|
-
assert_equal 1, res.first['v_int1']
|
155
|
-
assert_equal nil, res.first['v_int2']
|
156
|
-
|
157
206
|
client.update 'test01',{:v_int1=>2},'id = 1'
|
158
207
|
assert_equal 1, client.affected_rows
|
159
|
-
|
160
208
|
res = client.query "SELECT * FROM test01 WHERE id = 1"
|
161
209
|
assert_equal 2, res.first['v_int1']
|
162
210
|
assert_equal nil, res.first['v_int2']
|
@@ -164,6 +212,8 @@ CREATE TABLE IF NOT EXISTS `#{table}` (
|
|
164
212
|
assert_equal 1, res.first['v_int1']
|
165
213
|
assert_equal nil, res.first['v_int2']
|
166
214
|
|
215
|
+
client.update 'test01',{:v_int2=>3},{:id=>3}
|
216
|
+
assert_equal 1, client.affected_rows
|
167
217
|
client.update 'test01',{:v_int1=>3}, client.update_all_flag
|
168
218
|
|
169
219
|
assert_equal 3, client.affected_rows
|
@@ -174,8 +224,19 @@ CREATE TABLE IF NOT EXISTS `#{table}` (
|
|
174
224
|
assert_equal 3, res.first['v_int1']
|
175
225
|
assert_equal nil, res.first['v_int2']
|
176
226
|
client.update 'test01',{:v_int1=>3},Mysql2wrapper::Client::UPDATE_ALL
|
227
|
+
assert_equal 0, client.affected_rows # 更新行が無いので
|
228
|
+
|
229
|
+
client.update 'test01',{:v_int1=>4},{:v_int1=>2,:v_int2=>nil}
|
177
230
|
assert_equal 0, client.affected_rows
|
178
|
-
client.update 'test01',{:v_int1=>4},
|
231
|
+
client.update 'test01',{:v_int1=>4},{:v_int1=>3,:v_int2=>nil}
|
232
|
+
assert_equal 2, client.affected_rows
|
233
|
+
client.update 'test01',{:v_int1=>4},{:v_int1=>3,:v_int2=>3}
|
234
|
+
assert_equal 1, client.affected_rows
|
235
|
+
|
236
|
+
client.update 'test01',{:v_int1=>5},{:v_int1=>[1,2,3,4],:v_int2=>3}
|
237
|
+
assert_equal 1, client.affected_rows
|
238
|
+
|
239
|
+
client.update 'test01',{:v_int1=>6},client.update_all_flag
|
179
240
|
assert_equal 3, client.affected_rows
|
180
241
|
|
181
242
|
client.close
|
@@ -189,9 +250,12 @@ CREATE TABLE IF NOT EXISTS `#{table}` (
|
|
189
250
|
assert_raise(ArgumentError){
|
190
251
|
client.update 'test01',{:v_int1=>3},nil
|
191
252
|
}
|
253
|
+
assert_raise(ArgumentError){
|
254
|
+
client.update 'test01',{:v_int1=>3},''
|
255
|
+
}
|
192
256
|
|
193
257
|
assert_raise(Mysql2::Error){
|
194
|
-
client.update 'test01',{:
|
258
|
+
client.update 'test01',{:v_int5=>3},Mysql2wrapper::Client::UPDATE_ALL
|
195
259
|
}
|
196
260
|
end
|
197
261
|
|
@@ -206,6 +270,7 @@ CREATE TABLE IF NOT EXISTS `#{table}` (
|
|
206
270
|
client.close
|
207
271
|
end
|
208
272
|
|
273
|
+
|
209
274
|
def test_tranasction_simple
|
210
275
|
client = get_client
|
211
276
|
insert(client)
|
@@ -270,6 +335,44 @@ CREATE TABLE IF NOT EXISTS `#{table}` (
|
|
270
335
|
client2.close
|
271
336
|
end
|
272
337
|
|
338
|
+
def test_tranasction_nest
|
339
|
+
client = get_client
|
340
|
+
assert_raise(StandardError) do
|
341
|
+
client.transaction do
|
342
|
+
client.transaction do
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def test_blob
|
349
|
+
client = get_client
|
350
|
+
f = File.binread(TEST_IMAGE)
|
351
|
+
@i = 0
|
352
|
+
hash = {
|
353
|
+
:v_int1 => proc{ @i+=1 },
|
354
|
+
:v_int2 => 246,
|
355
|
+
:v_int3 => nil,
|
356
|
+
:v_str1=>"te'st日本語",
|
357
|
+
:v_str2=>"CONCAT('My','S','QL')".to_func,
|
358
|
+
:v_str3 => nil,
|
359
|
+
:v_bool1 => true,
|
360
|
+
:v_bool2 => false,
|
361
|
+
:v_bool3 => nil,
|
362
|
+
:v_date1 => Date.new(2000,1,2),
|
363
|
+
:v_date2 => nil,
|
364
|
+
:v_datetime1 => DateTime.new(2000,1,2,3,4,5),
|
365
|
+
:v_datetime2 => nil,
|
366
|
+
:v_time1 => Time.mktime(2000,1,2,3,4,5),
|
367
|
+
:v_time2 => nil,
|
368
|
+
:v_blob1 => f,
|
369
|
+
:created_at => 'NOW()'.to_func,
|
370
|
+
}
|
371
|
+
client.insert('test02',hash)
|
372
|
+
row = client.select('test02','*').first
|
373
|
+
assert_equal f, row['v_blob1']
|
374
|
+
end
|
375
|
+
|
273
376
|
def test_insert
|
274
377
|
client = get_client
|
275
378
|
@i = 0
|
@@ -379,4 +482,149 @@ CREATE TABLE IF NOT EXISTS `#{table}` (
|
|
379
482
|
assert_equal 2,client_master.count('tbl_master')
|
380
483
|
assert_equal 1,client_slave.count('tbl_slave')
|
381
484
|
end
|
485
|
+
|
486
|
+
def test_tables
|
487
|
+
client = get_client
|
488
|
+
assert_equal 2, client.tables.size
|
489
|
+
client.tables.each do |table_name|
|
490
|
+
assert %w|test01 test02|.include?(table_name)
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
def test_table_names
|
495
|
+
client = get_client
|
496
|
+
assert_equal 2, client.tables.size
|
497
|
+
client.tables.each do |table_name|
|
498
|
+
assert %w|test01 test02|.include?(table_name)
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
def test_config_from_yml
|
503
|
+
end
|
504
|
+
|
505
|
+
def test_table_informations
|
506
|
+
client = get_client
|
507
|
+
table_informations = client.table_informations
|
508
|
+
assert_equal 2, table_informations.size
|
509
|
+
table_informations.each do |hash|
|
510
|
+
assert %w|test01 test02|.include?(hash['TABLE_NAME'])
|
511
|
+
assert_not_nil hash['COLUMNS']
|
512
|
+
assert_not_nil hash['INDEXES']
|
513
|
+
assert_not_nil hash['CREATE TABLE']
|
514
|
+
case hash['TABLE_NAME']
|
515
|
+
when 'test02'
|
516
|
+
assert_equal 25, hash['COLUMNS'].size
|
517
|
+
assert_equal 2, hash['INDEXES'].size
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
def test_databases
|
523
|
+
client = get_client
|
524
|
+
databases = client.databases
|
525
|
+
assert_equal true, databases.include?('information_schema')
|
526
|
+
assert_equal false,databases.include?('tbl_master')
|
527
|
+
assert_equal true, databases.include?('mysql2wrapper_test')
|
528
|
+
assert_equal true, databases.include?('mysql2wrapper_test_master')
|
529
|
+
assert_equal true, databases.include?('mysql2wrapper_test_slave')
|
530
|
+
end
|
531
|
+
|
532
|
+
def test_array_select_one_must
|
533
|
+
ar = [1,2,2,3]
|
534
|
+
assert_equal 1,ar.select_one_must{|o|o == 1}
|
535
|
+
assert_equal 3,ar.select_one_must{|o|o == 3}
|
536
|
+
assert_raise StandardError do
|
537
|
+
ar.select_one_must{|o|o == 2}
|
538
|
+
end
|
539
|
+
assert_raise StandardError do
|
540
|
+
ar.select_one_must{|o|o == 4}
|
541
|
+
end
|
542
|
+
|
543
|
+
ar = [{:id=>1,:i=>1},{:id=>2,:i=>2}]
|
544
|
+
assert_equal ({:id=>1,:i=>1}),ar.select_one_must{|o|o[:id] == 1}
|
545
|
+
end
|
546
|
+
|
547
|
+
def test_mysql2_result_select_one_must
|
548
|
+
client = get_client
|
549
|
+
client.insert('test01',{:id=>1,:v_int1=>1,:created_at=>'NOW()'.to_func})
|
550
|
+
client.insert('test01',{:id=>2,:v_int1=>2,:created_at=>'NOW()'.to_func})
|
551
|
+
client.insert('test01',{:id=>3,:v_int1=>2,:created_at=>'NOW()'.to_func})
|
552
|
+
client.insert('test01',{:id=>4,:v_int1=>3,:created_at=>'NOW()'.to_func})
|
553
|
+
rows = client.query('select * from test01')
|
554
|
+
assert_equal 1, rows.select_one_must{|o|o['id'] == 1}['v_int1']
|
555
|
+
assert_equal 2, rows.select_one_must{|o|o['id'] == 3}['v_int1']
|
556
|
+
assert_raise StandardError do
|
557
|
+
rows.select_one_must{|o|o['v_int1'] == 2}
|
558
|
+
end
|
559
|
+
assert_raise StandardError do
|
560
|
+
rows.select_one_must{|o|o['v_int1'] == 4}
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
|
565
|
+
#
|
566
|
+
# http://info.dwango.co.jp/rd/2010/01/mysql.html
|
567
|
+
#
|
568
|
+
def test_queue
|
569
|
+
sample_row_size = 1000
|
570
|
+
client = get_client
|
571
|
+
ar = []
|
572
|
+
sample_row_size.times do
|
573
|
+
ar << {:v_int1=>1,:created_at=>'NOW()'.to_func}
|
574
|
+
end
|
575
|
+
client.insert('test01',ar)
|
576
|
+
|
577
|
+
assert_equal sample_row_size, client.count('test01')
|
578
|
+
|
579
|
+
cnt = 0
|
580
|
+
12.times do
|
581
|
+
threads = []
|
582
|
+
(sample_row_size / 10).times do
|
583
|
+
threads << Thread.new do
|
584
|
+
Thread.pass
|
585
|
+
th_client = get_client
|
586
|
+
query = '
|
587
|
+
UPDATE
|
588
|
+
test01
|
589
|
+
SET
|
590
|
+
id = LAST_INSERT_ID(id),
|
591
|
+
v_int1 = 2
|
592
|
+
WHERE
|
593
|
+
v_int1 = 1
|
594
|
+
ORDER BY id
|
595
|
+
LIMIT 1
|
596
|
+
'
|
597
|
+
th_client.query(query)
|
598
|
+
query = 'SELECT LAST_INSERT_ID() as last_id'
|
599
|
+
processing_id = th_client.query(query).first['last_id']
|
600
|
+
#puts processing_id
|
601
|
+
if processing_id != 0
|
602
|
+
begin
|
603
|
+
th_client.transaction do
|
604
|
+
query = "UPDATE test01 SET v_int2 = v_int2 + 1 WHERE id = #{processing_id}"
|
605
|
+
th_client.query(query)
|
606
|
+
end
|
607
|
+
rescue
|
608
|
+
end
|
609
|
+
begin
|
610
|
+
th_client.transaction do
|
611
|
+
query = "UPDATE test01 SET v_int2 = v_int2 + 1 WHERE id = #{processing_id}"
|
612
|
+
th_client.query(query)
|
613
|
+
raise 'koko'
|
614
|
+
end
|
615
|
+
rescue
|
616
|
+
end
|
617
|
+
query = "UPDATE test01 SET v_int2 = v_int2 + 1 WHERE id = #{processing_id}"
|
618
|
+
th_client.query(query)
|
619
|
+
cnt += 1
|
620
|
+
end
|
621
|
+
th_client.close
|
622
|
+
end
|
623
|
+
end
|
624
|
+
threads.each do |th|
|
625
|
+
th.join
|
626
|
+
end
|
627
|
+
end
|
628
|
+
assert_equal sample_row_size, cnt
|
629
|
+
end
|
382
630
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mysql2wrapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mysql2
|
@@ -42,11 +42,14 @@ files:
|
|
42
42
|
- config/database.yml
|
43
43
|
- config/database_multiple.yml
|
44
44
|
- example/sample.rb
|
45
|
+
- example/sample_table_information.rb
|
45
46
|
- lib/mysql2wrapper.rb
|
46
47
|
- lib/mysql2wrapper/client.rb
|
48
|
+
- lib/mysql2wrapper/core_ext.rb
|
47
49
|
- lib/mysql2wrapper/version.rb
|
48
50
|
- mysql2wrapper.gemspec
|
49
51
|
- test/by_hand.rb
|
52
|
+
- test/sample_datas/image.jpeg
|
50
53
|
- test/test.rb
|
51
54
|
- test/test_helper.rb
|
52
55
|
homepage: ''
|
@@ -75,6 +78,7 @@ specification_version: 3
|
|
75
78
|
summary: oreore mysql2 wrapper class
|
76
79
|
test_files:
|
77
80
|
- test/by_hand.rb
|
81
|
+
- test/sample_datas/image.jpeg
|
78
82
|
- test/test.rb
|
79
83
|
- test/test_helper.rb
|
80
84
|
has_rdoc:
|