jdbc-helper 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|