jdbc-helper 0.7.1 → 0.7.2

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.markdown CHANGED
@@ -112,6 +112,16 @@ end
112
112
  del_count = conn.update("DELETE FROM T")
113
113
  ```
114
114
 
115
+ ### Executing any SQL
116
+ ```ruby
117
+ rset = conn.execute("SELECT * FROM T")
118
+ rset.each do |row|
119
+ # Returned result must be used or closed
120
+ end
121
+
122
+ del_count = conn.execute("DELETE FROM T")
123
+ ```
124
+
115
125
  ### Transaction
116
126
  ```ruby
117
127
  committed = conn.transaction do |tx|
@@ -24,7 +24,7 @@ class ParameterizedStatement
24
24
  def set_param(idx, param)
25
25
  case param
26
26
  when NilClass
27
- @java_obj.setNull idx, java.sql.Types::NULL
27
+ set_null idx, param
28
28
  when Fixnum
29
29
  @java_obj.setLong idx, param
30
30
  when Bignum
@@ -64,6 +64,10 @@ class ParameterizedStatement
64
64
  end
65
65
 
66
66
  private
67
+ def set_null idx, param
68
+ @java_obj.setNull idx, java.sql.Types::NULL
69
+ end
70
+
67
71
  def measure_exec(type, &blk) # :nodoc:
68
72
  @conn.send(:measure_exec, type, &blk)
69
73
  end
@@ -1,6 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  # Junegunn Choi (junegunn.c@gmail.com)
3
3
 
4
+ require 'logger'
5
+
4
6
  module JDBCHelper
5
7
  class Connection
6
8
  # An encapsulation of Java PreparedStatment object.
@@ -15,8 +17,7 @@ class PreparedStatement < ParameterizedStatement
15
17
  # Returns the number of parameters required
16
18
  # @return [Fixnum]
17
19
  def parameter_count
18
- @pmd ||= @java_obj.get_parameter_meta_data
19
- @pmd.get_parameter_count
20
+ @pmd.getParameterCount
20
21
  end
21
22
 
22
23
  # @return [NilClass]
@@ -26,6 +27,18 @@ class PreparedStatement < ParameterizedStatement
26
27
  @java_obj = nil
27
28
  end
28
29
 
30
+ # @return [Fixnum|ResultSetEnumerator]
31
+ def execute(*params)
32
+ check_closed
33
+
34
+ set_params(params)
35
+ if measure_exec(:p_execute) { @java_obj.execute }
36
+ ResultSetEnumerator.new(measure_exec(:p_query) { @java_obj.getResultSet })
37
+ else
38
+ @java_obj.getUpdateCount
39
+ end
40
+ end
41
+
29
42
  # @return [Fixnum]
30
43
  def update(*params)
31
44
  check_closed
@@ -99,8 +112,23 @@ private
99
112
  end
100
113
  end
101
114
 
115
+ def set_null idx, param
116
+ @java_obj.setNull idx, @types ? @types[idx - 1] : java.sql.Types::NULL
117
+ end
118
+
102
119
  def initialize(*args)
103
120
  super(*args)
121
+
122
+ begin
123
+ @pmd = @java_obj.getParameterMetaData
124
+ @types = @pmd.getParameterCount.times.map { |idx|
125
+ # Oracle does not support getParameterType
126
+ @pmd.getParameterType(idx + 1) rescue java.sql.Types::NULL
127
+ }
128
+ rescue Exception => e
129
+ Logger.new($stderr).warn e.to_s
130
+ @types = nil
131
+ end
104
132
  end
105
133
  end#PreparedStatment
106
134
  end#Connection
@@ -252,6 +252,29 @@ class Connection
252
252
  status == :committed
253
253
  end
254
254
 
255
+ # Executes an SQL and returns the count of the update rows or a ResultSetEnumerator object
256
+ # depending on the type of the given statement.
257
+ # If a ResultSetEnumerator is returned, it must be enumerated or closed.
258
+ # @param [String] qstr SQL string
259
+ # @return [Fixnum|ResultSetEnumerator]
260
+ def execute(qstr)
261
+ check_closed
262
+
263
+ stmt = @spool.take
264
+ begin
265
+ if measure_exec(:execute) { stmt.execute(qstr) }
266
+ ResultSetEnumerator.send(:new, stmt.getResultSet) { @spool.give stmt }
267
+ else
268
+ rset = stmt.getUpdateCount
269
+ @spool.give stmt
270
+ rset
271
+ end
272
+ rescue Exception => e
273
+ @spool.give stmt
274
+ raise
275
+ end
276
+ end
277
+
255
278
  # Executes an update and returns the count of the updated rows.
256
279
  # @param [String] qstr SQL string
257
280
  # @return [Fixnum] Count of affected records
@@ -283,8 +306,8 @@ class Connection
283
306
  check_closed
284
307
 
285
308
  @spool.with do | stmt |
286
- measure_exec(:query) { stmt.execute(qstr) }
287
- process_and_close_rset(stmt.get_result_set, &blk)
309
+ rset = measure_exec(:query) { stmt.execute_query(qstr) }
310
+ process_and_close_rset(rset, &blk)
288
311
  end
289
312
  end
290
313
 
@@ -309,13 +332,12 @@ class Connection
309
332
 
310
333
  stmt = @spool.take
311
334
  begin
312
- measure_exec(:query) { stmt.execute(qstr) }
335
+ rset = measure_exec(:query) { stmt.execute_query(qstr) }
336
+ return ResultSetEnumerator.send(:new, rset) { @spool.give stmt }
313
337
  rescue Exception
