jdbc-helper 0.5.1 → 0.6.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.
@@ -5,69 +5,69 @@ module JDBCHelper
5
5
  class Connection
6
6
  # Interface to Java CallableStatment
7
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
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
16
 
17
- out_params = set_params(params)
18
- measure_exec(:call) { @java_obj.execute }
17
+ out_params = set_params(params)
18
+ measure_exec(:call) { @java_obj.execute }
19
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
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
28
 
29
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
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
41
 
42
- out_params = {}
43
- hash_params.each do | idx, value |
44
- # Symbols need to be transformed into string
45
- idx_ = idx.is_a?(Symbol) ? idx.to_s : idx
46
- case value
47
- # OUT parameter
48
- when Class
49
- jtype = JDBCHelper::Connection::RUBY_SQL_TYPE_MAP[value] || java.sql.Types::VARCHAR
50
- @java_obj.registerOutParameter(idx_, jtype)
51
- out_params[idx] = jtype
42
+ out_params = {}
43
+ hash_params.each do | idx, value |
44
+ # Symbols need to be transformed into string
45
+ idx_ = idx.is_a?(Symbol) ? idx.to_s : idx
46
+ case value
47
+ # OUT parameter
48
+ when Class
49
+ jtype = JDBCHelper::Connection::RUBY_SQL_TYPE_MAP[value] || java.sql.Types::VARCHAR
50
+ @java_obj.registerOutParameter(idx_, jtype)
51
+ out_params[idx] = jtype
52
52
 
53
- # INOUT parameter
54
- when Array
55
- set_param(idx_, value.first)
56
- jtype = JDBCHelper::Connection::RUBY_SQL_TYPE_MAP[value.last] || java.sql.Types::VARCHAR
57
- @java_obj.registerOutParameter(idx_, jtype)
58
- out_params[idx] = jtype
59
-
60
- # IN parameter
61
- else
62
- set_param(idx_, value)
63
- end
64
- end
65
- out_params
66
- end
53
+ # INOUT parameter
54
+ when Array
55
+ set_param(idx_, value.first)
56
+ jtype = JDBCHelper::Connection::RUBY_SQL_TYPE_MAP[value.last] || java.sql.Types::VARCHAR
57
+ @java_obj.registerOutParameter(idx_, jtype)
58
+ out_params[idx] = jtype
59
+
60
+ # IN parameter
61
+ else
62
+ set_param(idx_, value)
63
+ end
64
+ end
65
+ out_params
66
+ end
67
67
 
68
- def initialize(*args)
69
- super(*args)
70
- end
68
+ def initialize(*args)
69
+ super(*args)
70
+ end
71
71
  end#CallableStatment
72
72
  end#Connection
73
73
  end#JDBCHelper
@@ -6,60 +6,71 @@ class Connection
6
6
  # Base class for CallableStatement and PreparedStatment
7
7
  # @abstract
8
8
  class ParameterizedStatement
9
- # SQL string
10
- # @return [String]
11
- attr_reader :sql
9
+ # SQL string
10
+ # @return [String]
11
+ attr_reader :sql
12
12
 
13
- # Underlying Java object
14
- attr_reader :java_obj
13
+ # Underlying Java object
14
+ attr_reader :java_obj
15
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
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
23
 
24
- def set_param(idx, param)
25
- if setter = (JDBCHelper::Connection::SETTER_MAP[param.class] ||
26
- JDBCHelper::Connection::SETTER_MAP[param.class.to_s])
27
- case setter
28
- when :setNull
29
- return @java_obj.send setter, idx, java.sql.Types::NULL
30
- when :setBinaryStream
31
- return @java_obj.send setter, idx, param.getBinaryStream, param.length
32
- when :setTimestamp
33
- if param.kind_of?(Time)
34
- return @java_obj.send setter, idx, java.sql.Timestamp.new(param.to_i * 1000)
35
- end
36
- end
24
+ def set_param(idx, param)
25
+ case param
26
+ when NilClass
27
+ @java_obj.setNull idx, java.sql.Types::NULL
28
+ when Fixnum
29
+ @java_obj.setLong idx, param
30
+ when Bignum
31
+ @java_obj.setString idx, param.to_s # Safer
32
+ when BigDecimal
33
+ @java_obj.setBigDecimal idx, param.to_java
34
+ when String
35
+ @java_obj.setString idx, param
36
+ when Float
37
+ @java_obj.setDouble idx, param
38
+ when Time
39
+ @java_obj.setTimestamp idx, java.sql.Timestamp.new((param.to_f * 1000).to_i)
40
+ when java.sql.Date
41
+ @java_obj.setDate idx, param
42
+ when java.sql.Time
43
+ @java_obj.setTime idx, param
44
+ when java.sql.Timestamp
45
+ @java_obj.setTimestamp idx, param
46
+ when java.sql.Blob
47
+ @java_obj.setBinaryStream idx, param.getBinaryStream#, param.length
48
+ when java.io.InputStream
49
+ @java_obj.setBinaryStream idx, param
50
+ else
51
+ @java_obj.setString idx, param.to_s
52
+ end
53
+ end
37
54
 
