From 8b2aa2a71baf0199855ffacc206c2fdfea11f38b Mon Sep 17 00:00:00 2001 From: bpom Date: Sun, 25 Aug 2013 21:26:12 +0200 Subject: [PATCH 1/3] support booleans in records for in parameter --- lib/plsql/procedure_call.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/plsql/procedure_call.rb b/lib/plsql/procedure_call.rb index c00214f6..8483ace9 100644 --- a/lib/plsql/procedure_call.rb +++ b/lib/plsql/procedure_call.rb @@ -340,9 +340,16 @@ def record_assignment_sql_values_metadata(argument, argument_metadata, record_va metadata = argument_metadata[:fields][field] raise ArgumentError, "Wrong field name #{key.inspect} passed to PL/SQL record argument #{argument.inspect}" unless metadata bind_variable = :"#{argument}_f#{metadata[:position]}" - sql << "l_#{argument}.#{field} := :#{bind_variable};\n" - bind_values[bind_variable] = value - bind_metadata[bind_variable] = metadata + case metadata[:data_type] + when 'PL/SQL BOOLEAN' + sql << "l_#{argument}.#{field} := (:#{bind_variable} = 1);\n" + bind_values[bind_variable] = value.nil? ? nil : (value ? 1 : 0) + bind_metadata[bind_variable] = metadata.merge(:data_type => "NUMBER", :data_precision => 1) + else + sql << "l_#{argument}.#{field} := :#{bind_variable};\n" + bind_values[bind_variable] = value + bind_metadata[bind_variable] = metadata + end end [sql, bind_values, bind_metadata] end From 45424b5302013135be2f0a7d56f8f51d24fa1acc Mon Sep 17 00:00:00 2001 From: Yavor Nikolov Date: Sat, 9 May 2015 19:32:27 +0300 Subject: [PATCH 2/3] tests for record with boolean as in param --- spec/plsql/procedure_spec.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/spec/plsql/procedure_spec.rb b/spec/plsql/procedure_spec.rb index 40881d94..9b2723d7 100644 --- a/spec/plsql/procedure_spec.rb +++ b/spec/plsql/procedure_spec.rb @@ -629,6 +629,11 @@ hire_date DATE ); + TYPE t_candidate IS RECORD( + candidate_id NUMBER(5), + is_approved BOOLEAN + ); + TYPE table_of_records IS TABLE OF t_employee; FUNCTION test_full_name(p_employee t_employee) @@ -636,6 +641,9 @@ FUNCTION test_empty_records RETURN table_of_records; + + FUNCTION is_approved(p_candidate t_candidate) + RETURN BOOLEAN; END; SQL plsql.execute <<-SQL @@ -666,6 +674,13 @@ CLOSE employees_cur; RETURN employees_tab; END; + + FUNCTION is_approved(p_candidate t_candidate) + RETURN BOOLEAN + IS + BEGIN + RETURN p_candidate.is_approved; + END; END; SQL plsql.execute <<-SQL @@ -749,6 +764,18 @@ plsql.test_record.test_full_name(@p_employee).should == 'First Last' end + context "functions with record parameters having boolean attributes" do + def new_candidate(status) + {:candidate_id => 1, :is_approved => status} + end + + [true, false, nil].each do |status| + it "should execute function with record having boolean attribute (#{status})" do + expect(plsql.test_record.is_approved(new_candidate(status))).to eq status + end + end + end + end describe "Function with boolean parameters" do From 278b36db87679a8b294699bfde824fef6cc60c72 Mon Sep 17 00:00:00 2001 From: Yavor Nikolov Date: Sat, 9 May 2015 21:25:20 +0300 Subject: [PATCH 3/3] records with boolean as return and out params --- lib/plsql/procedure_call.rb | 23 +++++++++++++++++++---- spec/plsql/procedure_spec.rb | 29 +++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/lib/plsql/procedure_call.rb b/lib/plsql/procedure_call.rb index 8483ace9..25c527f0 100644 --- a/lib/plsql/procedure_call.rb +++ b/lib/plsql/procedure_call.rb @@ -372,9 +372,18 @@ def add_return_variable(argument, argument_metadata, is_return_value=false) # should use different output bind variable as JDBC does not support # if output bind variable appears in several places bind_variable = :"#{argument}_o#{metadata[:position]}" - @return_vars << bind_variable - @return_vars_metadata[bind_variable] = metadata - @return_sql << ":#{bind_variable} := l_#{argument}.#{field};\n" + case metadata[:data_type] + when 'PL/SQL BOOLEAN' + @return_vars << bind_variable + @return_vars_metadata[bind_variable] = metadata.merge(:data_type => "NUMBER", :data_precision => 1) + arg_field = "l_#{argument}.#{field}" + @return_sql << ":#{bind_variable} := " << "CASE WHEN #{arg_field} = true THEN 1 " << + "WHEN #{arg_field} = false THEN 0 ELSE NULL END;\n" + else + @return_vars << bind_variable + @return_vars_metadata[bind_variable] = metadata + @return_sql << ":#{bind_variable} := l_#{argument}.#{field};\n" + end end "l_#{argument} := " if is_return_value when 'PL/SQL BOOLEAN' @@ -478,7 +487,13 @@ def return_variable_value(argument, argument_metadata) when 'PL/SQL RECORD' return_value = {} argument_metadata[:fields].each do |field, metadata| - return_value[field] = @cursor[":#{argument}_o#{metadata[:position]}"] + field_value = @cursor[":#{argument}_o#{metadata[:position]}"] + case metadata[:data_type] + when 'PL/SQL BOOLEAN' + return_value[field] = field_value.nil? ? nil : field_value == 1 + else + return_value[field] = field_value + end end return_value when 'PL/SQL BOOLEAN' diff --git a/spec/plsql/procedure_spec.rb b/spec/plsql/procedure_spec.rb index 9b2723d7..310a10a4 100644 --- a/spec/plsql/procedure_spec.rb +++ b/spec/plsql/procedure_spec.rb @@ -644,6 +644,11 @@ FUNCTION is_approved(p_candidate t_candidate) RETURN BOOLEAN; + + FUNCTION f_set_candidate_status(p_candidate t_candidate, p_status boolean) + RETURN t_candidate; + + PROCEDURE p_set_candidate_status(p_candidate t_candidate, p_status boolean, p_result OUT t_candidate); END; SQL plsql.execute <<-SQL @@ -681,6 +686,22 @@ BEGIN RETURN p_candidate.is_approved; END; + + FUNCTION f_set_candidate_status(p_candidate t_candidate, p_status boolean) + RETURN t_candidate + IS + result t_candidate := p_candidate; + BEGIN + result.is_approved := p_status; + return result; + END; + + PROCEDURE p_set_candidate_status(p_candidate t_candidate, p_status boolean, p_result OUT t_candidate) + IS + BEGIN + p_result := p_candidate; + p_result.is_approved := p_status; + END; END; SQL plsql.execute <<-SQL @@ -773,6 +794,14 @@ def new_candidate(status) it "should execute function with record having boolean attribute (#{status})" do expect(plsql.test_record.is_approved(new_candidate(status))).to eq status end + + it "procedure should return record with boolean attribute as output parameter (#{status})" do + expect(plsql.test_record.p_set_candidate_status(new_candidate(nil), status)[:p_result]).to eq new_candidate(status) + end + + it "function should return record with boolean attribute (#{status})" do + expect(plsql.test_record.f_set_candidate_status(new_candidate(nil), status)).to eq new_candidate(status) + end end end