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 CHANGED
@@ -1,5 +1,7 @@
1
+ .DS_Store
1
2
  *.gem
2
3
  *.rbc
4
+ *.lock
3
5
  .bundle
4
6
  .config
5
7
  coverage
@@ -1,17 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mysql2wrapper (0.0.1)
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
@@ -1,6 +1,10 @@
1
- mysql2wrapper
1
+ #mysql2wrapper
2
2
  =============
3
3
 
4
4
  very simple mysql2 wrapper.
5
5
  it's ore ore library!
6
6
 
7
+ ## TODO
8
+
9
+ ActiveSupportのHashWithIndifferentAccess的なものをかませるか?
10
+
@@ -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 `hoges`'
25
+ DROP TABLE IF EXISTS `test01`'
25
26
  client.query query
26
27
  query = '
27
- CREATE TABLE IF NOT EXISTS `hoges` (
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
- logger.info "hoge has #{client.count 'hoges'}rows"
37
- client.query "INSERT INTO hoges (value1,created_at)VALUES(#{Time.now.to_i},NOW())"
38
- logger.info "hoge has #{client.count 'hoges'}rows"
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 "hoge has #{client.count 'hoges'}rows"
44
- client.query "INSERT INTO hoges (value1,created_at)VALUES(#{Time.now.to_i},NOW())"
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 "hoge has #{client.count 'hoges'}rows"
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 "hoge has #{client.count 'hoges'}rows"
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('hoges',hash)
71
+ client.insert('test01',hash)
60
72
  logger.info "affected_rows:#{client.affected_rows}"
61
- logger.info "hoge has #{client.count 'hoges'}rows"
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('hoges',ar)
78
+ client.insert('test01',ar)
67
79
  logger.info "affected_rows:#{client.affected_rows}" # Client#affected_rowsでマルチプルインサートのトータルインサート数が取れる
68
- logger.info "hoge has #{client.count 'hoges'}rows"
80
+ logger.info "test01 has #{client.count 'test01'}rows"
69
81
 
70
82
  # ハッシュを引数にしたアップデート
71
- client.update 'hoges',{:value1=>3},'id = 1'
72
- logger.info "hoge has #{client.count 'hoges'}rows"
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 'hoges',{:value1=>3},Mysql2wrapper::Client::UpdateAllClass
86
+ client.update 'test01',{:value1=>3},Mysql2wrapper::Client::UpdateAllClass
75
87
  # clientインスタンスにショートカットあり
76
- client.update 'hoges',{:value1=>4},client.update_all_flag
77
- logger.info "hoge has #{client.count 'hoges'}rows"
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
+
@@ -1,4 +1,5 @@
1
1
  require "mysql2wrapper/version"
2
+ require "mysql2wrapper/core_ext"
2
3
  require "mysql2wrapper/client"
3
4
 
4
5
  class String
@@ -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
- self.logger.info "mysql2 client created with #{config.inspect}"
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(str,color=QUERY_BASE_COLOR)
56
- res = self.class.query(self.client,str,self.logger,color)
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("SELECT COUNT(#{escape(key_name)}) AS cnt FROM #{escape(table_name)}").first['cnt']
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 String
108
- where = "WHERE #{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
- }" + where
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
- else
143
- s = value
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
- "'#{escape(value.to_s)}'"
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 = self.make_config_key_symbol(db_config[db_server_name])
198
- else
199
- db_config = self.make_config_key_symbol(db_config)
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
- db_config
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
@@ -1,3 +1,3 @@
1
1
  module Mysql2wrapper
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -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
- query = "INSERT INTO test01 (v_int1,created_at)VALUES(#{Time.now.to_i},NOW())"
117
- client.query query
118
- assert_equal 1,client.count('test01','id')
119
- query = "INSERT INTO test01 (v_int1,created_at)VALUES(#{Time.now.to_i},NOW())"
120
- client.query query
121
- assert_equal 2,client.count('test01','id')
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},client.update_all_flag
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',{:v_int1=>3},''
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.1
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-10-11 00:00:00.000000000 Z
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: