jdbc-helper 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +20 -0
- data/README.rdoc +114 -0
- data/lib/jdbc-helper.rb +21 -0
- data/lib/jdbc-helper/connection.rb +395 -0
- data/lib/jdbc-helper/connection/prepared_statement.rb +141 -0
- data/lib/jdbc-helper/connection/result_set_enumerator.rb +100 -0
- data/lib/jdbc-helper/connection/row.rb +110 -0
- data/lib/jdbc-helper/connection/statement_pool.rb +61 -0
- data/lib/jdbc-helper/connector.rb +6 -0
- data/lib/jdbc-helper/connector/mysql_connector.rb +28 -0
- data/lib/jdbc-helper/connector/oracle_connector.rb +29 -0
- data/lib/jdbc-helper/constants.rb +26 -0
- data/test/database.yml +13 -0
- data/test/helper.rb +17 -0
- data/test/test_jdbc-helper.rb +292 -0
- metadata +105 -0
@@ -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
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
|