Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions lib/plsql/procedure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,23 @@ def get_element_definition(argument_metadata) # :nodoc:

if elem_type_package != nil
element_metadata[:fields] = get_field_definitions(element_metadata)
elsif elem_type_name && elem_type_name =~ /\A(.+)%ROWTYPE\z/
# TABLE OF table%ROWTYPE: Oracle stores elem_type_name as "TABLE_NAME%ROWTYPE"
rowtype_table_name = $1
check_owner = elem_type_owner || @schema_name
object_type_row = @schema.select_first(
"SELECT object_type FROM ALL_OBJECTS WHERE owner = :owner AND object_name = :name AND object_type IN ('TABLE', 'VIEW')",
check_owner, rowtype_table_name)
if object_type_row
element_metadata[:type_owner] ||= check_owner
element_metadata[:type_name] = rowtype_table_name
element_metadata[:sql_type_name] = build_sql_type_name(check_owner, nil, rowtype_table_name)
element_metadata[:data_type] = "PL/SQL RECORD"
element_metadata[:type_object_type] = object_type_row[0]
element_metadata[:fields] = get_field_definitions(element_metadata)
else
raise ArgumentError, "Could not resolve #{check_owner}.#{rowtype_table_name} to a table or view for #{elem_type_name}"
end
end
when "TYPE"
r = @schema.select_first(
Expand Down
66 changes: 66 additions & 0 deletions spec/plsql/procedure_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2426,3 +2426,69 @@ def new_candidate(status)
expect(field_names.none? { |name| name.to_s.start_with?("sys_nc") }).to be true
end
end

describe "Function with TABLE OF %ROWTYPE parameter defined in package" do
before(:all) do
plsql.connect! CONNECTION_PARAMS
plsql.execute "DROP PACKAGE test_rowtype_pkg" rescue nil
plsql.execute "DROP TABLE test_rowtype_tbl" rescue nil
plsql.execute "CREATE TABLE test_rowtype_tbl (id NUMBER, name VARCHAR2(50))"
plsql.execute <<-SQL
CREATE OR REPLACE PACKAGE test_rowtype_pkg IS
TYPE t_tab IS TABLE OF test_rowtype_tbl%ROWTYPE;
FUNCTION test_fn(p_tab IN t_tab) RETURN NUMBER;
END;
SQL
plsql.execute <<-SQL
CREATE OR REPLACE PACKAGE BODY test_rowtype_pkg IS
FUNCTION test_fn(p_tab IN t_tab) RETURN NUMBER IS
BEGIN
RETURN p_tab.COUNT;
END;
END;
SQL
end

after(:all) do
plsql.execute "DROP PACKAGE test_rowtype_pkg" rescue nil
plsql.execute "DROP TABLE test_rowtype_tbl" rescue nil
plsql.logoff
end

it "should execute function with TABLE OF %ROWTYPE parameter" do
result = plsql.test_rowtype_pkg.test_fn([{ id: 1, name: "test" }])
expect(result).to eq(1)
end
end

describe "Function with TABLE OF RECORD parameter defined in package (workaround for %ROWTYPE)" do
before(:all) do
plsql.connect! CONNECTION_PARAMS
plsql.execute "DROP PACKAGE test_record_pkg" rescue nil
plsql.execute <<-SQL
CREATE OR REPLACE PACKAGE test_record_pkg IS
TYPE t_rec IS RECORD (id NUMBER, name VARCHAR2(50));
TYPE t_tab IS TABLE OF t_rec;
FUNCTION test_fn(p_tab IN t_tab) RETURN NUMBER;
END;
SQL
plsql.execute <<-SQL
CREATE OR REPLACE PACKAGE BODY test_record_pkg IS
FUNCTION test_fn(p_tab IN t_tab) RETURN NUMBER IS
BEGIN
RETURN p_tab.COUNT;
END;
END;
SQL
end

after(:all) do
plsql.execute "DROP PACKAGE test_record_pkg" rescue nil
plsql.logoff
end

it "should execute function with TABLE OF RECORD parameter" do
result = plsql.test_record_pkg.test_fn([{ id: 1, name: "test" }])
expect(result).to eq(1)
end
end