314
338
  @spool.give stmt
315
339
  raise
316
340
  end
317
-
318
- ResultSetEnumerator.send(:new, stmt.get_result_set) { @spool.give stmt }
319
341
  end
320
342
 
321
343
  # Adds a statement to be executed in batch
@@ -572,5 +572,102 @@ class TestConnection < Test::Unit::TestCase
572
572
  end
573
573
  end
574
574
  end
575
+
576
+ def test_invalid_sql
577
+ each_connection do | conn |
578
+ reset_test_table conn
579
+ assert_raise(NativeException) do
580
+ conn.query("delete from #{TEST_TABLE}")
581
+ end
582
+ omit "Oracle does not throw Exception when " +
583
+ "select statement given to executeUpdate" if conn.driver =~ /oracle/
584
+ assert_raise(NativeException) do
585
+ conn.update("select * from #{TEST_TABLE}")
586
+ end
587
+ end
588
+ end
589
+
590
+ def test_execute
591
+ each_connection do | conn |
592
+ reset_test_table conn
593
+
594
+ rse_class = JDBCHelper::Connection::ResultSetEnumerator
595
+
596
+ # Connection#execute
597
+ assert_equal 1, conn.execute("insert into #{TEST_TABLE} values (0, 'A')")
598
+ assert_equal 1, conn.execute("insert into #{TEST_TABLE} values (1, 'A')")
599
+ assert_equal rse_class, (ret = conn.execute("select * from #{TEST_TABLE}")).class
600
+ cnt = 0
601
+ ret.each do |row|
602
+ assert_equal 'A', row.b
603
+ cnt += 1
604
+ end
605
+ assert_equal 2, cnt
606
+ assert_equal 2, conn.execute("delete from #{TEST_TABLE}")
607
+
608
+ # PreparedStatment#execute
609
+ begin
610
+ pstmt_ins = conn.prepare "insert into #{TEST_TABLE} values (?, 'A')"
611
+ pstmt_sel = conn.prepare "select * from #{TEST_TABLE}"
612
+ pstmt_del = conn.prepare "delete from #{TEST_TABLE}"
613
+
614
+ assert_equal 1, pstmt_ins.execute(0)
615
+ assert_equal 1, pstmt_ins.execute(1)
616
+ assert_equal rse_class, (ret = pstmt_sel.execute).class
617
+ cnt = 0
618
+ ret.each do |row|
619
+ assert_equal 'A', row.b
620
+ cnt += 1
621
+ end
622
+ assert_equal 2, cnt
623
+ assert_equal 2, pstmt_del.execute
624
+ assert_equal rse_class, (ret = pstmt_sel.execute).class
625
+ ensure
626
+ [pstmt_ins, pstmt_sel, pstmt_del].each do |ps|
627
+ ps.close rescue nil
628
+ end
629
+ end
630
+ end
631
+ end
632
+
633
+ def test_statement_pool_leakage
634
+ q = "select * from #{TEST_TABLE}"
635
+ u = "update #{TEST_TABLE} set a = 1"
636
+ each_connection do |conn|
637
+ reset_test_table conn
638
+ conn.update "insert into #{TEST_TABLE} values (0, 'A')"
639
+
640
+ assert_equal 20, 20.times.select {
641
+ conn.execute(q).close
642
+ conn.enumerate(q).close
643
+ conn.query q
644
+ conn.update u
645
+
646
+ conn.execute(q).count == 1
647
+ }.count
648
+ end
649
+ end
650
+
651
+ def test_prepared_statement_set_null
652
+ each_connection do |conn|
653
+ conn.update "drop table #{TEST_TABLE}" rescue nil
654
+
655
+ begin
656
+ conn.update(
657
+ case conn.driver
658
+ when /sqlserver/
659
+ "create table #{TEST_TABLE} (a int, b varchar(100), c datetime2, d decimal(10, 2))"
660
+ else
661
+ "create table #{TEST_TABLE} (a int, b varchar(100), c timestamp, d decimal(10, 2))"
662
+ end
663
+ )
664
+ pstmt = conn.prepare "insert into #{TEST_TABLE} (a, b, c, d) values (?, ?, ?, ?)"
665
+ pstmt.update nil, nil, nil, nil
666
+ ensure
667
+ pstmt.close rescue nil
668
+ conn.update "drop table #{TEST_TABLE}"
669
+ end
670
+ end
671
+ end
575
672
  end
576
673
 
data/test/testrb ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ # 2012/03/07-
4
+
5
+ require 'rubygems'
6
+ ENV['BUNDLE_GEMFILE'] = File.join(File.dirname(__FILE__), '..', 'Gemfile')
7
+ require 'bundler/setup'
8
+ require 'test-unit'
9
+ exit Test::Unit::AutoRunner.run(true)
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: jdbc-helper
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.7.1
5
+ version: 0.7.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Junegunn Choi
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-02-28 00:00:00 Z
13
+ date: 2012-03-13 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: insensitive_hash
@@ -110,6 +110,7 @@ files:
110
110
  - test/test_connectors.rb
111
111
  - test/test_object_wrapper.rb
112
112
  - test/test_sql.rb
113
+ - test/testrb
113
114
  homepage: http://github.com/junegunn/jdbc-helper
114
115
  licenses:
115
116
  - MIT
@@ -149,3 +150,4 @@ test_files:
149
150
  - test/test_connectors.rb
150
151
  - test/test_object_wrapper.rb
151
152
  - test/test_sql.rb
153
+ - test/testrb