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
4 changes: 2 additions & 2 deletions lib/plsql/jdbc_connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def bind_param(arg, value, metadata)
if metadata[:in_out] =~ /OUT/
@out_types[arg] = type || ora_value.class
@out_index[arg] = bind_param_index(arg)
if ['TABLE','VARRAY','OBJECT'].include?(metadata[:data_type])
if ['TABLE','VARRAY','OBJECT','XMLTYPE'].include?(metadata[:data_type])
@statement.registerOutParameter(@out_index[arg], @connection.get_java_sql_type(ora_value,type),
metadata[:sql_type_name])
else
Expand Down Expand Up @@ -277,7 +277,7 @@ def set_bind_variable(stmt, i, value, type=nil, length=nil, metadata={})
when :Time, :'Java::JavaSql::Timestamp'
stmt.send("setTimestamp#{key && "AtName"}", key || i, value)
when :NilClass
if ['TABLE', 'VARRAY', 'OBJECT'].include?(metadata[:data_type])
if ['TABLE', 'VARRAY', 'OBJECT','XMLTYPE'].include?(metadata[:data_type])
stmt.send("setNull#{key && "AtName"}", key || i, get_java_sql_type(value, type),
metadata[:sql_type_name])
elsif metadata[:data_type] == 'REF CURSOR'
Expand Down
2 changes: 1 addition & 1 deletion lib/plsql/oci_connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def plsql_to_ruby_data_type(metadata)
[DateTime, nil]
when "TIMESTAMP", "TIMESTAMP WITH TIME ZONE", "TIMESTAMP WITH LOCAL TIME ZONE"
[Time, nil]
when "TABLE", "VARRAY", "OBJECT"
when "TABLE", "VARRAY", "OBJECT", "XMLTYPE"
# create Ruby class for collection
klass = OCI8::Object::Base.get_class_by_typename(metadata[:sql_type_name])
unless klass
Expand Down
2 changes: 1 addition & 1 deletion lib/plsql/procedure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def self.type_to_sql(metadata) #:nodoc:
when 'NVARCHAR2', 'NCHAR'
length = metadata[:char_length]
"#{metadata[:data_type]}#{length && "(#{length})"}"
when 'PL/SQL TABLE', 'TABLE', 'VARRAY', 'OBJECT'
when 'PL/SQL TABLE', 'TABLE', 'VARRAY', 'OBJECT', 'XMLTYPE'
metadata[:sql_type_name]
else
metadata[:data_type]
Expand Down
23 changes: 22 additions & 1 deletion lib/plsql/procedure_call.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def get_overload_from_arguments_list(args)
MATCHING_TYPES = {
:integer => ['NUMBER', 'NATURAL', 'NATURALN', 'POSITIVE', 'POSITIVEN', 'SIGNTYPE', 'SIMPLE_INTEGER', 'PLS_INTEGER', 'BINARY_INTEGER'],
:decimal => ['NUMBER', 'BINARY_FLOAT', 'BINARY_DOUBLE'],
:string => ['VARCHAR', 'VARCHAR2', 'NVARCHAR2', 'CHAR', 'NCHAR', 'CLOB', 'BLOB'],
:string => ['VARCHAR', 'VARCHAR2', 'NVARCHAR2', 'CHAR', 'NCHAR', 'CLOB', 'BLOB', 'XMLTYPE'],
:date => ['DATE'],
:time => ['DATE', 'TIMESTAMP', 'TIMESTAMP WITH TIME ZONE', 'TIMESTAMP WITH LOCAL TIME ZONE'],
:boolean => ['PL/SQL BOOLEAN'],
Expand Down Expand Up @@ -236,6 +236,14 @@ def add_argument(argument, value, argument_metadata=nil)
@bind_values[argument] = value.nil? ? nil : (value ? 1 : 0)
@bind_metadata[argument] = argument_metadata.merge(:data_type => "NUMBER", :data_precision => 1)
"l_#{argument}"
when 'UNDEFINED'
if argument_metadata[:type_name] == 'XMLTYPE'
@declare_sql << "l_#{argument} XMLTYPE;\n"
@assignment_sql << "l_#{argument} := XMLTYPE(:#{argument});\n" if not value.nil?
@bind_values[argument] = value if not value.nil?
@bind_metadata[argument] = argument_metadata.merge(:data_type => "CLOB")
"l_#{argument}"
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure about the behavior in case of data type 'UNDEFINED' and type name != 'XMLTYPE'? (Before it used to end it else/else clause. Now we trap it here leaving bind values unset).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jgebal, any opinion about that question? My concern is that we're maybe changing the semantics of non-xmltype 'UNDEFINED' (even though I'm not sure what exactly that might be).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Yavor.
I'll look into it this week.
Thanks for spotting that potential behavior change.
Jacek
On 25 Oct 2015 18:33, "Yavor Nikolov" [email protected] wrote:

In lib/plsql/procedure_call.rb
#91 (comment):

@@ -236,6 +236,14 @@ def add_argument(argument, value, argument_metadata=nil)
@bind_values[argument] = value.nil? ? nil : (value ? 1 : 0)
@bind_metadata[argument] = argument_metadata.merge(:data_type => "NUMBER", :data_precision => 1)
"l_#{argument}"

  •  when 'UNDEFINED'
    
  •    if argument_metadata[:type_name] == 'XMLTYPE'
    
  •      @declare_sql << "l_#{argument} XMLTYPE;\n"
    
  •      @assignment_sql << "l_#{argument} := XMLTYPE(:#{argument});\n" if not value.nil?
    
  •      @bind_values[argument] = value if not value.nil?
    
  •      @bind_metadata[argument] = argument_metadata.merge(:data_type => "CLOB")
    
  •      "l_#{argument}"
    
  •    end
    

@jgebal https://github.com/jgebal, any opinion about that question? My
concern is that we're maybe changing the semantics of non-xmltype
'UNDEFINED' (even though I'm not sure what exactly that might be).


Reply to this email directly or view it on GitHub
https://github.com/rsim/ruby-plsql/pull/91/files#r42948271.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that all the existing functionality is covered by unit tests and all existing unit tests are passing.
I did not verify what other types fall under UNDEFINED, but for sure none of them is currently supported by framework.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some other other UNDEFINED types (I'm checking that on http://sqlfiddle.com/):

select
  data_type, type_name, type_subname, pls_type, count(*) as cnt
from
  all_arguments a
where
  a.data_type = 'UNDEFINED'
group by
  data_type, type_name, type_subname, pls_type

It's an edge case indeed, yet I'm wondering about the behavior (how gracefully does it fail) when facing some of these unsupported types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regardless of the change introduced the unsupported datatypes (like ANYDATA) will not work.
But you're right that there is a change in the evaluation for UNDEFINED datatypes.
This can be changed so the rest of UNDEFINED fall into the behaviour prior to the change.
I'm not sure what would be the difference since one way or the other the types like ANYDATA are not supported.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. We may consider examining the unsupported features behaviour a separate topic.

else
# TABLE or PL/SQL TABLE type defined inside package
if argument_metadata[:tmp_table_name]
Expand Down Expand Up @@ -383,6 +391,15 @@ def add_return_variable(argument, argument_metadata, is_return_value=false)
end
end
"l_#{argument} := " if is_return_value
when 'UNDEFINED'
if argument_metadata[:type_name] == 'XMLTYPE'
@declare_sql << "l_#{argument} XMLTYPE;\n" if is_return_value
bind_variable = :"o_#{argument}"
@return_vars << bind_variable
@return_vars_metadata[bind_variable] = argument_metadata.merge(:data_type => "CLOB")
@return_sql << ":#{bind_variable} := CASE WHEN l_#{argument} IS NOT NULL THEN l_#{argument}.getclobval() END;\n"
"l_#{argument} := " if is_return_value
end
when 'PL/SQL BOOLEAN'
@declare_sql << "l_#{argument} BOOLEAN;\n" if is_return_value
@declare_sql << "o_#{argument} NUMBER(1);\n"
Expand Down Expand Up @@ -496,6 +513,10 @@ def return_variable_value(argument, argument_metadata)
when 'PL/SQL BOOLEAN'
numeric_value = @cursor[":o_#{argument}"]
numeric_value.nil? ? nil : numeric_value == 1
when 'UNDEFINED'
if argument_metadata[:type_name] == 'XMLTYPE'
@cursor[":o_#{argument}"]
end
else
if argument_metadata[:tmp_table_name]
is_index_by_table = argument_metadata[:data_type] == 'PL/SQL TABLE'
Expand Down
5 changes: 3 additions & 2 deletions lib/plsql/variable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ def metadata(type_string)
{:data_type => $1, :data_length => $3.to_i, :in_out => 'IN/OUT'}
when /^(CLOB|NCLOB|BLOB)$/,
/^(NUMBER)(\(.*\))?$/, /^(NATURAL|NATURALN|POSITIVE|POSITIVEN|SIGNTYPE|SIMPLE_INTEGER|PLS_INTEGER|BINARY_INTEGER)$/,
/^(DATE|TIMESTAMP|TIMESTAMP WITH TIME ZONE|TIMESTAMP WITH LOCAL TIME ZONE)$/
/^(DATE|TIMESTAMP|TIMESTAMP WITH TIME ZONE|TIMESTAMP WITH LOCAL TIME ZONE)$/,
/^(XMLTYPE)$/
{:data_type => $1, :in_out => 'IN/OUT'}
when /^INTEGER$/
{:data_type => 'NUMBER', :in_out => 'IN/OUT'}
Expand Down Expand Up @@ -143,4 +144,4 @@ def call_sql(params_string)

end

end
end
47 changes: 47 additions & 0 deletions spec/plsql/procedure_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,53 @@

end

describe "Function or procedure with XMLType parameters" do
before(:all) do
plsql.connect! CONNECTION_PARAMS
plsql.execute <<-SQL
CREATE OR REPLACE FUNCTION test_xmltype
( p_xml XMLTYPE )
RETURN XMLTYPE
IS
BEGIN
RETURN p_xml;
END test_xmltype;
SQL
plsql.execute <<-SQL
CREATE OR REPLACE PROCEDURE test_xmltype2
( p_xml XMLTYPE, po_xml OUT XMLTYPE )
IS
BEGIN
po_xml := p_xml;
END test_xmltype2;
SQL
end

after(:all) do
plsql.execute "DROP FUNCTION test_xmltype"
plsql.execute "DROP PROCEDURE test_xmltype2"
plsql.logoff
end

it "should process XMLType parameters" do
xml = '<DUMMY>value</DUMMY>'
result = plsql.test_xmltype(xml)
expect(result).to eq('<DUMMY>value</DUMMY>')
end

it "should work when passing a NULL value" do
result = plsql.test_xmltype(nil)
expect(result).to be_nil
end

it "should assign input parameter to putput parameter" do
xml = '<DUMMY>value</DUMMY>'
result = plsql.test_xmltype2(xml)
expect(result[:po_xml]).to eq('<DUMMY>value</DUMMY>')
end
end


describe "Procedure with output parameters" do
before(:all) do
plsql.connect! CONNECTION_PARAMS
Expand Down