ruby-plsql 0.1.2 → 0.1.3

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/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ == 0.1.3 2008-04-15
2
+
3
+ * Improvements
4
+ * Support for overloaded procedure definitions (named parameter calls compared by number of arguments and by argument names,
5
+ sequential parameters compared by number of arguments)
6
+ * Bug fixes
7
+ * Fixed BigDecimal support for procedure parameters (all number types except from Fixnum are converted to Float)
8
+ * Fixed Date parameters support (always will convert to DateTime)
9
+
1
10
  == 0.1.2 2008-04-02
2
11
 
3
12
  * Improvements
@@ -30,9 +30,12 @@ module PLSQL
30
30
  @procedure = procedure.to_s.upcase
31
31
  @package = package
32
32
  @arguments = {}
33
- @return = nil
33
+ @argument_list = {}
34
+ @out_list = {}
35
+ @return = {}
36
+ @overloaded = false
34
37
  num_rows = @schema.connection.exec("
35
- SELECT a.argument_name, a.position, a.data_type, a.in_out, a.data_length, a.data_precision, a.data_scale
38
+ SELECT a.argument_name, a.position, a.data_type, a.in_out, a.data_length, a.data_precision, a.data_scale, a.overload
36
39
  FROM all_arguments a, all_objects o
37
40
  WHERE o.owner = :owner
38
41
  AND o.object_name = :object_name
@@ -42,9 +45,17 @@ module PLSQL
42
45
  AND NVL(a.package_name,'nil') = :package
43
46
  ", @schema.schema_name, @package ? @package : @procedure, @procedure, @package ? @package : 'nil'
44
47
  ) do |r|
45
- argument_name, position, data_type, in_out, data_length, data_precision, data_scale = r
48
+
49
+ argument_name, position, data_type, in_out, data_length, data_precision, data_scale, overload = r
50
+
51
+ @overloaded ||= !overload.nil?
52
+ # if not overloaded then store arguments at key 0
53
+ overload ||= 0
54
+ @arguments[overload] ||= {}
55
+ @return[overload] ||= nil
56
+
46
57
  if argument_name
