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 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
- = Examples
9
+ == Examples
10
10
 
11
- == Prerequisites
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
- == Connecting to a database
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
- == Querying database table
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
- == Updating database table
74
+ === Updating database table
75
75
  del_count = conn.update("DELETE FROM T")
76
76
 
77
- == Transaction
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
- == Using batch interface
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
- == Using prepared statements
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
- == Using table wrappers (since 0.2.0)
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').count
119
- conn.table('test.data').empty?
120
- conn.table('test.data').select(:c => 3) do |row|
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
- conn.table('test.data').update(:a => 1, :b => 2, :where => { :c => 3 })
124
- conn.table('test.data').insert(:a => 10, :b => 20, :c => 30)
125
- conn.table('test.data').insert_ignore(:a => 10, :b => 20, :c => 30)
126
- conn.table('test.data').replace(:a => 10, :b => 20, :c => 30)
127
- conn.table('test.data').delete(:c => 3)
128
- conn.table('test.data').truncate_table!
129
- conn.table('test.data').drop_table!
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 ||= @pstmt.get_parameter_meta_data
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) { @pstmt.execute_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) { @pstmt.execute_query }, &blk)
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) { @pstmt.execute_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
- @pstmt.add_batch
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
- @pstmt.executeBatch
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
- @pstmt.clear_batch
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
- @pstmt.set_fetch_size fsz
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 = 0
115
- params.each do | param |
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 measure_exec(type, &blk) # :nodoc:
133
- @conn.send(:measure_exec, type, &blk)
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
- (1..@num_col).map { | i |
20
- v = @rset.send(GETTER_MAP.fetch(@cols_meta[i-1], :get_string), i)
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 = col_labels.map { | l | l.downcase }
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
+