jdbc-helper 0.7.7 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/{CHANGELOG.markdown → CHANGELOG.md} +14 -0
- data/{README.markdown → README.md} +82 -92
- data/jdbc-helper.gemspec +1 -0
- data/lib/jdbc-helper/connection/prepared_statement.rb +11 -14
- data/lib/jdbc-helper/connection/{result_set_enumerator.rb → result_set.rb} +39 -42
- data/lib/jdbc-helper/connection.rb +23 -59
- data/lib/jdbc-helper/connector/mariadb.rb +24 -0
- data/lib/jdbc-helper/connector/sqlite.rb +19 -0
- data/lib/jdbc-helper/connector.rb +2 -0
- data/lib/jdbc-helper/constants.rb +6 -0
- data/lib/jdbc-helper/sql/expression.rb +21 -79
- data/lib/jdbc-helper/sql/sql.rb +30 -91
- data/lib/jdbc-helper/sql/sql_prepared.rb +31 -122
- data/lib/jdbc-helper/version.rb +1 -1
- data/lib/jdbc-helper/wrapper/function_wrapper.rb +1 -1
- data/lib/jdbc-helper/wrapper/sequence_wrapper.rb +2 -2
- data/lib/jdbc-helper/wrapper/table_wrapper.rb +68 -43
- data/lib/jdbc-helper.rb +1 -0
- data/test/helper.rb +1 -1
- data/test/test_connection.rb +70 -15
- data/test/test_object_wrapper.rb +22 -9
- data/test/test_object_wrapper_0.7.rb +737 -0
- data/test/test_sql.rb +50 -53
- metadata +43 -31
@@ -1,3 +1,17 @@
|
|
1
|
+
### 0.8.0
|
2
|
+
|
3
|
+
0.8.0 introduces a few backward-incompatible changes.
|
4
|
+
|
5
|
+
* `Connection#ResultSetEnumerator` is renamed to `Connection::ResultSet`
|
6
|
+
* `Connection#query` method will return a ResultSet object instead of an Array
|
7
|
+
* `Connection#enumerate` method is now retired, and just a synonym for query method
|
8
|
+
* Partially consumed ResultSet must be closed explicitly
|
9
|
+
* `ResultSet#each` method will return an enumerator when block is not given
|
10
|
+
* Refined TableWrapper interface with external [sql_helper](https://github.com/junegunn/sql_helper) gem
|
11
|
+
* The use of `JDBCHelper::SQL` is deprecated
|
12
|
+
* Added MariaDB connector
|
13
|
+
* Added SQLite connector
|
14
|
+
|
1
15
|
### 0.7.7 / 2013/01/0?
|
2
16
|
* `PreparedStatment`s and `TableWrapper`s now inherit the fetch size of the connection
|
3
17
|
* Added `JDBCHelper::TableWrapper#fetch_size`
|
@@ -42,17 +42,17 @@ require 'jdbc-helper'
|
|
42
42
|
```ruby
|
43
43
|
# :driver and :url must be given
|
44
44
|
conn = JDBCHelper::Connection.new(
|
45
|
-
:
|
46
|
-
:
|
45
|
+
driver: 'com.mysql.jdbc.Driver',
|
46
|
+
url: 'jdbc:mysql://localhost/test')
|
47
47
|
conn.close
|
48
48
|
|
49
49
|
|
50
50
|
# Optional :user and :password
|
51
51
|
conn = JDBCHelper::Connection.new(
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
52
|
+
driver: 'com.mysql.jdbc.Driver',
|
53
|
+
url: 'jdbc:mysql://localhost/test',
|
54
|
+
user: 'mysql',
|
55
|
+
password: password)
|
56
56
|
conn.close
|
57
57
|
```
|
58
58
|
|
@@ -61,39 +61,32 @@ conn.close
|
|
61
61
|
jdbc-helper provides shortcut connectors for the following databases
|
62
62
|
so that you don't have to specify lengthy class names and JDBC URLs.
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
64
|
+
- MySQL (`JDBCHelper::MySQL`)
|
65
|
+
- MariaDB (`JDBCHelper::MariaDB`)
|
66
|
+
- Oracle (`JDBCHelper::Oracle`)
|
67
|
+
- PostgreSQL (`JDBCHelper::PostgreSQL`)
|
68
|
+
- MS SQL Server (`JDBCHelper::MSSQL`)
|
69
|
+
- Cassandra (`JDBCHelper::Cassandra`)
|
70
|
+
- FileMaker Pro (`JDBCHelper::FileMaker`)
|
71
|
+
- SQLite (`JDBCHelper::SQLite`)
|
70
72
|
|
71
73
|
```ruby
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
#
|
82
|
-
|
83
|
-
|
84
|
-
# Cassandra CQL3 connector
|
85
|
-
cc = JDBCHelper::Cassandra.connect(host, keyspace)
|
86
|
-
|
87
|
-
# FileMaker Pro shortcut connector
|
88
|
-
fmp = JDBCHelper::FileMaker.connect(host, user, password, db)
|
89
|
-
|
90
|
-
# Extra parameters
|
91
|
-
mc = JDBCHelper::MySQL.connect(host, user, password, db,
|
92
|
-
:rewriteBatchedStatements => true)
|
74
|
+
mysql = JDBCHelper::MySQL.connect(host, user, password, db)
|
75
|
+
mariadb = JDBCHelper::MariaDB.connect(host, user, password, db)
|
76
|
+
oracle = JDBCHelper::Oracle.connect(host, user, password, service_name)
|
77
|
+
postgres = JDBCHelper::PostgreSQL.connect(host, user, password, db)
|
78
|
+
mssql = JDBCHelper::MSSQL.connect(host, user, password, db)
|
79
|
+
cassandra = JDBCHelper::Cassandra.connect(host, keyspace)
|
80
|
+
filemaker = JDBCHelper::FileMaker.connect(host, user, password, db)
|
81
|
+
sqlite = JDBCHelper::SQLite.connect(file_path)
|
82
|
+
|
83
|
+
# With extra parameters
|
84
|
+
mysql = JDBCHelper::MySQL.connect(host, user, password, db,
|
85
|
+
rewriteBatchedStatements: true)
|
93
86
|
|
94
87
|
# With connection timeout of 30 seconds
|
95
|
-
|
96
|
-
|
88
|
+
mysql = JDBCHelper::MySQL.connect(host, user, password, db,
|
89
|
+
rewriteBatchedStatements: true, timeout: 30)
|
97
90
|
|
98
91
|
# When block is given, connection is automatically closed after the block is executed
|
99
92
|
JDBCHelper::Cassandra.connect(host, keyspace) do |cc|
|
@@ -104,7 +97,7 @@ end
|
|
104
97
|
### Querying database table
|
105
98
|
|
106
99
|
```ruby
|
107
|
-
conn.query(
|
100
|
+
conn.query('SELECT a, b, c FROM T') do |row|
|
108
101
|
row.labels
|
109
102
|
row.rownum
|
110
103
|
|
@@ -120,23 +113,26 @@ conn.query("SELECT a, b, c FROM T") do |row|
|
|
120
113
|
row.to_h # Row as a Hash
|
121
114
|
end
|
122
115
|
|
123
|
-
# Returns an array of rows when block is not given
|
124
|
-
rows = conn.query("SELECT b FROM T")
|
125
|
-
uniq_rows = rows.uniq
|
126
|
-
|
127
116
|
# You can even nest queries
|
128
|
-
conn.query(
|
117
|
+
conn.query('SELECT a FROM T') do |row1|
|
129
118
|
conn.query("SELECT * FROM T_#{row1.a}") do |row2|
|
130
119
|
# ...
|
131
120
|
end
|
132
121
|
end
|
133
122
|
|
134
|
-
#
|
135
|
-
#
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
123
|
+
# Connection::ResultSet object is returned when block is not given
|
124
|
+
# - ResultSet is automatically closed when entirely iterated
|
125
|
+
rows = conn.query('SELECT * FROM T')
|
126
|
+
uniq_rows = rows.to_a.uniq
|
127
|
+
|
128
|
+
# However, partially consumed ResultSet objects *must be closed* manually
|
129
|
+
rset = conn.query('SELECT * FROM T')
|
130
|
+
rows = rset.take(2)
|
131
|
+
rset.close
|
132
|
+
|
133
|
+
# Enumerator chain
|
134
|
+
conn.query('SELECT * FROM LARGE_T').each_slice(1000).with_index do |slice, idx|
|
135
|
+
slice.each do |row|
|
140
136
|
# ...
|
141
137
|
end
|
142
138
|
end
|
@@ -144,17 +140,17 @@ end
|
|
144
140
|
|
145
141
|
### Updating database table
|
146
142
|
```ruby
|
147
|
-
del_count = conn.update(
|
143
|
+
del_count = conn.update('DELETE FROM T')
|
148
144
|
```
|
149
145
|
|
150
146
|
### Executing any SQL
|
151
147
|
```ruby
|
152
|
-
rset = conn.execute(
|
148
|
+
rset = conn.execute('SELECT * FROM T')
|
153
149
|
rset.each do |row|
|
154
150
|
# Returned result must be used or closed
|
155
151
|
end
|
156
152
|
|
157
|
-
del_count = conn.execute(
|
153
|
+
del_count = conn.execute('DELETE FROM T')
|
158
154
|
```
|
159
155
|
|
160
156
|
### Transaction
|
@@ -175,21 +171,21 @@ end
|
|
175
171
|
|
176
172
|
### Using batch interface
|
177
173
|
```ruby
|
178
|
-
conn.add_batch(
|
174
|
+
conn.add_batch('DELETE FROM T')
|
179
175
|
conn.execute_batch
|
180
|
-
conn.add_batch(
|
176
|
+
conn.add_batch('DELETE FROM T')
|
181
177
|
conn.clear_batch
|
182
178
|
```
|
183
179
|
|
184
180
|
### Using prepared statements
|
185
181
|
```ruby
|
186
|
-
p_sel = conn.prepare(
|
182
|
+
p_sel = conn.prepare('SELECT * FROM T WHERE b = ? and c = ?')
|
187
183
|
p_sel.query(100, 200) do |row|
|
188
184
|
p row
|
189
185
|
end
|
190
186
|
p_sel.close
|
191
187
|
|
192
|
-
p_upd = conn.prepare(
|
188
|
+
p_upd = conn.prepare('UPDATE T SET a = ? WHERE b = ?')
|
193
189
|
count = 0
|
194
190
|
100.times do |i|
|
195
191
|
count += p_upd.update('updated a', i)
|
@@ -213,9 +209,6 @@ pstmt.java.getMetaData
|
|
213
209
|
|
214
210
|
### Using table wrappers (since 0.2.0)
|
215
211
|
```ruby
|
216
|
-
# For more complex examples, refer to test/test_object_wrapper.rb
|
217
|
-
SQL = JDBCHelper::SQL
|
218
|
-
|
219
212
|
# Creates a table wrapper
|
220
213
|
table = conn.table('test.data')
|
221
214
|
# Or equievalently,
|
@@ -223,43 +216,43 @@ table = conn['test.data']
|
|
223
216
|
|
224
217
|
# Counting the records in the table
|
225
218
|
table.count
|
226
|
-
table.count(:
|
227
|
-
table.where(:
|
219
|
+
table.count(a: 10)
|
220
|
+
table.where(a: 10).count
|
228
221
|
|
229
222
|
table.empty?
|
230
|
-
table.where(:
|
223
|
+
table.where(a: 10).empty?
|
231
224
|
|
232
|
-
# Selects the table by combining select, where, order and fetch_size methods
|
233
|
-
table.select('a apple', :b).where(:
|
225
|
+
# Selects the table by combining select, where, order, limit and fetch_size methods
|
226
|
+
table.select('a apple', :b).where(c: (1..10)).order('b desc', 'a asc').fetch_size(100).limit(1000).each do |row|
|
234
227
|
puts row.apple
|
235
228
|
end
|
236
229
|
|
237
230
|
# Build select SQL
|
238
|
-
sql = table.select('a apple', :b).where(:
|
231
|
+
sql = table.select('a apple', :b).where(c: (1..10)).order('b desc', 'a asc').sql
|
239
232
|
|
240
233
|
# Updates with conditions
|
241
|
-
table.where(:
|
234
|
+
table.where(c: 3).update(a: 'hello', b: { sql: 'now()' })
|
242
235
|
|
243
236
|
# Insert into the table
|
244
|
-
table.insert(:
|
245
|
-
table.insert_ignore(:
|
246
|
-
table.replace(:
|
237
|
+
table.insert(a: 10, b: 20, c: { sql: '10 + 20' })
|
238
|
+
table.insert_ignore(a: 10, b: 20, c: 30)
|
239
|
+
table.replace(a: 10, b: 20, c: 30)
|
247
240
|
|
248
241
|
# Update with common default values
|
249
|
-
with_defaults = table.default(:
|
250
|
-
with_defaults.insert(:
|
242
|
+
with_defaults = table.default(a: 10, b: 20)
|
243
|
+
with_defaults.insert(c: 30)
|
251
244
|
with_defaults.where('a != 10 or b != 20').update # sets a => 10, b => 20
|
252
245
|
|
253
246
|
# Batch updates with batch method
|
254
|
-
table.batch.insert(:
|
255
|
-
table.batch.insert_ignore(:
|
256
|
-
table.batch.where(:
|
247
|
+
table.batch.insert(a: 10, b: 20, c: { sql: '10 + 20' })
|
248
|
+
table.batch.insert_ignore(a: 10, b: 20, c: 30)
|
249
|
+
table.batch.where(a: 10).update(a: 20)
|
257
250
|
table.execute_batch :insert, :update
|
258
251
|
|
259
252
|
# Delete with conditions
|
260
|
-
table.delete(:
|
253
|
+
table.delete(c: 3)
|
261
254
|
# Or equivalently,
|
262
|
-
table.where(:
|
255
|
+
table.where(c: 3).delete
|
263
256
|
|
264
257
|
# Truncate or drop table (Cannot be undone)
|
265
258
|
table.truncate!
|
@@ -268,26 +261,23 @@ table.drop!
|
|
268
261
|
|
269
262
|
#### Building complex where clauses
|
270
263
|
```ruby
|
271
|
-
# Shortcut. Or you can just include JDBCHelper
|
272
|
-
SQL = JDBCHelper::SQL
|
273
|
-
|
274
264
|
# With any number of Strings, Arrays and Hashes
|
275
265
|
scope = table.where(
|
276
|
-
"x <> 'hello'",
|
277
|
-
["y = ? or z > ?", 'abc', 10],
|
278
|
-
:
|
279
|
-
:
|
280
|
-
:
|
281
|
-
:
|
282
|
-
:
|
283
|
-
:
|
284
|
-
:
|
285
|
-
:
|
286
|
-
:
|
287
|
-
:
|
288
|
-
:
|
266
|
+
"x <> 'hello'", # x <> 'hello'
|
267
|
+
["y = ? or z > ?", 'abc', 10], # and (y = 'abc' or z > 10)
|
268
|
+
a: 'abc', # and a = 'abc'
|
269
|
+
b: (1..10), # and b between 1 and 10
|
270
|
+
c: (1...10), # and c >= 1 and c < 10
|
271
|
+
d: %w[a b c], # and d in ('a', 'b', 'c')
|
272
|
+
e: { sql: 'sysdate' }, # and e = sysdate
|
273
|
+
f: { not: nil }, # and f is not null
|
274
|
+
g: { gt: 100, le: 200 }, # and g > 100 and g <= 200
|
275
|
+
h: { lt: 100 }, # and h < 100
|
276
|
+
i: { like: 'ABC%' }, # and i like 'ABC%'
|
277
|
+
j: { not: { like: 'ABC%' } }, # and j not like 'ABC%'
|
278
|
+
k: { le: { sql: 'sysdate' } } # and k <= sysdate
|
289
279
|
)
|
290
|
-
scope.update(:
|
280
|
+
scope.update(a: 'xyz')
|
291
281
|
```
|
292
282
|
|
293
283
|
#### Invalid use of plain String conditions
|
@@ -353,7 +343,7 @@ conn.procedure(:update_and_fetch_something).call(
|
|
353
343
|
|
354
344
|
# Bind by parameter name
|
355
345
|
conn.procedure(:update_and_fetch_something).call(
|
356
|
-
:
|
346
|
+
a: 100, b: ["value", String], c: Fixnum)
|
357
347
|
```
|
358
348
|
|
359
349
|
### Using sequence wrappers (since 0.4.2)
|
data/jdbc-helper.gemspec
CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = JDBCHelper::VERSION
|
17
17
|
|
18
18
|
gem.add_runtime_dependency 'insensitive_hash', '>= 0.2.4'
|
19
|
+
gem.add_runtime_dependency 'sql_helper', '~> 0.1.1'
|
19
20
|
gem.add_development_dependency "bundler"
|
20
21
|
gem.add_development_dependency "simplecov"
|
21
22
|
gem.add_development_dependency "test-unit"
|
@@ -27,13 +27,13 @@ class PreparedStatement < ParameterizedStatement
|
|
27
27
|
@java_obj = nil
|
28
28
|
end
|
29
29
|
|
30
|
-
# @return [Fixnum|
|
30
|
+
# @return [Fixnum|ResultSet]
|
31
31
|
def execute(*params)
|
32
32
|
check_closed
|
33
33
|
|
34
34
|
set_params(params)
|
35
35
|
if @java_obj.execute
|
36
|
-
|
36
|
+
ResultSet.new(@java_obj.getResultSet)
|
37
37
|
else
|
38
38
|
@java_obj.getUpdateCount
|
39
39
|
end
|
@@ -52,19 +52,16 @@ class PreparedStatement < ParameterizedStatement
|
|
52
52
|
check_closed
|
53
53
|
|
54
54
|
set_params(params)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
return query(*params, &blk) if block_given?
|
64
|
-
|
65
|
-
set_params(params)
|
66
|
-
ResultSetEnumerator.new(@java_obj.execute_query)
|
55
|
+
enum = ResultSet.new(@java_obj.execute_query)
|
56
|
+
if block_given?
|
57
|
+
enum.each do |row|
|
58
|
+
yield row
|
59
|
+
end
|
60
|
+
else
|
61
|
+
enum
|
62
|
+
end
|
67
63
|
end
|
64
|
+
alias enumerate query
|
68
65
|
|
69
66
|
# Adds to the batch
|
70
67
|
# @return [NilClass]
|
@@ -7,48 +7,47 @@ module JDBCHelper
|
|
7
7
|
class Connection
|
8
8
|
# Class for enumerating query results.
|
9
9
|
# Automatically closed after used. When not used, you must close it explicitly by calling "close".
|
10
|
-
class
|
10
|
+
class ResultSet
|
11
11
|
include Enumerable
|
12
12
|
|
13
13
|
def each
|
14
|
+
return enum_for(:each) unless block_given?
|
14
15
|
return if closed?
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
49
|
-
ensure
|
50
|
-
close
|
17
|
+
while @nrow
|
18
|
+
idx = 0
|
19
|
+
# Oracle returns numbers in NUMERIC type, which can be of any precision.
|
20
|
+
# So, we retrieve the numbers in String type not to lose their precision.
|
21
|
+
# This can be quite annoying when you're just working with integers,
|
22
|
+
# so I tried the following code to automatically convert integer string into integer
|
23
|
+
# when it's obvious. However, the performance drop is untolerable.
|
24
|
+
# Thus, commented out.
|
25
|
+
#
|
26
|
+
# if v && @cols_meta[i-1] == java.sql.Types::NUMERIC && v !~ /[\.e]/i
|
27
|
+
# v.to_i
|
28
|
+
# else
|
29
|
+
# v
|
30
|
+
# end
|
31
|
+
row = Connection::Row.new(
|
32
|
+
@col_labels,
|
33
|
+
@col_labels_d,
|
34
|
+
@getters.map { |gt|
|
35
|
+
case gt
|
36
|
+
when :getBigNum
|
37
|
+
v = @rset.getBigDecimal idx+=1
|
38
|
+
@rset.was_null ? nil : v.toPlainString.to_i
|
39
|
+
when :getBigDecimal
|
40
|
+
v = @rset.getBigDecimal idx+=1
|
41
|
+
@rset.was_null ? nil : BigDecimal.new(v.toPlainString)
|
42
|
+
else
|
43
|
+
v = @rset.send gt, idx+=1
|
44
|
+
@rset.was_null ? nil : v
|
45
|
+
end
|
46
|
+
}, @rownum += 1)
|
47
|
+
close unless @nrow = @rset.next
|
48
|
+
yield row
|
51
49
|
end
|
50
|
+
close
|
52
51
|
end
|
53
52
|
|
54
53
|
def close
|
@@ -90,11 +89,7 @@ private
|
|
90
89
|
if precision > 0 && scale >= 0
|
91
90
|
# Numbers with fractional parts
|
92
91
|
if scale > 0
|
93
|
-
|
94
|
-
:getDouble
|
95
|
-
else
|
96
|
-
:getBigDecimal
|
97
|
-
end
|
92
|
+
:getBigDecimal
|
98
93
|
# Numbers without fractional parts
|
99
94
|
else
|
100
95
|
if precision <= 9
|
@@ -119,9 +114,11 @@ private
|
|
119
114
|
|
120
115
|
end
|
121
116
|
|
117
|
+
@rownum = -1
|
118
|
+
@nrow = @rset.next
|
122
119
|
@closed = false
|
123
120
|
end
|
124
|
-
end#
|
121
|
+
end#ResultSet
|
125
122
|
end#Connection
|
126
123
|
end#JDBCHelper
|
127
124
|
|
@@ -8,7 +8,7 @@ require 'jdbc-helper/connection/parameterized_statement'
|
|
8
8
|
require 'jdbc-helper/connection/prepared_statement'
|
9
9
|
require 'jdbc-helper/connection/callable_statement'
|
10
10
|
require 'jdbc-helper/connection/statement_pool'
|
11
|
-
require 'jdbc-helper/connection/
|
11
|
+
require 'jdbc-helper/connection/result_set'
|
12
12
|
require 'jdbc-helper/connection/row'
|
13
13
|
|
14
14
|
require 'jdbc-helper/wrapper/object_wrapper'
|
@@ -137,7 +137,7 @@ class Connection
|
|
137
137
|
# @param [Hash] args
|
138
138
|
def initialize(args = {})
|
139
139
|
# Subsequent deletes should not affect the input
|
140
|
-
@args =
|
140
|
+
@args = args
|
141
141
|
args = InsensitiveHash[ @args ]
|
142
142
|
|
143
143
|
raise ArgumentError.new("driver not given") unless args.has_key? :driver
|
@@ -241,18 +241,18 @@ class Connection
|
|
241
241
|
status == :committed
|
242
242
|
end
|
243
243
|
|
244
|
-
# Executes an SQL and returns the count of the update rows or a
|
244
|
+
# Executes an SQL and returns the count of the update rows or a ResultSet object
|
245
245
|
# depending on the type of the given statement.
|
246
|
-
# If a
|
246
|
+
# If a ResultSet is returned, it must be enumerated or closed.
|
247
247
|
# @param [String] qstr SQL string
|
248
|
-
# @return [Fixnum|
|
248
|
+
# @return [Fixnum|ResultSet]
|
249
249
|
def execute(qstr)
|
250
250
|
check_closed
|
251
251
|
|
252
252
|
stmt = @spool.take
|
253
253
|
begin
|
254
254
|
if stmt.execute(qstr)
|
255
|
-
|
255
|
+
ResultSet.send(:new, stmt.getResultSet) { @spool.give stmt }
|
256
256
|
else
|
257
257
|
rset = stmt.getUpdateCount
|
258
258
|
@spool.give stmt
|
@@ -277,16 +277,14 @@ class Connection
|
|
277
277
|
|
278
278
|
# Executes a select query.
|
279
279
|
# When a code block is given, each row of the result is passed to the block one by one.
|
280
|
-
# If
|
281
|
-
#
|
282
|
-
#
|
283
|
-
# The concept of statement object of JDBC is encapsulated, so there's no need to do additional task,
|
284
|
-
# when you nest select queries, for example.
|
280
|
+
# If not given, ResultSet is returned, which can be used to enumerate through the result set.
|
281
|
+
# ResultSet is closed automatically when all the rows in the result set is consumed.
|
285
282
|
#
|
283
|
+
# @example Nested querying
|
286
284
|
# conn.query("SELECT a FROM T") do | trow |
|
287
|
-
#
|
288
|
-
#
|
289
|
-
#
|
285
|
+
# conn.query("SELECT * FROM U_#{trow.a}").each_slice(10) do | urows |
|
286
|
+
# # ...
|
287
|
+
# end
|
290
288
|
# end
|
291
289
|
# @param [String] qstr SQL string
|
292
290
|
# @yield [JDBCHelper::Connection::Row]
|
@@ -294,40 +292,24 @@ class Connection
|
|
294
292
|
def query(qstr, &blk)
|
295
293
|
check_closed
|
296
294
|
|
297
|
-
@spool.with do | stmt |
|
298
|
-
rset = stmt.execute_query(qstr)
|
299
|
-
process_and_close_rset(rset, &blk)
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
# Returns an enumerable object of the query result.
|
304
|
-
# "enumerate" method is preferable when dealing with a large result set,
|
305
|
-
# since it doesn't have to build a large array.
|
306
|
-
#
|
307
|
-
# The returned enumerator is automatically closed after enumeration.
|
308
|
-
#
|
309
|
-
# conn.enumerate('SELECT * FROM T').each_slice(10) do | slice |
|
310
|
-
# slice.each { | row | print row }
|
311
|
-
# puts
|
312
|
-
# end
|
313
|
-
#
|
314
|
-
# @param [String] qstr SQL string
|
315
|
-
# @yield [JDBCHelper::Connection::Row] Yields each record if block is given
|
316
|
-
# @return [JDBCHelper::Connection::ResultSetEnumerator] Returns an enumerator if block is not given
|
317
|
-
def enumerate(qstr, &blk)
|
318
|
-
check_closed
|
319
|
-
|
320
|
-
return query(qstr, &blk) if block_given?
|
321
|
-
|
322
295
|
stmt = @spool.take
|
323
296
|
begin
|
324
297
|
rset = stmt.execute_query(qstr)
|
325
|
-
|
326
|
-
rescue Exception
|
298
|
+
rescue Exception => e
|
327
299
|
@spool.give stmt
|
328
300
|
raise
|
329
301
|
end
|
302
|
+
|
303
|
+
enum = ResultSet.send(:new, rset) { @spool.give stmt }
|
304
|
+
if block_given?
|
305
|
+
enum.each do |row|
|
306
|
+
yield row
|
307
|
+
end
|
308
|
+
else
|
309
|
+
enum
|
310
|
+
end
|
330
311
|
end
|
312
|
+
alias enumerate query
|
331
313
|
|
332
314
|
# Adds a statement to be executed in batch
|
333
315
|
# Adds to the batch
|
@@ -480,24 +462,6 @@ private
|
|
480
462
|
stmt
|
481
463
|
end
|
482
464
|
|
483
|
-
def process_and_close_rset(rset) # :nodoc:
|
484
|
-
enum = ResultSetEnumerator.send :new, rset
|
485
|
-
rows = []
|
486
|
-
|
487
|
-
begin
|
488
|
-
enum.each do | row |
|
489
|
-
if block_given?
|
490
|
-
yield row
|
491
|
-
else
|
492
|
-
rows << row
|
493
|
-
end
|
494
|
-
end
|
495
|
-
block_given? ? nil : rows
|
496
|
-
ensure
|
497
|
-
enum.close
|
498
|
-
end
|
499
|
-
end
|
500
|
-
|
501
465
|
def close_pstmt pstmt
|
502
466
|
@pstmts.delete pstmt
|
503
467
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Junegunn Choi (junegunn.c@gmail.com)
|
3
|
+
|
4
|
+
module JDBCHelper
|
5
|
+
# Shortcut connector for MariaDB
|
6
|
+
module MariaDB
|
7
|
+
extend Connector
|
8
|
+
|
9
|
+
# @param [String] host
|
10
|
+
# @param [String] user
|
11
|
+
# @param [String] password
|
12
|
+
# @param [String] db
|
13
|
+
# @param [Hash] extra_params
|
14
|
+
# @return [JDBCHelper::Connection]
|
15
|
+
def self.connect(host, user, password, db, extra_params = {}, &block)
|
16
|
+
connect_impl :mariadb, {
|
17
|
+
:url => "jdbc:mysql://#{host}/#{db}",
|
18
|
+
:user => user,
|
19
|
+
:password => password
|
20
|
+
}, extra_params, &block
|
21
|
+
end
|
22
|
+
end#MariaDB::Connector
|
23
|
+
end#JDBCHelper
|
24
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Junegunn Choi (junegunn.c@gmail.com)
|
3
|
+
|
4
|
+
module JDBCHelper
|
5
|
+
# Shortcut connector for SQLite
|
6
|
+
module SQLite
|
7
|
+
extend Connector
|
8
|
+
|
9
|
+
# @param [String] path
|
10
|
+
# @param [Hash] extra_params
|
11
|
+
# @return [JDBCHelper::Connection]
|
12
|
+
def self.connect(path, extra_params = {}, &block)
|
13
|
+
connect_impl :sqlite, {
|
14
|
+
:url => "jdbc:sqlite:#{path}",
|
15
|
+
}, extra_params, &block
|
16
|
+
end
|
17
|
+
end#SQLite::Connector
|
18
|
+
end#JDBCHelper
|
19
|
+
|