47
- @arguments[argument_name.downcase.to_sym] = {
58
+ @arguments[overload][argument_name.downcase.to_sym] = {
48
59
  :position => position,
49
60
  :data_type => data_type,
50
61
  :in_out => in_out,
@@ -53,7 +64,7 @@ module PLSQL
53
64
  :data_scale => data_scale
54
65
  }
55
66
  else
56
- @return = {
67
+ @return[overload] = {
57
68
  :data_type => data_type,
58
69
  :in_out => in_out,
59
70
  :data_length => data_length,
@@ -62,34 +73,65 @@ module PLSQL
62
73
  }
63
74
  end
64
75
  end
65
- @argument_list = @arguments.keys.sort {|k1, k2| @arguments[k1][:position] <=> @arguments[k2][:position]}
66
- @out_list = @argument_list.select {|k| @arguments[k][:in_out] == 'OUT'}
76
+ @overloads = @arguments.keys.sort
77
+ @overloads.each do |overload|
78
+ @argument_list[overload] = @arguments[overload].keys.sort {|k1, k2| @arguments[overload][k1][:position] <=> @arguments[overload][k2][:position]}
79
+ @out_list[overload] = @argument_list[overload].select {|k| @arguments[overload][k][:in_out] == 'OUT'}
80
+ end
81
+ end
82
+
83
+ def overloaded?
84
+ @overloaded
67
85
  end
68
86
 
69
87
  def exec(*args)
88
+ # find which overloaded definition to use
89
+ # if definition is overloaded then match by number of arguments
90
+ if @overloaded
91
+ # named arguments
92
+ if args.size == 1 && args[0].is_a?(Hash)
93
+ number_of_args = args[0].keys.size
94
+ overload = @argument_list.keys.detect do |ov|
95
+ @argument_list[ov].size == number_of_args &&
96
+ @arguments[ov].keys.sort_by{|k| k.to_s} == args[0].keys.sort_by{|k| k.to_s}
97
+ end
98
+ # sequential arguments
99
+ # TODO: should try to implement matching by types of arguments
100
+ else
101
+ number_of_args = args.size
102
+ overload = @argument_list.keys.detect do |ov|
103
+ @argument_list[ov].size == number_of_args
104
+ end
105
+ end
106
+ raise ArgumentError, "Wrong number of arguments passed to overloaded PL/SQL procedure" unless overload
107
+ else
108
+ overload = 0
109
+ end
110
+
70
111
  sql = "BEGIN\n"
71
- sql << ":return := " if @return
112
+ sql << ":return := " if @return[overload]
72
113
  sql << "#{@schema.schema_name}." if @schema
73
114
  sql << "#{@package}." if @package
74
115
  sql << "#{@procedure}("
116
+
75
117
  # Named arguments
76
118
  args_list = []
77
119
  args_hash = {}
78
120
  if args.size == 1 and args[0].is_a?(Hash)
79
121
  sql << args[0].map do |k,v|
80
- raise ArgumentError, "Wrong argument passed to PL/SQL procedure" unless @arguments[k]
122
+ raise ArgumentError, "Wrong argument passed to PL/SQL procedure" unless @arguments[overload][k]
81
123
  args_list << k
82
124
  args_hash[k] = v
83
125
  "#{k.to_s} => :#{k.to_s}"
84
126
  end.join(', ')
85
- # Sequential arguments
127
+ # Sequential arguments
86
128
  else
87
- raise ArgumentError, "Too many arguments passed to PL/SQL procedure" if args.size > @argument_list.size
129
+ raise ArgumentError, "Too many arguments passed to PL/SQL procedure" if args.size > @argument_list[overload].size
88
130
  # Add missing arguments with nil value
89
- args = args + [nil]*(@argument_list.size-args.size) if args.size < @argument_list.size
131
+ args = args + [nil]*(@argument_list[overload].size-args.size) if args.size < @argument_list[overload].size
90
132
  i = 0
91
133
  sql << args.map do |v|
92
- k = @argument_list[i]
134
+ k = @argument_list[overload][i]
93
135
  i += 1
94
136
  args_list << k
95
137
  args_hash[k] = v
@@ -102,24 +144,24 @@ module PLSQL
102
144
  cursor = @schema.connection.parse(sql)
103
145
 
104
146
  args_list.each do |k|
105
- data_type, data_length = plsql_to_ruby_data_type(@arguments[k])
147
+ data_type, data_length = plsql_to_ruby_data_type(@arguments[overload][k])
106
148
  cursor.bind_param(":#{k.to_s}", ruby_value_to_ora_value(args_hash[k], data_type), data_type, data_length)
107
149
  end
108
150
 
109
- if @return
110
- data_type, data_length = plsql_to_ruby_data_type(@return)
151
+ if @return[overload]
152
+ data_type, data_length = plsql_to_ruby_data_type(@return[overload])
111
153
  cursor.bind_param(":return", nil, data_type, data_length)
112
154
  end
113
155
 
114
156
  cursor.exec
115
157
 
116
158
  # if function
117
- if @return
159
+ if @return[overload]
118
160
  result = ora_value_to_ruby_value(cursor[':return'])
119
161
  # if procedure with output parameters
120
- elsif @out_list.size > 0
162
+ elsif @out_list[overload].size > 0
121
163
  result = {}
122
- @out_list.each do |k|
164
+ @out_list[overload].each do |k|
123
165
  result[k] = ora_value_to_ruby_value(cursor[":#{k}"])
124
166
  end
125
167
  # if procedure without output parameters
@@ -151,7 +193,9 @@ module PLSQL
151
193
 
152
194
  def ruby_value_to_ora_value(val, type)
153
195
  if type == OraNumber
154
- val.is_a?(Bignum) ? val.to_f : val
196
+ val.is_a?(Fixnum) ? val : val.to_f
197
+ elsif type == DateTime
198
+ val ? val.to_datetime : nil
155
199
  else
156
200
  val
157
201
  end
@@ -2,7 +2,7 @@ module RubyPlsql #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 2
5
+ TINY = 3
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -1,5 +1,8 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
+ require "rubygems"
4
+ require "activerecord"
5
+
3
6
  describe "Procedure with string parameters" do
4
7
 
5
8
  before(:all) do
@@ -80,6 +83,12 @@ describe "Procedure with numeric parameters" do
80
83
  plsql.test_sum(123.123,456.456).should == 579.579
81
84
  end
82
85
 
86
+ it "should process BigDecimal parameters" do
87
+ plsql.test_sum(:p_num1 => BigDecimal.new("123.123"), :p_num2 => BigDecimal.new("456.456")).should == 579.579
88
+ end
89
+
90
+
91
+
83
92
  end
84
93
 
85
94
  describe "Procedure with date parameters" do
@@ -101,16 +110,30 @@ describe "Procedure with date parameters" do
101
110
  plsql.logoff
102
111
  end
103
112
 
104
- it "should process date parameters" do
113
+ it "should process DateTime parameters" do
105
114
  now = DateTime.new(2008,8,12,14,28,0)
106
115
  plsql.test_date(now).should == now + 1
107
116
  end
108
117
 
109
- it "should process old date parameters" do
118
+ it "should process old DateTime parameters" do
110
119
  now = DateTime.new(1900,1,1,12,0,0)
111
120
  plsql.test_date(now).should == now + 1
112
121
  end
113
122
 
123
+ it "should process Date parameters" do
124
+ now = Date.new(2008,8,12)
125
+ plsql.test_date(now).should == now + 1
126
+ end
127
+
128
+ it "should process old Date parameters" do
129
+ now = Date.new(1900,1,1)
130
+ plsql.test_date(now).should == now + 1
131
+ end
132
+
133
+ it "should process nil date parameters" do
134
+ plsql.test_date(nil).should be_nil
135
+ end
136
+
114
137
  end
115
138
 
116
139
  describe "Procedure with timestamp parameters" do
@@ -173,4 +196,93 @@ describe "Procedure with output parameters" do
173
196
  plsql.test_copy.should == { :p_to => nil, :p_to_double => nil }
174
197
  end
175
198
 
176
- end
199
+ end
200
+
201
+ describe "Package with procedures with same name but different argument lists" do
202
+ before(:all) do
203
+ plsql.connection = conn = OCI8.new("hr","hr","xe")
204
+ plsql.connection.exec <<-EOS
205
+ CREATE OR REPLACE PACKAGE test_package2 IS
206
+ FUNCTION test_procedure ( p_string VARCHAR2 )
207
+ RETURN VARCHAR2;
208
+ PROCEDURE test_procedure ( p_string VARCHAR2, p_result OUT VARCHAR2 )
209
+ ;
210
+ PROCEDURE test_procedure ( p_number NUMBER, p_result OUT VARCHAR2 )
211
+ ;
212
+ FUNCTION test_procedure2 ( p_string VARCHAR2 )
213
+ RETURN VARCHAR2;
214
+ END;
215
+ EOS
216
+ plsql.connection.exec <<-EOS
217
+ CREATE OR REPLACE PACKAGE BODY test_package2 IS
218
+ FUNCTION test_procedure ( p_string VARCHAR2 )
219
+ RETURN VARCHAR2
220
+ IS
221
+ BEGIN
222
+ RETURN UPPER(p_string);
223
+ END test_procedure;
224
+ PROCEDURE test_procedure ( p_string VARCHAR2, p_result OUT VARCHAR2 )
225
+ IS
226
+ BEGIN
227
+ p_result := UPPER(p_string);
228
+ END test_procedure;
229
+ PROCEDURE test_procedure ( p_number NUMBER, p_result OUT VARCHAR2 )
230
+ IS
231
+ BEGIN
232
+ p_result := LOWER(TO_CHAR(p_number));
233
+ END test_procedure;
234
+ FUNCTION test_procedure2 ( p_string VARCHAR2 )
235
+ RETURN VARCHAR2
236
+ IS
237
+ BEGIN
238
+ RETURN UPPER(p_string);
239
+ END test_procedure2;
240
+ END;
241
+ EOS
242
+
243
+ end
244
+
245
+ after(:all) do
246
+ plsql.logoff
247
+ end
248
+
249
+ it "should find existing package" do
250
+ PLSQL::Package.find(plsql, :test_package2).should_not be_nil
251
+ end
252
+
253
+ it "should identify overloaded procedure definition" do
254
+ @procedure = PLSQL::Procedure.find(plsql, :test_procedure, "TEST_PACKAGE2")
255
+ @procedure.should_not be_nil
256
+ @procedure.should be_overloaded
257
+ end
258
+
259
+ it "should identify non-overloaded procedure definition" do
260
+ @procedure = PLSQL::Procedure.find(plsql, :test_procedure2, "TEST_PACKAGE2")
261
+ @procedure.should_not be_nil
262
+ @procedure.should_not be_overloaded
263
+ end
264
+
265
+ it "should execute correct procedures based on number of arguments and return correct value" do
266
+ plsql.test_package2.test_procedure('xxx').should == 'XXX'
267
+ plsql.test_package2.test_procedure('xxx', nil).should == {:p_result => 'XXX'}
268
+ end
269
+
270
+ it "should execute correct procedures based on number of named arguments and return correct value" do
271
+ plsql.test_package2.test_procedure(:p_string => 'xxx').should == 'XXX'
272
+ plsql.test_package2.test_procedure(:p_string => 'xxx', :p_result => nil).should == {:p_result => 'XXX'}
273
+ end
274
+
275
+ it "should raise exception if procedure cannot be found based on number of arguments" do
276
+ lambda { plsql.test_package2.test_procedure() }.should raise_error(ArgumentError)
277
+ end
278
+
279
+ # TODO: should try to implement matching by types of arguments
280
+ # it "should find procedure based on types of arguments" do
281
+ # plsql.test_package2.test_procedure(111, nil).should == {:p_result => '111'}
282
+ # end
283
+
284
+ it "should find procedure based on names of named arguments" do
285
+ plsql.test_package2.test_procedure(:p_number => 111, :p_result => nil).should == {:p_result => '111'}
286
+ end
287
+
288
+ end
data/website/index.html CHANGED
@@ -33,7 +33,7 @@
33
33
  <h1>Ruby API for PL/SQL</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/ruby-plsql"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/ruby-plsql" class="numbers">0.1.2</a>
36
+ <a href="http://rubyforge.org/projects/ruby-plsql" class="numbers">0.1.3</a>
37
37
  </div>
38
38
  <h1>&#x2192; &#8216;ruby-plsql&#8217;</h1>
39
39
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-plsql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Raimonds Simanovskis
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-04-02 00:00:00 +03:00
12
+ date: 2008-04-16 00:00:00 +03:00
13
13
  default_executable:
14
14
  dependencies: []
15
15