DBA Data[Home] [Help]

PACKAGE BODY: APPS.FA_RX_UTIL_PKG

Source


1 package body fa_rx_util_pkg as
2 /* $Header: FARXUTLB.pls 120.10.12010000.1 2008/07/28 13:14:06 appldev ship $ */
3 
4 
5 ------------------------------------------------------------
6 -- Package types and global variables
7 ------------------------------------------------------------
8 
9 --
10 -- Values for <<WHO Columns>>
11 --
12 Request_Id number;
13 User_Id number;
14 Login_Id number;
15 Today date;
16 
17 CURSOR_COLUMN_VALUES integer; --* bug#3266462, rravunny
18 --
19 Initialization_Required boolean := true;
20 Run_Report_At_Proc varchar2(70) := null;
21 
22 -- Debug flag
23 m_debug_flag boolean := false;
24 m_dbms_output boolean := false;
25 m_output_cursor integer := null;
26 
27 g_print_debug boolean := fa_cache_pkg.fa_print_debug;
28 
29 ------------------------------------
30 -- Private Functions
31 ------------------------------------
32 -----------------------------------------------------------
33 --
34 -- FUNCTION build_select
35 --
36 -- Parameters
37 -- 	None
38 --
39 -- Returns
40 --	Varchar2	Select statement
41 --
42 -- Description
43 --	Builds the select statement from
44 -- 	Rep_Columns as well as From_Clause, Where_Clause,
45 --	Group_By_Clause, Having_Clause, and Order_By_Clause.
46 --
47 -- Modificaiton History
48 --  KMIZUTA    12-MAR-99    Created.
49 --
50 -----------------------------------------------------------
51 function build_select return varchar2
52 is
53   buffer varchar2(10000);
54   idx number;
55 begin
56   IF (g_print_debug) THEN
57      fa_rx_util_pkg.debug('fa_rx_util_pkg.build_select('||to_char(Num_Columns)||')+');
58   END IF;
59 
60   idx := 1;
61   while idx <= Num_Columns and Rep_Columns(idx).select_column_name is null loop
62 	idx := idx + 1;
63   end loop;
64   buffer := 'SELECT '||Hint_Clause||'
65 	'||Rep_Columns(idx).select_column_name;
66   loop
67     idx := idx + 1;
68     exit when idx > Num_Columns;
69 
70     if Rep_Columns(idx).select_column_name is not null then
71       buffer := buffer ||',
72 	'||Rep_Columns(idx).select_column_name;
73     end if;
74   end loop;
75 
76   buffer := buffer || '
77 FROM '||From_Clause;
78   if Where_Clause is not null then buffer := buffer ||'
79 WHERE '||Where_Clause;
80   end if;
81   if Group_By_Clause is not null then buffer := buffer ||'
82 GROUP BY '||Group_By_Clause;
83   end if;
84   if Having_Clause is not null then buffer := buffer ||'
85 HAVING '||Having_Clause;
86   end if;
87   if Order_By_Clause is not null then buffer := buffer ||'
88 ORDER BY '||Order_By_Clause;
89   end if;
90 
91  IF (g_print_debug) THEN
92     fa_rx_util_pkg.debug('SELECT Statement = ');
93     fa_rx_util_pkg.debug(buffer);
94     fa_rx_util_pkg.debug('fa_rx_util_pkg.build_select()-');
95   END IF;
96 
97   return buffer;
98 
99 exception
100   when no_data_found then
101      IF (g_print_debug) THEN
102 	fa_rx_util_pkg.debug('Missing item at '||to_char(idx));
103 	fa_rx_util_pkg.debug('Check your calls to assign_column() and make sure that you have that index');
104      END IF;
105 
106      raise;
107 end build_select;
108 
109 -----------------------------------------------------------
110 --
111 -- FUNCTION build_insert
112 --
113 -- Parameters
114 -- 	None
115 --
116 -- Returns
117 --	Varchar2	Insert statement
118 --
119 -- Description
120 --	Builds the insert statement from Rep_columns.
121 
122 -- Modificaiton History
123 --  KMIZUTA    12-MAR-99    Created.
124 --
125 -----------------------------------------------------------
126 function build_insert return varchar2
127 is
128   idx number;
129   buf1 varchar2(10000);
130   buf2 varchar2(10000);
131 begin
132 
133   IF (g_print_debug) THEN
134      fa_rx_util_pkg.debug('fa_rx_util_pkg.build_insert()+');
135   END IF;
136 
137   idx := 1;
138   while idx <= Num_Columns and Rep_Columns(idx).insert_column_name is null loop
139 	idx := idx + 1;
140   end loop;
141   buf1 := 'INSERT INTO '||Interface_Table||' (
142 	'||Rep_Columns(idx).insert_column_name;
143   buf2 := ') VALUES (
144 	:b'||to_char(idx);
145   loop
146     idx := idx + 1;
147     exit when idx > Num_Columns;
148 
149     if Rep_Columns(idx).insert_column_name is not null then
150       buf1 := buf1 ||',
151 	 '||Rep_Columns(idx).insert_column_name;
152       buf2 := buf2 ||',
153 	 :b'||to_char(idx);
154     end if;
155   end loop;
156   buf1 := buf1||', request_id, created_by, creation_date, last_updated_by, last_update_date, last_update_login';
157   buf2 := buf2 ||', :b_request_id, :b_user_id, :b_today, :b_user_id, :b_today, :b_login_id)';
158 
159   IF (g_print_debug) THEN
160      fa_rx_util_pkg.debug('INSERT Statement = ');
161      fa_rx_util_pkg.debug(buf1||buf2);
162      fa_rx_util_pkg.debug('fa_rx_util_pkg.build_insert()-');
163   END IF;
164 
165   return(buf1||buf2);
166 end build_insert;
167 
168 
169 -----------------------------------------------------------
170 --
171 -- PROCEDURE bind_insert
172 --
173 -- Parameters
174 -- 	p_cursor	Cursor for the parsed insert statement
175 --
176 -- Description
177 --	The insert statement which is returned by the above
178 --	function (build_insert) returns an INSERT statement
179 --	with bind variables for the placeholder variables.
180 --	This function actually binds the values.
181 --
182 -- Modificaiton History
183 --  KMIZUTA    12-MAR-99    Created.
184 --
185 -----------------------------------------------------------
186 
187 procedure bind_insert(p_cursor in number)
188 is
189   buffer varchar2(30000);
190   idx number;
191   c integer;
192   rows number;
193 begin
194  IF (g_print_debug) THEN
195  	fa_rx_util_pkg.debug('fa_rx_util_pkg.bind_insert()+');
196  END IF;
197 
198   buffer := 'BEGIN ';
199   for idx in 1..Num_Columns loop
200     if Rep_Columns(idx).insert_column_name is not null then
201 	buffer := buffer ||'dbms_sql.bind_variable('||to_char(p_cursor)||
202 				', '':b'||to_char(idx)||
203 				''', '||Rep_Columns(idx).placeholder_name||');
204 ';
205     end if;
206   end loop;
207   buffer := buffer ||' END;';
208 
209  IF (g_print_debug) THEN
210  	fa_rx_util_pkg.debug('bind_insert: ' || buffer);
211  END IF;
212 
213   c := dbms_sql.open_cursor;
214   dbms_sql.parse(c, buffer, dbms_sql.native);
215   rows := dbms_sql.execute(c);
216   dbms_sql.close_cursor(c);
217 
218   dbms_sql.bind_variable(p_cursor, 'b_request_id', Request_Id);
219   dbms_sql.bind_variable(p_cursor, 'b_user_id', User_Id);
220   dbms_sql.bind_variable(p_cursor, 'b_login_id', Login_Id);
221   dbms_sql.bind_variable(p_cursor, 'b_today', Today);
222 
223  IF (g_print_debug) THEN
224  	fa_rx_util_pkg.debug('fa_rx_util_pkg.bind_insert()-');
225  END IF;
226 end bind_insert;
227 
228 -----------------------------------------------------------
229 --
230 -- PROCEDURE define_columns
231 --
232 -- Parameters
233 -- 	p_cursor	Cursor for the parsed select statement
234 --
235 -- Description
236 --      When using dynamic SQL with a SELECT statement,
237 --      the select list must be described via a call to
238 --      dbms_sql.define_column.
239 --      This procedure does this.
240 --
241 -- Modificaiton History
242 --  KMIZUTA    12-MAR-99    Created.
243 --
244 -----------------------------------------------------------
245 procedure define_columns(p_cursor in number)
246 is
247   sel_idx   number;
248   idx       number;
249   c         number;
250   rows      number;
251 
252   buffer    varchar2(10000);
253 
254   l_varchar varchar2(10000);
255   l_number  number;
256   l_date    date;
257 
258 begin
259 
260   IF (g_print_debug) THEN
261   	fa_rx_util_pkg.debug('fa_rx_util_pkg.define_columns()+');
262   END IF;
263 
264   sel_idx := 1;
265 
266   -- Fix for Bug #3742493.  Replace dynamic sql method which creates a
267   -- string to define_column with straight define_column statements.  This
268   -- removes the literals issue which could drag performance.
269   for idx in 1..Num_Columns loop
270      if Rep_Columns(idx).select_column_name is not null then
271 
272         if Rep_Columns(idx).column_type = 'VARCHAR2' then
273 
274            dbms_sql.define_column(
275               c           => p_cursor,
276               position    => sel_idx,
277               column      => l_varchar,
278               column_size => to_char(Rep_Columns(idx).column_length));
279 
280         elsif Rep_Columns(idx).column_type = 'NUMBER' then
281 
282            dbms_sql.define_column(
283               c        => p_cursor,
284               position => sel_idx,
285               column   => l_number);
286 
287         elsif Rep_Columns(idx).column_type = 'DATE' then
288 
289            dbms_sql.define_column(
290               c        => p_cursor,
291               position => sel_idx,
292               column   => l_date);
293         else
294 
295            dbms_sql.define_column(
296               c        => p_cursor,
297               position => sel_idx,
298               column   => l_number);
299         end if;
300 
301         sel_idx := sel_idx + 1;
302      end if;
303   end loop;
304 
305 /*
306   buffer := 'BEGIN ';
307   for idx in 1..Num_Columns loop
308     if Rep_Columns(idx).select_column_name is not null then
309       buffer := buffer ||'dbms_sql.define_column('||
310 		to_char(p_cursor)||', '||
311 		to_char(sel_idx)||', '||
312 		Rep_Columns(idx).placeholder_name;
313       if Rep_Columns(idx).column_type = 'VARCHAR2' then
314 	  buffer := buffer ||', '||to_char(Rep_Columns(idx).column_length);
315       end if;
316       buffer := buffer || ');
317 ';
318       sel_idx := sel_idx + 1;
319     end if;
320   end loop;
321   buffer := buffer || 'END;';
322 
323  IF (g_print_debug) THEN
324  	fa_rx_util_pkg.debug('define_columns: ' || buffer);
325  END IF;
326 
327   c := dbms_sql.open_cursor;
328   dbms_sql.parse(c, buffer, dbms_sql.native);
329   rows := dbms_sql.execute(c);
330   dbms_sql.close_cursor(c);
331 */
332 
333  IF (g_print_debug) THEN
334  	fa_rx_util_pkg.debug('fa_rx_util_pkg.define_columns()-');
335  END IF;
336 end define_columns;
337 
338 
339 -----------------------------------------------------------
340 --
341 -- PROCEDURE column_values
342 --
343 -- Parameters
344 -- 	p_cursor	Cursor for the parsed select statement
345 --
346 -- Description
347 --      When using dynamic SQL with a SELECT statement,
348 --      the values from the select list must be retrieved using
349 --      dbms_sql.column_value.
350 --      This procedure does this.
351 --
352 -- Modificaiton History
353 --  KMIZUTA    12-MAR-99    Created.
354 --
355 -----------------------------------------------------------
356 procedure column_values(p_cursor in number)
357 is
358   sel_idx number;
359   idx number;
360   c integer default cursor_column_values; --* bug#3266462, rravunny
361   rows number;
362 
363   buffer varchar2(10000);
364 begin
365  IF (g_print_debug) THEN
366  	fa_rx_util_pkg.debug('fa_rx_util_pkg.column_values()+');
367  END IF;
368 
369   sel_idx := 1;
370   buffer := 'BEGIN ';
371   for idx in 1..Num_Columns loop
372     if Rep_Columns(idx).select_column_name is not null then
373       buffer := buffer ||'dbms_sql.column_value('||
374 		to_char(p_cursor)||','||
375 		to_char(sel_idx)||','||
376 		Rep_Columns(idx).placeholder_name||');
377 ';
378       sel_idx := sel_idx + 1;
379     end if;
380   end loop;
381   buffer := buffer || 'END;';
382 
383  IF (g_print_debug) THEN
384  	fa_rx_util_pkg.debug('column_values: ' || buffer);
385  END IF;
386 
387   --* bug#3266462, rravunny
388   If c is null then
389 	fa_rx_util_pkg.debug('cursor cursor_column_values/ c is defined for first time');
390 	c := dbms_sql.open_cursor;
391 	dbms_sql.parse(c, buffer, dbms_sql.native);
392   else
393   	fa_rx_util_pkg.debug('cursor cursor_column_values/ c is already defined');
394   End If;
395   rows := dbms_sql.execute(c);
396   --* bug#3266462, rravunny dbms_sql.close_cursor(c);
397 
398  IF (g_print_debug) THEN
399  	fa_rx_util_pkg.debug('fa_rx_util_pkg.column_values()-');
400  END IF;
401  cursor_column_values := c; --* bug#3266462, rravunny
402 end column_values;
403 
404 ------------------------------------
405 -- Public Functions/Procedures
406 ------------------------------------
407 
408 -------------------------------------------------------------------------
409 --
410 -- PROCEDURE init_request
411 --
412 -- Parameters
413 --		p_request_id	Request ID of this concurrent request.
414 --
415 -- Description
416 --   This function initializes some of the parameters needed by RX.
417 --   These include:
418 --		User_ID
419 --		Login_ID
420 --		Today's Date <-- All three used in <WHO Columns>
421 --		Interface Table name <-- retrieved using p_request_id
422 -- NOTES
423 --   If this function is called with a request id of 0, it will assume
424 --   that you are trying to debug this code from SQL*Plus and skip
425 --   this routine. It assumes that your testing script has already
426 --   called init_debug (below) to initialize these routines.
427 --
428 -- Modification History
429 --  KMIZUTA    12-MAR-99	Created.
430 --
431 -------------------------------------------------------------------------
432 procedure init_request(p_calling_proc in varchar2, p_request_id in number,
433 		p_interface_table in varchar2 default null)
434 is
435 begin
436  IF (g_print_debug) THEN
437  	fa_rx_util_pkg.debug('fa_rx_util_pkg.init_request('||to_char(p_request_id)||')+');
438  END IF;
439 
440   --
441   -- If Initialization has already occurred, then exit
442   if not Initialization_Required then return;
443   end if;
444   Initialization_Required := false;
445 
446   --
447   -- This is the procedure that will actually run the report.
448   Run_Report_At_Proc := p_calling_proc;
449   Num_Sections := 0;
450   Num_Columns := 0;
451   From_Clause := null;
452   Where_Clause := null;
453   Group_By_Clause := null;
454   Having_Clause := null;
455   Order_By_Clause := null;
456   User_Id := fnd_global.user_id;
457   Login_Id := fnd_global.login_id;
458   Today := sysdate;
459 
460   if p_request_id = 0 then
461 	--
462 	-- This is a debugging request
463 	IF (g_print_debug) THEN
464 		fa_rx_util_pkg.debug('init_request: ' || 'Running from SQL*Plus');
465 		fa_rx_util_pkg.debug('fa_rx_util_pkg.init_request(DEBUG)-');
466 	END IF;
467   elsif p_interface_table is not null then
468 	Interface_Table := p_interface_table;
469   else
470 	--
471 	-- Get the interface table name
472   	select
473 	  rx.interface_table
474 	into
475 	  Interface_Table
476 	from
477 	  fnd_concurrent_requests r,
478 	  fa_rx_reports rx
479 	where
480 	  r.request_id = p_request_id and
481 	  r.program_application_id = rx.application_id and
482 	  r.concurrent_program_id = rx.concurrent_program_id;
483   end if;
484 
485   Request_Id := p_request_id;
486 
487   --
488   -- Delete rows with the same request id in the interface table
489   -- NOTE: There should not be any rows here to delete except during debugging when
490   --       request id 0 is used multiple times.
491   declare
492     c integer;
493     rows integer;
494   begin
495     c := dbms_sql.open_cursor;
496 --*    bug#3207863, rravunny dbms_sql.parse(c, 'delete from '||Interface_Table||' where request_id = '||to_char(p_request_id), dbms_sql.native);
497     dbms_sql.parse(c, 'delete from '||Interface_Table||' where request_id = :request_id', dbms_sql.native); --*    bug#3207863, rravunny
498     DBMS_SQL.BIND_VARIABLE(c,':request_id',p_request_id); --*    bug#3207863, rravunny
499     rows := dbms_sql.execute(c);
500 
501    IF (g_print_debug) THEN
502    	fa_rx_util_pkg.debug('init_request: ' || to_char(dbms_sql.last_row_count)||' row(s) deleted from table '||Interface_Table);
503    END IF;
504     dbms_sql.close_cursor(c);
505   end;
506 
507  IF (g_print_debug) THEN
508  	fa_rx_util_pkg.debug('init_request: ' || 'Using RX Interface Table = '||Interface_Table);
509  	fa_rx_util_pkg.debug('fa_rx_util_pkg.init_request()-');
510  END IF;
511 exception
512   when no_data_found then
513    IF (g_print_debug) THEN
514    	fa_rx_util_pkg.debug('init_request: ' || 'No RX request with request id = '||to_char(p_request_id)||' found!');
515    	fa_rx_util_pkg.debug('fa_rx_util_pkg.init_request(NO_DATA_FOUND)-');
516    END IF;
517 end init_request;
518 
519 
520 
521 -------------------------------------------------------------------------
522 --
523 -- PROCEDURE init_debug
524 --
525 -- Parameters
526 --		p_interface_table	Interface table for the RX Report
527 --
528 -- Description
529 -- 	Does pretty much the same as init_request() except it initializes
530 --	the Interface Table name from the parameter. When debugging
531 --	using SQL*Plus, there will be no request_id from which you could
532 --	find out the interface table name.
533 --	You should prepare a test script whenever testing RX reports which
534 --	1) Calls fnd_global.initialize
535 --	   This initializes Oracle Applications.
536 --	2) Calls fa_rx_util_pkg.enable_debug
537 --	   Enable debugging for these routines
538 --	3) Calls fa_rx_util_pkg.init_debug
539 --	   Initialize these routines
540 --	4) Calls your RX report
541 --
542 -- Modification History
543 --  KMIZUTA    12-MAR-99	Created.
544 --
545 -------------------------------------------------------------------------
546 procedure init_debug(p_interface_table in varchar2)
547 is
548 begin
549  IF (g_print_debug) THEN
550  	fa_rx_util_pkg.debug('fa_rx_util_pkg.init_debug()+');
551  	fa_rx_util_pkg.debug('init_debug: ' || 'This initialization routine should only be called during debugging sessions from SQL*Plus!');
552  END IF;
553 
554   Interface_Table := p_interface_table;
555   Request_Id := 0;
556 
557  IF (g_print_debug) THEN
558  	fa_rx_util_pkg.debug('init_debug: ' || 'Using RX Interface Table = '||Interface_Table);
559  	fa_rx_util_pkg.debug('fa_rx_util_pkg.init_debug()-');
560  END IF;
561 end init_debug;
562 
563 
564 
565 -------------------------------------------------------------------------
566 --
567 -- PROCEDURE assign_column
568 --
569 -- Parameters
570 --	p_index		Position in report column table.
571 --			This is sort of like the primary key. Plug-ins
572 --			will be able to override what you specify
573 --			here using this index number.
574 --	p_select_column_name
575 --			This is the name of the column that you will
576 --			be selecting from. Make sure to fully qualify
577 --			the column name (i.e., make sure the table
578 --			alias is included as in cc.code_combination_id).
579 --	p_insert_column_name
580 --			This is the name of the column in the interface
581 --			table where this value will be stored.
582 --	p_placeholder_name
583 --			This is the name of the package variable into
584 --			which this value is temporarily stored.
585 --			Make sure to fully qualify your variable name
586 --			with the package name (i.e., package_foo.struct_bar.var_name)
587 --	p_column_type	Data type. Must be either VARCHAR2, NUMBER, DATE
588 --	p_column_length	Needed only if the column type is VARCHAR2.
589 --			The length of the PLACEHOLDER variable.
590 --
591 -- Description
592 --	This procedure assigns this column to the report. These values
593 --	will be used to construct the SELECT statement as well as the
594 --	INSERT statement.
595 --
596 -- NOTES:
597 --	You may want to SELECT from a column which will be used in your
598 --	after fetch trigger. If you do not want to insert this value into
599 --	the interface table, simply keep p_insert_column_name NULL.
600 --	On the other hand, you may have a value which you calculate in
601 --	the after fetch trigger, but there is no source column from
602 --	the select statement. In this case, simply leave p_select_column_name
603 --	NULL.
604 --	In either case, you must specify p_placeholder_name
605 --
606 -- Modification History
607 --  KMIZUTA    12-MAR-99       Created.
608 --
609 -------------------------------------------------------------------------
610 procedure assign_column(p_key in varchar2,
611 			p_select_column_name in varchar2,
612 			p_insert_column_name in varchar2,
613 			p_placeholder_name in varchar2,
614 			p_column_type in varchar2,
615 			p_column_length in number default null)
616 is
617   l_index number;
618 
619   function Find_Column_Index(pk in varchar2) return number
620   is
621     found_idx number;
622   begin
623     found_idx := null;
624     for idx in 1..Num_Columns loop
625       if Rep_Columns(idx).primary_key = pk then
626 	found_idx := idx;
627 	exit;
628       end if;
629     end loop;
630 
631     if found_idx is null then
632       Num_Columns := Num_Columns + 1;
633       found_idx := Num_Columns;
634       Rep_Columns(found_idx).primary_key := pk;
635     end if;
636 
637     return found_idx;
638   end Find_Column_Index;
639 
640 begin
641  IF (g_print_debug) THEN
642  	fa_rx_util_pkg.debug('fa_rx_util_pkg.assign_column('||
643 			p_key||','||
644 			p_select_column_name||','||
645 			p_insert_column_name||','||
646 			p_placeholder_name||','||
647 			p_column_type||'('||to_char(p_column_length)||'))+');
648  END IF;
649 
650   if p_placeholder_name is null then
651 	log('Placeholder name must not be NULL.');
652 	app_exception.raise_exception;
653   end if;
654   if p_column_type not in ('VARCHAR2', 'DATE', 'NUMBER') then
655 	log('Unknown column type = '||p_column_type);
656 	app_exception.raise_exception;
657   end if;
658   if p_column_type = 'VARCHAR2' and p_column_length is null then
659 	log('Length must be specified for columns of type VARCHAR2');
660 	app_exception.raise_exception;
661   end if;
662 
663   l_index := Find_Column_Index(p_key);
664 
665   Rep_Columns(l_index).select_column_name := p_select_column_name;
666   Rep_Columns(l_index).insert_column_name := p_insert_column_name;
667   Rep_Columns(l_index).placeholder_name := p_placeholder_name;
668   Rep_Columns(l_index).column_type := p_column_type;
669   Rep_Columns(l_index).column_length := p_column_length;
670 
671  IF (g_print_debug) THEN
672  	fa_rx_util_pkg.debug('fa_rx_util_pkg.assign_column()-');
673  END IF;
674 end assign_column;
675 
676 
677 
678 -------------------------------------------------------------------------
679 --
680 -- PROCEDURE assign_report
681 --
682 -- Parameters
683 --	p_section_number	Your report may have multiple sections
684 --				where each section has a different
685 --				SELECT statement. You can have this model
686 --				run through each of your SELECT statements
687 --				in separate sections. Specify your section
688 --				number here.
689 --	p_before_report
690 --	p_bind
691 --	p_after_fetch
692 --	p_after_report		These are the event triggers. Specify the
693 --				name of your procedure that you would
694 --				like to have called in each event. Make
695 --				sure to fully specify the procedure name
696 --				(i.e., add package name).
697 --
698 --	p_before_report_process_level
699 --	p_bind_process_level
700 --	p_after_fetch_process_level
701 --	p_after_report_process_level
702 --				This tells this function how to process
703 --				the new event block. Should your block
704 --				run before/after/replace the current
705 --				block assigned to that event.
706 --
707 -- Description
708 --	This procedure assigns the different event blocks for a given
709 --	section.
710 --
711 -- NOTES
712 --	The before report, after fetch, and after report event blocks
713 --	should not use any host variables.
714 --	The bind event must pass the host variable :CURSOR_SELECT.
715 --	This variable should be of type number or integer and you
716 --	should use this value as the cursor you pass to
717 --	dbms_sql.bind_variable().
718 --
719 -- Logic Flow
720 --	Blocks marked with a (*) are the events that are being set
721 --	by this procedure.
722 --
723 --         ------------------
724 --         | Before Report* |<----|
725 --         ------------------     |
726 --                 |              |
727 --                 v              |
728 --         ------------------     |
729 --         | Build Select   |     |
730 --         ------------------     |
731 --                 |              |
732 --                 v              |
733 --         ------------------     |
734 --         | Bind Select*   |     |
735 --         ------------------     |
736 --                 |              |
737 --                 v              |
738 --         ------------------     |
739 --         | Fetch Row      |<-|  |
740 --         ------------------  |  |
741 --                 |           |  |
742 --                 v           |  |
743 --         ------------------  |  |
744 --         | After Fetch*   |  |  |
745 --         ------------------  |  |
746 --                 |           |  |
747 --                 v           |  |
748 --         ------------------  |  |
749 --         | Insert Row     |  |  |
750 --         ------------------  |  |
751 --                 |           |  |
752 --                 v           |  |
753 --         ------------------  |  |
754 --         | Get Next Row   |--|  |
755 --         ------------------     |
756 --                 |              |
757 --               no more          |
758 --                 |              |
759 --                 v              |
760 --         ------------------     |
761 --         | Next Section   |-----|
762 --         ------------------
763 --                 |
764 --               no more
765 --                 |
766 --                 v
767 --         ------------------
768 --         | After Report*  |
769 --         ------------------
770 --                 |
771 --                 v
772 --
773 -- Before Report
774 --	Before report should call assign_column and set values to
775 --	From_Clause, Where_Clause, Group_By_Clause, Having_Clause,
776 --	Order_By_Clause. This is basically building up the SELECT
777 --	statement and the insert statement.
778 --	You may also do any preprocessing that may be required such
779 --	as leaving an audit of your run.
780 --
781 -- Bind
782 --	The bind event is called once after the select statement is
783 --	built and it has been parsed. You will be passed the value
784 --	of the cursor for the SELECT statement in a host variable
785 --	by the name of :CURSOR_SELECT. You will need to call
786 --	dbms_sql.bind_variabe to bind any variables that you may
787 --	have included in your Where_Clause, Group_By_Clause,
788 --	Having_Clause, or Order_By_Clause.
789 --
790 -- After Fetch
791 --	This event is called after each row is fetched. You can
792 --	assume that the placeholder variables that you specified
793 --	in your calls to assign_column are holding the value
794 -- 	for the current row. Do any processing that needs to
795 --	be done before the insert.
796 --
797 -- After Report
798 --	This may not really be necessary in most cases, but it is
799 --	here for you to do any cleaning up before exiting from the report.
800 --
801 -- Modification History
802 --  KMIZUTA    12-MAR-99       Created.
803 --
804 -------------------------------------------------------------------------
805 procedure assign_report(p_section_name in varchar2,
806 			p_enabled in boolean,
807 			p_before_report in varchar2,
808 			p_bind in varchar2,
809 			p_after_fetch in varchar2,
810 			p_after_report in varchar2)
811 is
812   l_section_number number;
813 
814   function Find_Report_Index(pk in varchar2) return number
815   is
816     l_index number;
817   begin
818     l_index := null;
819     for idx in 1..nvl(Num_Sections,0) loop
820       if Report(idx).section_name = pk then
821 	l_index := idx;
822 	exit;
823       end if;
824     end loop;
825 
826     if l_index is null then
827       l_index := nvl(Num_Sections,0)+1;
828       Report(l_index).section_name := pk;
829       Report(l_index).enabled := false;
830       Report(l_index).before_report := null;
831       Report(l_index).bind := null;
832       Report(l_index).after_fetch := null;
833       Report(l_index).after_report := null;
834     end if;
835 
836     Num_Sections := greatest(nvl(Num_Sections,0), l_index);
837 
838     return l_index;
839   end Find_Report_Index;
840 
841 begin
842  IF (g_print_debug) THEN
843  	fa_rx_util_pkg.debug('fa_rx_util_pkg.assign_report()+');
844  END IF;
845 
846   l_section_number := Find_Report_Index(p_section_name);
847 
848   Report(l_section_number).enabled := p_enabled;
849 
850   Report(l_section_number).before_report :=
851 			Report(l_section_number).before_report || p_before_report;
852   Report(l_section_number).bind :=
853 			Report(l_section_number).bind || p_bind;
854   Report(l_section_number).after_fetch :=
855 			Report(l_section_number).after_fetch || p_after_fetch;
856   Report(l_section_number).after_report :=
857 			Report(l_section_number).after_report || p_after_report;
858 
859 
860  IF (g_print_debug) THEN
861  	fa_rx_util_pkg.debug('fa_rx_util_pkg.assign_report('||to_char(l_section_number)||')-');
862  END IF;
863 end assign_report;
864 
865 
866 
867 -------------------------------------------------------------------------
868 --
869 -- PROCEDURE run_report
870 --
871 -- Parameters
872 --	None
873 --
874 -- Description
875 --	This is the procedure which actually runs your report. The logic
876 --	flow that is described above (in assign_report), is actually
877 --	performed by this procedure. Make sure to call this procedure
878 --	only after you have called init_request (or init_debug) and
879 --	assign_report.
880 --
881 -- Modification History
882 --  KMIZUTA    12-MAR-99      Created.
883 --
884 -------------------------------------------------------------------------
885 procedure run_report(p_calling_proc in varchar2, retcode out nocopy number, errbuf out varchar2)
886 is
887   l_user_id number;
888   l_login_id number;
889   l_today date;
890 
891   idx number;
892   rows number;
893 
894   cursor_select integer;
895   cursor_insert integer;
896   cursor_before_report integer;
897   cursor_bind integer;
898   cursor_after_fetch integer;
899   cursor_after_report integer;
900 
901 begin
902  IF (g_print_debug) THEN
903  	fa_rx_util_pkg.debug('fa_rx_util_pkg.run_report()+');
904  END IF;
905 
906   retcode := 0;
907   errbuf := null;
908 
909   if not p_calling_proc = Run_Report_At_Proc then
910 	return; -- Don't run the report yet.
911   end if;
912   Initialization_Required := true;
913 
914   for idx in 1..Num_Sections loop
915     Current_Section := Report(idx).section_name;
916    IF (g_print_debug) THEN
917    	fa_rx_util_pkg.debug('run_report: ' || 'Current section = '||current_Section);
918    END IF;
919 
920     if not Report(idx).enabled then
921 	goto next_section;
922     end if;
923 
924     -- Before calling the before report trigger
925     -- reset the select/insert list. This will be initialized within
926     -- the before report trigger itself.
927     Num_Columns := 0;
928     From_Clause := null;
929     Where_Clause := null;
930     Group_By_Clause := null;
931     Having_Clause := null;
932     Order_By_Clause := null;
933 
934     -- Before Report Trigger
935    IF (g_print_debug) THEN
936    	fa_rx_util_pkg.debug('run_report: ' || 'Before Report = '''||Report(idx).before_report||'''');
937    END IF;
938     if Report(idx).before_report is not null then
939       cursor_before_report := dbms_sql.open_cursor;
940       dbms_sql.parse(cursor_before_report,
941 		'BEGIN '||Report(idx).before_report||' END;',
942 		dbms_sql.native);
943       rows := dbms_sql.execute(cursor_before_report);
944       dbms_sql.close_cursor(cursor_before_report);
945     end if;
946 
947 
948     -- Fetch
949     cursor_select := dbms_sql.open_cursor;
950     dbms_sql.parse(cursor_select,
951 			build_select,
952 			dbms_sql.native);
953     if Report(idx).bind is not null then
954     -- Bind variables in the select statement
955      IF (g_print_debug) THEN
956      	fa_rx_util_pkg.debug('run_report: ' || ' Bind...');
957      	fa_rx_util_pkg.debug('run_report: ' || Report(idx).bind);
958      END IF;
959       cursor_bind := dbms_sql.open_cursor;
960       dbms_sql.parse(cursor_bind,
961 			'BEGIN '||Report(idx).bind||' END;',
962 			dbms_sql.native);
963       dbms_sql.bind_variable(cursor_bind,
964 				':CURSOR_SELECT',
965 				cursor_select);
966       rows := dbms_sql.execute(cursor_bind);
967       dbms_sql.close_cursor(cursor_bind);
968     end if; -- of Bind
969     define_columns(cursor_select);
970 
971    IF (g_print_debug) THEN
972    	fa_rx_util_pkg.debug('run_report: ' || 'Executing SELECT statement');
973    END IF;
974     rows := dbms_sql.execute(cursor_select);
975 
976    IF (g_print_debug) THEN
977    	fa_rx_util_pkg.debug('run_report: ' || 'Building INSERT');
978    END IF;
979     cursor_insert := dbms_sql.open_cursor;
980     dbms_sql.parse(cursor_insert, build_insert, dbms_sql.native);
981 
982    IF (g_print_debug) THEN
983    	fa_rx_util_pkg.debug('run_report: ' || 'After Fetch Initialization');
984    END IF;
985     if Report(idx).after_fetch is not null then
986       cursor_after_fetch := dbms_sql.open_cursor;
987       dbms_sql.parse(cursor_after_fetch,
988 		'BEGIN '||Report(idx).after_fetch||' END;',
989 		dbms_sql.native);
990     else
991       cursor_after_fetch := null;
992     end if;
993 
994     loop
995 	rows := dbms_sql.fetch_rows(cursor_select);
996 	exit when rows < 1;
997 
998 	IF (g_print_debug) THEN
999 		fa_rx_util_pkg.debug('run_report: ' || 'Get values ');
1000 	END IF;
1001 	column_values(cursor_select);
1002 
1003 	IF (g_print_debug) THEN
1004 		fa_rx_util_pkg.debug('run_report: ' || 'After Fetch');
1005 	END IF;
1006 	if cursor_after_fetch is not null then
1007 	  rows := dbms_sql.execute(cursor_after_fetch);
1008 	end if;
1009 
1010 	IF (g_print_debug) THEN
1011 		fa_rx_util_pkg.debug('run_report: ' || 'Insert Row');
1012 	END IF;
1013         bind_insert(cursor_insert);
1014         rows := dbms_sql.execute(cursor_insert);
1015     end loop; -- Fetch
1016     if cursor_after_fetch is not null then
1017       dbms_sql.close_cursor(cursor_after_fetch);
1018     end if;
1019     dbms_sql.close_cursor(cursor_insert);
1020     dbms_sql.close_cursor(cursor_select);
1021     if cursor_column_values is not null then
1022 	dbms_sql.close_cursor(cursor_column_values);
1023     end if;
1024 
1025     -- After Report Trigger
1026    IF (g_print_debug) THEN
1027    	fa_rx_util_pkg.debug('run_report: ' || ' After Report Trigger, Pass #'||to_char(idx));
1028    END IF;
1029     if Report(idx).after_report is not null then
1030       cursor_after_report := dbms_sql.open_cursor;
1031       dbms_sql.parse(cursor_after_report,
1032 		'BEGIN '||Report(idx).after_report||' END;',
1033 		dbms_sql.native);
1034       rows := dbms_sql.execute(cursor_after_report);
1035       dbms_sql.close_cursor(cursor_after_report);
1036     end if;
1037 
1038   <<next_section>>
1039     null;
1040   end loop;
1041 
1042  IF (g_print_debug) THEN
1043  	fa_rx_util_pkg.debug('fa_rx_util_pkg.run_report()-');
1044  END IF;
1045 exception
1046 when others then
1047  IF (g_print_debug) THEN
1048  	fa_rx_util_pkg.debug('run_report: ' || sqlerrm);
1049  	fa_rx_util_pkg.debug('fa_rx_util_pkg.run_report(EXCEPTION)-');
1050  END IF;
1051 
1052   retcode := 2; -- Error
1053   errbuf := sqlerrm;
1054 end run_report;
1055 
1056 
1057 ------------------------------------
1058 -- Debuggin Routines
1059 ------------------------------------
1060 
1061 -------------------------------------------------------------------------
1062 -- PROCEDURE enable_debug
1063 --
1064 -- Parameters
1065 --	None
1066 --		OR
1067 --	debug_dir	Directory where the debug file will reside
1068 --	debug_file	Filename of debug file.
1069 --
1070 -- Description
1071 --	If you are calling this routine from a PL/SQL concurrent program
1072 --	then you should call the version with no parameters. This will
1073 --	automatically route all of your debug statements to the log file.
1074 --	If you are calling this routine from a PL/SQL package called from
1075 --	within SQL*Plus, you must specify the directory and file name
1076 --	of the debug file. NOTE: the database must have write permission.
1077 --	(Such as /sqlcom/log).
1078 --
1079 -- Modification History
1080 --  KMIZUTA    12-MAR-99      Created.
1081 --
1082 -------------------------------------------------------------------------
1083 procedure enable_debug
1084 is
1085 begin
1086   m_debug_flag := true;
1087  fa_rx_util_pkg.debug('Enabling debug...');
1088 end enable_debug;
1089 
1090 procedure enable_debug(debug_dir in varchar2, debug_file in varchar2)
1091 is
1092 begin
1093   fnd_file.put_names(debug_file||'.log', debug_file||'.out', debug_dir);
1094   enable_debug;
1095 end enable_debug;
1096 
1097 procedure enable_debug(bufsize in number)
1098 is
1099   sqlstmt varchar2(100);
1100   rows number;
1101 begin
1102   enable_debug;
1103   if not m_dbms_output then
1104     m_dbms_output := true;
1105     m_output_cursor := dbms_sql.open_cursor;
1106     sqlstmt := 'begin dbms_'||'output.enable(:b_size); end;';
1107     dbms_sql.parse(m_output_cursor, sqlstmt, dbms_sql.native);
1108     dbms_sql.bind_variable(m_output_cursor, 'b_size', bufsize);
1109     rows := dbms_sql.execute(m_output_cursor);
1110     dbms_sql.close_cursor(m_output_cursor);
1111 
1112     m_output_cursor := dbms_sql.open_cursor;
1113     sqlstmt := 'begin dbms_'||'output.put_line(:b_msg); end;';
1114     dbms_sql.parse(m_output_cursor, sqlstmt, dbms_sql.native);
1115 
1116 --    dbms_output.enable(bufsize);
1117   end if;
1118 end enable_debug;
1119 
1120 -------------------------------------------------------------------------
1121 -- PROCEDURE disable_debug
1122 --
1123 -- Parameters
1124 --	None
1125 --
1126 -- Description
1127 --	Stop debugging
1128 --
1129 -- Modification History
1130 --  KMIZUTA    12-MAR-99      Created.
1131 --
1132 -------------------------------------------------------------------------
1133 procedure disable_debug
1134 is
1135 begin
1136  fa_rx_util_pkg.debug('Disabling debug...');
1137   if Request_Id = 0 then
1138     fnd_file.close;
1139   end if;
1140   m_debug_flag := false;
1141   if m_dbms_output then
1142     m_dbms_output := false;
1143     dbms_sql.close_cursor(m_output_cursor);
1144   end if;
1145 end disable_debug;
1146 
1147 -------------------------------------------------------------------------
1148 -- PROCEDURE debug_enabled
1149 --
1150 -- Parameters
1151 --	None
1152 --
1153 -- Returns
1154 --	Boolean		Returns true if debugging is enabled.
1155 --
1156 -- Description
1157 --	Checks to see if debugging is enabled. Call this function
1158 --	if you want to have a block of code run only if debugging
1159 --	is enabled.
1160 --	If you have a whole bunch offa_rx_util_pkg.debug() calls in succession,
1161 --	then it is preferable if you first check to see if debuggin
1162 --	is enabled.
1163 --
1164 -- Modification History
1165 --  KMIZUTA    12-MAR-99      Created.
1166 --
1167 -------------------------------------------------------------------------
1168 function debug_enabled return boolean
1169 is
1170 begin
1171   return m_debug_flag;
1172 end debug_enabled;
1173 
1174 PROCEDURE dbms_log(msg IN VARCHAR2)
1175   IS
1176      maxidx NUMBER;
1177      rows NUMBER;
1178 BEGIN
1179     maxidx := trunc(lengthb(msg)/255);
1180     for idx in 0..maxidx loop
1181 
1182       dbms_sql.bind_variable(m_output_cursor, 'b_msg', substrb(msg,idx*255+1,255));
1183       rows := dbms_sql.execute(m_output_cursor);
1184 --      dbms_output.put_line(substrb(msg,idx*255+1,255));
1185     end loop;
1186 END dbms_log;
1187 
1188 -------------------------------------------------------------------------
1189 -- PROCEDURE debug
1190 --
1191 -- Parameters
1192 --	msg	String to be logged to the debug file
1193 --
1194 -- Description
1195 --	Send debug message to the debug (log) file.
1196 --
1197 -- Modification History
1198 --  KMIZUTA    12-MAR-99      Created.
1199 --
1200 -------------------------------------------------------------------------
1201 procedure debug(msg in varchar2)
1202 is
1203   idx number;
1204   maxidx number;
1205   rows number;
1206 begin
1207   if not m_debug_flag then return;
1208   end if;
1209 
1210   if not m_dbms_output then
1211     fnd_file.put_line(fnd_file.log,msg);
1212   else
1213      dbms_log(msg);
1214   end if;
1215 
1216 exception
1217 when others then
1218   begin
1219     fnd_file.put_line(fnd_file.log, '**** Exception occurred while outputing to file...');
1220   exception when others then null;
1221   end;
1222 end debug;
1223 
1224 
1225 -------------------------------------------------------------------------
1226 --
1227 -- PROCEDURE log
1228 -- PROCEDURE out
1229 --
1230 -- Parameters
1231 --	msg	String to be logged/outputted
1232 --
1233 -- Description
1234 --	These files are wrappers to other routines. It basically handles
1235 --	your output to log and output files. This was added here so that
1236 --	if you ever need to quickly make it so that all output goes
1237 --	through dbms_output, you can just modify these functions.
1238 --
1239 -- Modification History
1240 --  KMIZUTA    12-MAR-99      Created.
1241 --
1242 -------------------------------------------------------------------------
1243 procedure log(msg in varchar2)
1244 is
1245 begin
1246   if not m_dbms_output then
1247     fnd_file.put_line(fnd_file.log,msg);
1248   else
1249     dbms_log(msg);
1250   end if;
1251 
1252 exception
1253 when others then
1254   begin
1255     fnd_file.put_line(fnd_file.log, '**** Exception occurred while outputing to file...');
1256   exception when others then null;
1257   end;
1258 end log;
1259 
1260 procedure out(msg in varchar2)
1261 is
1262 begin
1263   if not m_dbms_output then
1264     fnd_file.put_line(fnd_file.output,msg);
1265   else
1266     dbms_log(msg);
1267   end if;
1268 
1269 exception
1270 when others then
1271   begin
1272     fnd_file.put_line(fnd_file.log, '**** Exception occurred while outputing to file...');
1273   exception when others then null;
1274   end;
1275 end out;
1276 
1277 
1278 -------------------------------------------------------------------------
1279 -- PROCEDURE enable_trace, disable_trace
1280 --
1281 -- Parameters
1282 --	None
1283 --
1284 -- Description
1285 --	Enable and disable SQL Tracing
1286 --
1287 -- Modification History
1288 --  KMIZUTA    12-MAR-99      Created.
1289 --
1290 -------------------------------------------------------------------------
1291 procedure enable_trace
1292 is
1293 begin
1294   --* bug#3344455, rravunny dbms_session.set_sql_trace(true);
1295   Null;
1296 end enable_trace;
1297 
1298 
1299 procedure disable_trace
1300 is
1301 begin
1302   --* bug#3344455, rravunny dbms_session.set_sql_trace(false);
1303   Null;
1304 end disable_trace;
1305 
1306 end fa_rx_util_pkg;