38
- @java_obj.send setter, idx, param
39
- else
40
- @java_obj.set_string idx, param.to_s
41
- end
42
- end
55
+ # @return [NilClass]
56
+ def close
57
+ @java_obj.close
58
+ @java_obj = nil
59
+ end
43
60
 
44
- # @return [NilClass]
45
- def close
46
- @java_obj.close
47
- @java_obj = nil
48
- end
49
-
50
- # @return [Boolean]
51
- def closed?
52
- @java_obj.nil?
53
- end
61
+ # @return [Boolean]
62
+ def closed?
63
+ @java_obj.nil? || @java_obj.isClosed
64
+ end
54
65
 
55
66
  private
56
- def measure_exec(type, &blk) # :nodoc:
57
- @conn.send(:measure_exec, type, &blk)
58
- end
67
+ def measure_exec(type, &blk) # :nodoc:
68
+ @conn.send(:measure_exec, type, &blk)
69
+ end
59
70
 
60
- def check_closed
61
- raise RuntimeError.new("Object already closed") if closed?
62
- end
71
+ def check_closed
72
+ raise RuntimeError.new("Object already closed") if closed?
73
+ end
63
74
 
64
75
  end#ParameterizedStatement
65
76
  end#Connection
@@ -12,96 +12,96 @@ class Connection
12
12
  # rows = pstmt.query(10, 20)
13
13
  # enum = pstmt.enumerate(10, 20)
14
14
  class PreparedStatement < ParameterizedStatement
15
- # Returns the number of parameters required
16
- # @return [Fixnum]
17
- def parameter_count
18
- @pmd ||= @java_obj.get_parameter_meta_data
19
- @pmd.get_parameter_count
20
- end
21
-
22
- # @return [NilClass]
23
- def close
15
+ # Returns the number of parameters required
16
+ # @return [Fixnum]
17
+ def parameter_count
18
+ @pmd ||= @java_obj.get_parameter_meta_data
19
+ @pmd.get_parameter_count
20
+ end
21
+
22
+ # @return [NilClass]
23
+ def close
24
24
  @conn.send(:close_pstmt, self)
