jdbc-helper 0.2.1 → 0.3.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/README.rdoc +80 -19
- data/lib/jdbc-helper/connection/callable_statement.rb +75 -0
- data/lib/jdbc-helper/connection/parameterized_statement.rb +64 -0
- data/lib/jdbc-helper/connection/prepared_statement.rb +13 -75
- data/lib/jdbc-helper/connection/result_set_enumerator.rb +24 -38
- data/lib/jdbc-helper/connection/row.rb +2 -2
- data/lib/jdbc-helper/connection/type_map.rb +72 -0
- data/lib/jdbc-helper/connection.rb +38 -9
- data/lib/jdbc-helper/sql.rb +67 -55
- data/lib/jdbc-helper/wrapper/function_wrapper.rb +26 -0
- data/lib/jdbc-helper/wrapper/object_wrapper.rb +32 -0
- data/lib/jdbc-helper/wrapper/procedure_wrapper.rb +28 -0
- data/lib/jdbc-helper/{object_wrapper.rb → wrapper/table_wrapper.rb} +5 -29
- data/lib/jdbc-helper.rb +0 -1
- data/test/database.yml +6 -8
- data/test/helper.rb +46 -0
- data/test/test_connection.rb +83 -6
- data/test/test_connectors.rb +3 -3
- data/test/test_object_wrapper.rb +53 -9
- data/test/test_performance.rb +21 -1
- data/test/test_sql.rb +29 -15
- metadata +20 -3
data/README.rdoc
CHANGED
@@ -6,14 +6,14 @@ crucial database operations from primitive selects and updates to more complex o
|
|
6
6
|
batch updates, prepared statements and transactions.
|
7
7
|
As the name implies, this gem only works on JRuby.
|
8
8
|
|
9
|
-
|
9
|
+
== Examples
|
10
10
|
|
11
|
-
|
11
|
+
=== Prerequisites
|
12
12
|
Add JDBC driver of the DBMS you're willing to use to your CLASSPATH
|
13
13
|
export CLASSPATH=$CLASSPATH:~/lib/mysql-connector-java.jar
|
14
14
|
|
15
15
|
|
16
|
-
|
16
|
+
=== Connecting to a database
|
17
17
|
|
18
18
|
# :driver and :url must be given
|
19
19
|
conn = JDBCHelper::Connection.new(
|
@@ -35,7 +35,7 @@ Add JDBC driver of the DBMS you're willing to use to your CLASSPATH
|
|
35
35
|
conn = JDBCHelper::MySQLConnector.connect('localhost', 'mysql', '', 'test')
|
36
36
|
conn.close
|
37
37
|
|
38
|
-
|
38
|
+
=== Querying database table
|
39
39
|
|
40
40
|
conn.query("SELECT a, b, c FROM T") do | row |
|
41
41
|
row.labels
|
@@ -71,10 +71,10 @@ Add JDBC driver of the DBMS you're willing to use to your CLASSPATH
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
|
74
|
+
=== Updating database table
|
75
75
|
del_count = conn.update("DELETE FROM T")
|
76
76
|
|
77
|
-
|
77
|
+
=== Transaction
|
78
78
|
committed = conn.transaction do | tx |
|
79
79
|
# ...
|
80
80
|
# Transaction logic here
|
@@ -87,13 +87,13 @@ Add JDBC driver of the DBMS you're willing to use to your CLASSPATH
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
-
|
90
|
+
=== Using batch interface
|
91
91
|
conn.add_batch("DELETE FROM T");
|
92
92
|
conn.execute_batch
|
93
93
|
conn.add_batch("DELETE FROM T");
|
94
94
|
conn.clear_batch
|
95
95
|
|
96
|
-
|
96
|
+
=== Using prepared statements
|
97
97
|
p_sel = conn.prepare("SELECT * FROM T WHERE b = ? and c = ?")
|
98
98
|
p_sel.query(100, 200) do | row |
|
99
99
|
p row
|
@@ -112,21 +112,82 @@ Add JDBC driver of the DBMS you're willing to use to your CLASSPATH
|
|
112
112
|
p_upd.execute_batch
|
113
113
|
p_upd.close
|
114
114
|
|
115
|
-
|
115
|
+
=== Using table wrappers (since 0.2.0)
|
116
116
|
# For more complex examples, refer to test/test_object_wrapper.rb
|
117
117
|
|
118
|
-
conn.table('test.data')
|
119
|
-
|
120
|
-
|
118
|
+
table = conn.table('test.data')
|
119
|
+
table.count
|
120
|
+
table.empty?
|
121
|
+
table.select(:c => 3) do |row|
|
121
122
|
puts row.a
|
122
123
|
end
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
124
|
+
table.update(:a => 1, :b => 2, :where => { :c => 3 })
|
125
|
+
table.insert(:a => 10, :b => 20, :c => 30)
|
126
|
+
table.insert_ignore(:a => 10, :b => 20, :c => 30)
|
127
|
+
table.replace(:a => 10, :b => 20, :c => 30)
|
128
|
+
table.delete(:c => 3)
|
129
|
+
table.truncate_table!
|
130
|
+
table.drop_table!
|
131
|
+
|
132
|
+
=== Using function wrappers (since 0.2.2)
|
133
|
+
conn.function(:mod).call 5, 3
|
134
|
+
conn.function(:coalesce).call(nil, nil, 'king')
|
135
|
+
|
136
|
+
=== Using procedure wrappers (since 0.3.0)
|
137
|
+
# Working with IN/INOUT/OUT parameteres
|
138
|
+
# Bind by ordinal number
|
139
|
+
conn.procedure(:update_and_fetch_something).call(
|
140
|
+
100, ["value", String], Fixnum)
|
141
|
+
|
142
|
+
# Bind by parameter name
|
143
|
+
conn.procedure(:update_and_fetch_something).call(
|
144
|
+
:a => 100, :b => ["value", String], :c => Fixnum)
|
145
|
+
|
146
|
+
== Notes on vendor-independence
|
147
|
+
|
148
|
+
jdbc-helper tries to be a vendor-independent library, so that it behaves the same on any RDBMS,
|
149
|
+
and that is why it's built on JDBC in the first place which can be used to minimize the amount of vendor-specific code.
|
150
|
+
(Ideally, one codebase for all RDBMSs.)
|
151
|
+
So far so good, but not great. It has small amount of code that is vendor-specific, non-standard JDBC.
|
152
|
+
And it has been confirmed to work the same for both MySQL and Oracle, except for stored procedures.
|
153
|
+
MySQL and Oracle implement parameter binding of CallableStatement differently.
|
154
|
+
See the following example.
|
155
|
+
# Let's say we have a stored procedure named my_procedure
|
156
|
+
# which takes 3 parameters, param1, param2, and param3.
|
157
|
+
|
158
|
+
# Creates a CallableStatemet
|
159
|
+
cstmt = conn.prepare_call("{call my_procedure(?, ?, ?)}")
|
160
|
+
|
161
|
+
cstmt.call(10, "ten", Fixnum)
|
162
|
+
# OK for both MySQL and Oracle. Filling paramters sequentially.
|
163
|
+
|
164
|
+
cstmt.call(:param1 => 10, :param2 => "ten", :param3 => Fixnum)
|
165
|
+
# MySQL automatically binds values by the parameter names in the original procedure definition.
|
166
|
+
# Oracle fails to do so.
|
167
|
+
cstmt.close
|
168
|
+
|
169
|
+
# For Oracle, if you prepare as follows,
|
170
|
+
cstmt = conn.prepare_call("{call my_procedure(:p1, :p2, :p3)}")
|
171
|
+
|
172
|
+
# Then you can do this.
|
173
|
+
cstmt.call(:p1 => 10, :p2 => "ten", :p3 => Fixnum)
|
174
|
+
# However, p1, p2, p3 have nothing to do with the original
|
175
|
+
# parameter names (param1, param2, param3) in the procedure definition.
|
176
|
+
# They're just aliases for ordinal positions.
|
177
|
+
# So, it's semantically different from the first example.
|
178
|
+
|
179
|
+
cstmt.close
|
180
|
+
|
181
|
+
There's no way to find out the original parameter names and their ordinal positions without looking up the metadata of the database,
|
182
|
+
which requires having to write vendor-specific code branches, and that is definitely not desirable.
|
183
|
+
ProcedureWrapper prepares call with '?'s as the first example.
|
184
|
+
So it would work fine for MySQL, but you can't use it with parameter names on Oracle.
|
185
|
+
|
186
|
+
# Good for both
|
187
|
+
conn.procedure(:my_procedure).call(10, "ten", Fixnum)
|
188
|
+
|
189
|
+
# Only for MySQL
|
190
|
+
conn.procedure(:my_procedure).call(:param1 => 10, :param2 => "ten", :param3 => Fixnum)
|
130
191
|
|
131
192
|
== Contributing to jdbc-helper
|
132
193
|
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Junegunn Choi (junegunn.c@gmail.com)
|
3
|
+
|
4
|
+
module JDBCHelper
|
5
|
+
class Connection
|
6
|
+
# Interface to Java CallableStatment
|
7
|
+
class CallableStatement < ParameterizedStatement
|
8
|
+
# Array or Hash (for named parameters)
|
9
|
+
# - IN parameter: value
|
10
|
+
# - OUT parameter: class
|
11
|
+
# - INOUT parameter: [value, class]
|
12
|
+
# (Although class can be inferred from the value,
|
13
|
+
# we still need a way to figure out if it's INOUT parameter)
|
14
|
+
def call *params
|
15
|
+
check_closed
|
16
|
+
|
17
|
+
out_params = set_params(params)
|
18
|
+
measure_exec(:call) { @java_obj.execute }
|
19
|
+
|
20
|
+
result = {}
|
21
|
+
out_params.each do |idx, jtype|
|
22
|
+
getter = JDBCHelper::Connection::GETTER_MAP.fetch(jtype, :get_string)
|
23
|
+
value = @java_obj.send(getter, idx.is_a?(Symbol) ? idx.to_s : idx)
|
24
|
+
result[idx] = @java_obj.was_null ? nil : value
|
25
|
+
end
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def set_params(params) # :nodoc:
|
31
|
+
hash_params =
|
32
|
+
if params.first.kind_of? Hash
|
33
|
+
raise ArgumentError.new("More than one Hash given") if params.length > 1
|
34
|
+
params.first
|
35
|
+
else
|
36
|
+
params.each_with_index.inject({}) { |hash, pair|
|
37
|
+
hash[pair.last + 1] = pair.first
|
38
|
+
hash
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
out_params = {}
|
43
|
+
hash_params.each do | idx, value |
|
44
|
+
# Symbol need to be transformed into string
|
45
|
+
|
46
|
+
idx_ = idx.is_a?(Symbol) ? idx.to_s : idx
|
47
|
+
case value
|
48
|
+
# OUT parameter
|
49
|
+
when Class
|
50
|
+
jtype = JDBCHelper::Connection::RUBY_SQL_TYPE_MAP[value] || java.sql.Types::VARCHAR
|
51
|
+
@java_obj.registerOutParameter(idx_, jtype)
|
52
|
+
out_params[idx] = jtype
|
53
|
+
|
54
|
+
# INOUT parameter
|
55
|
+
when Array
|
56
|
+
set_param(idx_, value.first)
|
57
|
+
jtype = JDBCHelper::Connection::RUBY_SQL_TYPE_MAP[value.last] || java.sql.Types::VARCHAR
|
58
|
+
@java_obj.registerOutParameter(idx_, jtype)
|
59
|
+
out_params[idx] = jtype
|
60
|
+
|
61
|
+
# IN parameter
|
62
|
+
else
|
63
|
+
set_param(idx_, value)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
out_params
|
67
|
+
end
|
68
|
+
|
69
|
+
def initialize(*args)
|
70
|
+
super(*args)
|
71
|
+
end
|
72
|
+
end#CallableStatment
|
73
|
+
end#Connection
|
74
|
+
end#JDBCHelper
|
75
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Junegunn Choi (junegunn.c@gmail.com)
|
3
|
+
|
4
|
+
module JDBCHelper
|
5
|
+
class Connection
|
6
|
+
# Base class for CallableStatement and PreparedStatment
|
7
|
+
# @abstract
|
8
|
+
class ParameterizedStatement
|
9
|
+
# SQL string
|
10
|
+
# @return [String]
|
11
|
+
attr_reader :sql
|
12
|
+
|
13
|
+
# Underlying Java object
|
14
|
+
attr_reader :java_obj
|
15
|
+
|
16
|
+
# @param [JDBCHelper::Connection] conn
|
17
|
+
# @param [String] cstmt_str
|
18
|
+
def initialize(conn, sql, obj)
|
19
|
+
@conn = conn
|
20
|
+
@sql = sql
|
21
|
+
@java_obj = obj
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_param(idx, param)
|
25
|
+
if param.nil?
|
26
|
+
@java_obj.set_null idx, java.sql.Types::NULL
|
27
|
+
elsif setter = JDBCHelper::Connection::SETTER_MAP[param.class.to_s]
|
28
|
+
if setter == :setBinaryStream
|
29
|
+
@java_obj.send setter, idx, param.getBinaryStream, param.length
|
30
|
+
elsif setter == :setTimestamp && param.is_a?(Time)
|
31
|
+
@java_obj.send setter, idx, java.sql.Timestamp.new(param.to_i * 1000)
|
32
|
+
else
|
33
|
+
@java_obj.send setter, idx, param
|
34
|
+
end
|
35
|
+
else
|
36
|
+
@java_obj.set_string idx, param.to_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [NilClass]
|
41
|
+
def close
|
42
|
+
@java_obj.close
|
43
|
+
@java_obj = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Boolean]
|
47
|
+
def closed?
|
48
|
+
@java_obj.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def measure_exec(type, &blk) # :nodoc:
|
53
|
+
@conn.send(:measure_exec, type, &blk)
|
54
|
+
end
|
55
|
+
|
56
|
+
def check_closed
|
57
|
+
raise RuntimeError.new("Object already closed") if closed?
|
58
|
+
end
|
59
|
+
|
60
|
+
end#ParameterizedStatement
|
61
|
+
end#Connection
|
62
|
+
end#JDBCHelper
|
63
|
+
|
64
|
+
|
@@ -11,20 +11,11 @@ class Connection
|
|
11
11
|
# pstmt = conn.prepare("SELECT * FROM T WHERE a = ? and b = ?")
|
12
12
|
# rows = pstmt.query(10, 20)
|
13
13
|
# enum = pstmt.enumerate(10, 20)
|
14
|
-
class PreparedStatement
|
15
|
-
# SQL string
|
16
|
-
# @return [String]
|
17
|
-
attr_reader :sql
|
18
|
-
|
19
|
-
# Returns the encapsulated JDBC PreparedStatement object.
|
20
|
-
def java_obj
|
21
|
-
@pstmt
|
22
|
-
end
|
23
|
-
|
14
|
+
class PreparedStatement < ParameterizedStatement
|
24
15
|
# Returns the number of parameters required
|
25
16
|
# @return [Fixnum]
|
26
17
|
def parameter_count
|
27
|
-
@pmd ||= @
|
18
|
+
@pmd ||= @java_obj.get_parameter_meta_data
|
28
19
|
@pmd.get_parameter_count
|
29
20
|
end
|
30
21
|
|
@@ -33,7 +24,7 @@ class PreparedStatement
|
|
33
24
|
check_closed
|
34
25
|
|
35
26
|
set_params(params)
|
36
|
-
measure_exec(:p_update) { @
|
27
|
+
measure_exec(:p_update) { @java_obj.execute_update }
|
37
28
|
end
|
38
29
|
|
39
30
|
# @return [Array] Returns an Array if block is not given
|
@@ -43,7 +34,7 @@ class PreparedStatement
|
|
43
34
|
set_params(params)
|
44
35
|
# sorry, ignoring privacy
|
45
36
|
@conn.send(:process_and_close_rset,
|
46
|
-
measure_exec(:p_query) { @
|
37
|
+
measure_exec(:p_query) { @java_obj.execute_query }, &blk)
|
47
38
|
end
|
48
39
|
|
49
40
|
# @return [JDBCHelper::Connection::ResultSetEnumerator]
|
@@ -53,7 +44,7 @@ class PreparedStatement
|
|
53
44
|
return query(*params, &blk) if block_given?
|
54
45
|
|
55
46
|
set_params(params)
|
56
|
-
ResultSetEnumerator.new(measure_exec(:p_query) { @
|
47
|
+
ResultSetEnumerator.new(measure_exec(:p_query) { @java_obj.execute_query })
|
57
48
|
end
|
58
49
|
|
59
50
|
# Adds to the batch
|
@@ -62,14 +53,14 @@ class PreparedStatement
|
|
62
53
|
check_closed
|
63
54
|
|
64
55
|
set_params(params)
|
65
|
-
@
|
56
|
+
@java_obj.add_batch
|
66
57
|
end
|
67
58
|
# Executes the batch
|
68
59
|
def execute_batch
|
69
60
|
check_closed
|
70
61
|
|
71
62
|
measure_exec(:p_execute_batch) {
|
72
|
-
@
|
63
|
+
@java_obj.executeBatch
|
73
64
|
}
|
74
65
|
end
|
75
66
|
# Clears the batch
|
@@ -77,7 +68,7 @@ class PreparedStatement
|
|
77
68
|
def clear_batch
|
78
69
|
check_closed
|
79
70
|
|
80
|
-
@
|
71
|
+
@java_obj.clear_batch
|
81
72
|
end
|
82
73
|
|
83
74
|
# Gives the JDBC driver a hint of the number of rows to fetch from the database by a single interaction.
|
@@ -86,72 +77,19 @@ class PreparedStatement
|
|
86
77
|
def set_fetch_size(fsz)
|
87
78
|
check_closed
|
88
79
|
|
89
|
-
@
|
80
|
+
@java_obj.set_fetch_size fsz
|
90
81
|
end
|
91
82
|
|
92
|
-
# Closes the prepared statement
|
93
|
-
# @return [NilClass]
|
94
|
-
def close
|
95
|
-
return if closed?
|
96
|
-
@pstmt.close
|
97
|
-
@pstmts.delete @sql
|
98
|
-
@pstmt = @pstmts = nil
|
99
|
-
end
|
100
|
-
|
101
|
-
# @return [Boolean]
|
102
|
-
def closed?
|
103
|
-
@pstmt.nil?
|
104
|
-
end
|
105
83
|
private
|
106
|
-
def initialize(conn, pstmts, sql, pstmt) # :nodoc:
|
107
|
-
@conn = conn
|
108
|
-
@pstmts = pstmts
|
109
|
-
@sql = sql
|
110
|
-
@pstmt = pstmt
|
111
|
-
end
|
112
|
-
|
113
84
|
def set_params(params) # :nodoc:
|
114
|
-
idx
|
115
|
-
|
116
|
-
if param.nil?
|
117
|
-
@pstmt.set_null(idx += 1, java.sql.Types::NULL)
|
118
|
-
elsif setter = SETTER_MAP[param.class.to_s]
|
119
|
-
if setter == :setBinaryStream
|
120
|
-
@pstmt.send(setter, idx += 1, param.getBinaryStream, param.length)
|
121
|
-
elsif setter == :setTimestamp && param.is_a?(Time)
|
122
|
-
@pstmt.send(setter, idx += 1, java.sql.Timestamp.new(param.to_i * 1000))
|
123
|
-
else
|
124
|
-
@pstmt.send(setter, idx += 1, param)
|
125
|
-
end
|
126
|
-
else
|
127
|
-
@pstmt.set_string(idx += 1, param.to_s)
|
128
|
-
end
|
85
|
+
params.each_with_index do | param, idx |
|
86
|
+
set_param(idx + 1, param)
|
129
87
|
end
|
130
88
|
end
|
131
89
|
|
132
|
-
def
|
133
|
-
|
134
|
-
end
|
135
|
-
|
136
|
-
def check_closed
|
137
|
-
raise RuntimeError.new("Prepared statement already closed") if closed?
|
90
|
+
def initialize(*args)
|
91
|
+
super(*args)
|
138
92
|
end
|
139
|
-
|
140
|
-
SETTER_MAP =
|
141
|
-
{
|
142
|
-
'Java::JavaSql::Date' => :setDate,
|
143
|
-
'Java::JavaSql::Time' => :setTime,
|
144
|
-
'Java::JavaSql::Timestamp' => :setTimestamp,
|
145
|
-
'Time' => :setTimestamp,
|
146
|
-
'Java::JavaSql::Blob' => :setBinaryStream,
|
147
|
-
|
148
|
-
# Only available when MySQL JDBC driver is loaded.
|
149
|
-
# So we use the string representation of the class.
|
150
|
-
'Java::ComMysqlJdbc::Blob' => :setBinaryStream
|
151
|
-
|
152
|
-
# FIXME-MORE
|
153
|
-
} # :nodoc:
|
154
|
-
|
155
93
|
end#PreparedStatment
|
156
94
|
end#Connection
|
157
95
|
end#JDBCHelper
|
@@ -2,9 +2,9 @@
|
|
2
2
|
# Junegunn Choi (junegunn.c@gmail.com)
|
3
3
|
|
4
4
|
module JDBCHelper
|
5
|
-
# Class for enumerating query results
|
6
|
-
# Automatically closed after used. When not used, you must close it explicitly by calling "close".
|
7
5
|
class Connection
|
6
|
+
# Class for enumerating query results.
|
7
|
+
# Automatically closed after used. When not used, you must close it explicitly by calling "close".
|
8
8
|
class ResultSetEnumerator
|
9
9
|
include Enumerable
|
10
10
|
|
@@ -14,10 +14,24 @@ class ResultSetEnumerator
|
|
14
14
|
count = -1
|
15
15
|
begin
|
16
16
|
while @rset.next
|
17
|
+
idx = 0
|
18
|
+
# Oracle returns numbers in NUMERIC type, which can be of any precision.
|
19
|
+
# So, we retrieve the numbers in String type not to lose their precision.
|
20
|
+
# This can be quite annoying when you're just working with integers,
|
21
|
+
# so I tried the following code to automatically convert integer string into integer
|
22
|
+
# when it's obvious. However, the performance drop is untolerable.
|
23
|
+
# Thus, commented out.
|
24
|
+
#
|
25
|
+
# if v && @cols_meta[i-1] == java.sql.Types::NUMERIC && v !~ /[\.e]/i
|
26
|
+
# v.to_i
|
27
|
+
# else
|
28
|
+
# v
|
29
|
+
# end
|
17
30
|
yield Connection::Row.new(
|
18
31
|
@col_labels,
|
19
|
-
|
20
|
-
|
32
|
+
@col_labels_d,
|
33
|
+
@getters.map { |gt|
|
34
|
+
v = @rset.send gt, idx+=1
|
21
35
|
@rset.was_null ? nil : v
|
22
36
|
},
|
23
37
|
count += 1)
|
@@ -52,48 +66,20 @@ private
|
|
52
66
|
@rsmd = @rset.get_meta_data
|
53
67
|
@num_col = @rsmd.get_column_count
|
54
68
|
@cols_meta = []
|
69
|
+
@getters = []
|
55
70
|
@col_labels = []
|
71
|
+
@col_labels_d = []
|
56
72
|
(1..@num_col).each do | i |
|
57
73
|
@cols_meta << @rsmd.get_column_type(i)
|
74
|
+
@getters << JDBCHelper::Connection::GETTER_MAP.fetch(@cols_meta.last, :get_string)
|
75
|
+
|
58
76
|
@col_labels << @rsmd.get_column_label(i)
|
77
|
+
@col_labels_d << @col_labels.last.downcase
|
78
|
+
|
59
79
|
end
|
60
80
|
|
61
81
|
@closed = false
|
62
82
|
end
|
63
|
-
|
64
|
-
GETTER_MAP =
|
65
|
-
{
|
66
|
-
java.sql.Types::TINYINT => :get_int,
|
67
|
-
java.sql.Types::SMALLINT => :get_int,
|
68
|
-
java.sql.Types::INTEGER => :get_int,
|
69
|
-
java.sql.Types::BIGINT => :get_long,
|
70
|
-
|
71
|
-
java.sql.Types::CHAR => :get_string,
|
72
|
-
java.sql.Types::VARCHAR => :get_string,
|
73
|
-
java.sql.Types::LONGVARCHAR => :get_string,
|
74
|
-
(java.sql.Types::NCHAR rescue nil) => :get_string,
|
75
|
-
(java.sql.Types::NVARCHAR rescue nil) => :get_string,
|
76
|
-
(java.sql.Types::LONGNVARCHAR rescue nil) => :get_blob, # FIXME: MySQL
|
77
|
-
java.sql.Types::BINARY => :get_string,
|
78
|
-
java.sql.Types::VARBINARY => :get_string,
|
79
|
-
java.sql.Types::LONGVARBINARY => :get_blob, # FIXME: MySQL
|
80
|
-
|
81
|
-
java.sql.Types::REAL => :get_double,
|
82
|
-
java.sql.Types::FLOAT => :get_float,
|
83
|
-
java.sql.Types::DOUBLE => :get_double,
|
84
|
-
java.sql.Types::NUMERIC => :get_string, # FIXME
|
85
|
-
java.sql.Types::DECIMAL => :get_string, # FIXME
|
86
|
-
|
87
|
-
java.sql.Types::DATE => :get_date,
|
88
|
-
java.sql.Types::TIME => :get_time,
|
89
|
-
java.sql.Types::TIMESTAMP => :get_timestamp,
|
90
|
-
|
91
|
-
java.sql.Types::BLOB => :get_blob,
|
92
|
-
java.sql.Types::CLOB => :get_string,
|
93
|
-
(java.sql.Types::NCLOB rescue nil) => :get_string,
|
94
|
-
|
95
|
-
java.sql.Types::BOOLEAN => :get_boolean
|
96
|
-
} # :nodoc:
|
97
83
|
end#ResultSetEnumerator
|
98
84
|
end#Connection
|
99
85
|
end#JDBCHelper
|
@@ -105,9 +105,9 @@ class Row
|
|
105
105
|
alias :== :eql?
|
106
106
|
|
107
107
|
private
|
108
|
-
def initialize(col_labels, values, rownum) # :nodoc:
|
108
|
+
def initialize(col_labels, col_labels_d, values, rownum) # :nodoc:
|
109
109
|
@labels = col_labels
|
110
|
-
@labels_d =
|
110
|
+
@labels_d = col_labels_d
|
111
111
|
@values = values
|
112
112
|
@rownum = rownum
|
113
113
|
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Junegunn Choi (junegunn.c@gmail.com)
|
3
|
+
|
4
|
+
module JDBCHelper
|
5
|
+
class Connection
|
6
|
+
RUBY_SQL_TYPE_MAP = {
|
7
|
+
Fixnum => java.sql.Types::INTEGER,
|
8
|
+
Bignum => java.sql.Types::BIGINT,
|
9
|
+
String => java.sql.Types::VARCHAR,
|
10
|
+
Float => java.sql.Types::DOUBLE,
|
11
|
+
Time => java.sql.Types::TIMESTAMP
|
12
|
+
}
|
13
|
+
|
14
|
+
SETTER_MAP =
|
15
|
+
{
|
16
|
+
'String' => :setString,
|
17
|
+
'Fixnum' => :setInt,
|
18
|
+
'Float' => :setDouble,
|
19
|
+
# See there's a caveat. Check out ParameterizedStatement#set_param
|
20
|
+
'Time' => :setTimestamp,
|
21
|
+
|
22
|
+
'Java::JavaSql::Date' => :setDate,
|
23
|
+
'Java::JavaSql::Time' => :setTime,
|
24
|
+
'Java::JavaSql::Timestamp' => :setTimestamp,
|
25
|
+
'Java::JavaSql::Blob' => :setBinaryStream,
|
26
|
+
|
27
|
+
#########
|
28
|
+
# MySQL #
|
29
|
+
#########
|
30
|
+
# Only available when MySQL JDBC driver is loaded.
|
31
|
+
# So we use the string representation of the class.
|
32
|
+
'Java::ComMysqlJdbc::Blob' => :setBinaryStream
|
33
|
+
|
34
|
+
# FIXME-MORE
|
35
|
+
} # :nodoc:
|
36
|
+
|
37
|
+
GETTER_MAP =
|
38
|
+
{
|
39
|
+
java.sql.Types::TINYINT => :getInt,
|
40
|
+
java.sql.Types::SMALLINT => :getInt,
|
41
|
+
java.sql.Types::INTEGER => :getInt,
|
42
|
+
java.sql.Types::BIGINT => :getLong,
|
43
|
+
|
44
|
+
java.sql.Types::CHAR => :getString,
|
45
|
+
java.sql.Types::VARCHAR => :getString,
|
46
|
+
java.sql.Types::LONGVARCHAR => :getString,
|
47
|
+
(java.sql.Types::NCHAR rescue nil) => :getString,
|
48
|
+
(java.sql.Types::NVARCHAR rescue nil) => :getString,
|
49
|
+
(java.sql.Types::LONGNVARCHAR rescue nil) => :getBlob, # FIXME: MySQL
|
50
|
+
java.sql.Types::BINARY => :getString,
|
51
|
+
java.sql.Types::VARBINARY => :getString,
|
52
|
+
java.sql.Types::LONGVARBINARY => :getBlob, # FIXME: MySQL
|
53
|
+
|
54
|
+
java.sql.Types::REAL => :getDouble,
|
55
|
+
java.sql.Types::FLOAT => :getFloat,
|
56
|
+
java.sql.Types::DOUBLE => :getDouble,
|
57
|
+
java.sql.Types::NUMERIC => :getString, # FIXME: get_big_decimal=no inherent jruby support
|
58
|
+
java.sql.Types::DECIMAL => :getString, # FIXME: get_big_decimal
|
59
|
+
|
60
|
+
java.sql.Types::DATE => :getDate,
|
61
|
+
java.sql.Types::TIME => :getTime,
|
62
|
+
java.sql.Types::TIMESTAMP => :getTimestamp,
|
63
|
+
|
64
|
+
java.sql.Types::BLOB => :getBlob,
|
65
|
+
java.sql.Types::CLOB => :getString,
|
66
|
+
(java.sql.Types::NCLOB rescue nil) => :getString,
|
67
|
+
|
68
|
+
java.sql.Types::BOOLEAN => :getBoolean
|
69
|
+
} # :nodoc:
|
70
|
+
end#Connection
|
71
|
+
end#JDBCHelper
|
72
|
+
|