From 00084e4e97d94cdab04ca1eb16275e0ed88c9490 Mon Sep 17 00:00:00 2001 From: Alex Rothenberg Date: Wed, 19 Aug 2009 14:42:02 -0400 Subject: [PATCH] added optional dbms_output logging on each call --- .../oracle_enhanced_adapter.rb | 44 ++++++++++++- .../oracle_enhanced_adapter_spec.rb | 62 +++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb b/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb index 789da3729..19145b1b2 100644 --- a/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +++ b/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb @@ -524,7 +524,6 @@ def disconnect! #:nodoc: @connection.logoff rescue nil end - # DATABASE STATEMENTS ====================================== # # see: abstract/database_statements.rb @@ -1152,6 +1151,49 @@ def column_for(table_name, column_name) column end + public + # DBMS_OUTPUT ============================================= + # + # PL/SQL in Oracle uses dbms_output for logging print statements + # These methods stick that output into the Rails log so Ruby and PL/SQL + # code can can be debugged together in a single application + DBMS_OUTPUT_BUFFER_SIZE = 10000 #can be 1-1000000 + DBMS_LINE_MAX_SIZE = 1000 + # Turn DBMS_Output logging on + def enable_dbms_output + @enable_dbms_output = true + execute "BEGIN dbms_output.enable(#{DBMS_OUTPUT_BUFFER_SIZE}); END;" + end + # Turn DBMS_Output logging off + def disable_dbms_output + @enable_dbms_output = false + execute "BEGIN dbms_output.disable(); END;" + end + # Is DBMD_Output logging enabled? + def dbms_output_enabled? + @enable_dbms_output + end + + protected + def log(sql, name) + super sql, name + ensure + log_dbms_output if dbms_output_enabled? + end + + private + def log_next_line_of_dbms_output + dbms_output_text, status = @connection.exec "BEGIN dbms_output.get_line(:return, :status); END;", ' '*DBMS_LINE_MAX_SIZE, 1 + got_text = (status == 0) + @logger.debug "DBMS_OUTPUT: #{dbms_output_text}" if got_text + got_text + end + + def log_dbms_output + while log_next_line_of_dbms_output do + end + end + end end end diff --git a/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb b/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb index d217c3586..dead9b993 100644 --- a/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +++ b/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb @@ -657,3 +657,65 @@ class ::TestEmployee < ActiveRecord::Base; end end end + +describe "logging dbms_output from plsql" do + include LoggerSpecHelper + + before(:all) do + @buffer = StringIO.new + ActiveRecord::Base.establish_connection(CONNECTION_PARAMS) + ActiveRecord::Base.connection.execute <<-SQL + create or replace + FUNCTION MORE_THAN_FIVE_CHARACTERS_LONG (some_text VARCHAR2) RETURN INTEGER + AS + longer_than_five INTEGER; + BEGIN + dbms_output.put_line('before the if -' || some_text || '-'); + IF length(some_text) > 5 THEN + dbms_output.put_line('it is longer than 5'); + longer_than_five := 1; + ELSE + dbms_output.put_line('it is 5 or shorter'); + longer_than_five := 0; + END IF; + dbms_output.put_line('about to return: ' || longer_than_five); + RETURN longer_than_five; + END; + SQL + end + + before(:each) do + @buffer = StringIO.new + log_to @buffer + ActiveRecord::Base.establish_connection(CONNECTION_PARAMS) + @conn = ActiveRecord::Base.connection + end + + it "should NOT log dbms output when dbms output is disabled" do + @conn.disable_dbms_output + + @conn.select_all("select more_than_five_characters_long('hi there') is_it_long from dual").should == [{'is_it_long'=>1}] + + @buffer.string.should_not match(/^DBMS_OUTPUT/) + end + + it "should log dbms output lines to the rails log" do + @conn.enable_dbms_output + + @conn.select_all("select more_than_five_characters_long('hi there') is_it_long from dual").should == [{'is_it_long'=>1}] + + @buffer.string.should match(/^DBMS_OUTPUT: before the if -hi there-$/) + @buffer.string.should match(/^DBMS_OUTPUT: it is longer than 5$/) + @buffer.string.should match(/^DBMS_OUTPUT: about to return: 1$/) + end + + it "should log dbms output lines to the rails log" do + @conn.enable_dbms_output + + @conn.select_all("select more_than_five_characters_long('short') is_it_long from dual").should == [{'is_it_long'=>0}] + + @buffer.string.should match(/^DBMS_OUTPUT: before the if -short-$/) + @buffer.string.should match(/^DBMS_OUTPUT: it is 5 or shorter$/) + @buffer.string.should match(/^DBMS_OUTPUT: about to return: 0$/) + end +end \ No newline at end of file