jdbc-helper 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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