ruby-plsql 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.codeclimate.yml +30 -0
- data/.github/stale.yml +37 -0
- data/.rubocop.yml +153 -0
- data/.travis.yml +20 -6
- data/.travis/oracle/download.sh +9 -10
- data/.travis/oracle/install.sh +6 -6
- data/Gemfile +13 -9
- data/History.txt +26 -0
- data/README.md +9 -5
- data/Rakefile +31 -26
- data/VERSION +1 -1
- data/Vagrantfile +2 -2
- 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/lib/plsql/connection.rb +16 -18
- data/lib/plsql/helpers.rb +1 -3
- data/lib/plsql/jdbc_connection.rb +66 -61
- data/lib/plsql/oci8_patches.rb +2 -2
- data/lib/plsql/oci_connection.rb +51 -69
- data/lib/plsql/package.rb +5 -8
- data/lib/plsql/procedure.rb +75 -78
- data/lib/plsql/procedure_call.rb +498 -501
- data/lib/plsql/schema.rb +95 -100
- data/lib/plsql/sequence.rb +10 -13
- data/lib/plsql/sql_statements.rb +9 -11
- data/lib/plsql/table.rb +59 -63
- data/lib/plsql/type.rb +71 -76
- data/lib/plsql/variable.rb +89 -94
- data/lib/plsql/version.rb +1 -1
- data/lib/plsql/view.rb +16 -19
- data/ruby-plsql.gemspec +41 -37
- data/spec/plsql/connection_spec.rb +67 -67
- data/spec/plsql/package_spec.rb +15 -15
- data/spec/plsql/procedure_spec.rb +286 -233
- data/spec/plsql/schema_spec.rb +22 -23
- data/spec/plsql/sequence_spec.rb +2 -2
- data/spec/plsql/sql_statements_spec.rb +5 -5
- data/spec/plsql/table_spec.rb +77 -77
- data/spec/plsql/type_spec.rb +23 -29
- data/spec/plsql/variable_spec.rb +59 -59
- data/spec/plsql/version_spec.rb +4 -4
- data/spec/plsql/view_spec.rb +42 -42
- data/spec/spec_helper.rb +37 -29
- data/spec/support/test_db.rb +12 -13
- metadata +44 -26
- data/.travis/oracle/LICENSE +0 -5
- data/.travis/oracle/README.md +0 -64
- data/.travis/oracle/download.js +0 -100
data/lib/plsql/oci8_patches.rb
CHANGED
data/lib/plsql/oci_connection.rb
CHANGED
@@ -18,17 +18,16 @@ require "plsql/oci8_patches"
|
|
18
18
|
|
19
19
|
# check ruby-oci8 version
|
20
20
|
required_oci8_version = [2, 0, 3]
|
21
|
-
oci8_version_ints = OCI8::VERSION.scan(/\d+/).map{|s| s.to_i}
|
21
|
+
oci8_version_ints = OCI8::VERSION.scan(/\d+/).map { |s| s.to_i }
|
22
22
|
if (oci8_version_ints <=> required_oci8_version) < 0
|
23
23
|
raise LoadError, "ERROR: ruby-oci8 version #{OCI8::VERSION} is too old. Please install ruby-oci8 version #{required_oci8_version.join('.')} or later."
|
24
24
|
end
|
25
25
|
|
26
26
|
module PLSQL
|
27
27
|
class OCIConnection < Connection #:nodoc:
|
28
|
-
|
29
28
|
def self.create_raw(params)
|
30
29
|
connection_string = if params[:host]
|
31
|
-
"//#{params[:host]}:#{params[:port]||1521}/#{params[:database]}"
|
30
|
+
"//#{params[:host]}:#{params[:port] || 1521}/#{params[:database]}"
|
32
31
|
else
|
33
32
|
params[:database]
|
34
33
|
end
|
@@ -47,7 +46,7 @@ module PLSQL
|
|
47
46
|
def rollback
|
48
47
|
raw_connection.rollback
|
49
48
|
end
|
50
|
-
|
49
|
+
|
51
50
|
def autocommit?
|
52
51
|
raw_connection.autocommit?
|
53
52
|
end
|
@@ -86,7 +85,7 @@ module PLSQL
|
|
86
85
|
self.new(conn, raw_cursor)
|
87
86
|
end
|
88
87
|
|
89
|
-
def self.new_from_query(conn, sql, bindvars=[], options={})
|
88
|
+
def self.new_from_query(conn, sql, bindvars = [], options = {})
|
90
89
|
cursor = new_from_parse(conn, sql)
|
91
90
|
if prefetch_rows = options[:prefetch_rows]
|
92
91
|
cursor.prefetch_rows = prefetch_rows
|
@@ -104,7 +103,7 @@ module PLSQL
|
|
104
103
|
ora_value = @connection.ruby_value_to_ora_value(value, type)
|
105
104
|
@raw_cursor.bind_param(arg, ora_value, type, length)
|
106
105
|
end
|
107
|
-
|
106
|
+
|
108
107
|
def exec(*bindvars)
|
109
108
|
@raw_cursor.exec(*bindvars)
|
110
109
|
end
|
@@ -115,11 +114,11 @@ module PLSQL
|
|
115
114
|
|
116
115
|
def fetch
|
117
116
|
row = @raw_cursor.fetch
|
118
|
-
row && row.map{|v| @connection.ora_value_to_ruby_value(v)}
|
117
|
+
row && row.map { |v| @connection.ora_value_to_ruby_value(v) }
|
119
118
|
end
|
120
119
|
|
121
120
|
def fields
|
122
|
-
@fields ||= @raw_cursor.get_col_names.map{|c| c.downcase.to_sym}
|
121
|
+
@fields ||= @raw_cursor.get_col_names.map { |c| c.downcase.to_sym }
|
123
122
|
end
|
124
123
|
|
125
124
|
def close_raw_cursor
|
@@ -133,14 +132,13 @@ module PLSQL
|
|
133
132
|
end
|
134
133
|
close_raw_cursor
|
135
134
|
end
|
136
|
-
|
137
135
|
end
|
138
136
|
|
139
137
|
def parse(sql)
|
140
138
|
Cursor.new_from_parse(self, sql)
|
141
139
|
end
|
142
140
|
|
143
|
-
def cursor_from_query(sql, bindvars=[], options={})
|
141
|
+
def cursor_from_query(sql, bindvars = [], options = {})
|
144
142
|
Cursor.new_from_query(self, sql, bindvars, options)
|
145
143
|
end
|
146
144
|
|
@@ -174,18 +172,16 @@ module PLSQL
|
|
174
172
|
end
|
175
173
|
end
|
176
174
|
|
177
|
-
def ruby_value_to_ora_value(value, type=nil)
|
175
|
+
def ruby_value_to_ora_value(value, type = nil)
|
178
176
|
type ||= value.class
|
179
177
|
case type.to_s.to_sym
|
180
|
-
when :
|
178
|
+
when :Integer, :BigDecimal, :String
|
181
179
|
value
|
182
180
|
when :OraNumber
|
183
181
|
# pass parameters as OraNumber to avoid rounding errors
|
184
182
|
case value
|
185
|
-
when Bignum
|
186
|
-
OraNumber.new(value.to_s)
|
187
183
|
when BigDecimal
|
188
|
-
OraNumber.new(value.to_s(
|
184
|
+
OraNumber.new(value.to_s("F"))
|
189
185
|
when TrueClass
|
190
186
|
OraNumber.new(1)
|
191
187
|
when FalseClass
|
@@ -218,7 +214,7 @@ module PLSQL
|
|
218
214
|
raise ArgumentError, "You should pass Array value for collection type parameter" unless value.is_a?(Array)
|
219
215
|
elem_list = value.map do |elem|
|
220
216
|
if (attr_tdo = tdo.coll_attr.typeinfo)
|
221
|
-
attr_type,
|
217
|
+
attr_type, _ = plsql_to_ruby_data_type(data_type: "OBJECT", sql_type_name: attr_tdo.typename)
|
222
218
|
else
|
223
219
|
attr_type = elem.class
|
224
220
|
end
|
@@ -227,7 +223,7 @@ module PLSQL
|
|
227
223
|
# construct collection value
|
228
224
|
# TODO: change setting instance variable to appropriate ruby-oci8 method call when available
|
229
225
|
collection = type.new(raw_oci_connection)
|
230
|
-
collection.instance_variable_set(
|
226
|
+
collection.instance_variable_set("@attributes", elem_list)
|
231
227
|
collection
|
232
228
|
else # object type
|
233
229
|
raise ArgumentError, "You should pass Hash value for object type parameter" unless value.is_a?(Hash)
|
@@ -237,7 +233,7 @@ module PLSQL
|
|
237
233
|
case attr.datatype
|
238
234
|
when OCI8::TDO::ATTR_NAMED_TYPE, OCI8::TDO::ATTR_NAMED_COLLECTION
|
239
235
|
# nested object type or collection
|
240
|
-
attr_type,
|
236
|
+
attr_type, _ = plsql_to_ruby_data_type(data_type: "OBJECT", sql_type_name: attr.typeinfo.typename)
|
241
237
|
object_attrs[key] = ruby_value_to_ora_value(object_attrs[key], attr_type)
|
242
238
|
end
|
243
239
|
end
|
@@ -266,7 +262,7 @@ module PLSQL
|
|
266
262
|
when OCI8::Object::Base
|
267
263
|
tdo = raw_oci_connection.get_tdo_by_class(value.class)
|
268
264
|
if tdo.is_collection?
|
269
|
-
value.to_ary.map{|e| ora_value_to_ruby_value(e)}
|
265
|
+
value.to_ary.map { |e| ora_value_to_ruby_value(e) }
|
270
266
|
else # object type
|
271
267
|
tdo.attributes.inject({}) do |hash, attr|
|
272
268
|
hash[attr.name] = ora_value_to_ruby_value(value.instance_variable_get(:@attributes)[attr.name])
|
@@ -280,63 +276,49 @@ module PLSQL
|
|
280
276
|
end
|
281
277
|
end
|
282
278
|
|
283
|
-
def describe_synonym(schema_name, synonym_name)
|
284
|
-
if schema_name == 'PUBLIC'
|
285
|
-
full_name = synonym_name.to_s
|
286
|
-
else
|
287
|
-
full_name = "#{schema_name}.#{synonym_name}"
|
288
|
-
end
|
289
|
-
metadata = raw_connection.describe_synonym(full_name)
|
290
|
-
[metadata.schema_name, metadata.name]
|
291
|
-
rescue OCIError
|
292
|
-
nil
|
293
|
-
end
|
294
|
-
|
295
279
|
def database_version
|
296
|
-
@database_version ||= (version = raw_connection.oracle_server_version) &&
|
280
|
+
@database_version ||= (version = raw_connection.oracle_server_version) &&
|
297
281
|
[version.major, version.minor, version.update, version.patch]
|
298
282
|
end
|
299
283
|
|
300
284
|
private
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
def ora_number_to_ruby_number(num)
|
313
|
-
# return BigDecimal instead of Float to avoid rounding errors
|
314
|
-
num == (num_to_i = num.to_i) ? num_to_i : (num.is_a?(BigDecimal) ? num : BigDecimal.new(num.to_s))
|
315
|
-
end
|
316
|
-
|
317
|
-
def ora_date_to_ruby_date(val)
|
318
|
-
case val
|
319
|
-
when DateTime
|
320
|
-
# similar implementation as in oracle_enhanced adapter
|
321
|
-
begin
|
322
|
-
Time.send(plsql.default_timezone, val.year, val.month, val.day, val.hour, val.min, val.sec)
|
323
|
-
rescue
|
324
|
-
offset = plsql.default_timezone.to_sym == :local ? plsql.local_timezone_offset : 0
|
325
|
-
DateTime.civil(val.year, val.month, val.day, val.hour, val.min, val.sec, offset)
|
326
|
-
end
|
327
|
-
when OraDate
|
328
|
-
# similar implementation as in oracle_enhanced adapter
|
329
|
-
begin
|
330
|
-
Time.send(plsql.default_timezone, val.year, val.month, val.day, val.hour, val.minute, val.second)
|
331
|
-
rescue
|
332
|
-
offset = plsql.default_timezone.to_sym == :local ? plsql.local_timezone_offset : 0
|
333
|
-
DateTime.civil(val.year, val.month, val.day, val.hour, val.minute, val.second, offset)
|
285
|
+
|
286
|
+
def raw_oci_connection
|
287
|
+
if raw_connection.is_a? OCI8
|
288
|
+
raw_connection
|
289
|
+
# ActiveRecord Oracle enhanced adapter puts OCI8EnhancedAutoRecover wrapper around OCI8
|
290
|
+
# in this case we need to pass original OCI8 connection
|
291
|
+
else
|
292
|
+
raw_connection.instance_variable_get(:@connection)
|
334
293
|
end
|
335
|
-
else
|
336
|
-
val
|
337
294
|
end
|
338
|
-
end
|
339
295
|
|
296
|
+
def ora_number_to_ruby_number(num)
|
297
|
+
# return BigDecimal instead of Float to avoid rounding errors
|
298
|
+
num == (num_to_i = num.to_i) ? num_to_i : (num.is_a?(BigDecimal) ? num : BigDecimal(num.to_s))
|
299
|
+
end
|
300
|
+
|
301
|
+
def ora_date_to_ruby_date(val)
|
302
|
+
case val
|
303
|
+
when DateTime
|
304
|
+
# similar implementation as in oracle_enhanced adapter
|
305
|
+
begin
|
306
|
+
Time.send(plsql.default_timezone, val.year, val.month, val.day, val.hour, val.min, val.sec)
|
307
|
+
rescue
|
308
|
+
offset = plsql.default_timezone.to_sym == :local ? plsql.local_timezone_offset : 0
|
309
|
+
DateTime.civil(val.year, val.month, val.day, val.hour, val.min, val.sec, offset)
|
310
|
+
end
|
311
|
+
when OraDate
|
312
|
+
# similar implementation as in oracle_enhanced adapter
|
313
|
+
begin
|
314
|
+
Time.send(plsql.default_timezone, val.year, val.month, val.day, val.hour, val.minute, val.second)
|
315
|
+
rescue
|
316
|
+
offset = plsql.default_timezone.to_sym == :local ? plsql.local_timezone_offset : 0
|
317
|
+
DateTime.civil(val.year, val.month, val.day, val.hour, val.minute, val.second, offset)
|
318
|
+
end
|
319
|
+
else
|
320
|
+
val
|
321
|
+
end
|
322
|
+
end
|
340
323
|
end
|
341
|
-
|
342
324
|
end
|
data/lib/plsql/package.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module PLSQL
|
2
|
-
|
3
2
|
module PackageClassMethods #:nodoc:
|
4
3
|
def find(schema, package)
|
5
4
|
package_name = package.to_s.upcase
|
@@ -56,11 +55,11 @@ module PLSQL
|
|
56
55
|
|
57
56
|
private
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
def method_missing(method, *args, &block)
|
59
|
+
method = method.to_s
|
60
|
+
method.chop! if (assignment = method[/=$/])
|
62
61
|
|
63
|
-
|
62
|
+
case (object = self[method])
|
64
63
|
when Procedure
|
65
64
|
if assignment
|
66
65
|
raise ArgumentError, "Cannot assign value to package procedure '#{method.upcase}'"
|
@@ -82,9 +81,7 @@ module PLSQL
|
|
82
81
|
end
|
83
82
|
else
|
84
83
|
raise ArgumentError, "No PL/SQL procedure or variable '#{method.upcase}' found"
|
84
|
+
end
|
85
85
|
end
|
86
|
-
end
|
87
|
-
|
88
86
|
end
|
89
|
-
|
90
87
|
end
|
data/lib/plsql/procedure.rb
CHANGED
@@ -1,45 +1,44 @@
|
|
1
1
|
module PLSQL
|
2
|
-
|
3
2
|
module ProcedureClassMethods #:nodoc:
|
4
3
|
def find(schema, procedure, package = nil, override_schema_name = nil)
|
5
4
|
if package.nil?
|
6
5
|
if (row = schema.select_first(
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
"SELECT #{procedure_object_id_src(schema)}.object_id
|
7
|
+
FROM all_procedures p, all_objects o
|
8
|
+
WHERE p.owner = :owner
|
9
|
+
AND p.object_name = :object_name
|
10
|
+
AND o.owner = p.owner
|
11
|
+
AND o.object_name = p.object_name
|
12
|
+
AND o.object_type in ('PROCEDURE', 'FUNCTION')",
|
14
13
|
schema.schema_name, procedure.to_s.upcase))
|
15
14
|
new(schema, procedure, nil, nil, row[0])
|
16
15
|
# search for synonym
|
17
16
|
elsif (row = schema.select_first(
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
17
|
+
"SELECT o.owner, o.object_name, #{procedure_object_id_src(schema)}.object_id
|
18
|
+
FROM all_synonyms s, all_objects o, all_procedures p
|
19
|
+
WHERE s.owner IN (:owner, 'PUBLIC')
|
20
|
+
AND s.synonym_name = :synonym_name
|
21
|
+
AND o.owner = s.table_owner
|
22
|
+
AND o.object_name = s.table_name
|
23
|
+
AND o.object_type IN ('PROCEDURE','FUNCTION')
|
24
|
+
AND o.owner = p.owner
|
25
|
+
AND o.object_name = p.object_name
|
26
|
+
ORDER BY DECODE(s.owner, 'PUBLIC', 1, 0)",
|
28
27
|
schema.schema_name, procedure.to_s.upcase))
|
29
28
|
new(schema, row[1], nil, row[0], row[2])
|
30
29
|
else
|
31
30
|
nil
|
32
31
|
end
|
33
32
|
elsif package && (row = schema.select_first(
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
33
|
+
# older Oracle versions do not have object_id column in all_procedures
|
34
|
+
"SELECT #{procedure_object_id_src(schema)}.object_id
|
35
|
+
FROM all_procedures p, all_objects o
|
36
|
+
WHERE p.owner = :owner
|
37
|
+
AND p.object_name = :object_name
|
38
|
+
AND p.procedure_name = :procedure_name
|
39
|
+
AND o.owner = p.owner
|
40
|
+
AND o.object_name = p.object_name
|
41
|
+
AND o.object_type = 'PACKAGE'",
|
43
42
|
override_schema_name || schema.schema_name, package, procedure.to_s.upcase))
|
44
43
|
new(schema, procedure, package, override_schema_name, row[0])
|
45
44
|
else
|
@@ -49,9 +48,9 @@ module PLSQL
|
|
49
48
|
|
50
49
|
private
|
51
50
|
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
def procedure_object_id_src(schema)
|
52
|
+
(schema.connection.database_version <=> [11, 1, 0, 0]) >= 0 ? "p" : "o"
|
53
|
+
end
|
55
54
|
end
|
56
55
|
|
57
56
|
module ProcedureCommon #:nodoc:
|
@@ -61,21 +60,21 @@ module PLSQL
|
|
61
60
|
# return type string from metadata that can be used in DECLARE block or table definition
|
62
61
|
def self.type_to_sql(metadata) #:nodoc:
|
63
62
|
case metadata[:data_type]
|
64
|
-
when
|
63
|
+
when "NUMBER"
|
65
64
|
precision, scale = metadata[:data_precision], metadata[:data_scale]
|
66
|
-
"NUMBER#{precision ? "(#{precision}#{scale ? ",#{scale}": ""})" : ""}"
|
67
|
-
when
|
65
|
+
"NUMBER#{precision ? "(#{precision}#{scale ? ",#{scale}" : ""})" : ""}"
|
66
|
+
when "VARCHAR", "VARCHAR2", "CHAR"
|
68
67
|
length = case metadata[:char_used]
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
when "C" then "#{metadata[:char_length]} CHAR"
|
69
|
+
when "B" then "#{metadata[:data_length]} BYTE"
|
70
|
+
else
|
71
|
+
metadata[:data_length]
|
73
72
|
end
|
74
73
|
"#{metadata[:data_type]}#{length && "(#{length})"}"
|
75
|
-
when
|
74
|
+
when "NVARCHAR2", "NCHAR"
|
76
75
|
length = metadata[:char_length]
|
77
76
|
"#{metadata[:data_type]}#{length && "(#{length})"}"
|
78
|
-
when
|
77
|
+
when "PL/SQL TABLE", "TABLE", "VARRAY", "OBJECT", "XMLTYPE"
|
79
78
|
metadata[:sql_type_name]
|
80
79
|
else
|
81
80
|
metadata[:data_type]
|
@@ -99,9 +98,9 @@ module PLSQL
|
|
99
98
|
@tmp_tables_created = {}
|
100
99
|
|
101
100
|
# subprogram_id column is available just from version 10g
|
102
|
-
subprogram_id_column = (@schema.connection.database_version <=> [10, 2, 0, 2]) >= 0 ?
|
101
|
+
subprogram_id_column = (@schema.connection.database_version <=> [10, 2, 0, 2]) >= 0 ? "subprogram_id" : "NULL"
|
103
102
|
# defaulted is available just from version 11g
|
104
|
-
defaulted_column = (@schema.connection.database_version <=> [11, 0, 0, 0]) >= 0 ?
|
103
|
+
defaulted_column = (@schema.connection.database_version <=> [11, 0, 0, 0]) >= 0 ? "defaulted" : "NULL"
|
105
104
|
|
106
105
|
@schema.select_all(
|
107
106
|
"SELECT #{subprogram_id_column}, object_name, TO_NUMBER(overload), argument_name, position, data_level,
|
@@ -138,7 +137,7 @@ module PLSQL
|
|
138
137
|
# then generate unique ID from object_name and overload
|
139
138
|
subprogram_id ||= "#{object_name.hash % 10000}#{overload}"
|
140
139
|
tmp_table_name = "#{Connection::RUBY_TEMP_TABLE_PREFIX}#{@schema.connection.session_id}_#{@object_id}_#{subprogram_id}_#{position}"
|
141
|
-
elsif data_type !=
|
140
|
+
elsif data_type != "PL/SQL RECORD"
|
142
141
|
# raise exception only when there are no overloaded procedure definitions
|
143
142
|
# (as probably this overload will not be used at all)
|
144
143
|
raise ArgumentError, "Parameter type #{sql_type_name} definition inside package is not supported, use CREATE TYPE outside package" if overload == 0
|
@@ -146,19 +145,19 @@ module PLSQL
|
|
146
145
|
end
|
147
146
|
|
148
147
|
argument_metadata = {
|
149
|
-
:
|
150
|
-
:
|
151
|
-
:
|
152
|
-
:
|
153
|
-
:
|
154
|
-
:
|
155
|
-
:
|
156
|
-
:
|
157
|
-
:
|
158
|
-
:
|
159
|
-
:
|
160
|
-
:
|
161
|
-
:
|
148
|
+
position: position && position.to_i,
|
149
|
+
data_type: data_type,
|
150
|
+
in_out: in_out,
|
151
|
+
data_length: data_length && data_length.to_i,
|
152
|
+
data_precision: data_precision && data_precision.to_i,
|
153
|
+
data_scale: data_scale && data_scale.to_i,
|
154
|
+
char_used: char_used,
|
155
|
+
char_length: char_length && char_length.to_i,
|
156
|
+
type_owner: type_owner,
|
157
|
+
type_name: type_name,
|
158
|
+
type_subname: type_subname,
|
159
|
+
sql_type_name: sql_type_name,
|
160
|
+
defaulted: defaulted
|
162
161
|
}
|
163
162
|
if tmp_table_name
|
164
163
|
@tmp_table_names[overload] << [(argument_metadata[:tmp_table_name] = tmp_table_name), argument_metadata]
|
@@ -166,14 +165,14 @@ module PLSQL
|
|
166
165
|
|
167
166
|
if composite_type?(data_type)
|
168
167
|
case data_type
|
169
|
-
when
|
168
|
+
when "PL/SQL RECORD"
|
170
169
|
argument_metadata[:fields] = {}
|
171
170
|
end
|
172
171
|
previous_level_argument_metadata[data_level] = argument_metadata
|
173
172
|
end
|
174
173
|
|
175
174
|
# if function has return value
|
176
|
-
if argument_name.nil? && data_level == 0 && in_out ==
|
175
|
+
if argument_name.nil? && data_level == 0 && in_out == "OUT"
|
177
176
|
@return[overload] = argument_metadata
|
178
177
|
# if parameter
|
179
178
|
else
|
@@ -184,9 +183,9 @@ module PLSQL
|
|
184
183
|
# or lower level part of composite type
|
185
184
|
else
|
186
185
|
case previous_level_argument_metadata[data_level - 1][:data_type]
|
187
|
-
when
|
186
|
+
when "PL/SQL RECORD"
|
188
187
|
previous_level_argument_metadata[data_level - 1][:fields][argument_name.downcase.to_sym] = argument_metadata
|
189
|
-
when
|
188
|
+
when "PL/SQL TABLE", "TABLE", "VARRAY", "REF CURSOR"
|
190
189
|
previous_level_argument_metadata[data_level - 1][:element] = argument_metadata
|
191
190
|
end
|
192
191
|
end
|
@@ -201,8 +200,8 @@ module PLSQL
|
|
201
200
|
def construct_argument_list_for_overloads #:nodoc:
|
202
201
|
@overloads = @arguments.keys.sort
|
203
202
|
@overloads.each do |overload|
|
204
|
-
@argument_list[overload] = @arguments[overload].keys.sort {|k1, k2| @arguments[overload][k1][:position] <=> @arguments[overload][k2][:position]}
|
205
|
-
@out_list[overload] = @argument_list[overload].select {|k| @arguments[overload][k][:in_out] =~ /OUT/}
|
203
|
+
@argument_list[overload] = @arguments[overload].keys.sort { |k1, k2| @arguments[overload][k1][:position] <=> @arguments[overload][k2][:position] }
|
204
|
+
@out_list[overload] = @argument_list[overload].select { |k| @arguments[overload][k][:in_out] =~ /OUT/ }
|
206
205
|
end
|
207
206
|
end
|
208
207
|
|
@@ -210,19 +209,19 @@ module PLSQL
|
|
210
209
|
return if @tmp_tables_created.nil? || @tmp_tables_created[overload]
|
211
210
|
@tmp_table_names[overload] && @tmp_table_names[overload].each do |table_name, argument_metadata|
|
212
211
|
sql = "CREATE GLOBAL TEMPORARY TABLE #{table_name} (\n"
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
212
|
+
element_metadata = argument_metadata[:element]
|
213
|
+
case element_metadata[:data_type]
|
214
|
+
when "PL/SQL RECORD"
|
215
|
+
fields_metadata = element_metadata[:fields]
|
216
|
+
fields_sorted_by_position = fields_metadata.keys.sort_by { |k| fields_metadata[k][:position] }
|
217
|
+
sql << fields_sorted_by_position.map do |field|
|
218
|
+
metadata = fields_metadata[field]
|
219
|
+
"#{field} #{ProcedureCommon.type_to_sql(metadata)}"
|
220
|
+
end.join(",\n")
|
221
|
+
else
|
222
|
+
sql << "element #{ProcedureCommon.type_to_sql(element_metadata)}"
|
223
|
+
end
|
224
|
+
sql << ",\ni__ NUMBER(38)\n"
|
226
225
|
sql << ") ON COMMIT PRESERVE ROWS\n"
|
227
226
|
sql_block = "DECLARE\nPRAGMA AUTONOMOUS_TRANSACTION;\nBEGIN\nEXECUTE IMMEDIATE :sql;\nEND;\n"
|
228
227
|
@schema.execute sql_block, sql
|
@@ -230,12 +229,12 @@ module PLSQL
|
|
230
229
|
@tmp_tables_created[overload] = true
|
231
230
|
end
|
232
231
|
|
233
|
-
PLSQL_COMPOSITE_TYPES = [
|
232
|
+
PLSQL_COMPOSITE_TYPES = ["PL/SQL RECORD", "PL/SQL TABLE", "TABLE", "VARRAY", "REF CURSOR"].freeze
|
234
233
|
def composite_type?(data_type) #:nodoc:
|
235
234
|
PLSQL_COMPOSITE_TYPES.include? data_type
|
236
235
|
end
|
237
236
|
|
238
|
-
PLSQL_COLLECTION_TYPES = [
|
237
|
+
PLSQL_COLLECTION_TYPES = ["PL/SQL TABLE", "TABLE", "VARRAY"].freeze
|
239
238
|
def collection_type?(data_type) #:nodoc:
|
240
239
|
PLSQL_COLLECTION_TYPES.include? data_type
|
241
240
|
end
|
@@ -266,7 +265,5 @@ module PLSQL
|
|
266
265
|
call = ProcedureCall.new(self, args)
|
267
266
|
call.exec(&block)
|
268
267
|
end
|
269
|
-
|
270
268
|
end
|
271
|
-
|
272
269
|
end
|