ruby-plsql 0.5.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +5 -5
  2. data/.github/stale.yml +37 -0
  3. data/.github/workflows/rubocop.yml +37 -0
  4. data/.github/workflows/test.yml +69 -0
  5. data/.rubocop.yml +147 -0
  6. data/.travis.yml +88 -0
  7. data/.travis/oracle/download.sh +15 -0
  8. data/.travis/oracle/install.sh +32 -0
  9. data/.travis/setup_accounts.sh +9 -0
  10. data/Gemfile +17 -9
  11. data/History.txt +76 -0
  12. data/README.md +29 -6
  13. data/Rakefile +31 -26
  14. data/VERSION +1 -1
  15. data/Vagrantfile +4 -4
  16. data/ci/network/admin/tnsnames.ora +7 -0
  17. data/ci/setup_accounts.sh +9 -0
  18. data/gemfiles/Gemfile.activerecord-5.0 +21 -0
  19. data/gemfiles/Gemfile.activerecord-5.1 +21 -0
  20. data/gemfiles/Gemfile.activerecord-5.2 +21 -0
  21. data/gemfiles/Gemfile.activerecord-6.0 +21 -0
  22. data/gemfiles/Gemfile.activerecord-6.1 +21 -0
  23. data/gemfiles/Gemfile.activerecord-main +21 -0
  24. data/lib/plsql/connection.rb +19 -22
  25. data/lib/plsql/helpers.rb +1 -3
  26. data/lib/plsql/jdbc_connection.rb +70 -68
  27. data/lib/plsql/oci8_patches.rb +2 -2
  28. data/lib/plsql/oci_connection.rb +62 -77
  29. data/lib/plsql/package.rb +61 -46
  30. data/lib/plsql/procedure.rb +358 -78
  31. data/lib/plsql/procedure_call.rb +508 -463
  32. data/lib/plsql/schema.rb +96 -101
  33. data/lib/plsql/sequence.rb +10 -13
  34. data/lib/plsql/sql_statements.rb +9 -11
  35. data/lib/plsql/table.rb +60 -63
  36. data/lib/plsql/type.rb +71 -76
  37. data/lib/plsql/variable.rb +90 -94
  38. data/lib/plsql/version.rb +1 -1
  39. data/lib/plsql/view.rb +16 -19
  40. data/ruby-plsql.gemspec +55 -35
  41. data/spec/plsql/connection_spec.rb +72 -66
  42. data/spec/plsql/package_spec.rb +63 -14
  43. data/spec/plsql/procedure_spec.rb +603 -261
  44. data/spec/plsql/schema_spec.rb +47 -23
  45. data/spec/plsql/sequence_spec.rb +2 -2
  46. data/spec/plsql/sql_statements_spec.rb +6 -6
  47. data/spec/plsql/table_spec.rb +84 -79
  48. data/spec/plsql/type_spec.rb +24 -30
  49. data/spec/plsql/variable_spec.rb +80 -88
  50. data/spec/plsql/version_spec.rb +4 -4
  51. data/spec/plsql/view_spec.rb +42 -42
  52. data/spec/spec_helper.rb +38 -35
  53. data/spec/support/create_arunit_user.sql +2 -0
  54. data/spec/support/custom_config.rb.sample +14 -0
  55. data/spec/support/test_db.rb +12 -13
  56. data/spec/support/unlock_and_setup_hr_user.sql +2 -0
  57. metadata +111 -34
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe "Package" do
4
4
  before(:all) do
@@ -20,17 +20,16 @@ describe "Package" do
20
20
  END test_procedure;
21
21
  END;
22
22
  SQL
23
-
24
23
  end
25
-
24
+
26
25
  after(:all) do
27
26
  plsql.execute "DROP PACKAGE test_package"
28
27
  plsql.logoff
29
28
  end
30
-
29
+
31
30
  before(:each) do
32
31
  end
33
-
32
+
34
33
  it "should find existing package" do
35
34
  expect(PLSQL::Package.find(plsql, :test_package)).not_to be_nil
36
35
  end
@@ -44,7 +43,7 @@ describe "Package" do
44
43
  end
45
44
 
46
45
  it "should execute package function and return correct value" do
47
- expect(plsql.test_package.test_procedure('xxx')).to eq('XXX')
46
+ expect(plsql.test_package.test_procedure("xxx")).to eq("XXX")
48
47
  end
49
48
 
50
49
  it "should report an existing procedure as existing" do
@@ -55,6 +54,56 @@ describe "Package" do
55
54
  expect(plsql.test_package.procedure_defined?(:inexistent_procedure)).to be_falsey
56
55
  end
57
56
 
57
+ it "should search objects via []" do
58
+ package = PLSQL::Package.find(plsql, :test_package)
59
+
60
+ [:Test_Procedure, :test_procedure, "test_procedure", "TEST_PROCEDURE"].each do |name_variant|
61
+ expect(package[name_variant]).to be_a PLSQL::Procedure
62
+ end
63
+
64
+ [:Test_Variable, :test_variable, "test_variable", "TEST_VARIABLE"].each do |name_variant|
65
+ expect(package[name_variant]).to be_a PLSQL::Variable
66
+ end
67
+ end
68
+
69
+ context "with a user with execute privilege who is not the package owner" do
70
+ before(:all) do
71
+ plsql.execute("grant execute on TEST_PACKAGE to #{DATABASE_USERS_AND_PASSWORDS[1][0]}")
72
+ @original_connection = plsql.connection
73
+ @conn = get_connection(1)
74
+ end
75
+
76
+ before(:each) do
77
+ # resetting connection clears cached package objects and schema name
78
+ plsql.connection = @conn
79
+ end
80
+
81
+ after(:all) do
82
+ plsql.logoff
83
+ plsql.connection = @original_connection
84
+ end
85
+
86
+ it "should not find existing package" do
87
+ expect(PLSQL::Package.find(plsql, :test_package)).to be_nil
88
+ end
89
+
90
+ context "who sets current_schema to match the package owner" do
91
+ before(:all) do
92
+ plsql.execute "ALTER SESSION set current_schema=#{DATABASE_USERS_AND_PASSWORDS[0][0]}"
93
+ end
94
+
95
+ it "should find existing package" do
96
+ expect(PLSQL::Package.find(plsql, :test_package)).not_to be_nil
97
+ end
98
+
99
+ it "should report an existing procedure as existing" do
100
+ expect(plsql.test_package.procedure_defined?(:test_procedure)).to be_truthy
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
58
107
  describe "variables" do
59
108
  it "should set and get package variable value" do
60
109
  plsql.test_package.test_variable = 1
@@ -65,7 +114,7 @@ describe "Package" do
65
114
  end
66
115
 
67
116
  describe "Synonym to package" do
68
-
117
+
69
118
  before(:all) do
70
119
  plsql.connection = get_connection
71
120
  plsql.execute <<-SQL
@@ -86,38 +135,38 @@ describe "Synonym to package" do
86
135
  SQL
87
136
  plsql.execute "CREATE SYNONYM test_pkg_synonym FOR hr.test_package"
88
137
  end
89
-
138
+
90
139
  after(:all) do
91
140
  plsql.execute "DROP SYNONYM test_pkg_synonym" rescue nil
92
141
  plsql.logoff
93
142
  end
94
-
143
+
95
144
  it "should find synonym to package" do
96
145
  expect(PLSQL::Package.find(plsql, :test_pkg_synonym)).not_to be_nil
97
146
  end
98
147
 
99
148
  it "should execute package function using synonym and return correct value" do
100
- expect(plsql.test_pkg_synonym.test_procedure('xxx')).to eq('XXX')
149
+ expect(plsql.test_pkg_synonym.test_procedure("xxx")).to eq("XXX")
101
150
  end
102
151
 
103
152
  end
104
153
 
105
154
  describe "Public synonym to package" do
106
-
155
+
107
156
  before(:all) do
108
157
  plsql.connection = get_connection
109
158
  end
110
-
159
+
111
160
  after(:all) do
112
161
  plsql.logoff
113
162
  end
114
-
163
+
115
164
  it "should find public synonym to package" do
116
165
  expect(PLSQL::Package.find(plsql, :utl_encode)).not_to be_nil
117
166
  end
118
167
 
119
168
  it "should execute package function using public synonym and return correct value" do
120
- expect(plsql.utl_encode.base64_encode('abc')).to eq('4372773D')
169
+ expect(plsql.utl_encode.base64_encode("abc")).to eq("4372773D")
121
170
  end
122
171
 
123
172
  end
@@ -1,27 +1,28 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe "Parameter type mapping /" do
6
- describe "Function with string parameters" do
6
+
7
+ shared_examples "Function with string parameters" do |datatype|
7
8
  before(:all) do
8
9
  plsql.connect! CONNECTION_PARAMS
9
10
  plsql.execute <<-SQL
10
11
  CREATE OR REPLACE FUNCTION test_uppercase
