diff --git a/lib/plsql/jdbc_connection.rb b/lib/plsql/jdbc_connection.rb
index 1b930d98..5c5674ce 100644
--- a/lib/plsql/jdbc_connection.rb
+++ b/lib/plsql/jdbc_connection.rb
@@ -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
@@ -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'
diff --git a/lib/plsql/oci_connection.rb b/lib/plsql/oci_connection.rb
index 374023d9..e9e3c310 100644
--- a/lib/plsql/oci_connection.rb
+++ b/lib/plsql/oci_connection.rb
@@ -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
diff --git a/lib/plsql/procedure.rb b/lib/plsql/procedure.rb
index 4ad3ff17..f17be90a 100644
--- a/lib/plsql/procedure.rb
+++ b/lib/plsql/procedure.rb
@@ -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]
diff --git a/lib/plsql/procedure_call.rb b/lib/plsql/procedure_call.rb
index 74c95c9e..5955fb83 100644
--- a/lib/plsql/procedure_call.rb
+++ b/lib/plsql/procedure_call.rb
@@ -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'],
@@ -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
else
# TABLE or PL/SQL TABLE type defined inside package
if argument_metadata[:tmp_table_name]
@@ -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"
@@ -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'
diff --git a/lib/plsql/variable.rb b/lib/plsql/variable.rb
index d5243dab..667fc513 100644
--- a/lib/plsql/variable.rb
+++ b/lib/plsql/variable.rb
@@ -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'}
@@ -143,4 +144,4 @@ def call_sql(params_string)
end
-end
\ No newline at end of file
+end
diff --git a/spec/plsql/procedure_spec.rb b/spec/plsql/procedure_spec.rb
index 4bdee21a..12c8c1e3 100644
--- a/spec/plsql/procedure_spec.rb
+++ b/spec/plsql/procedure_spec.rb
@@ -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 = 'value'
+ result = plsql.test_xmltype(xml)
+ expect(result).to eq('value')
+ 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 = 'value'
+ result = plsql.test_xmltype2(xml)
+ expect(result[:po_xml]).to eq('value')
+ end
+ end
+
+
describe "Procedure with output parameters" do
before(:all) do
plsql.connect! CONNECTION_PARAMS