|
| 1 | +create or replace type body ut_output_dbms_pipe as |
| 2 | + |
| 3 | + constructor function ut_output_dbms_pipe(self in out nocopy ut_output_dbms_pipe) return self as result is |
| 4 | + begin |
| 5 | + self.output_type := $$plsql_unit; |
| 6 | + self.output_id := self.generate_output_id; |
| 7 | + return; |
| 8 | + end; |
| 9 | + |
| 10 | + overriding member procedure open(self in out nocopy ut_output_dbms_pipe) is |
| 11 | + l_flag integer; |
| 12 | + begin |
| 13 | + --create an explicit private pipe. Explicitly created pipes need to be removed explicitly |
| 14 | + --otherwise they stay in memmory forever https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_pipe.htm#CHDEICJI |
| 15 | + --to check if there are any non-purged pipes execute: select * from v$db_pipes where pipe_size > 0 order by name desc; |
| 16 | + l_flag := dbms_pipe.create_pipe(self.output_id); |
| 17 | + end; |
| 18 | + |
| 19 | + overriding member procedure send_line(self in out nocopy ut_output_dbms_pipe, a_text varchar2) is |
| 20 | + begin |
| 21 | + self.send_clob(a_text); |
| 22 | + end; |
| 23 | + |
| 24 | + overriding member procedure send_clob(self in out nocopy ut_output_dbms_pipe, a_text clob) is |
| 25 | + c_size_limit_chars constant integer := ut_output_pipe_helper.gc_size_limit_chars; |
| 26 | + l_text_part ut_output_pipe_helper.t_pipe_item; |
| 27 | + i integer := 0; |
| 28 | + begin |
| 29 | + --split test into pieces of a size valid for pipe and send to pipe |
| 30 | + while i < length(a_text) loop |
| 31 | + l_text_part := substr( a_text, i + 1, c_size_limit_chars ); |
| 32 | + ut_output_pipe_helper.send_text( self.output_id, l_text_part); |
| 33 | + i := i + c_size_limit_chars; |
| 34 | + end loop; |
| 35 | + --SEND is closed by a EOM message |
| 36 | + ut_output_pipe_helper.send_eom(self.output_id); |
| 37 | + end; |
| 38 | + |
| 39 | + --we do not remove the pipe here, it is responsibility of the consumer, |
| 40 | + --when the pipe is fully consumed (recieved 'eot') then the consumer removed the pipe |
| 41 | + overriding member procedure close(self in out nocopy ut_output_dbms_pipe, a_timeout_sec integer) is |
| 42 | + begin |
| 43 | + ut_output_pipe_helper.send_eot(self.output_id); |
| 44 | + ut_output_pipe_helper.flush(self.output_id, a_timeout_sec); |
| 45 | + end; |
| 46 | + |
| 47 | + overriding member function get_lines(a_output_id varchar2, a_timeout_sec naturaln) return ut_varchar2_list pipelined is |
| 48 | + c_max_line_length constant integer := 4000; |
| 49 | + l_text clob; |
| 50 | + l_result_flag integer; |
| 51 | + l_results_tab ut_varchar2_list; |
| 52 | + begin |
| 53 | + if a_output_id is null then |
| 54 | + return; |
| 55 | + end if; |
| 56 | + |
| 57 | + loop |
| 58 | + dbms_lob.createtemporary(l_text, true); |
| 59 | + --get message as a clob data and recieve information if the message is ended, timed out or it is the end of transmission |
| 60 | + l_result_flag := ut_output_pipe_helper.get_message(a_output_id, a_timeout_sec, l_text); |
| 61 | + -- convert message into collection of varchar2(4000) for SQL processing |
| 62 | + l_results_tab := ut_utils.clob_to_table(l_text, c_max_line_length); |
| 63 | + --pipe results one by one |
| 64 | + for i in 1 .. l_results_tab.count loop |
| 65 | + pipe row( l_results_tab(i) ); |
| 66 | + end loop; |
| 67 | + dbms_lob.freetemporary(l_text); |
| 68 | + |
| 69 | + exit when l_result_flag in (ut_output_pipe_helper.gc_eot, ut_output_pipe_helper.gc_timeout); |
| 70 | + end loop; |
| 71 | + if l_result_flag = ut_output_pipe_helper.gc_eot then |
| 72 | + ut_output_pipe_helper.remove_pipe(a_output_id); |
| 73 | + end if; |
| 74 | + return; |
| 75 | + end; |
| 76 | + |
| 77 | + overriding final member function get_clob_lines(a_output_id varchar2, a_timeout_sec naturaln) return ut_clob_list pipelined is |
| 78 | + l_text clob; |
| 79 | + l_result_flag integer; |
| 80 | + l_results_tab ut_varchar2_list; |
| 81 | + begin |
| 82 | + if a_output_id is null then |
| 83 | + return; |
| 84 | + end if; |
| 85 | + |
| 86 | + loop |
| 87 | + dbms_lob.createtemporary(l_text, true); |
| 88 | + l_result_flag := ut_output_pipe_helper.get_message(a_output_id, a_timeout_sec, l_text); |
| 89 | + exit when l_result_flag in (ut_output_pipe_helper.gc_eot, ut_output_pipe_helper.gc_timeout); |
| 90 | + pipe row( l_text ); |
| 91 | + dbms_lob.freetemporary(l_text); |
| 92 | + end loop; |
| 93 | + dbms_lob.freetemporary(l_text); |
| 94 | + if l_result_flag = ut_output_pipe_helper.gc_eot then |
| 95 | + ut_output_pipe_helper.remove_pipe(a_output_id); |
| 96 | + end if; |
| 97 | + return; |
| 98 | + end; |
| 99 | + |
| 100 | +end; |
| 101 | +/ |
0 commit comments