25
- @java_obj.close
26
- @java_obj = nil
27
- end
28
-
29
- # @return [Fixnum]
30
- def update(*params)
31
- check_closed
32
-
33
- set_params(params)
34
- measure_exec(:p_update) { @java_obj.execute_update }
35
- end
36
-
37
- # @return [Array] Returns an Array if block is not given
38
- def query(*params, &blk)
39
- check_closed
40
-
41
- set_params(params)
42
- # sorry, ignoring privacy
43
- @conn.send(:process_and_close_rset,
44
- measure_exec(:p_query) { @java_obj.execute_query }, &blk)
45
- end
46
-
47
- # @return [JDBCHelper::Connection::ResultSetEnumerator]
48
- def enumerate(*params, &blk)
49
- check_closed
50
-
51
- return query(*params, &blk) if block_given?
52
-
53
- set_params(params)
54
- ResultSetEnumerator.new(measure_exec(:p_query) { @java_obj.execute_query })
55
- end
56
-
57
- # Adds to the batch
58
- # @return [NilClass]
59
- def add_batch(*params)
60
- check_closed
61
-
62
- set_params(params)
63
- @java_obj.add_batch
64
- end
65
- # Executes the batch
66
- def execute_batch
67
- check_closed
68
-
69
- measure_exec(:p_execute_batch) {
70
- @java_obj.executeBatch
71
- }
72
- end
73
- # Clears the batch
74
- # @return [NilClass]
75
- def clear_batch
76
- check_closed
77
-
78
- @java_obj.clear_batch
79
- end
80
-
81
- # Gives the JDBC driver a hint of the number of rows to fetch from the database by a single interaction.
82
- # This is only a hint. It may no effect at all.
83
- # @return [NilClass]
84
- def set_fetch_size(fsz)
85
- check_closed
86
-
87
- @fetch_size = fsz
88
- @java_obj.set_fetch_size fsz
89
- end
90
- alias fetch_size= set_fetch_size
91
-
92
- # Returns the fetch size of the prepared statement. If not set, nil is returned.
93
- # @return [Fixnum]
94
- attr_reader :fetch_size
25
+ @java_obj.close
26
+ @java_obj = nil
27
+ end
28
+
29
+ # @return [Fixnum]
30
+ def update(*params)
31
+ check_closed
32
+
33
+ set_params(params)
34
+ measure_exec(:p_update) { @java_obj.execute_update }
35
+ end
36
+
37
+ # @return [Array] Returns an Array if block is not given
38
+ def query(*params, &blk)
39
+ check_closed
40
+
41
+ set_params(params)
42
+ # sorry, ignoring privacy
43
+ @conn.send(:process_and_close_rset,
44
+ measure_exec(:p_query) { @java_obj.execute_query }, &blk)
45
+ end
46
+
47
+ # @return [JDBCHelper::Connection::ResultSetEnumerator]
48
+ def enumerate(*params, &blk)
49
+ check_closed
50
+
51
+ return query(*params, &blk) if block_given?
52
+
53
+ set_params(params)
54
+ ResultSetEnumerator.new(measure_exec(:p_query) { @java_obj.execute_query })
55
+ end
56
+
57
+ # Adds to the batch
58
+ # @return [NilClass]
59
+ def add_batch(*params)
60
+ check_closed
61
+
62
+ set_params(params)
63
+ @java_obj.add_batch
64
+ end
65
+ # Executes the batch
66
+ def execute_batch
67
+ check_closed
68
+
69
+ measure_exec(:p_execute_batch) {
70
+ @java_obj.executeBatch
71
+ }
72
+ end
73
+ # Clears the batch
74
+ # @return [NilClass]
75
+ def clear_batch
76
+ check_closed
77
+
78
+ @java_obj.clear_batch
79
+ end
80
+
81
+ # Gives the JDBC driver a hint of the number of rows to fetch from the database by a single interaction.
82
+ # This is only a hint. It may no effect at all.
83
+ # @return [NilClass]
84
+ def set_fetch_size(fsz)
85
+ check_closed
86
+
87
+ @fetch_size = fsz
88
+ @java_obj.set_fetch_size fsz
89
+ end
90
+ alias fetch_size= set_fetch_size
91
+
92
+ # Returns the fetch size of the prepared statement. If not set, nil is returned.
93
+ # @return [Fixnum]
94
+ attr_reader :fetch_size
95
95
  private
96
- def set_params(params) # :nodoc:
97
- params.each_with_index do | param, idx |
98
- set_param(idx + 1, param)
99
- end
100
- end
101
-
102
- def initialize(*args)
103
- super(*args)
104
- end
96
+ def set_params(params) # :nodoc:
97
+ params.each_with_index do | param, idx |
98
+ set_param(idx + 1, param)
99
+ end
100
+ end
101
+
102
+ def initialize(*args)
103
+ super(*args)
104
+ end
105
105
  end#PreparedStatment
106
106
  end#Connection
107
107
  end#JDBCHelper
@@ -1,115 +1,126 @@
1
1
  # encoding: UTF-8
2
2
  # Junegunn Choi (junegunn.c@gmail.com)
3
3
 
4
+ require 'bigdecimal'
5
+
4
6
  module JDBCHelper
5
7
  class Connection
6
8
  # Class for enumerating query results.
7
9
  # Automatically closed after used. When not used, you must close it explicitly by calling "close".
8
10
  class ResultSetEnumerator
9
- include Enumerable
11
+ include Enumerable
10
12
 
11
- def each
12
- return if closed?
13
+ def each
14
+ return if closed?
13
15
 
14
- count = -1
15
- begin
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
30
- yield Connection::Row.new(
31
- @col_labels,
32
- @col_labels_d,
33
- @getters.map { |gt|
34
- v = @rset.send gt, idx+=1
35
- @rset.was_null ? nil : v
36
- },
37
- count += 1)
38
- end
39
- ensure
40
- close
41
- end
42
- end
16
+ count = -1
17
+ begin
18
+ while @rset.next
19
+ idx = 0
20
+ # Oracle returns numbers in NUMERIC type, which can be of any precision.
21
+ # So, we retrieve the numbers in String type not to lose their precision.
22
+ # This can be quite annoying when you're just working with integers,
23
+ # so I tried the following code to automatically convert integer string into integer
24
+ # when it's obvious. However, the performance drop is untolerable.
25
+ # Thus, commented out.
26
+ #
27
+ # if v && @cols_meta[i-1] == java.sql.Types::NUMERIC && v !~ /[\.e]/i
28
+ # v.to_i
29
+ # else
30
+ # v
31
+ # end
32
+ yield Connection::Row.new(
33
+ @col_labels,
34
+ @col_labels_d,
35
+ @getters.map { |gt|
36
+ case gt
37
+ when :getBigNum
38
+ v = @rset.getBigDecimal idx+=1
39
+ @rset.was_null ? nil : BigDecimal.new(v.toPlainString).to_i
40
+ when :getBigDecimal
41
+ v = @rset.getBigDecimal idx+=1
42
+ @rset.was_null ? nil : BigDecimal.new(v.toPlainString)
43
+ else
44
+ v = @rset.send gt, idx+=1
45
+ @rset.was_null ? nil : v
46
+ end
47
+ },
48
+ count += 1)
49
+ end
50
+ ensure
51
+ close
52
+ end
53
+ end
43
54
 
