ruby-plsql 0.5.3 → 0.8.0
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.
- checksums.yaml +5 -5
- data/.github/stale.yml +37 -0
- data/.github/workflows/rubocop.yml +37 -0
- data/.github/workflows/test.yml +69 -0
- data/.rubocop.yml +147 -0
- data/.travis.yml +88 -0
- data/.travis/oracle/download.sh +15 -0
- data/.travis/oracle/install.sh +32 -0
- data/.travis/setup_accounts.sh +9 -0
- data/Gemfile +17 -9
- data/History.txt +76 -0
- data/README.md +29 -6
- data/Rakefile +31 -26
- data/VERSION +1 -1
- data/Vagrantfile +4 -4
- data/ci/network/admin/tnsnames.ora +7 -0
- data/ci/setup_accounts.sh +9 -0
- data/gemfiles/Gemfile.activerecord-5.0 +21 -0
- data/gemfiles/Gemfile.activerecord-5.1 +21 -0
- data/gemfiles/Gemfile.activerecord-5.2 +21 -0
- data/gemfiles/Gemfile.activerecord-6.0 +21 -0
- data/gemfiles/Gemfile.activerecord-6.1 +21 -0
- data/gemfiles/Gemfile.activerecord-main +21 -0
- data/lib/plsql/connection.rb +19 -22
- data/lib/plsql/helpers.rb +1 -3
- data/lib/plsql/jdbc_connection.rb +70 -68
- data/lib/plsql/oci8_patches.rb +2 -2
- data/lib/plsql/oci_connection.rb +62 -77
- data/lib/plsql/package.rb +61 -46
- data/lib/plsql/procedure.rb +358 -78
- data/lib/plsql/procedure_call.rb +508 -463
- data/lib/plsql/schema.rb +96 -101
- data/lib/plsql/sequence.rb +10 -13
- data/lib/plsql/sql_statements.rb +9 -11
- data/lib/plsql/table.rb +60 -63
- data/lib/plsql/type.rb +71 -76
- data/lib/plsql/variable.rb +90 -94
- data/lib/plsql/version.rb +1 -1
- data/lib/plsql/view.rb +16 -19
- data/ruby-plsql.gemspec +55 -35
- data/spec/plsql/connection_spec.rb +72 -66
- data/spec/plsql/package_spec.rb +63 -14
- data/spec/plsql/procedure_spec.rb +603 -261
- data/spec/plsql/schema_spec.rb +47 -23
- data/spec/plsql/sequence_spec.rb +2 -2
- data/spec/plsql/sql_statements_spec.rb +6 -6
- data/spec/plsql/table_spec.rb +84 -79
- data/spec/plsql/type_spec.rb +24 -30
- data/spec/plsql/variable_spec.rb +80 -88
- data/spec/plsql/version_spec.rb +4 -4
- data/spec/plsql/view_spec.rb +42 -42
- data/spec/spec_helper.rb +38 -35
- data/spec/support/create_arunit_user.sql +2 -0
- data/spec/support/custom_config.rb.sample +14 -0
- data/spec/support/test_db.rb +12 -13
- data/spec/support/unlock_and_setup_hr_user.sql +2 -0
- metadata +111 -34
data/spec/plsql/package_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
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(
|
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(
|
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(
|
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
|
3
|
+
require "spec_helper"
|
4
4
|
|
5
5
|
describe "Parameter type mapping /" do
|
6
|
-
|
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
|
12
|
-
RETURN
|
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(
|
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(:
|
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(
|
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(:
|
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(
|
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
|
-
|
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
|
65
|
-
RETURN
|
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
|
111
|
-
expect(plsql.test_sum(
|
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
|
-
|
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
|
119
|
-
expect(plsql.test_sum(
|
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
|
-
|
123
|
-
|
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.
|
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.
|
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(
|
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(:
|
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(
|
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(:
|
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(
|
355
|
-
expect(plsql.test_package2.test_procedure(
|
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(:
|
360
|
-
expect(plsql.test_package2.test_procedure(:
|
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(
|
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(:
|
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(:
|
377
|
-
expect(plsql.test_package2.test_function(:
|
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, { :
|
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(:
|
409
|
-
[3, { :
|
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, { :
|
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 =
|
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 =
|
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
|
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
|
681
|
+
last_name VARCHAR(50),
|
630
682
|
hire_date DATE
|
631
683
|
);
|
632
684
|
|
633
|
-
TYPE
|
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
|
-
:
|
694
|
-
:
|
695
|
-
:
|
696
|
-
:
|
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
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
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(:
|
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(
|
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(
|
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 :
|
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, {:
|
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(
|
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(
|
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(
|
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(
|
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
|
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
|
-
:
|
867
|
-
:
|
868
|
-
:
|
869
|
-
:
|
870
|
-
:
|
871
|
-
:
|
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(:
|
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(
|
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 :
|
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, {:
|
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
|
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
|
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
|
-
:
|
1101
|
-
:
|
1102
|
-
:
|
1103
|
-
:
|
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
|
-
:
|
1109
|
-
:
|
1110
|
-
:
|
1111
|
-
:
|
1112
|
-
:
|
1113
|
-
:
|
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 = [
|
1166
|
-
expect(plsql.test_copy_strings(strings)).to eq([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],
|
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],
|
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],
|
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], {:
|
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], {:
|
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], {:
|
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, {:
|
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, {:
|
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, {:
|
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, {:
|
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 = [{:
|
1212
|
-
expect(plsql.test_copy_objects(phones)).to eq([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, {:
|
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], {:
|
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, {:
|
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
|
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
|
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
|
-
:
|
1343
|
-
:
|
1344
|
-
:
|
1345
|
-
:
|
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,
|
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,
|
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,
|
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, {:
|
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, {:
|
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, {:
|
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, {:
|
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(
|
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
|
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, {:
|
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 = [
|
1527
|
-
expect(plsql.test_copy_strings(strings)).to eq([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 = [{:
|
1532
|
-
expect(plsql.test_copy_objects(phones)).to eq([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, {:
|
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],
|
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],
|
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],
|
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 = [
|
1665
|
-
expect(plsql.test_collections.test_copy_strings(strings)).to eq([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 = [{:
|
1670
|
-
expect(plsql.test_collections.test_copy_objects(phones)).to eq([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
|
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
|
-
:
|
1734
|
-
:
|
1735
|
-
:
|
1736
|
-
:
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
2011
|
-
}.to raise_error(
|
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(
|
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(
|
2037
|
-
expect(plsql.nvl(nil, BigDecimal(
|
2038
|
-
expect(plsql.nvl(
|
2039
|
-
expect(plsql.nvl(nil,
|
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
|