jdbc-helper 0.7.1 → 0.7.2

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