44
- def close
45
- return if closed?
55
+ def close
56
+ return if closed?
46
57
 
47
- @rset.close
48
- @close_callback.call if @close_callback
49
- @closed = true
50
- end
58
+ @rset.close
59
+ @close_callback.call if @close_callback
60
+ @closed = true
61
+ end
51
62
 
52
- def closed?
53
- @closed
54
- end
63
+ def closed?
64
+ @closed
65
+ end
55
66
 
56
67
  private
57
- def initialize(rset, &close_callback) # :nodoc:
58
- unless rset.respond_to? :get_meta_data
59
- rset.close if rset
60
- @closed = true
61
- return
62
- end
68
+ def initialize(rset, &close_callback) # :nodoc:
69
+ unless rset.respond_to? :get_meta_data
70
+ rset.close if rset
71
+ @closed = true
72
+ return
73
+ end
63
74
 
64
- @close_callback = close_callback
65
- @rset = rset
66
- @rsmd = @rset.get_meta_data
67
- @num_col = @rsmd.get_column_count
68
- @getters = []
69
- @col_labels = []
70
- @col_labels_d = []
71
- (1..@num_col).each do | i |
72
- type = @rsmd.get_column_type(i)
75
+ @close_callback = close_callback
76
+ @rset = rset
77
+ @rsmd = @rset.get_meta_data
78
+ @num_col = @rsmd.get_column_count
79
+ @getters = []
80
+ @col_labels = []
81
+ @col_labels_d = []
82
+ (1..@num_col).each do | i |
83
+ type = @rsmd.get_column_type(i)
73
84
 
74
- @getters <<
75
- case type
76
- when java.sql.Types::NUMERIC, java.sql.Types::DECIMAL
77
- precision = @rsmd.get_precision(i)
78
- scale = @rsmd.get_scale(i)
85
+ @getters <<
86
+ case type
87
+ when java.sql.Types::NUMERIC, java.sql.Types::DECIMAL
88
+ precision = @rsmd.get_precision(i)
89
+ scale = @rsmd.get_scale(i)
79
90
 
80
- if precision > 0 && scale >= 0
81
- # Numbers with fractional parts
82
- if scale > 0
83
- if precision <= 16
84
- :getFloat
85
- else
86
- :getString
87
- end
88
- # Numbers without fractional parts
89
- else
90
- if precision <= 9
91
- :getInt
92
- elsif precision <= 18
93
- :getLong
94
- else
95
- :getString
96
- end
97
- end
98
- # No guarantee
99
- else
100
- :getString
101
- end
102
- else
103
- JDBCHelper::Connection::GETTER_MAP.fetch(type, :get_string)
104
- end
91
+ if precision > 0 && scale >= 0
92
+ # Numbers with fractional parts
93
+ if scale > 0
94
+ if precision <= 15
95
+ :getDouble
96
+ else
97
+ :getBigDecimal
98
+ end
99
+ # Numbers without fractional parts
100
+ else
101
+ if precision <= 9
102
+ :getInt
103
+ elsif precision <= 18
104
+ :getLong
105
+ else
106
+ :getBigNum
107
+ end
108
+ end
109
+ # No guarantee
110
+ else
111
+ :getBigDecimal
112
+ end
113
+ else
114
+ JDBCHelper::Connection::GETTER_MAP.fetch(type, :get_string)
115
+ end
105
116
 
106
- @col_labels << @rsmd.get_column_label(i)
107
- @col_labels_d << @col_labels.last.downcase
117
+ @col_labels << @rsmd.get_column_label(i)
118
+ @col_labels_d << @col_labels.last.downcase
108
119
 
109
- end
120
+ end
110
121
 
111
- @closed = false
112
- end
122
+ @closed = false
123
+ end
113
124
  end#ResultSetEnumerator
114
125
  end#Connection
115
126
  end#JDBCHelper