11
- ( p_string VARCHAR2 )
12
- RETURN VARCHAR2
12
+ ( p_string #{datatype} )
13
+ RETURN #{datatype}
13
14
  IS
14
15
  BEGIN
15
16
  RETURN UPPER(p_string);
16
17
  END test_uppercase;
17
18
  SQL
18
19
  end
19
-
20
+
20
21
  after(:all) do
21
22
  plsql.execute "DROP FUNCTION test_uppercase"
22
23
  plsql.logoff
23
24
  end
24
-
25
+
25
26
  it "should find existing procedure" do
26
27
  expect(PLSQL::Procedure.find(plsql, :test_uppercase)).not_to be_nil
27
28
  end
@@ -31,23 +32,23 @@ describe "Parameter type mapping /" do
31
32
  end
32
33
 
33
34
  it "should execute function and return correct value" do
34
- expect(plsql.test_uppercase('xxx')).to eq('XXX')
35
+ expect(plsql.test_uppercase("xxx")).to eq("XXX")
35
36
  end
36
37
 
37
38
  it "should execute function with named parameters and return correct value" do
38
- expect(plsql.test_uppercase(:p_string => 'xxx')).to eq('XXX')
39
+ expect(plsql.test_uppercase(p_string: "xxx")).to eq("XXX")
39
40
  end
40
41
 
41
42
  it "should raise error if wrong number of arguments is passed" do
42
- expect { plsql.test_uppercase('xxx','yyy') }.to raise_error(ArgumentError)
43
+ expect { plsql.test_uppercase("xxx", "yyy") }.to raise_error(ArgumentError)
43
44
  end
44
45
 
45
46
  it "should raise error if wrong named argument is passed" do
46
- expect { plsql.test_uppercase(:p_string2 => 'xxx') }.to raise_error(ArgumentError)
47
+ expect { plsql.test_uppercase(p_string2: "xxx") }.to raise_error(ArgumentError)
47
48
  end
48
-
49
+
49
50
  it "should execute function with schema name specified" do
50
- expect(plsql.hr.test_uppercase('xxx')).to eq('XXX')
51
+ expect(plsql.hr.test_uppercase("xxx")).to eq("XXX")
51
52
  end
52
53
 
53
54
  it "should process nil parameter as NULL" do
@@ -56,88 +57,90 @@ describe "Parameter type mapping /" do
56
57
 
57
58
  end
58
59
 
59
- describe "Function with numeric parameters" do
60
+ ["VARCHAR", "VARCHAR2"].each do |datatype|
61
+ describe "Function with #{datatype} parameters" do
62
+ it_should_behave_like "Function with string parameters", datatype
63
+ end
64
+ end
65
+
66
+ shared_examples "Function with numeric" do |ora_data_type, class_, num1, num2, expected, mandatory|
60
67
  before(:all) do
61
68
  plsql.connect! CONNECTION_PARAMS
62
69
  plsql.execute <<-SQL
63
70
  CREATE OR REPLACE FUNCTION test_sum
64
- ( p_num1 NUMBER, p_num2 NUMBER )
65
- RETURN NUMBER
71
+ ( p_num1 #{ora_data_type}, p_num2 #{ora_data_type} )
72
+ RETURN #{ora_data_type}
66
73
  IS
67
74
  BEGIN
68
75
  RETURN p_num1 + p_num2;
69
76
  END test_sum;
70
77
  SQL
71
- plsql.execute <<-SQL
72
- CREATE OR REPLACE FUNCTION test_number_1
73
- ( p_num NUMBER )
74
- RETURN VARCHAR2
75
- IS
76
- BEGIN
77
- IF p_num = 1 THEN
78
- RETURN 'Y';
79
- ELSIF p_num = 0 THEN
80
- RETURN 'N';
81
- ELSIF p_num IS NULL THEN
82
- RETURN NULL;
83
- ELSE
84
- RETURN 'UNKNOWN';
85
- END IF;
86
- END test_number_1;
87
- SQL
88
- plsql.execute <<-SQL
89
- CREATE OR REPLACE PROCEDURE test_integers
90
- ( p_pls_int PLS_INTEGER, p_bin_int BINARY_INTEGER, x_pls_int OUT PLS_INTEGER, x_bin_int OUT BINARY_INTEGER )
91
- IS
92
- BEGIN
93
- x_pls_int := p_pls_int;
94
- x_bin_int := p_bin_int;
95
- END;
96
- SQL
97
78
  end
98
-
79
+
99
80
  after(:all) do
100
81
  plsql.execute "DROP FUNCTION test_sum"
101
- plsql.execute "DROP FUNCTION test_number_1"
102
- plsql.execute "DROP PROCEDURE test_integers"
103
82
  plsql.logoff
104
83
  end
105
-
106
- it "should process integer parameters" do
107
- expect(plsql.test_sum(123,456)).to eq(579)
108
- end
109
84
 
110
- it "should process big integer parameters" do
111
- expect(plsql.test_sum(123123123123,456456456456)).to eq(579579579579)
85
+ it "should get #{ora_data_type} variable type mapped to #{class_.to_s}" do
86
+ expect(plsql.test_sum(num1, num2)).to be_a class_
112
87
  end
113
-
114
- it "should process float parameters and return BigDecimal" do
115
- expect(plsql.test_sum(123.123,456.456)).to eq(BigDecimal("579.579"))
88
+ it "should process input parameters and return correct result" do
89
+ expect(plsql.test_sum(num1, num2)).to eq(expected)
116
90
  end
117
91
 
118
- it "should process BigDecimal parameters and return BigDecimal" do
119
- expect(plsql.test_sum(:p_num1 => BigDecimal("123.123"), :p_num2 => BigDecimal("456.456"))).to eq(BigDecimal("579.579"))
92
+ it "should process nil parameter as NULL" do
93
+ expect(plsql.test_sum(num1, nil)).to be_nil
94
+ end unless mandatory
95
+
96
+ end
97
+
98
+ @big_number = ("1234567890" * 3).to_i
99
+ [
100
+ { ora_data_type: "INTEGER", class: Integer, num1: @big_number, num2: @big_number, expected: @big_number * 2 },
101
+ { ora_data_type: "NUMBER", class: BigDecimal, num1: 12345.12345, num2: 12345.12345, expected: 24690.2469 },
102
+ { ora_data_type: "PLS_INTEGER", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578 },
103
+ { ora_data_type: "BINARY_INTEGER", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578 },
104
+ { ora_data_type: "SIMPLE_INTEGER", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578, mandatory: true },
105
+ { ora_data_type: "NATURAL", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578 },
106
+ { ora_data_type: "NATURALN", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578, mandatory: true },
107
+ { ora_data_type: "POSITIVE", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578 },
108
+ { ora_data_type: "POSITIVEN", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578, mandatory: true },
109
+ { ora_data_type: "SIGNTYPE", class: Integer, num1: 1, num2: -1, expected: 0 },
110
+ ].each do |row|
111
+ ora_data_type, class_, num1, num2, expected, mandatory = row.values
112
+ describe ora_data_type do
113
+ include_examples "Function with numeric", ora_data_type, class_, num1, num2, expected, mandatory
120
114
  end
115
+ end
121
116
 
122
- it "should process nil parameter as NULL" do
123
- expect(plsql.test_sum(123,nil)).to be_nil
117
+ describe "Boolean to NUMBER conversion" do
118
+ before(:all) do
119
+ plsql.connect! CONNECTION_PARAMS
120
+ plsql.execute <<-SQL
121
+ CREATE OR REPLACE FUNCTION test_num ( p_num NUMBER) RETURN NUMBER
122
+ IS
123
+ BEGIN
124
+ RETURN p_num;
125
+ END test_num;
126
+ SQL
124
127
  end
125
128
 
129
+ after(:all) do
130
+ plsql.execute "DROP FUNCTION test_num"
131
+ plsql.logoff
132
+ end
126
133
  it "should convert true value to 1 for NUMBER parameter" do
127
- expect(plsql.test_number_1(true)).to eq('Y')
134
+ expect(plsql.test_num(true)).to eq(1)
128
135
  end
129
136
 
130
137
  it "should convert false value to 0 for NUMBER parameter" do
131
- expect(plsql.test_number_1(false)).to eq('N')
132
- end
133
-
134
- it "should process binary integer parameters" do
135
- expect(plsql.test_integers(123, 456)).to eq({:x_pls_int => 123, :x_bin_int => 456})
138
+ expect(plsql.test_num(false)).to eq(0)
136
139
  end
137
140
  end
138
141
 
139
142
  describe "Function with date parameters" do
140
-
143
+
141
144
  before(:all) do
142
145
  plsql.connect! CONNECTION_PARAMS
143
146
  plsql.execute <<-SQL
@@ -150,7 +153,7 @@ describe "Parameter type mapping /" do
150
153
  END test_date;
151
154
  SQL
152
155
  end
153
-
156
+
154
157
  before(:each) do
155
158
  plsql.default_timezone = :local
156
159
  end
@@ -159,46 +162,46 @@ describe "Parameter type mapping /" do
159
162
  plsql.execute "DROP FUNCTION test_date"
160
163
  plsql.logoff
161
164
  end
162
-
165
+
163
166
  it "should process Time parameters" do
164
- now = Time.local(2008,8,12,14,28,0)
165
- expect(plsql.test_date(now)).to eq(now + 60*60*24)
167
+ now = Time.local(2008, 8, 12, 14, 28, 0)
168
+ expect(plsql.test_date(now)).to eq(now + 60 * 60 * 24)
166
169
  end
167
170
 
168
171
  it "should process UTC Time parameters" do
169
172
  plsql.default_timezone = :utc
170
- now = Time.utc(2008,8,12,14,28,0)
171
- expect(plsql.test_date(now)).to eq(now + 60*60*24)
173
+ now = Time.utc(2008, 8, 12, 14, 28, 0)
174
+ expect(plsql.test_date(now)).to eq(now + 60 * 60 * 24)
172
175
  end
173
176
 
174
177
  it "should process DateTime parameters" do
175
- now = DateTime.parse(Time.local(2008,8,12,14,28,0).iso8601)
178
+ now = DateTime.parse(Time.local(2008, 8, 12, 14, 28, 0).iso8601)
176
179
  result = plsql.test_date(now)
177
180
  expect(result.class).to eq(Time)
178
181
  expect(result).to eq(Time.parse((now + 1).strftime("%c")))
179
182
  end
180
-
183
+
181
184
  it "should process old DateTime parameters" do
182
- now = DateTime.civil(1901,1,1,12,0,0,plsql.local_timezone_offset)
185
+ now = DateTime.civil(1901, 1, 1, 12, 0, 0, plsql.local_timezone_offset)
183
186
  result = plsql.test_date(now)
184
187
  expect(result.class).to eq(Time)
185
188
  expect(result).to eq(Time.parse((now + 1).strftime("%c")))
186
189
  end
187
190
 
188
191
  it "should process Date parameters" do
189
- now = Date.new(2008,8,12)
192
+ now = Date.new(2008, 8, 12)
190
193
  result = plsql.test_date(now)
191
194
  expect(result.class).to eq(Time)
192
195
  expect(result).to eq(Time.parse((now + 1).strftime("%c")))
193
196
  end
194
-
197
+
195
198
  it "should process old Date parameters" do
196
- now = Date.new(1901,1,1)
199
+ now = Date.new(1901, 1, 1)
197
200
  result = plsql.test_date(now)
198
201
  expect(result.class).to eq(Time)
199
202
  expect(result).to eq(Time.parse((now + 1).strftime("%c")))
200
203
  end
201
-
204
+
202
205
  it "should process nil date parameter as NULL" do
203
206
  expect(plsql.test_date(nil)).to be_nil
204
207
  end
@@ -218,18 +221,67 @@ describe "Parameter type mapping /" do
218
221
  END test_timestamp;
219
222
  SQL
220
223
  end
221
-
224
+
222
225
  after(:all) do
223
226
  plsql.execute "DROP FUNCTION test_timestamp"
224
227
  plsql.logoff
225
228
  end
226
-
229
+
227
230
  it "should process timestamp parameters" do
228
231
  # now = Time.now
229
- now = Time.local(2008,8,12,14,28,0)
230
- expect(plsql.test_timestamp(now)).to eq(now + 60*60*24)
232
+ now = Time.local(2008, 8, 12, 14, 28, 0)
233
+ expect(plsql.test_timestamp(now)).to eq(now + 60 * 60 * 24)
234
+ end
235
+
236
+ end
237
+
238
+ describe "Function or procedure with XMLType parameters" do
239
+ before(:all) do
240
+ plsql.connect! CONNECTION_PARAMS
241
+ @oracle12c_or_higher = !! plsql.connection.select_all(
242
+ "select * from product_component_version where product like 'Oracle%' and to_number(substr(version,1,2)) >= 12")
243
+ skip "Skip until furtuer investigation for #114" if @oracle12c_or_higher
244
+ plsql.execute <<-SQL
245
+ CREATE OR REPLACE FUNCTION test_xmltype
246
+ ( p_xml XMLTYPE )
247
+ RETURN XMLTYPE
248
+ IS
249
+ BEGIN
250
+ RETURN p_xml;
251
+ END test_xmltype;
252
+ SQL
253
+ plsql.execute <<-SQL
254
+ CREATE OR REPLACE PROCEDURE test_xmltype2
255
+ ( p_xml XMLTYPE, po_xml OUT XMLTYPE )
256
+ IS
257
+ BEGIN
258
+ po_xml := p_xml;
259
+ END test_xmltype2;
260
+ SQL
261
+ end
262
+
263
+ after(:all) do
264
+ plsql.execute "DROP FUNCTION test_xmltype" unless @oracle12c_or_higher
265
+ plsql.execute "DROP PROCEDURE test_xmltype2" unless @oracle12c_or_higher
266
+ plsql.logoff
267
+ end
268
+
269
+ it "should process XMLType parameters" do
270
+ xml = "<DUMMY>value</DUMMY>"
271
+ result = plsql.test_xmltype(xml)
272
+ expect(result).to eq("<DUMMY>value</DUMMY>")
273
+ end
274
+
275
+ it "should work when passing a NULL value" do
276
+ result = plsql.test_xmltype(nil)
277
+ expect(result).to be_nil
231
278
  end
232
279
 
280
+ it "should assign input parameter to putput parameter" do
281
+ xml = "<DUMMY>value</DUMMY>"
282
+ result = plsql.test_xmltype2(xml)
283
+ expect(result[:po_xml]).to eq("<DUMMY>value</DUMMY>")
284
+ end
233
285
  end
234
286
 
235
287
  describe "Procedure with output parameters" do
@@ -245,26 +297,26 @@ describe "Parameter type mapping /" do
245
297
  END test_copy;
246
298
  SQL
247
299
  end
248
-
300
+
249
301
  after(:all) do
250
302
  plsql.execute "DROP PROCEDURE test_copy"
251
303
  plsql.logoff
252
304
  end
253
-
305
+
254
306
  it "should return hash with output parameters" do
255
- expect(plsql.test_copy("abc", nil, nil)).to eq({ :p_to => "abc", :p_to_double => "abcabc" })
307
+ expect(plsql.test_copy("abc", nil, nil)).to eq(p_to: "abc", p_to_double: "abcabc")
256
308
  end
257
309
 
258
310
  it "should return hash with output parameters when called with named parameters" do
259
- expect(plsql.test_copy(:p_from => "abc", :p_to => nil, :p_to_double => nil)).to eq({ :p_to => "abc", :p_to_double => "abcabc" })
311
+ expect(plsql.test_copy(p_from: "abc", p_to: nil, p_to_double: nil)).to eq(p_to: "abc", p_to_double: "abcabc")
260
312
  end
261
313
 
262
314
  it "should substitute output parameters with nil if they are not specified" do
263
- expect(plsql.test_copy("abc")).to eq({ :p_to => "abc", :p_to_double => "abcabc" })
315
+ expect(plsql.test_copy("abc")).to eq(p_to: "abc", p_to_double: "abcabc")
264
316
  end
265
317
 
266
318
  it "should substitute named output parameters with nil if they are not specified" do
267
- expect(plsql.test_copy(:p_from => "abc")).to eq({ :p_to => "abc", :p_to_double => "abcabc" })
319
+ expect(plsql.test_copy(p_from: "abc")).to eq(p_to: "abc", p_to_double: "abcabc")
268
320
  end
269
321
 
270
322
  end
@@ -328,12 +380,12 @@ describe "Parameter type mapping /" do
328
380
  SQL
329
381
 
330
382
  end
331
-
383
+
332
384
  after(:all) do
333
385
  plsql.execute "DROP PACKAGE test_package2"
334
386
  plsql.logoff
335
387
  end
336
-
388
+
337
389
  it "should find existing package" do
338
390
  expect(PLSQL::Package.find(plsql, :test_package2)).not_to be_nil
339
391
  end
@@ -351,30 +403,30 @@ describe "Parameter type mapping /" do
351
403
  end
352
404
 
353
405
  it "should execute correct procedures based on number of arguments and return correct value" do
354
- expect(plsql.test_package2.test_procedure('xxx')).to eq('XXX')
355
- expect(plsql.test_package2.test_procedure('xxx', nil)).to eq({:p_result => 'XXX'})
406
+ expect(plsql.test_package2.test_procedure("xxx")).to eq("XXX")
407
+ expect(plsql.test_package2.test_procedure("xxx", nil)).to eq(p_result: "XXX")
356
408
  end
357
409
 
358
410
  it "should execute correct procedures based on number of named arguments and return correct value" do
359
- expect(plsql.test_package2.test_procedure(:p_string => 'xxx')).to eq('XXX')
360
- expect(plsql.test_package2.test_procedure(:p_string => 'xxx', :p_result => nil)).to eq({:p_result => 'XXX'})
411
+ expect(plsql.test_package2.test_procedure(p_string: "xxx")).to eq("XXX")
412
+ expect(plsql.test_package2.test_procedure(p_string: "xxx", p_result: nil)).to eq(p_result: "XXX")
361
413
  end
362
414
 
363
415
  it "should raise exception if procedure cannot be found based on number of arguments" do
364
416
  expect { plsql.test_package2.test_procedure() }.to raise_error(/wrong number or types of arguments/i)
365
417
  end
366
-
418
+
367
419
  it "should find procedure based on types of arguments" do
368
- expect(plsql.test_package2.test_procedure(111, nil)).to eq({:p_result => '111'})
420
+ expect(plsql.test_package2.test_procedure(111, nil)).to eq(p_result: "111")
369
421
  end
370
422
 
371
423
  it "should find procedure based on names of named arguments" do
372
- expect(plsql.test_package2.test_procedure(:p_number => 111, :p_result => nil)).to eq({:p_result => '111'})
424
+ expect(plsql.test_package2.test_procedure(p_number: 111, p_result: nil)).to eq(p_result: "111")
373
425
  end
374
426
 
375
427
  it "should find matching procedure based on partial list of named arguments" do
376
- expect(plsql.test_package2.test_function(:p_string => 'xxx')).to eq('xxx ')
377
- expect(plsql.test_package2.test_function(:p_number => 1)).to eq(2)
428
+ expect(plsql.test_package2.test_function(p_string: "xxx")).to eq("xxx ")
429
+ expect(plsql.test_package2.test_function(p_number: 1)).to eq(2)
378
430
  end
379
431
 
380
432
  end
@@ -394,24 +446,24 @@ describe "Parameter type mapping /" do
394
446
  END test_copy_function;
395
447
  SQL
396
448
  end
397
-
449
+
398
450
  after(:all) do
399
451
  plsql.execute "DROP FUNCTION test_copy_function"
400
452
  plsql.logoff
401
453
  end
402
-
454
+
403
455
  it "should return array with return value and hash of output parameters" do
404
- expect(plsql.test_copy_function("abc", nil, nil)).to eq([3, { :p_to => "abc", :p_to_double => "abcabc" }])
456
+ expect(plsql.test_copy_function("abc", nil, nil)).to eq([3, { p_to: "abc", p_to_double: "abcabc" }])
405
457
  end
406
458
 
407
459
  it "should return array with return value and hash of output parameters when called with named parameters" do
408
- expect(plsql.test_copy_function(:p_from => "abc", :p_to => nil, :p_to_double => nil)).to eq(
409
- [3, { :p_to => "abc", :p_to_double => "abcabc" }]
460
+ expect(plsql.test_copy_function(p_from: "abc", p_to: nil, p_to_double: nil)).to eq(
461
+ [3, { p_to: "abc", p_to_double: "abcabc" }]
410
462
  )
411
463
  end
412
464
 
413
465
  it "should substitute output parameters with nil if they are not specified" do
414
- expect(plsql.test_copy_function("abc")).to eq([3, { :p_to => "abc", :p_to_double => "abcabc" }])
466
+ expect(plsql.test_copy_function("abc")).to eq([3, { p_to: "abc", p_to_double: "abcabc" }])
415
467
  end
416
468
 
417
469
  end
@@ -435,7 +487,7 @@ describe "Parameter type mapping /" do
435
487
  END test_proc_no_params;
436
488
  SQL
437
489
  end
438
-
490
+
439
491
  after(:all) do
440
492
  plsql.execute "DROP FUNCTION test_no_params"
441
493
  plsql.execute "DROP PROCEDURE test_proc_no_params"
@@ -481,7 +533,7 @@ describe "Parameter type mapping /" do
481
533
  CURSOR clob_cur IS
482
534
  SELECT clob_col
483
535
  FROM test_clob_table;
484
-
536
+
485
537
  v_dummy CLOB;
486
538
  BEGIN
487
539
  DELETE FROM test_clob_table;
@@ -490,47 +542,47 @@ describe "Parameter type mapping /" do
490
542
  OPEN clob_cur;
491
543
  FETCH clob_cur INTO v_dummy;
492
544
  CLOSE clob_cur;
493
-
545
+
494
546
  RETURN v_dummy;
495
547
  END test_clob_insert;
496
548
  SQL
497
549
  end
498
-
550
+
499
551
  after(:all) do
500
552
  plsql.execute "DROP FUNCTION test_clob"
501
553
  plsql.execute "DROP FUNCTION test_clob_insert"
502
554
  plsql.execute "DROP TABLE test_clob_table"
503
555
  plsql.logoff
504
556
  end
505
-
557
+
506
558
  it "should find existing procedure" do
507
559
  expect(PLSQL::Procedure.find(plsql, :test_clob)).not_to be_nil
508
560
  end
509
561
 
510
562
  it "should execute function and return correct value" do
511
- large_text = 'ābčdēfghij' * 10_000
563
+ large_text = "ābčdēfghij" * 10_000
512
564
  expect(plsql.test_clob(large_text)).to eq(large_text)
513
565
  end
514
566
 
515
567
  unless defined?(JRUBY_VERSION)
516
568
 
517
569
  it "should execute function with empty string and return nil (oci8 cannot pass empty CLOB parameter)" do
518
- text = ''
570
+ text = ""
519
571
  expect(plsql.test_clob(text)).to be_nil
520
572
  end
521
573
 
522
574
  it "should execute function which inserts the CLOB parameter into a table with empty string and return nil" do
523
- text = ''
575
+ text = ""
524
576
  expect(plsql.test_clob_insert(text)).to be_nil
525
577
  end
526
-
578
+
527
579
  else
528
580
 
529
581
  it "should execute function with empty string and return empty string" do
530
- text = ''
582
+ text = ""
531
583
  expect(plsql.test_clob(text)).to eq(text)
532
584
  end
533
-
585
+
534
586
  end
535
587
 
536
588
  it "should execute function with nil and return nil" do
@@ -540,7 +592,7 @@ describe "Parameter type mapping /" do
540
592
  it "should execute function which inserts the CLOB parameter into a table with nil and return nil" do
541
593
  expect(plsql.test_clob_insert(nil)).to be_nil
542
594
  end
543
-
595
+
544
596
  end
545
597
 
546
598
  describe "Procedrue with CLOB parameter and return value" do
@@ -556,18 +608,18 @@ describe "Parameter type mapping /" do
556
608
  END test_clob_proc;
557
609
  SQL
558
610
  end
559
-
611
+
560
612
  after(:all) do
561
613
  plsql.execute "DROP PROCEDURE test_clob_proc"
562
614
  plsql.logoff
563
615
  end
564
-
616
+
565
617
  it "should find existing procedure" do
566
618
  expect(PLSQL::Procedure.find(plsql, :test_clob_proc)).not_to be_nil
567
619
  end
568
620
 
569
621
  it "should execute function and return correct value" do
570
- large_text = 'ābčdēfghij' * 10_000
622
+ large_text = "ābčdēfghij" * 10_000
571
623
  expect(plsql.test_clob_proc(large_text)[:p_return]).to eq(large_text)
572
624
  end
573
625
  end
@@ -585,12 +637,12 @@ describe "Parameter type mapping /" do
585
637
  END test_blob_proc;
586
638
  SQL
587
639
  end
588
-
640
+
589
641
  after(:all) do
590
642
  plsql.execute "DROP PROCEDURE test_blob_proc"
591
643
  plsql.logoff
592
644
  end
593
-
645
+
594
646
  it "should find existing procedure" do
595
647
  expect(PLSQL::Procedure.find(plsql, :test_blob_proc)).not_to be_nil
596
648
  end
@@ -609,7 +661,7 @@ describe "Parameter type mapping /" do
609
661
  CREATE TABLE test_employees (
610
662
  employee_id NUMBER(15),
611
663
  first_name VARCHAR2(50),
612
- last_name VARCHAR2(50),
664
+ last_name VARCHAR(50),
613
665
  hire_date DATE
614
666
  )
615
667
  SQL
@@ -626,17 +678,30 @@ describe "Parameter type mapping /" do
626
678
  TYPE t_employee IS RECORD(
627
679
  employee_id NUMBER(15),
628
680
  first_name VARCHAR2(50),
629
- last_name VARCHAR2(50),
681
+ last_name VARCHAR(50),
630
682
  hire_date DATE
631
683
  );
632
684
 
633
- TYPE table_of_records IS TABLE OF t_employee;
685
+ TYPE t_candidate IS RECORD(
686
+ candidate_id NUMBER(5),
687
+ is_approved BOOLEAN
688
+ );
689
+
690
+ TYPE table_of_records IS TABLE OF test_record.t_employee;
634
691
 
635
692
  FUNCTION test_full_name(p_employee t_employee)
636
693
  RETURN VARCHAR2;
637
694
 
638
695
  FUNCTION test_empty_records
639
696
  RETURN table_of_records;
697
+
698
+ FUNCTION is_approved(p_candidate t_candidate)
699
+ RETURN BOOLEAN;
700
+
701
+ FUNCTION f_set_candidate_status(p_candidate t_candidate, p_status boolean)
702
+ RETURN t_candidate;
703
+
704
+ PROCEDURE p_set_candidate_status(p_candidate t_candidate, p_status boolean, p_result OUT t_candidate);
640
705
  END;
641
706
  SQL
642
707
  plsql.execute <<-SQL
@@ -653,7 +718,7 @@ describe "Parameter type mapping /" do
653
718
  IS
654
719
  CURSOR employees_cur
655
720
  IS
656
- SELECT
721
+ SELECT
657
722
  null employee_id,
658
723
  null first_name,
659
724
  null last_name,
@@ -667,6 +732,29 @@ describe "Parameter type mapping /" do
667
732
  CLOSE employees_cur;
668
733
  RETURN employees_tab;
669
734
  END;
735
+
736
+ FUNCTION is_approved(p_candidate t_candidate)
737
+ RETURN BOOLEAN
738
+ IS
739
+ BEGIN
740
+ RETURN p_candidate.is_approved;
741
+ END;
742
+
743
+ FUNCTION f_set_candidate_status(p_candidate t_candidate, p_status boolean)
744
+ RETURN t_candidate
745
+ IS
746
+ result t_candidate := p_candidate;
747
+ BEGIN
748
+ result.is_approved := p_status;
749
+ return result;
750
+ END;
751
+
752
+ PROCEDURE p_set_candidate_status(p_candidate t_candidate, p_status boolean, p_result OUT t_candidate)
753
+ IS
754
+ BEGIN
755
+ p_result := p_candidate;
756
+ p_result.is_approved := p_status;
757
+ END;
670
758
  END;
671
759
  SQL
672
760
  plsql.execute <<-SQL
@@ -690,16 +778,16 @@ describe "Parameter type mapping /" do
690
778
  END test_employee_record2;
691
779
  SQL
692
780
  @p_employee = {
693
- :employee_id => 1,
694
- :first_name => 'First',
695
- :last_name => 'Last',
696
- :hire_date => Time.local(2000,01,31)
781
+ employee_id: 1,
782
+ first_name: "First",
783
+ last_name: "Last",
784
+ hire_date: Time.local(2000, 01, 31)
697
785
  }
698
786
  @p_employee2 = {
699
- 'employee_id' => 1,
700
- 'FIRST_NAME' => 'Second',
701
- 'last_name' => 'Last',
702
- 'hire_date' => Time.local(2000,01,31)
787
+ "employee_id" => 1,
788
+ "FIRST_NAME" => "Second",
789
+ "last_name" => "Last",
790
+ "hire_date" => Time.local(2000, 01, 31)
703
791
  }
704
792
  end
705
793
 
@@ -717,23 +805,23 @@ describe "Parameter type mapping /" do
717
805
  end
718
806
 
719
807
  it "should execute function with named parameter and return correct value" do
720
- expect(plsql.test_full_name(:p_employee => @p_employee)).to eq('First Last')
808
+ expect(plsql.test_full_name(p_employee: @p_employee)).to eq("First Last")
721
809
  end
722
810
 
723
811
  it "should execute function with sequential parameter and return correct value" do
724
- expect(plsql.test_full_name(@p_employee)).to eq('First Last')
812
+ expect(plsql.test_full_name(@p_employee)).to eq("First Last")
725
813
  end
726
814
 
727
815
  it "should execute function with Hash parameter using strings as keys" do
728
- expect(plsql.test_full_name(@p_employee2)).to eq('Second Last')
816
+ expect(plsql.test_full_name(@p_employee2)).to eq("Second Last")
729
817
  end
730
818
 
731
819
  it "should raise error if wrong field name is passed for record parameter" do
732
820
  expect do
733
- expect(plsql.test_full_name(@p_employee.merge :xxx => 'xxx')).to eq('Second Last')
821
+ expect(plsql.test_full_name(@p_employee.merge xxx: "xxx")).to eq("Second Last")
734
822
  end.to raise_error(ArgumentError)
735
823
  end
736
-
824
+
737
825
  it "should return empty table of records" do
738
826
  expect(plsql.test_record.test_empty_records()).to eq([])
739
827
  end
@@ -743,11 +831,31 @@ describe "Parameter type mapping /" do
743
831
  end
744
832
 
745
833
  it "should return record return value and output record parameter value" do
746
- expect(plsql.test_employee_record2(@p_employee, @p_employee2)).to eq([@p_employee, {:x_employee => @p_employee}])
834
+ expect(plsql.test_employee_record2(@p_employee, @p_employee2)).to eq([@p_employee, { x_employee: @p_employee }])
747
835
  end
748
836
 
749
837
  it "should execute package function with parameter with record type defined in package" do
750
- expect(plsql.test_record.test_full_name(@p_employee)).to eq('First Last')
838
+ expect(plsql.test_record.test_full_name(@p_employee)).to eq("First Last")
839
+ end
840
+
841
+ context "functions with record parameters having boolean attributes" do
842
+ def new_candidate(status)
843
+ { candidate_id: 1, is_approved: status }
844
+ end
845
+
846
+ [true, false, nil].each do |status|
847
+ it "should execute function with record having boolean attribute (#{status})" do
848
+ expect(plsql.test_record.is_approved(new_candidate(status))).to eq status
849
+ end
850
+
851
+ it "procedure should return record with boolean attribute as output parameter (#{status})" do
852
+ expect(plsql.test_record.p_set_candidate_status(new_candidate(nil), status)[:p_result]).to eq new_candidate(status)
853
+ end
854
+
855
+ it "function should return record with boolean attribute (#{status})" do
856
+ expect(plsql.test_record.f_set_candidate_status(new_candidate(nil), status)).to eq new_candidate(status)
857
+ end
858
+ end
751
859
  end
752
860
 
753
861
  end
@@ -793,15 +901,15 @@ describe "Parameter type mapping /" do
793
901
  end
794
902
 
795
903
  it "should accept true value and assign true value to output parameter" do
796
- expect(plsql.test_boolean2(true, nil)).to eq({:x_boolean => true})
904
+ expect(plsql.test_boolean2(true, nil)).to eq(x_boolean: true)
797
905
  end
798
906
 
799
907
  it "should accept false value and assign false value to output parameter" do
800
- expect(plsql.test_boolean2(false, nil)).to eq({:x_boolean => false})
908
+ expect(plsql.test_boolean2(false, nil)).to eq(x_boolean: false)
801
909
  end
802
910
 
803
911
  it "should accept nil value and assign nil value to output parameter" do
804
- expect(plsql.test_boolean2(nil, nil)).to eq({:x_boolean => nil})
912
+ expect(plsql.test_boolean2(nil, nil)).to eq(x_boolean: nil)
805
913
  end
806
914
 
807
915
  end
@@ -831,7 +939,7 @@ describe "Parameter type mapping /" do
831
939
  CREATE OR REPLACE TYPE t_employee AS OBJECT (
832
940
  employee_id NUMBER(15),
833
941
  first_name VARCHAR2(50),
834
- last_name VARCHAR2(50),
942
+ last_name VARCHAR(50),
835
943
  hire_date DATE,
836
944
  address t_address,
837
945
  phones t_phones
@@ -863,12 +971,12 @@ describe "Parameter type mapping /" do
863
971
  END;
864
972
  SQL
865
973
  @p_employee = {
866
- :employee_id => 1,
867
- :first_name => 'First',
868
- :last_name => 'Last',
869
- :hire_date => Time.local(2000,01,31),
870
- :address => {:street => 'Main street 1', :city => 'Riga', :country => 'Latvia'},
871
- :phones => [{:type => 'mobile', :phone_number => '123456'}, {:type => 'home', :phone_number => '654321'}]
974
+ employee_id: 1,
975
+ first_name: "First",
976
+ last_name: "Last",
977
+ hire_date: Time.local(2000, 01, 31),
978
+ address: { street: "Main street 1", city: "Riga", country: "Latvia" },
979
+ phones: [{ type: "mobile", phone_number: "123456" }, { type: "home", phone_number: "654321" }]
872
980
  }
873
981
  end
874
982
 
@@ -888,16 +996,16 @@ describe "Parameter type mapping /" do
888
996
  end
889
997
 
890
998
  it "should execute function with named parameter and return correct value" do
891
- expect(plsql.test_full_name(:p_employee => @p_employee)).to eq('First Last')
999
+ expect(plsql.test_full_name(p_employee: @p_employee)).to eq("First Last")
892
1000
  end
893
1001
 
894
1002
  it "should execute function with sequential parameter and return correct value" do
895
- expect(plsql.test_full_name(@p_employee)).to eq('First Last')
1003
+ expect(plsql.test_full_name(@p_employee)).to eq("First Last")
896
1004
  end
897
1005
 
898
1006
  it "should raise error if wrong field name is passed for record parameter" do
899
1007
  expect do
900
- plsql.test_full_name(@p_employee.merge :xxx => 'xxx')
1008
+ plsql.test_full_name(@p_employee.merge xxx: "xxx")
901
1009
  end.to raise_error(ArgumentError)
902
1010
  end
903
1011
 
@@ -906,7 +1014,7 @@ describe "Parameter type mapping /" do
906
1014
  end
907
1015
 
908
1016
  it "should return object type return value and output object type parameter value" do
909
- expect(plsql.test_employee_object2(@p_employee, nil)).to eq([@p_employee, {:x_employee => @p_employee}])
1017
+ expect(plsql.test_employee_object2(@p_employee, nil)).to eq([@p_employee, { x_employee: @p_employee }])
910
1018
  end
911
1019
 
912
1020
  it "should accept NULL as input parameter" do
@@ -915,7 +1023,6 @@ describe "Parameter type mapping /" do
915
1023
 
916
1024
  end
917
1025
 
918
-
919
1026
  describe "Function with table parameter" do
920
1027
  before(:all) do
921
1028
  plsql.connect! CONNECTION_PARAMS
@@ -941,7 +1048,7 @@ describe "Parameter type mapping /" do
941
1048
  END IF;
942
1049
  END;
943
1050
  SQL
944
-
1051
+
945
1052
  plsql.execute <<-SQL
946
1053
  CREATE OR REPLACE FUNCTION test_increment(p_numbers IN t_numbers, p_increment_by IN NUMBER DEFAULT 1)
947
1054
  RETURN t_numbers
@@ -991,19 +1098,19 @@ describe "Parameter type mapping /" do
991
1098
  TYPE t_employee IS RECORD(
992
1099
  employee_id NUMBER(15),
993
1100
  first_name VARCHAR2(50),
994
- last_name VARCHAR2(50),
1101
+ last_name VARCHAR(50),
995
1102
  hire_date DATE
996
1103
  );
997
- TYPE t_employees IS TABLE OF t_employee;
1104
+ TYPE t_employees IS TABLE OF test_collections.t_employee;
998
1105
  FUNCTION test_employees (p_employees IN OUT t_employees)
999
1106
  RETURN t_employees;
1000
1107
  -- these types with tables in lower level are not yet supported
1001
1108
  TYPE t_employee2 IS RECORD(
1002
1109
  employee_id NUMBER(15),
1003
1110
  first_name VARCHAR2(50),
1004
- last_name VARCHAR2(50),
1111
+ last_name VARCHAR(50),
1005
1112
  hire_date DATE,
1006
- numbers t_numbers
1113
+ numbers test_collections.t_numbers
1007
1114
  );
1008
1115
  FUNCTION test_employee2 (p_employee IN OUT t_employee2)
1009
1116
  RETURN t_employee2;
@@ -1097,20 +1204,20 @@ describe "Parameter type mapping /" do
1097
1204
  SQL
1098
1205
  @employees = (1..10).map do |i|
1099
1206
  {
1100
- :employee_id => i,
1101
- :first_name => "First #{i}",
1102
- :last_name => "Last #{i}",
1103
- :hire_date => Time.local(2000,01,i),
1207
+ employee_id: i,
1208
+ first_name: "First #{i}",
1209
+ last_name: "Last #{i}",
1210
+ hire_date: Time.local(2000, 01, i),
1104
1211
  }
1105
1212
  end
1106
1213
  @nstrings = (1..5).map do |i|
1107
1214
  {
1108
- :ch_10bytes => "Ch #{i}B ",
1109
- :ch_10chars => "Ch #{i}C ",
1110
- :nch_10chars => "NCh #{i} ",
1111
- :str_10bytes => "Str #{i}C",
1112
- :str_10chars => "Str #{i}B",
1113
- :nstr_10chars => "NStr #{i}",
1215
+ ch_10bytes: "Ch #{i}B ",
1216
+ ch_10chars: "Ch #{i}C ",
1217
+ nch_10chars: "NCh #{i} ",
1218
+ str_10bytes: "Str #{i}C",
1219
+ str_10chars: "Str #{i}B",
1220
+ nstr_10chars: "NStr #{i}",
1114
1221
  }
1115
1222
  end
1116
1223
 
@@ -1154,78 +1261,78 @@ describe "Parameter type mapping /" do
1154
1261
  end
1155
1262
 
1156
1263
  it "should execute function with number array parameter" do
1157
- expect(plsql.test_sum([1,2,3,4])).to eq(10)
1264
+ expect(plsql.test_sum([1, 2, 3, 4])).to eq(10)
1158
1265
  end
1159
-
1266
+
1160
1267
  it "should return number array return value" do
1161
- expect(plsql.test_increment([1,2,3,4], 1)).to eq([2,3,4,5])
1268
+ expect(plsql.test_increment([1, 2, 3, 4], 1)).to eq([2, 3, 4, 5])
1162
1269
  end
1163
1270
 
1164
1271
  it "should execute function with string array and return string array output parameter" do
1165
- strings = ['1','2','3','4']
1166
- expect(plsql.test_copy_strings(strings)).to eq([strings, {:x_strings => strings}])
1272
+ strings = ["1", "2", "3", "4"]
1273
+ expect(plsql.test_copy_strings(strings)).to eq([strings, { x_strings: strings }])
1167
1274
  end
1168
1275
 
1169
1276
  it "should execute function with table of numbers type (defined inside package) parameter" do
1170
- expect(plsql.test_collections.test_sum([1,2,3,4])).to eq(10)
1277
+ expect(plsql.test_collections.test_sum([1, 2, 3, 4])).to eq(10)
1171
1278
  end
1172
1279
 
1173
1280
  it "should clear temporary tables after executing function with table of numbers type even if an error occurs in the package" do
1174
1281
  # this should work fine
1175
- expect(plsql.test_collections.test_function_failure([1,2,3,4], 'N')).to eq(4)
1282
+ expect(plsql.test_collections.test_function_failure([1, 2, 3, 4], "N")).to eq(4)
1176
1283
  # we will force a package error here to see if things get cleaned up before the next call
1177
- expect { plsql.test_collections.test_function_failure([1,2,3,4], 'Y') }.to raise_error(/Simulate business error to test clearing of temp table/)
1284
+ expect { plsql.test_collections.test_function_failure([1, 2, 3, 4], "Y") }.to raise_error(/Simulate business error to test clearing of temp table/)
1178
1285
  # after the error in the first call temporary tables should be cleared
1179
- expect(plsql.test_collections.test_function_failure([5,6,7], 'N')).to eq(3)
1286
+ expect(plsql.test_collections.test_function_failure([5, 6, 7], "N")).to eq(3)
1180
1287
  end
1181
1288
 
1182
1289
  it "should return table of numbers type (defined inside package)" do
1183
- expect(plsql.test_collections.test_numbers([1,2,3,4])).to eq([[1,2,3,4], {:x_numbers => [1,2,3,4]}])
1290
+ expect(plsql.test_collections.test_numbers([1, 2, 3, 4])).to eq([[1, 2, 3, 4], { x_numbers: [1, 2, 3, 4] }])
1184
1291
  end
1185
1292
 
1186
1293
  it "should clear temporary tables after executing function with table of numbers type (defined inside package) parameter" do
1187
- expect(plsql.test_collections.test_numbers([1,2,3,4])).to eq([[1,2,3,4], {:x_numbers => [1,2,3,4]}])
1294
+ expect(plsql.test_collections.test_numbers([1, 2, 3, 4])).to eq([[1, 2, 3, 4], { x_numbers: [1, 2, 3, 4] }])
1188
1295
  # after first call temporary tables should be cleared
1189
- expect(plsql.test_collections.test_numbers([1,2,3,4])).to eq([[1,2,3,4], {:x_numbers => [1,2,3,4]}])
1296
+ expect(plsql.test_collections.test_numbers([1, 2, 3, 4])).to eq([[1, 2, 3, 4], { x_numbers: [1, 2, 3, 4] }])
1190
1297
  end
1191
1298
 
1192
1299
  it "should clear temporary tables when autocommit with table of numbers type (defined inside package) parameter" do
1193
1300
  old_autocommit = plsql.connection.autocommit?
1194
1301
  plsql.connection.autocommit = true
1195
1302
  numbers_array = (1..400).to_a
1196
- expect(plsql.test_collections.test_numbers(numbers_array)).to eq([numbers_array, {:x_numbers => numbers_array}])
1303
+ expect(plsql.test_collections.test_numbers(numbers_array)).to eq([numbers_array, { x_numbers: numbers_array }])
1197
1304
  # after first call temporary tables should be cleared
1198
- expect(plsql.test_collections.test_numbers(numbers_array)).to eq([numbers_array, {:x_numbers => numbers_array}])
1305
+ expect(plsql.test_collections.test_numbers(numbers_array)).to eq([numbers_array, { x_numbers: numbers_array }])
1199
1306
  plsql.connection.autocommit = old_autocommit
1200
1307
  end
1201
1308
 
1202
1309
  it "should execute function with table of records type (defined inside package) parameter" do
1203
- expect(plsql.test_collections.test_employees(@employees)).to eq([@employees, {:p_employees => @employees}])
1310
+ expect(plsql.test_collections.test_employees(@employees)).to eq([@employees, { p_employees: @employees }])
1204
1311
  end
1205
1312
 
1206
1313
  it "should execute function with table of records type (defined inside package and includes NVARCHAR columns) parameter" do
1207
- expect(plsql.test_collections.test_nstring(@nstrings)).to eq([(1..5).map{|i| "NCh #{i}NStr #{i},"}.join, {:p_out => @nstrings}])
1314
+ expect(plsql.test_collections.test_nstring(@nstrings)).to eq([(1..5).map { |i| "NCh #{i}NStr #{i}," }.join, { p_out: @nstrings }])
1208
1315
  end
1209
1316
 
1210
1317
  it "should execute function with object array and return object array output parameter" do
1211
- phones = [{:type => 'mobile', :phone_number => '123456'}, {:type => 'home', :phone_number => '654321'}]
1212
- expect(plsql.test_copy_objects(phones)).to eq([phones, {:x_phones => phones}])
1318
+ phones = [{ type: "mobile", phone_number: "123456" }, { type: "home", phone_number: "654321" }]
1319
+ expect(plsql.test_copy_objects(phones)).to eq([phones, { x_phones: phones }])
1213
1320
  end
1214
1321
 
1215
1322
  it "should execute function with empty object array" do
1216
1323
  phones = []
1217
- expect(plsql.test_copy_objects(phones)).to eq([phones, {:x_phones => phones}])
1324
+ expect(plsql.test_copy_objects(phones)).to eq([phones, { x_phones: phones }])
1218
1325
  end
1219
1326
 
1220
1327
  it "should raise error with record parameter that has table as element" do
1221
1328
  expect {
1222
- expect(plsql.test_collections.test_employee2(@employees[0])).to eq([@employees[0], {:p_employee => @employees[0]}])
1329
+ expect(plsql.test_collections.test_employee2(@employees[0])).to eq([@employees[0], { p_employee: @employees[0] }])
1223
1330
  }.to raise_error(ArgumentError, /TEST_COLLECTIONS\.T_NUMBERS definition inside package is not supported/)
1224
1331
  end
1225
1332
 
1226
1333
  it "should raise error with table of records parameter when record has table as element" do
1227
1334
  expect {
1228
- expect(plsql.test_collections.test_employees2(@employees)).to eq([@employees, {:p_employees => @employees}])
1335
+ expect(plsql.test_collections.test_employees2(@employees)).to eq([@employees, { p_employees: @employees }])
1229
1336
  }.to raise_error(ArgumentError, /TEST_COLLECTIONS\.T_NUMBERS definition inside package is not supported/)
1230
1337
  end
1231
1338
 
@@ -1238,7 +1345,7 @@ describe "Parameter type mapping /" do
1238
1345
  CREATE TABLE test_employees (
1239
1346
  employee_id NUMBER(15),
1240
1347
  first_name VARCHAR2(50),
1241
- last_name VARCHAR2(50),
1348
+ last_name VARCHAR(50),
1242
1349
  hire_date DATE
1243
1350
  )
1244
1351
  SQL
@@ -1256,10 +1363,10 @@ describe "Parameter type mapping /" do
1256
1363
  TYPE t_employee IS RECORD(
1257
1364
  employee_id NUMBER(15),
1258
1365
  first_name VARCHAR2(50),
1259
- last_name VARCHAR2(50),
1366
+ last_name VARCHAR(50),
1260
1367
  hire_date DATE
1261
1368
  );
1262
- TYPE t_employees IS TABLE OF t_employee
1369
+ TYPE t_employees IS TABLE OF test_collections.t_employee
1263
1370
  INDEX BY BINARY_INTEGER;
1264
1371
  FUNCTION test_employees (p_employees IN OUT t_employees)
1265
1372
  RETURN t_employees;
@@ -1334,15 +1441,15 @@ describe "Parameter type mapping /" do
1334
1441
  END;
1335
1442
  SQL
1336
1443
  # test with negative PL/SQL table indexes
1337
- @numbers = Hash[*(1..4).map{|i|[-i,i]}.flatten]
1338
- @numbers2 = Hash[*(5..7).map{|i|[-i,i]}.flatten]
1444
+ @numbers = Hash[*(1..4).map { |i|[-i, i] }.flatten]
1445
+ @numbers2 = Hash[*(5..7).map { |i|[-i, i] }.flatten]
1339
1446
  # test with reversed PL/SQL table indexes
1340
1447
  @employees = Hash[*(1..10).map do |i|
1341
- [11-i, {
1342
- :employee_id => i,
1343
- :first_name => "First #{i}",
1344
- :last_name => "Last #{i}",
1345
- :hire_date => Time.local(2000,01,i)
1448
+ [11 - i, {
1449
+ employee_id: i,
1450
+ first_name: "First #{i}",
1451
+ last_name: "Last #{i}",
1452
+ hire_date: Time.local(2000, 01, i)
1346
1453
  }]
1347
1454
  end.flatten]
1348
1455
  end
@@ -1356,11 +1463,11 @@ describe "Parameter type mapping /" do
1356
1463
 
1357
1464
  it "should clear temporary tables after executing function with index-by table of numbers type even if an error occurs in the package" do
1358
1465
  # this should work fine
1359
- expect(plsql.test_collections.test_function_failure(@numbers, 'N')).to eq(10)
1466
+ expect(plsql.test_collections.test_function_failure(@numbers, "N")).to eq(10)
1360
1467
  # we will force a package error here to see if things get cleaned up before the next call
1361
- expect { plsql.test_collections.test_function_failure(@numbers, 'Y') }.to raise_error(/Simulate business error to test clearing of temp table/)
1468
+ expect { plsql.test_collections.test_function_failure(@numbers, "Y") }.to raise_error(/Simulate business error to test clearing of temp table/)
1362
1469
  # after the error in the first call temporary tables should be cleared
1363
- expect(plsql.test_collections.test_function_failure(@numbers2, 'N')).to eq(18)
1470
+ expect(plsql.test_collections.test_function_failure(@numbers2, "N")).to eq(18)
1364
1471
  end
1365
1472
 
1366
1473
  it "should execute function with index-by table of numbers type (defined inside package) parameter" do
@@ -1368,25 +1475,25 @@ describe "Parameter type mapping /" do
1368
1475
  end
1369
1476
 
1370
1477
  it "should return index-by table of numbers type (defined inside package)" do
1371
- expect(plsql.test_collections.test_numbers(@numbers)).to eq([@numbers, {:x_numbers => @numbers}])
1478
+ expect(plsql.test_collections.test_numbers(@numbers)).to eq([@numbers, { x_numbers: @numbers }])
1372
1479
  end
1373
1480
 
1374
1481
  it "should clear temporary tables when autocommit with index-by table of numbers type (defined inside package) parameter" do
1375
1482
  old_autocommit = plsql.connection.autocommit?
1376
1483
  plsql.connection.autocommit = true
1377
- numbers_hash = Hash[*(1..400).map{|i|[i,i]}.flatten]
1378
- expect(plsql.test_collections.test_numbers(numbers_hash)).to eq([numbers_hash, {:x_numbers => numbers_hash}])
1484
+ numbers_hash = Hash[*(1..400).map { |i|[i, i] }.flatten]
1485
+ expect(plsql.test_collections.test_numbers(numbers_hash)).to eq([numbers_hash, { x_numbers: numbers_hash }])
1379
1486
  # after first call temporary tables should be cleared
1380
- expect(plsql.test_collections.test_numbers(numbers_hash)).to eq([numbers_hash, {:x_numbers => numbers_hash}])
1487
+ expect(plsql.test_collections.test_numbers(numbers_hash)).to eq([numbers_hash, { x_numbers: numbers_hash }])
1381
1488
  plsql.connection.autocommit = old_autocommit
1382
1489
  end
1383
1490
 
1384
1491
  it "should execute function with index-by table of records type (defined inside package) parameter" do
1385
- expect(plsql.test_collections.test_employees(@employees)).to eq([@employees, {:p_employees => @employees}])
1492
+ expect(plsql.test_collections.test_employees(@employees)).to eq([@employees, { p_employees: @employees }])
1386
1493
  end
1387
1494
 
1388
1495
  it "should execute procedure with index-by table of records type (defined inside package) parameter" do
1389
- expect(plsql.test_collections.test_employees_prc(@employees)).to eq({:p_employees => @employees})
1496
+ expect(plsql.test_collections.test_employees_prc(@employees)).to eq(p_employees: @employees)
1390
1497
  end
1391
1498
 
1392
1499
  it "should create temporary tables in autonomous transaction" do
@@ -1394,13 +1501,19 @@ describe "Parameter type mapping /" do
1394
1501
  plsql.connection.autocommit = false
1395
1502
  plsql.test_employees.insert @employees[1]
1396
1503
  # procedure call should not commit initial insert
1397
- plsql.test_collections.insert_employees(2=>@employees[2], 3=>@employees[3])
1504
+ plsql.test_collections.insert_employees(2 => @employees[2], 3 => @employees[3])
1398
1505
  plsql.rollback
1399
1506
  expect(plsql.test_employees.all).to be_empty
1400
1507
  plsql.connection.autocommit = old_autocommit
1401
1508
  end
1402
1509
 
1403
1510
  describe "using Oracle 9.2" do
1511
+ before(:all) do
1512
+ # get actual database_version
1513
+ plsql.connect! CONNECTION_PARAMS
1514
+ skip "Skip if the actual database version is 18c or higher" if (plsql.connection.database_version <=> [18, 0, 0, 0]) >= 0
1515
+ end
1516
+
1404
1517
  before do
1405
1518
  # simulate Oracle 9.2 connection
1406
1519
  plsql(:oracle_9).connection = get_connection
@@ -1412,14 +1525,13 @@ describe "Parameter type mapping /" do
1412
1525
  end
1413
1526
 
1414
1527
  it "should create temporary tables when using Oracle 9.2" do
1415
- expect(plsql(:oracle_9).test_collections.test_numbers(@numbers)).to eq([@numbers, {:x_numbers => @numbers}])
1528
+ expect(plsql(:oracle_9).test_collections.test_numbers(@numbers)).to eq([@numbers, { x_numbers: @numbers }])
1416
1529
  end
1417
1530
 
1418
1531
  end
1419
1532
 
1420
1533
  end
1421
1534
 
1422
-
1423
1535
  describe "Function with VARRAY parameter" do
1424
1536
  before(:all) do
1425
1537
  plsql.connect! CONNECTION_PARAMS
@@ -1515,26 +1627,26 @@ describe "Parameter type mapping /" do
1515
1627
  end
1516
1628
 
1517
1629
  it "should execute function with number array parameter" do
1518
- expect(plsql.test_sum([1,2,3,4])).to eq(10)
1630
+ expect(plsql.test_sum([1, 2, 3, 4])).to eq(10)
1519
1631
  end
1520
1632
 
1521
1633
  it "should return number array return value" do
1522
- expect(plsql.test_increment([1,2,3,4], 1)).to eq([2,3,4,5])
1634
+ expect(plsql.test_increment([1, 2, 3, 4], 1)).to eq([2, 3, 4, 5])
1523
1635
  end
1524
1636
 
1525
1637
  it "should execute function with string array and return string array output parameter" do
1526
- strings = ['1','2','3','4']
1527
- expect(plsql.test_copy_strings(strings)).to eq([strings, {:x_strings => strings}])
1638
+ strings = ["1", "2", "3", "4"]
1639
+ expect(plsql.test_copy_strings(strings)).to eq([strings, { x_strings: strings }])
1528
1640
  end
1529
1641
 
1530
1642
  it "should execute function with object array and return object array output parameter" do
1531
- phones = [{:type => 'mobile', :phone_number => '123456'}, {:type => 'home', :phone_number => '654321'}]
1532
- expect(plsql.test_copy_objects(phones)).to eq([phones, {:x_phones => phones}])
1643
+ phones = [{ type: "mobile", phone_number: "123456" }, { type: "home", phone_number: "654321" }]
1644
+ expect(plsql.test_copy_objects(phones)).to eq([phones, { x_phones: phones }])
1533
1645
  end
1534
1646
 
1535
1647
  it "should execute function with empty object array" do
1536
1648
  phones = []
1537
- expect(plsql.test_copy_objects(phones)).to eq([phones, {:x_phones => phones}])
1649
+ expect(plsql.test_copy_objects(phones)).to eq([phones, { x_phones: phones }])
1538
1650
  end
1539
1651
 
1540
1652
  end
@@ -1644,30 +1756,30 @@ describe "Parameter type mapping /" do
1644
1756
  end
1645
1757
 
1646
1758
  it "should execute function with number array parameter" do
1647
- expect(plsql.test_collections.test_sum([1,2,3,4])).to eq(10)
1759
+ expect(plsql.test_collections.test_sum([1, 2, 3, 4])).to eq(10)
1648
1760
  end
1649
1761
 
1650
1762
  it "should clear temporary tables after executing function with varray of numbers type even if an error occurs in the package" do
1651
1763
  # this should work fine
1652
- expect(plsql.test_collections.test_function_failure([1,2,3,4], 'N')).to eq(10)
1764
+ expect(plsql.test_collections.test_function_failure([1, 2, 3, 4], "N")).to eq(10)
1653
1765
  # we will force a package error here to see if things get cleaned up before the next call
1654
- expect { plsql.test_collections.test_function_failure([5,6,7], 'Y') }.to raise_error(/Simulate business error to test clearing of temp table/)
1766
+ expect { plsql.test_collections.test_function_failure([5, 6, 7], "Y") }.to raise_error(/Simulate business error to test clearing of temp table/)
1655
1767
  # after the error in the first call temporary tables should be cleared
1656
- expect(plsql.test_collections.test_function_failure([3,4,5,6], 'N')).to eq(18)
1768
+ expect(plsql.test_collections.test_function_failure([3, 4, 5, 6], "N")).to eq(18)
1657
1769
  end
1658
1770
 
1659
1771
  it "should return number array return value" do
1660
- expect(plsql.test_collections.test_increment([1,2,3,4], 1)).to eq([2,3,4,5])
1772
+ expect(plsql.test_collections.test_increment([1, 2, 3, 4], 1)).to eq([2, 3, 4, 5])
1661
1773
  end
1662
1774
 
1663
1775
  it "should execute function with string array and return string array output parameter" do
1664
- strings = ['1','2','3','4']
1665
- expect(plsql.test_collections.test_copy_strings(strings)).to eq([strings, {:x_strings => strings}])
1776
+ strings = ["1", "2", "3", "4"]
1777
+ expect(plsql.test_collections.test_copy_strings(strings)).to eq([strings, { x_strings: strings }])
1666
1778
  end
1667
1779
 
1668
1780
  it "should execute function with object array and return object array output parameter" do
1669
- phones = [{:type => 'mobile', :phone_number => '123456'}, {:type => 'home', :phone_number => '654321'}]
1670
- expect(plsql.test_collections.test_copy_objects(phones)).to eq([phones, {:x_phones => phones}])
1781
+ phones = [{ type: "mobile", phone_number: "123456" }, { type: "home", phone_number: "654321" }]
1782
+ expect(plsql.test_collections.test_copy_objects(phones)).to eq([phones, { x_phones: phones }])
1671
1783
  end
1672
1784
 
1673
1785
  # This test fails without wcmatthysen's "Procedure-call Fix." pull request.
@@ -1686,7 +1798,7 @@ describe "Parameter type mapping /" do
1686
1798
  CREATE TABLE test_employees (
1687
1799
  employee_id NUMBER(15),
1688
1800
  first_name VARCHAR2(50),
1689
- last_name VARCHAR2(50),
1801
+ last_name VARCHAR(50),
1690
1802
  hire_date DATE
1691
1803
  )
1692
1804
  SQL
@@ -1730,10 +1842,10 @@ describe "Parameter type mapping /" do
1730
1842
  @fields = [:employee_id, :first_name, :last_name, :hire_date]
1731
1843
  @employees = (1..10).map do |i|
1732
1844
  {
1733
- :employee_id => i,
1734
- :first_name => "First #{i}",
1735
- :last_name => "Last #{i}",
1736
- :hire_date => Time.local(2000,01,i)
1845
+ employee_id: i,
1846
+ first_name: "First #{i}",
1847
+ last_name: "Last #{i}",
1848
+ hire_date: Time.local(2000, 01, i)
1737
1849
  }
1738
1850
  end
1739
1851
  @employees.each do |e|
@@ -1757,7 +1869,7 @@ describe "Parameter type mapping /" do
1757
1869
 
1758
1870
  it "should return cursor and fetch first row" do
1759
1871
  expect(plsql.test_cursor do |cursor|
1760
- expect(cursor.fetch).to eq(@fields.map{|f| @employees[0][f]})
1872
+ expect(cursor.fetch).to eq(@fields.map { |f| @employees[0][f] })
1761
1873
  end).to be_nil
1762
1874
  end
1763
1875
 
@@ -1766,7 +1878,7 @@ describe "Parameter type mapping /" do
1766
1878
  expect(plsql.test_cursor do |cursor|
1767
1879
  cursor2 = cursor
1768
1880
  end).to be_nil
1769
- expect { cursor2.fetch }.to raise_error
1881
+ expect { cursor2.fetch }.to raise_error(/Cursor was already closed|Closed Statement/)
1770
1882
  end
1771
1883
 
1772
1884
  it "should not raise error if cursor is closed inside block" do
@@ -1785,7 +1897,7 @@ describe "Parameter type mapping /" do
1785
1897
 
1786
1898
  it "should fetch all rows from returned cursor" do
1787
1899
  plsql.test_cursor do |cursor|
1788
- expect(cursor.fetch_all).to eq(@employees.map{|e| @fields.map{|f| e[f]}})
1900
+ expect(cursor.fetch_all).to eq(@employees.map { |e| @fields.map { |f| e[f] } })
1789
1901
  end
1790
1902
  end
1791
1903
 
@@ -1803,7 +1915,7 @@ describe "Parameter type mapping /" do
1803
1915
 
1804
1916
  it "should return output parameter with cursor and fetch first row" do
1805
1917
  expect(plsql.test_cursor_out do |result|
1806
- expect(result[:x_cursor].fetch).to eq(@fields.map{|f| @employees[0][f]})
1918
+ expect(result[:x_cursor].fetch).to eq(@fields.map { |f| @employees[0][f] })
1807
1919
  end).to be_nil
1808
1920
  end
1809
1921
 
@@ -1853,7 +1965,7 @@ describe "Parameter type mapping /" do
1853
1965
  SQL
1854
1966
 
1855
1967
  @fields = [:col1, :col2 ]
1856
- @rows = (1..3).map{|i| ["row #{i}", i]}
1968
+ @rows = (1..3).map { |i| ["row #{i}", i] }
1857
1969
  plsql.typed_ref_cursor_table.insert_values *@rows
1858
1970
  plsql.commit
1859
1971
 
@@ -1897,7 +2009,7 @@ describe "Synonyms /" do
1897
2009
  end
1898
2010
 
1899
2011
  describe "Local synonym to function" do
1900
-
2012
+
1901
2013
  before(:all) do
1902
2014
  plsql.execute <<-SQL
1903
2015
  CREATE OR REPLACE FUNCTION hr.test_uppercase
@@ -1910,24 +2022,24 @@ describe "Synonyms /" do
1910
2022
  SQL
1911
2023
  plsql.execute "CREATE SYNONYM test_synonym FOR hr.test_uppercase"
1912
2024
  end
1913
-
2025
+
1914
2026
  after(:all) do
1915
2027
  plsql.execute "DROP SYNONYM test_synonym"
1916
2028
  plsql.execute "DROP FUNCTION hr.test_uppercase"
1917
2029
  end
1918
-
2030
+
1919
2031
  it "should find synonym to function" do
1920
2032
  expect(PLSQL::Procedure.find(plsql, :test_synonym)).not_to be_nil
1921
2033
  end
1922
2034
 
1923
2035
  it "should execute function using synonym and return correct value" do
1924
- expect(plsql.test_synonym('xxx')).to eq('XXX')
2036
+ expect(plsql.test_synonym("xxx")).to eq("XXX")
1925
2037
  end
1926
2038
 
1927
2039
  end
1928
2040
 
1929
2041
  describe "Public synonym to function" do
1930
-
2042
+
1931
2043
  before(:all) do
1932
2044
  plsql.execute <<-SQL
1933
2045
  CREATE OR REPLACE FUNCTION hr.test_ora_login_user
@@ -1938,17 +2050,17 @@ describe "Synonyms /" do
1938
2050
  END test_ora_login_user;
1939
2051
  SQL
1940
2052
  end
1941
-
2053
+
1942
2054
  after(:all) do
1943
2055
  plsql.execute "DROP FUNCTION hr.test_ora_login_user"
1944
2056
  end
1945
-
2057
+
1946
2058
  it "should find public synonym to function" do
1947
2059
  expect(PLSQL::Procedure.find(plsql, :ora_login_user)).not_to be_nil
1948
2060
  end
1949
2061
 
1950
2062
  it "should execute function using public synonym and return correct value" do
1951
- expect(plsql.ora_login_user).to eq('HR')
2063
+ expect(plsql.ora_login_user).to eq("HR")
1952
2064
  end
1953
2065
 
1954
2066
  it "should not find public synonym if schema prefix is used" do
@@ -1960,10 +2072,10 @@ describe "Synonyms /" do
1960
2072
  plsql.connection = get_connection
1961
2073
  plsql.execute "DROP SYNONYM ora_login_user" rescue nil
1962
2074
  plsql.execute "CREATE SYNONYM ora_login_user FOR hr.test_ora_login_user"
1963
- expect(plsql.ora_login_user).to eq('XXX')
2075
+ expect(plsql.ora_login_user).to eq("XXX")
1964
2076
  plsql.execute "DROP SYNONYM ora_login_user"
1965
2077
  plsql.connection = get_connection
1966
- expect(plsql.ora_login_user).to eq('HR')
2078
+ expect(plsql.ora_login_user).to eq("HR")
1967
2079
  end
1968
2080
 
1969
2081
  end
@@ -2001,14 +2113,67 @@ describe "Synonyms /" do
2001
2113
 
2002
2114
  it "should raise error when invalid function is called" do
2003
2115
  expect {
2004
- plsql.test_invalid_function('test')
2116
+ plsql.test_invalid_function("test")
2005
2117
  }.to raise_error(ArgumentError, /is not in valid status/)
2006
2118
  end
2007
2119
 
2008
2120
  it "should raise error when function from invalid package body is called" do
2009
2121
  expect {
2010
- plsql.test_invalid_package.test_invalid_function('test')
2011
- }.to raise_error(ArgumentError, /body is not in valid status/)
2122
+ plsql.test_invalid_package.test_invalid_function("test")
2123
+ }.to raise_error(oracle_error_class, /ORA-04063/)
2124
+ end
2125
+ end
2126
+
2127
+ describe "invalid objects that can be automatically recompiled" do
2128
+ before(:all) do
2129
+ plsql.execute "DROP TABLE test_recompilable_table" rescue nil
2130
+ plsql.execute "CREATE TABLE test_recompilable_table (dummy VARCHAR2(10))"
2131
+ plsql.execute <<-SQL
2132
+ CREATE OR REPLACE FUNCTION test_recompilable_function(p_dummy VARCHAR2) RETURN VARCHAR2 IS
2133
+ l_dummy test_recompilable_table.dummy%TYPE;
2134
+ BEGIN
2135
+ RETURN p_dummy;
2136
+ END;
2137
+ SQL
2138
+ plsql.execute <<-SQL
2139
+ CREATE OR REPLACE PACKAGE test_recompilable_package IS
2140
+ FUNCTION test_recompilable_function(p_dummy VARCHAR2) RETURN VARCHAR2;
2141
+ END;
2142
+ SQL
2143
+ plsql.execute <<-SQL
2144
+ CREATE OR REPLACE PACKAGE BODY test_recompilable_package IS
2145
+ FUNCTION test_recompilable_function(p_dummy VARCHAR2) RETURN VARCHAR2 IS
2146
+ l_dummy test_recompilable_table.dummy%TYPE;
2147
+ BEGIN
2148
+ RETURN p_dummy;
2149
+ END;
2150
+ END;
2151
+ SQL
2152
+ end
2153
+
2154
+ before(:each) do
2155
+ # Cause the dependent function and package to go into INVALID status
2156
+ plsql.execute "ALTER TABLE test_recompilable_table MODIFY (dummy VARCHAR2(10))"
2157
+ end
2158
+
2159
+ after(:all) do
2160
+ plsql.execute "DROP TABLE test_recompilable_table"
2161
+ plsql.execute "DROP FUNCTION test_recompilable_function"
2162
+ plsql.execute "DROP PACKAGE test_recompilable_package"
2163
+ end
2164
+
2165
+ it "should successfully call invalid function that can be recompiled" do
2166
+ expect {
2167
+ result = plsql.test_recompilable_function("test")
2168
+ expect(result).to eq("test")
2169
+ }.not_to raise_error
2170
+ end
2171
+
2172
+ it "should successfully call invalid package body that can be recompiled" do
2173
+ expect {
2174
+ result = plsql.test_recompilable_package.test_recompilable_function("test")
2175
+ expect(result).to eq("test")
2176
+ }.not_to raise_error
2012
2177
  end
2013
2178
  end
2014
2179
 
@@ -2025,7 +2190,7 @@ describe "SYS.STANDARD procedures /" do
2025
2190
  end
2026
2191
 
2027
2192
  it "should execute function from SYS.STANDARD package" do
2028
- expect(plsql.upper('abc')).to eq('ABC')
2193
+ expect(plsql.upper("abc")).to eq("ABC")
2029
2194
  end
2030
2195
 
2031
2196
  it "should find function overload based on types of sequential arguments" do
@@ -2033,16 +2198,193 @@ describe "SYS.STANDARD procedures /" do
2033
2198
  expect(plsql.nvl(nil, 2)).to eq(2)
2034
2199
  expect(plsql.nvl(1.1, 2.2)).to eq(1.1)
2035
2200
  expect(plsql.nvl(nil, 2.2)).to eq(2.2)
2036
- expect(plsql.nvl(BigDecimal('1.1'), BigDecimal('2.2'))).to eq(BigDecimal('1.1'))
2037
- expect(plsql.nvl(nil, BigDecimal('2.2'))).to eq(BigDecimal('2.2'))
2038
- expect(plsql.nvl('a', 'b')).to eq('a')
2039
- expect(plsql.nvl(nil, 'b')).to eq('b')
2040
- expect(plsql.nvl(Date.new(2010,1,13), Date.new(2010,1,19))).to eq(Time.local(2010,1,13))
2041
- expect(plsql.nvl(nil, Date.new(2010,1,19))).to eq(Time.local(2010,1,19))
2042
- expect(plsql.nvl(Time.local(2010,1,13), Time.local(2010,1,19))).to eq(Time.local(2010,1,13))
2043
- expect(plsql.nvl(nil, Time.local(2010,1,19))).to eq(Time.local(2010,1,19))
2201
+ expect(plsql.nvl(BigDecimal("1.1"), BigDecimal("2.2"))).to eq(BigDecimal("1.1"))
2202
+ expect(plsql.nvl(nil, BigDecimal("2.2"))).to eq(BigDecimal("2.2"))
2203
+ expect(plsql.nvl("a", "b")).to eq("a")
2204
+ expect(plsql.nvl(nil, "b")).to eq("b")
2205
+ expect(plsql.nvl(Date.new(2010, 1, 13), Date.new(2010, 1, 19))).to eq(Time.local(2010, 1, 13))
2206
+ expect(plsql.nvl(nil, Date.new(2010, 1, 19))).to eq(Time.local(2010, 1, 19))
2207
+ expect(plsql.nvl(Time.local(2010, 1, 13), Time.local(2010, 1, 19))).to eq(Time.local(2010, 1, 13))
2208
+ expect(plsql.nvl(nil, Time.local(2010, 1, 19))).to eq(Time.local(2010, 1, 19))
2044
2209
  expect(plsql.nvl(true, false)).to eq(true)
2045
2210
  expect(plsql.nvl(nil, false)).to eq(false)
2046
2211
  end
2047
2212
 
2048
2213
  end
2214
+
2215
+ describe "PLS_INTEGER/SIMPLE_INTEGER should be nullable" do
2216
+
2217
+ before(:all) do
2218
+ plsql.connect! CONNECTION_PARAMS
2219
+ plsql.execute <<-SQL
2220
+ CREATE OR REPLACE FUNCTION test_pls_f ( p_num PLS_INTEGER ) RETURN PLS_INTEGER IS
2221
+ BEGIN
2222
+ RETURN p_num;
2223
+ END;
2224
+ SQL
2225
+ plsql.execute <<-SQL
2226
+ CREATE OR REPLACE FUNCTION test_bin_f ( p_num BINARY_INTEGER ) RETURN BINARY_INTEGER IS
2227
+ BEGIN
2228
+ RETURN p_num;
2229
+ END;
2230
+ SQL
2231
+ plsql.execute <<-SQL
2232
+ CREATE OR REPLACE FUNCTION test_int_f ( p_num INTEGER ) RETURN INTEGER IS
2233
+ BEGIN
2234
+ RETURN p_num;
2235
+ END;
2236
+ SQL
2237
+ plsql.execute <<-SQL
2238
+ CREATE OR REPLACE PROCEDURE test_pls_p ( p_num IN OUT PLS_INTEGER ) IS
2239
+ BEGIN
2240
+ NULL;
2241
+ END;
2242
+ SQL
2243
+ plsql.execute <<-SQL
2244
+ CREATE OR REPLACE PROCEDURE test_bin_p ( p_num IN OUT BINARY_INTEGER ) IS
2245
+ BEGIN
2246
+ NULL;
2247
+ END;
2248
+ SQL
2249
+ plsql.execute <<-SQL
2250
+ CREATE OR REPLACE PROCEDURE test_int_p ( p_num IN OUT INTEGER ) IS
2251
+ BEGIN
2252
+ NULL;
2253
+ END;
2254
+ SQL
2255
+ plsql.execute <<-SQL
2256
+ CREATE OR REPLACE PROCEDURE test_flt_p ( p_num IN OUT BINARY_FLOAT ) IS
2257
+ BEGIN
2258
+ NULL;
2259
+ END;
2260
+ SQL
2261
+ plsql.execute <<-SQL
2262
+ CREATE OR REPLACE PROCEDURE test_dbl_p ( p_num IN OUT BINARY_DOUBLE ) IS
2263
+ BEGIN
2264
+ NULL;
2265
+ END;
2266
+ SQL
2267
+ end
2268
+
2269
+ after(:all) do
2270
+ plsql.execute "DROP FUNCTION test_pls_f"
2271
+ plsql.execute "DROP FUNCTION test_bin_f"
2272
+ plsql.execute "DROP FUNCTION test_int_f"
2273
+ plsql.execute "DROP PROCEDURE test_pls_p"
2274
+ plsql.execute "DROP PROCEDURE test_int_p"
2275
+ plsql.execute "DROP PROCEDURE test_flt_p"
2276
+ plsql.execute "DROP PROCEDURE test_dbl_p"
2277
+ plsql.logoff
2278
+ end
2279
+
2280
+ it "should return null for a function call with NULL PLS_INTEGER param" do
2281
+ expect(plsql.test_pls_f(nil)).to be_nil
2282
+ end
2283
+
2284
+ it "should return null for a function call with NULL BINARY_INTEGER param" do
2285
+ expect(plsql.test_bin_f(nil)).to be_nil
2286
+ end
2287
+
2288
+ it "should return null for a function call with NULL INTEGER param" do
2289
+ expect(plsql.test_int_f(nil)).to be_nil
2290
+ end
2291
+
2292
+ it "should return null for a procedure call with NULL PLS_INTEGER param" do
2293
+ expect(plsql.test_pls_p(nil)[:p_num]).to be_nil
2294
+ end
2295
+
2296
+ it "should return null for a procedure call with NULL BINARY_INTEGER param" do
2297
+ expect(plsql.test_bin_p(nil)[:p_num]).to be_nil
2298
+ end
2299
+
2300
+ it "should return null for a procedure call with NULL INTEGER param" do
2301
+ expect(plsql.test_int_p(nil)[:p_num]).to be_nil
2302
+ end
2303
+
2304
+ it "should return null for a procedure call with NULL BINARY_FLOAT param" do
2305
+ expect(plsql.test_flt_p(nil)[:p_num]).to be_nil
2306
+ end
2307
+
2308
+ it "should return null for a procedure call with NULL BINARY_DOUBLE param" do
2309
+ expect(plsql.test_dbl_p(nil)[:p_num]).to be_nil
2310
+ end
2311
+
2312
+ end
2313
+
2314
+ describe "#get_argument_metadata" do
2315
+ before(:all) do
2316
+ plsql.connect! CONNECTION_PARAMS
2317
+ end
2318
+
2319
+ after(:all) do
2320
+ plsql.logoff
2321
+ end
2322
+
2323
+ before(:each) do
2324
+ plsql.execute <<-SQL
2325
+ CREATE OR REPLACE FUNCTION magic_number(p_num INTEGER #{defaulted_clause})
2326
+ RETURN INTEGER
2327
+ IS
2328
+ BEGIN
2329
+ RETURN p_num * 2;
2330
+ END magic_number;
2331
+ SQL
2332
+ end
2333
+
2334
+ after(:each) do
2335
+ plsql.execute "DROP FUNCTION magic_number"
2336
+ end
2337
+
2338
+ context "on procedure with defaulted field" do
2339
+ let(:defaulted_clause) { "DEFAULT 21" }
2340
+
2341
+ it 'field\'s metadata attribute "defaulted" is Y' do
2342
+ procedure = PLSQL::Procedure.find(plsql, :magic_number)
2343
+ expect(procedure.arguments[0][:p_num][:defaulted]).to eq("Y")
2344
+ end
2345
+ end
2346
+
2347
+ context "procedure without defaulted field" do
2348
+ let(:defaulted_clause) { "" }
2349
+
2350
+ it 'field\'s metadata attribute "defaulted" is N' do
2351
+ procedure = PLSQL::Procedure.find(plsql, :magic_number)
2352
+ expect(procedure.arguments[0][:p_num][:defaulted]).to eq("N")
2353
+ end
2354
+ end
2355
+
2356
+ context "oracle <= 10g without defaulted functionality" do
2357
+ let(:defaulted_clause) { "" }
2358
+
2359
+ it 'field\'s metadata attribute "defaulted" is nil' do
2360
+ allow(plsql.connection).to receive(:database_version).and_return([10, 2, 0, 2])
2361
+
2362
+ procedure = PLSQL::Procedure.find(plsql, :magic_number)
2363
+ expect(procedure.arguments[0][:p_num][:defaulted]).to be_nil
2364
+ end
2365
+ end
2366
+ end
2367
+
2368
+ describe "case-insensitive params" do
2369
+ before(:all) do
2370
+ plsql.connect! CONNECTION_PARAMS
2371
+ plsql.execute <<-SQL
2372
+ CREATE OR REPLACE FUNCTION test_func
2373
+ ( p_string VARCHAR2 )
2374
+ RETURN VARCHAR2
2375
+ IS
2376
+ BEGIN
2377
+ RETURN UPPER(p_string);
2378
+ END test_func;
2379
+ SQL
2380
+ end
2381
+
2382
+ after(:all) do
2383
+ plsql.execute "DROP FUNCTION test_func"
2384
+ plsql.logoff
2385
+ end
2386
+
2387
+ it "should call procedure/function with case-insensitive param names" do
2388
+ expect { plsql.test_func(p_STRING: "xxx") }.not_to raise_error
2389
+ end
2390
+ end