jdbc-helper 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,29 @@
1
+ # encoding: UTF-8
2
+ # Junegunn Choi (junegunn.c@gmail.com)
3
+
4
+ module JDBCHelper
5
+ # Shortcut connector for Oracle
6
+ module OracleConnector
7
+ include Constants
8
+ include Constants::Connector
9
+
10
+ def self.connect(host, user, password, service_name, timeout = DEFAULT_LOGIN_TIMEOUT)
11
+ Connection.new(
12
+ :driver => JDBC_DRIVER[:oracle],
13
+ :url => "jdbc:oracle:thin:@#{host}/#{service_name}",
14
+ :user => user,
15
+ :password => password,
16
+ :timeout => timeout)
17
+ end
18
+
19
+ def self.connect_by_sid(host, user, password, sid, timeout = DEFAULT_LOGIN_TIMEOUT)
20
+ Connection.new(
21
+ :driver => JDBC_DRIVER[:oracle],
22
+ :url => "jdbc:oracle:thin:@#{host}:#{sid}",
23
+ :user => user,
24
+ :password => password,
25
+ :timeout => timeout)
26
+ end
27
+ end#OracleConnector
28
+ end#JDBCHelper
29
+
@@ -0,0 +1,26 @@
1
+ # encoding: UTF-8
2
+ # Junegunn Choi (junegunn.c@gmail.com)
3
+
4
+ module JDBCHelper
5
+ module Constants
6
+ # Default login timeout is set to 60 seconds
7
+ DEFAULT_LOGIN_TIMEOUT = 60
8
+
9
+ # Constants only for Connectors
10
+ module Connector
11
+ JDBC_DRIVER = {
12
+ :oracle => 'oracle.jdbc.driver.OracleDriver',
13
+ :mysql => 'com.mysql.jdbc.Driver'
14
+ }
15
+
16
+ DEFAULT_PARAMETERS = {
17
+ :mysql => {
18
+ 'zeroDateTimeBehavior' => 'convertToNull',
19
+ 'rewriteBatchedStatements' => 'true',
20
+ 'useServerPrepStmts' => 'true',
21
+ 'useCursorFetch' => 'true'
22
+ }
23
+ }
24
+ end#Connector
25
+ end#Constants
26
+ end#JDBCHelper
data/test/database.yml ADDED
@@ -0,0 +1,13 @@
1
+ ---
2
+ mysql:
3
+ driver: com.mysql.jdbc.Driver
4
+ url: jdbc:mysql://localhost/test
5
+ user: mysql
6
+ password:
7
+
8
+ # oracle:
9
+ # driver: com.mysql.jdbc.Driver
10
+ # url: jdbc:mysql://localhost/test
11
+ # user: mysql
12
+ # password:
13
+
data/test/helper.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ require 'jdbc-helper'
15
+
16
+ class Test::Unit::TestCase
17
+ end
@@ -0,0 +1,292 @@
1
+ require 'helper'
2
+
3
+ class TestJdbcHelper < Test::Unit::TestCase
4
+ def setup
5
+ require 'yaml'
6
+ @config = YAML.load File.read(File.dirname(__FILE__) + '/database.yml')
7
+ end
8
+
9
+ def teardown
10
+
11
+ end
12
+
13
+ TEST_TABLE = 'tmp_jdbc_helper_test'
14
+
15
+ def each_connection
16
+ @config.each do | db, conn_info |
17
+ conn = JDBCHelper::Connection.new(conn_info)
18
+ begin
19
+ yield conn
20
+ ensure
21
+ conn.close
22
+ end
23
+ end
24
+ end
25
+
26
+ def get_one_two
27
+ "
28
+ select 1 one, 'two' two from dual
29
+ union all
30
+ select 1 one, 'two' two from dual
31
+ "
32
+ end
33
+
34
+ def check_one_two(rec)
35
+ assert_equal 2, rec.length
36
+
37
+ assert_equal 1, rec.one
38
+ assert_equal 1, rec[0]
39
+ assert_equal 1, rec['one']
40
+
41
+ assert_equal 'two', rec.two
42
+ assert_equal 'two', rec[1]
43
+ assert_equal 'two', rec['two']
44
+
45
+ assert_raise(NameError) { rec.three }
46
+ assert_raise(NameError) { rec['three'] }
47
+ assert_raise(RangeError) { rec[3] }
48
+ end
49
+
50
+ def reset_test_table conn
51
+ conn.update "drop table #{TEST_TABLE}" rescue nil
52
+ cnt = conn.update '
53
+ create table tmp_jdbc_helper_test (
54
+ a int primary key,
55
+ b varchar(100)
56
+ )'
57
+ assert_equal 0, cnt
58
+ end
59
+
60
+ # ---------------------------------------------------------------
61
+
62
+ def test_connect_and_close
63
+ @config.each do | db, conn_info |
64
+ 4.times do | i |
65
+ # With or without timeout parameter
66
+ conn_info['timeout'] = 60 if i % 2 == 1
67
+
68
+ # Can connect with hash with symbol keys?
69
+ conn_info.keys.each do | str_key |
70
+ conn_info[str_key.to_sym] = conn_info.delete str_key
71
+ end if i % 2 == 0
72
+
73
+ conn = JDBCHelper::Connection.new(conn_info)
74
+ assert_equal(conn.closed?, false)
75
+ conn.close
76
+ assert_equal(conn.closed?, true)
77
+ [ :query, :update, :add_batch, :prepare ].each do | met |
78
+ assert_raise(RuntimeError) { conn.send met, "A" }
79
+ end
80
+ [ :execute_batch, :clear_batch ].each do | met |
81
+ assert_raise(RuntimeError) { conn.send met }
82
+ end
83
+
84
+ # initialize with execution block
85
+ conn = JDBCHelper::Connection.new(conn_info) do | c |
86
+ c.query('select 1 from dual')
87
+ assert_equal c.closed?, false
88
+ end
89
+ assert conn.closed?
90
+ end
91
+ end
92
+ end
93
+
94
+ def test_query_enumerate
95
+ each_connection do | conn |
96
+ # Query without a block => Array
97
+ query_result = conn.query get_one_two
98
+ assert query_result.is_a? Array
99
+ assert_equal 2, query_result.length
100
+ check_one_two(query_result.first)
101
+
102
+ # Query with a block
103
+ count = 0
104
+ conn.query(get_one_two) do | row |
105
+ check_one_two row
106
+ count += 1
107
+ end
108
+ assert_equal 2, count
109
+
110
+ # Enumerate
111
+ enum = conn.enumerate(get_one_two)
112
+ assert enum.is_a? Enumerable
113
+ assert enum.closed? == false
114
+ a = enum.to_a
115
+ assert_equal 2, a.length
116
+ check_one_two a.first
117
+ assert enum.closed? == true
118
+ end
119
+ end
120
+
121
+ def test_update_batch
122
+ each_connection do | conn |
123
+ reset_test_table conn
124
+ count = 100
125
+
126
+ iq = lambda do | i |
127
+ "insert into #{TEST_TABLE} values (#{i}, 'A')"
128
+ end
129
+
130
+ # update
131
+ assert_equal 1, conn.update(iq.call 0)
132
+ assert_equal 1, conn.prev_stat.success_count
133
+
134
+ # add_batch execute_batch
135
+ reset_test_table conn
136
+
137
+ count.times do | p |
138
+ conn.add_batch iq.call(p)
139
+ end
140
+ conn.execute_batch
141
+ assert_equal count, conn.query("select count(*) from #{TEST_TABLE}")[0][0]
142
+
143
+ # add_batch clear_batch
144
+ reset_test_table conn
145
+
146
+ count.times do | p |
147
+ conn.add_batch iq.call(p)
148
+ end
149
+ conn.clear_batch
150
+ assert_equal 0, conn.query("select count(*) from #{TEST_TABLE}")[0][0]
151
+ end
152
+ end
153
+
154
+ def test_prepared_query_enumerate
155
+ each_connection do | conn |
156
+ sel = conn.prepare get_one_two
157
+ assert sel.closed? == false
158
+
159
+ # Query without a block => Array
160
+ query_result = sel.query
161
+ assert query_result.is_a? Array
162
+ assert_equal 2, query_result.length
163
+ check_one_two(query_result.first)
164
+
165
+ # Query with a block
166
+ count = 0
167
+ sel.query do | row |
168
+ check_one_two row
169
+ count += 1
170
+ end
171
+ assert_equal 2, count
172
+
173
+ # Enumerate
174
+ enum = sel.enumerate
175
+ assert enum.is_a? Enumerable
176
+ assert enum.closed? == false
177
+ a = enum.to_a
178
+ assert_equal 2, a.length
179
+ check_one_two a.first
180
+ assert enum.closed? == true
181
+
182
+ sel.close
183
+ assert sel.closed?
184
+ [ :query, :update, :add_batch, :execute_batch, :clear_batch ].each do | met |
185
+ assert_raise(RuntimeError) { sel.send met }
186
+ end
187
+ end
188
+ end
189
+
190
+ def test_prepared_update_batch
191
+ each_connection do | conn |
192
+ reset_test_table conn
193
+ ins = conn.prepare "insert into #{TEST_TABLE} values (?, ?)"
194
+ count = 100
195
+
196
+ # update
197
+ assert ins.closed? == false
198
+ assert_equal 1, ins.update(0, 'A')
199
+ assert_equal 1, conn.prev_stat.success_count
200
+ ins.close
201
+
202
+ # add_batch execute_batch
203
+ reset_test_table conn
204
+ ins = conn.prepare "insert into #{TEST_TABLE} values (?, ?)"
205
+
206
+ count.times do | p |
207
+ ins.add_batch(p + 1, 'A')
208
+ end
209
+ ins.execute_batch
210
+ assert_equal count, conn.query("select count(*) from #{TEST_TABLE}")[0][0]
211
+ ins.close
212
+
213
+ # add_batch clear_batch
214
+ reset_test_table conn
215
+ ins = conn.prepare "insert into #{TEST_TABLE} values (?, ?)"
216
+
217
+ count.times do | p |
218
+ ins.add_batch(p + 1, 'A')
219
+ end
220
+ ins.clear_batch
221
+ assert_equal 0, conn.query("select count(*) from #{TEST_TABLE}")[0][0]
222
+
223
+ # close closed?
224
+ assert ins.closed? == false
225
+ ins.close
226
+ assert ins.closed?
227
+ [ :query, :update, :add_batch, :execute_batch, :clear_batch ].each do | met |
228
+ assert_raise(RuntimeError) { ins.send met }
229
+ end
230
+ end
231
+ end
232
+
233
+ def test_transaction
234
+ each_connection do | conn |
235
+ reset_test_table conn
236
+ count = 100
237
+
238
+ 3.times do | i |
239
+ sum = 0
240
+ conn.update "delete from #{TEST_TABLE}"
241
+ conn.transaction do | tx |
242
+ count.times.each_slice(10) do | slice |
243
+ slice.each do | p |
244
+ conn.add_batch("insert into #{TEST_TABLE} values (#{p}, 'xxx')")
245
+ sum += p
246
+ end
247
+ conn.execute_batch
248
+ end
249
+ result = conn.query("select count(*), sum(a) from #{TEST_TABLE}").first
250
+
251
+ assert_equal count, result.first
252
+ assert_equal sum, result.last.to_i
253
+
254
+ case i
255
+ when 0 then tx.rollback
256
+ when 1 then tx.commit
257
+ else
258
+ nil # committed implicitly
259
+ end
260
+
261
+ flunk 'This should not be executed' if i < 2
262
+ end
263
+
264
+ assert_equal (i == 0 ? 0 : count),
265
+ conn.query("select count(*) from #{TEST_TABLE}").first.first
266
+ end
267
+ end
268
+ end
269
+
270
+ def test_connectors
271
+ @config.each do | db, conn_info |
272
+ if db == 'mysql'
273
+ host = conn_info['url'].match(%r{//(.*?)/})[1]
274
+ db = conn_info['url'].match(%r{/([^/?]*?)(\?.*)?$})[1]
275
+ conn = JDBCHelper::MySQLConnector.connect(host, conn_info['user'], conn_info['password'], db)
276
+
277
+ assert conn.closed? == false
278
+ conn.close
279
+ assert conn.closed?
280
+ elsif db == 'oracle'
281
+ host = conn_info['url'].match(%r{//(.*?)/})[1]
282
+ svc = conn_info['url'].match(%r{/([^/?]*?)(\?.*)?$})[1]
283
+ conn = JDBCHelper::OracleConnector.connect(host, conn_info['user'], conn_info['password'], svc)
284
+
285
+ assert conn.closed? == false
286
+ conn.close
287
+ assert conn.closed?
288
+ end
289
+ end
290
+ end
291
+ end
292
+
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jdbc-helper
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.2
6
+ platform: ruby
7
+ authors:
8
+ - Junegunn Choi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-04-01 00:00:00 +09:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: bundler
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: 1.0.0
25
+ type: :development
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: jeweler
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: 1.5.2
36
+ type: :development
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: rcov
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id003
49
+ description: JDBCHelper::Connection object wraps around a JDBC connection and provides much nicer interface to crucial database operations from primitive selects and updates to more complex ones involving batch updates, prepared statements and transactions.
50
+ email: junegunn.c@gmail.com
51
+ executables: []
52
+
53
+ extensions: []
54
+
55
+ extra_rdoc_files:
56
+ - LICENSE.txt
57
+ - README.rdoc
58
+ files:
59
+ - lib/jdbc-helper.rb
60
+ - lib/jdbc-helper/connection.rb
61
+ - lib/jdbc-helper/connection/prepared_statement.rb
62
+ - lib/jdbc-helper/connection/result_set_enumerator.rb
63
+ - lib/jdbc-helper/connection/row.rb
64
+ - lib/jdbc-helper/connection/statement_pool.rb
65
+ - lib/jdbc-helper/connector.rb
66
+ - lib/jdbc-helper/connector/mysql_connector.rb
67
+ - lib/jdbc-helper/connector/oracle_connector.rb
68
+ - lib/jdbc-helper/constants.rb
69
+ - LICENSE.txt
70
+ - README.rdoc
71
+ - test/database.yml
72
+ - test/helper.rb
73
+ - test/test_jdbc-helper.rb
74
+ has_rdoc: true
75
+ homepage: http://github.com/junegunn/jdbc-helper
76
+ licenses:
77
+ - MIT
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ requirements: []
96
+
97
+ rubyforge_project:
98
+ rubygems_version: 1.5.1
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: A JDBC helper for Ruby/Database developers
102
+ test_files:
103
+ - test/database.yml
104
+ - test/helper.rb
105
+ - test/test_jdbc-helper.rb