DBA Data[Home] [Help]

PACKAGE BODY: APPS.BSC_AW_UTILITY

Source


1 package body BSC_AW_UTILITY AS
2 /*$Header: BSCAWUTB.pls 120.34 2006/06/16 21:32:45 vsurendr ship $*/
3 
4 function in_array(
5 p_array dbms_sql.varchar2_table,
6 p_value varchar2
7 ) return boolean is
8 Begin
9   for i in 1..p_array.count loop
10     if p_array(i)=p_value then
11       return true;
12     end if;
13   end loop;
14   return false;
15 Exception when others then
16   log('Exception in in_array '||sqlerrm);
17   raise;
18 End;
19 
20 function in_array(
21 p_array dbms_sql.number_table,
22 p_value number
23 ) return boolean is
24 Begin
25   for i in 1..p_array.count loop
26     if p_array(i)=p_value then
27       return true;
28     end if;
29   end loop;
30   return false;
31 Exception when others then
32   log('Exception in in_array '||sqlerrm);
33   raise;
34 End;
35 
36 function in_array(
37 p_array varchar2_table,
38 p_value varchar2
39 ) return boolean is
40 l_val varchar2(200);
41 Begin
42   l_val:=p_array(p_value);
43   return true;
44 Exception when others then
45   return false;
46 End;
47 
48 function get_array_index(
49 p_array dbms_sql.varchar2_table,
50 p_value varchar2
51 ) return number is
52 Begin
53   for i in 1..p_array.count loop
54     if p_array(i)=p_value then
55       return i;
56     end if;
57   end loop;
58   return null;
59 Exception when others then
60   log('Exception in get_array_index '||sqlerrm);
61   raise;
62 End;
63 
64 function get_array_index(
65 p_array dbms_sql.number_table,
66 p_value number
67 ) return number is
68 Begin
69   for i in 1..p_array.count loop
70     if p_array(i)=p_value then
71       return i;
72     end if;
73   end loop;
74   return null;
75 Exception when others then
76   log('Exception in get_array_index '||sqlerrm);
77   raise;
78 End;
79 
80 /*
81 given a set of options in a string like DEBUG,LOG=N,TABLESPACE=USER_DATA etc, we will pass in DEBUG and this api will return the value of
82 the parameter back
83 if param=DEBUG, return Y
84 if param=TABLESPACE return USER_DATA
85 */
86 function get_parameter_value(p_string varchar2,p_parameter varchar2,p_separator varchar2) return varchar2 is
87 l_length number;
88 l_start number;
89 l_end number;
90 --
91 l_values value_tb;
92 Begin
93   parse_parameter_values(p_string,p_separator,l_values);
94   return get_parameter_value(l_values,p_parameter);
95 Exception when others then
96   log('Exception in get_parameter_value '||sqlerrm);
97   raise;
98 End;
99 
100 --this is the 2nd implementation...given a table of options, return the value
101 function get_parameter_value(p_options value_tb,p_parameter varchar2) return varchar2 is
102 Begin
103   for i in 1..p_options.count loop
104     if p_options(i).parameter=p_parameter then
105       return p_options(i).value;
106     end if;
107   end loop;
108   return null;
109 Exception when others then
110   log('Exception in get_parameter_value '||sqlerrm);
111   raise;
112 End;
113 
114 function get_parameter_value(p_parameter varchar2) return varchar2 is
115 Begin
116   return get_parameter_value(g_options,p_parameter);
117 Exception when others then
118   log('Exception in get_parameter_value '||sqlerrm);
119   raise;
120 End;
121 
122 
123 /*
124 this procedure will parse the option string and put the values into value_tb table
125 */
126 procedure parse_parameter_values(
127 p_string varchar2,
128 p_separator varchar2,
129 p_values out nocopy value_tb
130 ) is
131 --
132 l_parse_strings dbms_sql.varchar2_table;
133 Begin
134   parse_parameter_values(p_string,p_separator,l_parse_strings);
135   for i in 1..l_parse_strings.count loop
136     resolve_into_value_r(l_parse_strings(i),p_values(p_values.count+1));
137   end loop;
138 Exception when others then
139   log('Exception in parse_parameter_values '||sqlerrm);
140   raise;
141 End;
142 
143 --given TABLESPACE=USER_DATA or DEBUG LOG it will resolve it into value_r record
144 procedure resolve_into_value_r(
145 p_string varchar2,
146 p_value out nocopy value_r) is
147 l_end number;
148 l_len number;
149 Begin
150   l_end:=instr(p_string,'=');
151   if l_end=0 then
152     p_value.parameter:=p_string;
153     p_value.value:='Y';
154   else
155     l_len:=length(p_string);
156     p_value.parameter:=substr(p_string,1,l_end-1);
157     --we can have lowest level,zero code=,. here l_end=l_len
158     --open:do we have 'N' or null. we will keep null. the calling routine can interpret it as N
159     if l_end=l_len then
160       p_value.value:=null;
161     else
162       p_value.value:=substr(p_string,l_end+1,l_len-l_end);
163     end if;
164   end if;
165 Exception when others then
166   log('Exception in resolve_into_value_r '||sqlerrm);
167   raise;
168 End;
169 
170 /*
171 earlier, we just had
172 parse_parameter_values(p_string,p_separator,l_values);
173 for i in 1..l_values.count loop
174   p_values(p_values.count+1):=l_values(i).parameter;
175 end loop;
176 this will not do. parse_parameter_values(p_string,p_separator,l_values); breaks into parameter and value.
177 which means if it encounters an "=" sign, its split into a parameter + value. this will not do for us.
178 we have to strictly break up the string according to p_separator
179 */
180 procedure parse_parameter_values(
181 p_string varchar2,
182 p_separator varchar2,
183 p_values out nocopy dbms_sql.varchar2_table
184 ) is
185 --
186 l_start number;
187 l_end number;
188 l_len number;
189 Begin
190   if p_string is null or p_string='' then
191     return;
192   end if;
193   l_len:=length(p_string);
194   if l_len<=0 then
195     return;
196   end if;
197   l_start:=1;
198   loop
199     l_end:=instr(p_string,p_separator,l_start);
200     if l_end=0 then
201       l_end:=l_len+1;
202     end if;
203     if l_end>l_start then
204       p_values(p_values.count+1):=ltrim(rtrim(substr(p_string,l_start,(l_end-l_start))));
205     end if;
206     l_start:=l_end+length(p_separator);
207     --we could have p_string as "recursive,multi level," a comma at the end
208     if l_end>=l_len or l_start>=l_len then
209       exit;
210     end if;
211   end loop;
212 Exception when others then
213   log('Exception in parse_parameter_values '||sqlerrm);
214   raise;
215 End;
216 
217 function get_min(num1 number,num2 number) return number is
218 Begin
219   if num1<num2 then
220     return num1;
221   else
222     return num2;
223   end if;
224 Exception when others then
225   log('Exception in get_min '||sqlerrm);
226   raise;
227 End;
228 
229 function contains(p_text varchar2,p_check varchar2) return boolean is
230 Begin
231   if instr(p_text,p_check)>0 then
232     return true;
233   end if;
234   return false;
235 Exception when others then
236   log('Exception in contains '||sqlerrm);
237   raise;
238 End;
239 
240 --used to populate created by etc
241 function get_who return number is
242 Begin
243   return 0;
244 Exception when others then
245   log('Exception in get_who '||sqlerrm);
246   raise;
247 End;
248 
249 procedure delete_aw_object(p_object varchar2) is
250 Begin
251   if p_object is not null then
252     bsc_aw_dbms_aw.execute('delete '||p_object);
253   end if;
254 Exception when others then
255   null;--may try to delete an object that does not exist
256 End;
257 
258 procedure execute_ddl_ne(p_stmt varchar2) is
259 Begin
260   if g_debug then
261     log(p_stmt);
262   end if;
263   execute immediate p_stmt;
264 Exception when others then
265   log('Exception in execute_ddl_ne '||sqlerrm);
266 End;
267 
268 procedure execute_ddl(p_stmt varchar2) is
269 Begin
270   if g_debug then
271     log(p_stmt);
272   end if;
273   execute immediate p_stmt;
274 Exception when others then
275   log('Exception in execute_ddl '||sqlerrm);
276   raise;
277 End;
278 
279 procedure execute_stmt(p_stmt varchar2) is
280 Begin
281   if g_debug then
282     log_s('@ '||p_stmt||'(S:'||get_time);
283   end if;
284   execute immediate p_stmt;
285   if g_debug then
286     log(',E:'||get_time||') Processed '||sql%rowcount||' rows ');
287   end if;
288 Exception when others then
289   log('Exception in execute_stmt '||sqlerrm);
290   raise;
291 End;
292 
293 procedure execute_stmt_ne(p_stmt varchar2) is
294 Begin
295   execute_stmt(p_stmt);
296 Exception when others then
297   null;
298 End;
299 
300 procedure delete_table(p_table varchar2,p_where varchar2) is
301 --
302 l_stmt varchar2(1000);
303 Begin
304   if g_debug then
305     log('delete '||p_table||' where '||p_where);
306   end if;
307   if p_where is null then
308     l_stmt:='delete '||p_table;
309   else
310     l_stmt:='delete '||p_table||' where '||p_where;
311   end if;
312   if g_debug then
313     log(l_stmt||get_time);
314   end if;
315   execute immediate l_stmt;
316   if g_debug then
317     log('Deleted '||sql%rowcount||' rows '||get_time);
318   end if;
319 Exception when others then
320   log('Exception in delete_table '||sqlerrm);
321   raise;
322 End;
323 
324 /*
325 this api will normalize a denorm relation. if the relation is already normalized,
326 no change will happen. so we can pass both denorm arrays and normal arrays
327 for each parent, check each of the children to see if the children have their
328 own children. if so, remove children's children from the list
329 parent  child
330 year     qtr,month,week,day
331 qtr      month,day
332 month    day
333 week     day
334 qtr has month and day as its children. so remove month and day from year...
335 */
336 procedure normalize_denorm_relation(p_relation in out nocopy parent_child_tb) is
337 l_relation parent_child_tb;
338 l_count number;
339 Begin
340   for i in 1..p_relation.count loop
341     if p_relation(i).child is not null and p_relation(i).status is null then
342       for j in 1..p_relation.count loop
343         if p_relation(j).parent=p_relation(i).child and p_relation(j).status is null then
344           for k in 1..p_relation.count loop
345             if p_relation(k).parent=p_relation(i).parent and p_relation(k).child=p_relation(j).child then
346               p_relation(k).status:='R'; --R means remove
347               exit;
348             end if;
349           end loop;
350         end if;
351       end loop;
352     end if;
353   end loop;
354   l_relation:=p_relation;
355   p_relation.delete;
356   l_count:=0;
357   for i in 1..l_relation.count loop
358     if l_relation(i).status is null then
359       l_count:=l_count+1;
360       p_relation(l_count):=l_relation(i);
361     end if;
362   end loop;
363 Exception when others then
364   log('Exception in normalize_denorm_relation '||sqlerrm);
365   raise;
366 End;
367 
368 --p_type is 'program' or 'aggmap'
369 procedure make_stmt_for_aw(p_program varchar2,p_stmt in out nocopy varchar2,p_type varchar2) is
370 Begin
371   p_stmt:=p_type||' joinlines(obj('||p_type||' '''||p_program||'''),'''||p_stmt||''')';
372 Exception when others then
373   log('Exception in make_stmt_for_aw '||sqlerrm);
374   raise;
375 End;
376 
377 procedure add_g_commands(p_commands in out nocopy dbms_sql.varchar2_table,p_command varchar2) is
378 Begin
379   p_commands(p_commands.count+1):=p_command;
380 Exception when others then
381   log('Exception in add_g_commands '||sqlerrm);
382   raise;
383 End;
384 
385 function get_g_commands(p_commands dbms_sql.varchar2_table,p_index number) return varchar2 is
386 Begin
387   if p_commands.count>0 then
388     if p_index is null then --latest
389       return p_commands(p_commands.count);
390     else
391       return p_commands(p_index);
392     end if;
393   else
394     return null;
395   end if;
396 Exception when others then
397   log('Exception in get_g_commands '||sqlerrm);
398   raise;
399 End;
400 
401 procedure trim_g_commands(p_commands in out nocopy dbms_sql.varchar2_table,p_trim number,p_add varchar2) is
402 Begin
403   p_commands(p_commands.count):=substr(p_commands(p_commands.count),1,length(p_commands(p_commands.count))-p_trim)||p_add;
404 Exception when others then
405   log('Exception in trim_g_commands '||sqlerrm);
406   raise;
407 End;
408 
409 procedure exec_program_commands(p_program varchar2,p_commands dbms_sql.varchar2_table) is
410 Begin
411   --the first stmt is 'dfn abc program' this does not have "joinlines"
412   --first try and drop the programs if it exists.
413   bsc_aw_dbms_aw.execute_ne('delete '||p_program);
414   exec_aw_program_aggmap(p_program,p_commands,'program');
415   bsc_aw_dbms_aw.execute('compile '||p_program);
416 Exception when others then
417   log('Exception in exec_program_commands '||sqlerrm);
418   raise;
419 End;
420 
421 procedure exec_aggmap_commands(p_aggmap varchar2,p_commands dbms_sql.varchar2_table) is
422 Begin
423   --the first stmt is 'dfn abc program' this does not have "joinlines"
424   bsc_aw_dbms_aw.execute_ne('delete '||p_aggmap);
425   exec_aw_program_aggmap(p_aggmap,p_commands,'aggmap');
426   bsc_aw_dbms_aw.execute('compile '||p_aggmap);
427 Exception when others then
428   log('Exception in exec_aggmap_commands '||sqlerrm);
429   raise;
430 End;
431 
432 --p_type is 'program' or 'aggmap'
433 procedure exec_aw_program_aggmap(p_name varchar2,p_commands dbms_sql.varchar2_table,p_type varchar2) is
434 l_commands varchar2(8000);
435 Begin
436   bsc_aw_dbms_aw.execute(p_commands(1));
437   for i in 2..p_commands.count loop
438     l_commands:=p_commands(i);
439     make_stmt_for_aw(p_name,l_commands,p_type);
440     bsc_aw_dbms_aw.execute(l_commands);
441   end loop;
442 Exception when others then
443   log('Exception in exec_aw_program_aggmap '||sqlerrm);
444   raise;
445 End;
446 
447 procedure dmp_g_options(p_options value_tb) is
448 Begin
449   log('Options :-');
450   for i in 1..p_options.count loop
451     log(p_options(i).parameter||'='||p_options(i).value);
452   end loop;
453 Exception when others then
454   log('Exception in dmp_g_options '||sqlerrm);
455   raise;
456 End;
457 
458 /*
459 called from bsc_aw_adapter_kpi.create_base_table_sql
460 this procedure strips out the aggregation functions from the formula.
461 the base table may have the same number of keys as the dim set in this case, there is no need to do the aggregation
462 when loading the cube from the base table. so we need to remove  the agg functions
463 bsc supports
464 Apply aggregation method to the each element of the formula, e.g.: SUM(source_column1)/SUM(source_column2)
465 Apply aggregation method to the overall formula, e.g.: SUM(source_column1/source_column2)
466 Formulas between 2 calculated Measures e.g.: SUM(source_col1/source_col2)/AVG(source_col3+source_col4)
467 
468 for case II, we simply remove string till the first (
469 
470 if the agg function is count(), we simply replace it with 1. since there is no group by, count() will anyway be returning 1.
471 this is not working. getting this error
472 ORA-34738: (NOUPDATE) A severe problem has been detected. Analytic workspace operations have been disabled.
473 ORA-06512: at "APPS.BSC_AW_UTILITY", line 466
474 ORA-06512: at "APPS.BSC_AW_LOAD", line 112
475 ORA-37666: ** SYSTEM ERROR xsSqlImport01 **
476 A severe problem has been detected. Please save your work via EXPORT or OUTFILE and exit as soon as possible.
477 As a safety measure, analytic workspace operations have been disabled. Call Oracle OLAP technical support.
478 ORA-06512: at line 7
479 somehow, hardcoded 1 is interpreted as true / false 1.
480 so we will see if count is in the formula. if yes, we will go for groupby
481 */
482 procedure parse_out_agg_function(p_formula varchar2,p_noagg_formula out nocopy varchar2) is
483 --
484 l_agg_function varchar2(100);
485 Begin
486   l_agg_function:=ltrim(rtrim(substr(p_formula,1,instr(p_formula,'(')-1)));
487   if lower(l_agg_function)='count' then
488     p_noagg_formula:='(1)';
489   else
490     p_noagg_formula:=substr(p_formula,instr(p_formula,'('));
491   end if;
492 Exception when others then
493   log('Exception in parse_out_agg_function '||sqlerrm);
494   raise;
495 End;
496 
497 /*
498 given a number array, get the max
499 */
500 function get_max(p_array dbms_sql.number_table) return number is
501 l_max number;
502 Begin
503   if p_array.count<=0 then
504     return null;
505   end if;
506   l_max:=p_array(1);
507   for i in 2..p_array.count loop
508     if p_array(i)>l_max then
509       l_max:=p_array(i);
510     end if;
511   end loop;
512   return l_max;
513 Exception when others then
514   log('Exception in get_max '||sqlerrm);
515   raise;
516 End;
517 
518 
519 function does_table_have_data(p_table varchar2,p_where varchar2) return varchar2 is
520 --
521 TYPE CurTyp IS REF CURSOR;
522 cv   CurTyp;
523 l_res number;
524 Begin
525   g_stmt:='select 1 from '||p_table;
526   if p_where is not null then
527     g_stmt:=g_stmt||' where '||p_where||' and rownum=1';
528   else
529     g_stmt:=g_stmt||' where rownum=1';
530   end if;
531   if g_debug then
532     log(g_stmt);
533   end if;
534   open cv for g_stmt;
535   fetch cv into l_res;
536   close cv;
537   if g_debug then
538     log('result='||l_res);
539   end if;
540   if l_res=1 then
541     return 'Y';
542   else
543     return 'N';
544   end if;
545 Exception when others then
546   log('Exception in does_table_have_data '||sqlerrm);
547   raise;
548 End;
549 
550 /*
551 this function is used to see if the aggregation is a simple aggregation or if this is a formula
552 its a formula when we have averaqge at the lowest level
553 */
554 function is_std_aggregation_function(p_agg_formula varchar2) return varchar2 is
555 Begin
556   if g_debug then
557     log('In is_std_aggregation_function, p_agg_formula='||p_agg_formula);
558   end if;
559   if upper(p_agg_formula)='SUM' or upper(p_agg_formula)='AVERAGE' or upper(p_agg_formula)='MAX' or upper(p_agg_formula)='MIN' or
560     upper(p_agg_formula)='COUNT' then
561     if g_debug then
562       log('Yes');
563     end if;
564     return 'Y';
565   end if;
566   if g_debug then
567     log('No');
568   end if;
569   return 'N';
570 Exception when others then
571   log('Exception in is_std_aggregation_function '||sqlerrm);
572   raise;
573 End;
574 
575 /*this sees if an aggregation formula can be safely partitioned even if there are aggregations */
576 function is_PT_aggregation_function(p_agg_formula varchar2) return varchar2 is
577 Begin
578   if upper(p_agg_formula)='SUM' or upper(p_agg_formula)='MAX' or upper(p_agg_formula)='MIN' then
579     return 'Y';
580   end if;
581   return 'N';
582 Exception when others then
583   log('Exception in is_pt_aggregation_function '||sqlerrm);
584   raise;
585 End;
586 
587 /*currently, only sum has CC. not able to get aggcount to work ie create cube <...> with aggcount and then aggregate cube using aggmap */
588 function is_CC_aggregation_function(p_agg_formula varchar2) return varchar2 is
589 Begin
590   if upper(p_agg_formula)='SUM' then
591     return 'Y';
592   end if;
593   return 'N';
594 Exception when others then
595   log('Exception in is_CC_aggregation_function '||sqlerrm);
596   raise;
597 End;
598 
599 /*
600 if we have non-std agg, we execute it as cube=formula. there is no aggmap
601 so we look for std agg : average
602 */
603 function is_avg_aggregation_function(p_agg_formula varchar2) return varchar2 is
604 Begin
605   if upper(p_agg_formula)='AVERAGE' or upper(p_agg_formula)='AVG' then
606     return 'Y';
607   else
608     return 'N';
609   end if;
610 Exception when others then
611   log('Exception in is_avg_aggregation_function '||sqlerrm);
612   raise;
613 End;
614 
615 /*
616 this function is used by aggregation module to see if a measure is a part of an agg formula
617 the aggregtion module will then substitute the measure with the cube name
618 
619 p_strng is the original  string
620 p_text thisis the text to search for
621 p_location a table of all locations in p_string where p_text occurs
622 */
623 function is_string_present(
624 p_string varchar2,
625 p_text varchar2,
626 p_location out nocopy dbms_sql.number_table
627 ) return boolean is
628 --
629 l_start number;
630 l_end number;
631 l_len number;
632 l_char varchar2(10);
633 l_flag boolean;
634 Begin
635   --there can be multiple occurances of text in string
636   l_start:=1;
637   l_len:=length(p_string);
638   loop
639     l_start:=instr(p_string,p_text,l_start);
640     if l_start=0 then
641       exit;
642     else --l_start>1
643       l_flag:=true;
644       l_end:=l_start+length(p_text);
645       if l_start>1 then
646         l_char:=substr(p_string,l_start-1,1);
647         if is_ascii(l_char) then
648           l_flag:=false;
649         end if;
650       end if;
651       if l_flag and l_end<l_len then
652         l_char:=substr(p_string,l_end,1);
653         if is_ascii(l_char) then
654           l_flag:=false;
655         end if;
656       end if;
657       if l_flag then --we did find p_text in p_string
658         p_location(p_location.count+1):=l_start;
659       end if;
660       l_start:=l_end;
661     end if;
662   end loop;
663   if p_location.count>0 then
664     return true;
665   else
666     return false;
667   end if;
668 Exception when others then
669   log('Exception in is_string_present '||sqlerrm);
670   raise;
671 End;
672 
673 /*
674 this fucntion sees if a character is a special char or a variable name continuing
675 example
676 sees if the char is between A and Z, 0 and 9 or _
677 
678 p_char is one char
679 */
680 function is_ascii(p_char varchar2) return boolean is
681 l_ascii_a number;
682 l_ascii_z number;
683 l_ascii_0 number;
684 l_ascii_9 number;
685 l_char number;
686 Begin
687   l_ascii_a:=ascii('A');
688   l_ascii_z:=ascii('Z');
689   l_ascii_0:=ascii('0');
690   l_ascii_9:=ascii('9');
691   l_char:=ascii(upper(p_char));
692   if p_char='_' then
693     return true;
694   elsif is_in_between(l_char,l_ascii_a,l_ascii_z) then
695     return true;
696   elsif is_in_between(l_char,l_ascii_0,l_ascii_9) then
697     return true;
698   else
699     return false;
700   end if;
701 Exception when others then
702   log('Exception in is_ascii '||sqlerrm);
703   raise;
704 End;
705 
706 function is_in_between(p_input number,p_left number,p_right number) return boolean is
707 Begin
708   if p_left>p_right then
709     if p_input>=p_right and p_input<=p_left then
710       return true;
711     else
712       return false;
713     end if;
714   else
715     if p_input<=p_right and p_input>=p_left then
716       return true;
717     else
718       return false;
719     end if;
720   end if;
721 Exception when others then
722   log('Exception in is_in_between '||sqlerrm);
723   raise;
724 End;
725 
726 /*
727 this procedure is used by the agg module to replace the measure names with the cube names
728 database replace procedure does not support replacing the occurance of a string at a particular location. we cannot
729 blindly replace. example, we may have formula : cons_revenue / revenue + cost
730 if we have to replace revenue with "cube_revenue", we cannot do replace(agg_formula,'revenue','cube_revenue'). it will make
731 this cons_cube_revenue + cube_revenue + cost. this is wrong. so we have this procedure which will replace at the
732 secified locations
733 
734 if a string is mm + abcd/123 + abcd/mnq
735 we need to relace abcd with cube_abcd
736 we will first break it into parts without abcd
737 l_string_parts(1):=mm +
738 l_string_parts(2):=/123 +
739 l_string_parts(3):=/mnq
740 then we simply put them together as
741 l_string_parts(1)||cube_abcd||l_string_parts(2)||cube_abcd||l_string_parts(3)
742 */
743 procedure replace_string(
744 p_string in out nocopy varchar2,
745 p_old_text varchar2,
746 p_new_text varchar2,
747 p_start_array dbms_sql.number_table
748 ) is
749 --
750 l_string_parts dbms_sql.varchar2_table;
751 l_start number;
752 l_len number;
753 l_length number;
754 Begin
755   l_start:=1;
756   l_len:=length(p_old_text);
757   l_length:=length(p_string);
758   for i in 1..p_start_array.count loop
759     l_string_parts(l_string_parts.count+1):=substr(p_string,l_start,p_start_array(i)-l_start);
760     l_start:=p_start_array(i)+l_len;
761   end loop;
762   --now we add the last part of the strin
763   if l_start<l_length then
764     l_string_parts(l_string_parts.count+1):=substr(p_string,l_start,l_length-l_start+1);
765   else
766     l_string_parts(l_string_parts.count+1):=null;
767   end if;
768   --now reform the string , this time with the new string
769   p_string:=null;
770   for i in 1..l_string_parts.count-1 loop
771     p_string:=p_string||l_string_parts(i)||p_new_text;
772   end loop;
773   --append the last part
774   p_string:=p_string||l_string_parts(l_string_parts.count);
775 Exception when others then
776   log('Exception in replace_string '||sqlerrm);
777   raise;
778 End;
779 
780 function get_adv_sum_profile return number is
781 --
782 l_adv_sum_profile number;
783 Begin
784   l_adv_sum_profile:=bsc_aw_utility.get_parameter_value(g_options,'SUMMARIZATION LEVEL');
785   if l_adv_sum_profile is null or l_adv_sum_profile=0 then
786     l_adv_sum_profile:=1000000;
787   end if;
788   return l_adv_sum_profile;
789 Exception when others then
790   log('Exception in get_adv_sum_profile '||sqlerrm);
791   raise;
792 End;
793 ---------------------------
794 
795 procedure truncate_table(p_table varchar2) is
796 --
797 l_owner varchar2(100);
798 l_stmt varchar2(1000);
799 Begin
800   if instr(p_table,'.')>0 then
801     l_stmt:='truncate table '||p_table;
802   else
803     l_owner:=get_table_owner(p_table);
804     l_stmt:='truncate table '||l_owner||'.'||p_table;
805   end if;
806   if g_debug then
807     log(l_stmt||get_time);
808   end if;
809   execute immediate l_stmt;
810   if g_debug then
811     log(get_time);
812   end if;
813 Exception when others then
814   log('Exception in truncate_table '||sqlerrm);
815   raise;
816 End;
817 
818 function get_table_owner(p_table varchar2) return varchar2 is
819 --
820 cursor c1 is select table_owner from user_synonyms where synonym_name=upper(p_table);
821 l_owner varchar2(100);
822 Begin
823   if instr(p_table,'.')>0 then
824     l_owner:=substr(p_table,1,instr(p_table,'.')-1);
825     return l_owner;
826   end if;
827   open c1;
828   fetch c1 into l_owner;
829   close c1;
830   if l_owner is null then
831     l_owner:=get_apps_schema_name;
832   end if;
833   return l_owner;
834 Exception when others then
835   log('Exception in get_table_owner '||sqlerrm);
836   return null;
837 End;
838 
839 FUNCTION get_apps_schema_name RETURN VARCHAR2 IS
840   l_apps_schema_name VARCHAR2(30);
841   CURSOR c_apps_schema_name IS
842   SELECT oracle_username
843   FROM fnd_oracle_userid WHERE oracle_id
844   BETWEEN 900 AND 999 AND read_only_flag = 'U';
845 BEGIN
846   OPEN c_apps_schema_name;
847   FETCH c_apps_schema_name INTO l_apps_schema_name;
848   CLOSE c_apps_schema_name;
849   RETURN l_apps_schema_name;
850 EXCEPTION
851   WHEN OTHERS THEN
852   RETURN NULL;
853 END get_apps_schema_name;
854 
855 ---------------------------
856 procedure init_all(p_debug boolean) is
857 Begin
858   g_debug:=p_debug;
859   if nvl(get_parameter_value('TRACE'),'N')='Y' then
860     set_aw_trace;
861   end if;
862 Exception when others then
863   raise;
864 End;
865 
866 /*
867 this will init all procedures
868 this is useful if we dont need to worry about which all packs's init have been called.
869 useful for dbms jobs
870 */
871 procedure init_all_procedures is
872 Begin
873   if get_parameter_value(g_options,'DEBUG LOG')='Y'
874   or bsc_aw_utility.g_log_level>=FND_LOG.G_CURRENT_RUNTIME_LEVEL then
875     g_debug:=true;
876   else
877     g_debug:=false;
878   end if;
879   init_all(g_debug);
880   bsc_aw_adapter_dim.init_all;
881   bsc_aw_adapter_kpi.init_all;
882   bsc_aw_bsc_metadata.init_all;
883   bsc_metadata.init_all;
884   bsc_aw_load_dim.init_all;
885   bsc_aw_load_kpi.init_all;
886   bsc_aw_dbms_aw.init_all;
887   bsc_aw_md_api.init_all;
888   bsc_aw_md_wrapper.init_all;
889   bsc_aw_management.init_all;
890   bsc_aw_calendar.init_all;
891   bsc_aw_adapter.init_all;
892   bsc_aw_load.init_all;
893   bsc_aw_read.init_all;
894 Exception when others then
895   raise;
896 End;
897 
898 
899 --write to same line
900 procedure log_s(p_message varchar2) is
901 Begin
902   write_to_file('LOG',p_message,false);
903 Exception when others then
904   null;
905 End;
906 
907 procedure log(p_message varchar2) is
908 Begin
909   write_to_file('LOG',p_message,true);
910 Exception when others then
911   null;
912 End;
913 
914 procedure log_n(p_message varchar2) is
915 Begin
916   log('  ');
917   log(p_message);
918 Exception when others then
919   null;
920 End;
921 
922 function get_time return varchar2 is
923 Begin
924   return ' '||to_char(sysdate,'MM/DD/YYYY HH24:MI:SS')||' ';
925 Exception when others then
926   null;
927 End;
928 
929 procedure write_to_file(p_type varchar2,p_message varchar2,p_new_line boolean) is
930 l_len number;
931 l_start number:=1;
932 l_end number:=1;
933 last_reached boolean:=false;
934 Begin
935   if p_message is null or p_message='' then
936     return;
937   end if;
938   l_len:=nvl(length(p_message),0);
939   if l_len <=0 then
940     return;
941   end if;
942   loop
943     l_end:=l_start+250;
944     if l_end >= l_len then
945       l_end:=l_len;
946       last_reached:=true;
947     end if;
948     if p_new_line then
949       if p_type='LOG' then
950         FND_FILE.PUT_LINE(FND_FILE.LOG,substr(p_message, l_start, 250));
951       else
952         FND_FILE.PUT_LINE(FND_FILE.OUTPUT,substr(p_message, l_start, 250));
953       end if;
954     else
955       if p_type='LOG' then
956         FND_FILE.PUT(FND_FILE.LOG,substr(p_message, l_start, 250)||' ');
957       else
958         FND_FILE.PUT(FND_FILE.OUTPUT,substr(p_message, l_start, 250)||' ');
959       end if;
960     end if;
961     l_start:=l_start+250;
962     if last_reached then
963       exit;
964     end if;
965   end loop;
966   log_fnd(p_message,bsc_aw_utility.g_log_level);
967 Exception when others then
968   null;
969 End;
970 
971 procedure log_fnd(p_message varchar2,p_severity number) is
972 l_table dbms_sql.varchar2_table;
973 Begin
974   if p_severity>=FND_LOG.G_CURRENT_RUNTIME_LEVEL then
975     convert_varchar2_to_table(p_message,3990,l_table);
976     for i in 1..l_table.count loop
977       FND_LOG.STRING(p_severity,'BSC-AW',l_table(i));
978     end loop;
979   end if;
980 Exception when others then
981   null;
982 End;
983 
984 procedure open_file(p_object_name varchar2) is
985 l_dir varchar2(200);
986 Begin
987   l_dir:=null;
988   l_dir:=get_parameter_value('UTL_FILE_LOG');
989   if l_dir is null then
990     l_dir:=fnd_profile.value('UTL_FILE_LOG');
991   end if;
992   if l_dir is null then
993     l_dir:='/sqlcom/log';
994   end if;
995   FND_FILE.PUT_NAMES(p_object_name||'.log',p_object_name||'.out',l_dir);
996   log('File Directory is '||l_dir);
997   if l_dir is null then
998     log('Please set profile option UTL_FILE_LOG to point to a valid directory the database can write to. Only then can you see the log files');
999     log('generated from parallel jobs(when Debug Mode is true) for load and aggregations');
1000   end if;
1001 Exception when others then
1002   raise;
1003 End;
1004 
1005 procedure create_temp_tables is
1006 Begin
1007   g_stmt:='create global temporary table bsc_aw_temp_vn (name varchar2(400),id number)';
1008   execute_ddl_ne(g_stmt);--execute_ddl_ne = ignore exception
1009   g_stmt:='create global temporary table bsc_aw_temp_pc(parent varchar2(300),child varchar2(300),id number)';
1010   execute_ddl_ne(g_stmt);--execute_ddl_ne = ignore exception
1011   g_stmt:='create global temporary table bsc_aw_temp_cv(change_vector_min_value number,change_vector_max_value number,change_vector_base_table varchar2(30))'; --for change vector
1012   execute_ddl_ne(g_stmt);--execute_ddl_ne = ignore exception
1013   --tables to normalize a denorm hierarchy
1014   --for parent, child, we can re-use bsc_aw_temp_pc
1015   --for count of each dim value, we can use bsc_aw_temp_vn
1016 Exception when others then
1017   log_n('Exception in create_temp_tables '||sqlerrm);
1018   raise;
1019 End;
1020 
1021 /*5121276 bsc_aw_dim_delete needs to be created here too*/
1022 procedure create_perm_tables is
1023 table_columns bsc_update_util.t_array_temp_table_cols;
1024 l_tablespace varchar2(300);
1025 l_idx_tablespace varchar2(300);
1026 all_tables all_tables_tb;
1027 table_name varchar2(40);
1028 stmt varchar2(2000);
1029 flag boolean;
1030 Begin
1031   /*use BSC api to do the creation same way as loader */
1032   table_name:='bsc_aw_dim_delete';
1033   BSC_APPS.Init_Bsc_Apps;
1034   l_tablespace:=BSC_APPS.Get_Tablespace_Name(BSC_APPS.dimension_table_tbs_type);
1035   l_idx_tablespace:=BSC_APPS.Get_Tablespace_Name(BSC_APPS.dimension_index_tbs_type);
1036   table_columns.delete;
1037   table_columns(table_columns.count+1).column_name:='DIM_LEVEL';
1038   table_columns(table_columns.count).data_type:='VARCHAR2';
1039   table_columns(table_columns.count).data_size:=300;
1040   table_columns(table_columns.count).add_to_index:='N';
1041   table_columns(table_columns.count+1).column_name:='DELETE_VALUE';
1042   table_columns(table_columns.count).data_type:='VARCHAR2';
1043   table_columns(table_columns.count).data_size:=400;
1044   table_columns(table_columns.count).add_to_index:='N';
1045   /* */
1046   flag:=false;
1047   all_tables:=get_db_table_parameters(table_name,get_table_owner(table_name));
1048   if all_tables.count>0 then
1049     if all_tables(1).TEMPORARY='Y' then
1050       /*this is old implementation. drop and recreate */
1051       log(table_name||' is Temp Table. Dropping to create as permanent');
1052       stmt:='drop table '||table_name;
1053       BSC_APPS.Do_DDL(stmt,AD_DDL.DROP_TABLE,table_name);
1054       flag:=true;
1055     end if;
1056   else
1057     flag:=true;
1058   end if;
1059   if flag then
1060     if bsc_update_util.Create_Permanent_Table(table_name,table_columns,table_columns.count,l_tablespace,l_idx_tablespace)=false then
1061       log_n('Exception in bsc_update_util.Create_Permanent_Table. For now, not raising this exception...');
1062     end if;
1063   end if;
1064 Exception when others then
1065   log_n('Exception in create_perm_tables '||sqlerrm);
1066   raise;
1067 End;
1068 
1069 /*
1070 9.204 for 9i
1071 10.104 or 10.103 etc for 10g
1072 */
1073 function get_db_version return number is
1074 l_version varchar2(200);
1075 l_compatibility varchar2(200);
1076 counter number;
1077 Begin
1078   if g_db_version is null then
1079     l_version:=get_parameter_value('DB VERSION');
1080     /*5335425. some languages have decimal representation as 10,2 instead od 10.2  */
1081     if l_version is null then
1082       dbms_utility.db_version(l_version,l_compatibility);
1083       l_version:=substr(l_version,1,instr(l_version,'.'))||replace(substr(l_version,instr(l_version,'.')+1),'.');
1084       l_version:=substr(l_version,1,instr(l_version,','))||replace(substr(l_version,instr(l_version,',')+1),',');
1085     end if;
1086     counter:=0;
1087     loop
1088       begin
1089         counter:=counter+1;
1090         if counter>=3 then
1091           log('get_db_version failed for attempts with , and .  could not derive db version info');
1092           raise g_exception;
1093         end if;
1094         g_db_version:=to_number(l_version);
1095         exit;
1096       exception when others then
1097         if sqlcode=-6502 then /*ORA-06502: PL/SQL: numeric or value error: character to number conversion error */
1098           if instr(l_version,'.')>0 then
1099             l_version:=replace(l_version,'.',',');
1100           elsif instr(l_version,',')>0 then
1101             l_version:=replace(l_version,',','.');
1102           else
1103             raise;
1104           end if;
1105         else
1106           raise;
1107         end if;
1108       end;
1109     end loop;
1110     if g_debug then
1111       log('DB Version='||g_db_version);
1112     end if;
1113   end if;
1114   return g_db_version;
1115 Exception when others then
1116   log_n('Exception in get_db_version '||sqlerrm);
1117   raise;
1118 End;
1119 
1120 /*
1121 procedure takes in a string upto 32000 characters and breaks it up to the specified length based on space " "
1122 and creates varchar2 table
1123 we need this to make the filter stmt.
1124 say start =1, limit =1000. see 1001th character. is it " " ? if yes, end=end-1. break up string
1125 if not, run backwards till we find " ". end=end-1. break up string
1126 */
1127 procedure convert_varchar2_to_table(
1128 p_string varchar2,
1129 p_limit number,
1130 p_table out nocopy dbms_sql.varchar2_table
1131 ) is
1132 --
1133 l_length number;
1134 l_start number;
1135 l_end number;
1136 l_space_found boolean;
1137 Begin
1138   if p_string is null then
1139     return;
1140   end if;
1141   l_length:=length(p_string);
1142   if l_length<=p_limit then
1143     p_table(1):=p_string;
1144     return;
1145   end if;
1146   --
1147   l_start:=1;
1148   loop
1149     l_end:=l_start+p_limit;
1150     if l_end>=l_length then
1151       l_end:=l_length;
1152       p_table(p_table.count+1):=substr(p_string,l_start,l_end-l_start+1);
1153       exit;
1154     else
1155       if substr(p_string,l_end,1) <> ' ' then
1156         --go backwards till we find ' '
1157         l_space_found:=false;
1158         for i in reverse l_start..l_end loop
1159           if substr(p_string,i,1)=' ' then
1160             l_end:=i;
1161             l_space_found:=true;
1162             exit;
1163           end if;
1164         end loop;
1165         --if we dont get a space, we cannot split the line. we have an exception
1166         if l_space_found=false then
1167           log('Could not find space to split line in convert_varchar2_to_table. Fatal...');
1168           raise no_data_found;
1169         end if;
1170         --
1171       end if;
1172       --split the line
1173       p_table(p_table.count+1):=substr(p_string,l_start,l_end-l_start);
1174       l_start:=l_end+1;
1175     end if;
1176   end loop;
1177 Exception when others then
1178   log_n('Exception in convert_varchar2_to_table '||sqlerrm);
1179   log('String='||p_string);
1180   raise;
1181 End;
1182 
1183 procedure drop_db_object_ne(p_object varchar2,p_object_type varchar2) is
1184 Begin
1185   drop_db_object(p_object,p_object_type);
1186 Exception when others then
1187   null;
1188 End;
1189 
1190 procedure drop_db_object(p_object varchar2,p_object_type varchar2) is
1191 Begin
1192   execute immediate 'drop '||p_object_type||' '||p_object;
1193 Exception when others then
1194   log_n('Exception in drop_db_object '||sqlerrm);
1195   raise;
1196 End;
1197 
1198 /*
1199 sleep_time=20 sec
1200 random_time=10 sec
1201 sleep for 20+random(1 to 10)
1202 */
1203 procedure sleep(p_sleep_time integer,p_random_time integer) is
1204 Begin
1205   dbms_lock.sleep(p_sleep_time);
1206   if p_random_time is not null and p_random_time>0 then
1207     dbms_lock.sleep(get_random_number(p_random_time));
1208   end if;
1209 Exception when others then
1210   log_n('Exception in sleep '||sqlerrm);
1211   raise;
1212 End;
1213 
1214 function get_random_number(p_seed number) return number is
1215 Begin
1216   return dbms_utility.get_hash_value(to_char(get_dbms_time),0,p_seed);
1217 Exception when others then
1218   log_n('Exception in get_random_number '||sqlerrm);
1219   raise;
1220 End;
1221 
1222 procedure remove_array_element(p_array in out nocopy dbms_sql.varchar2_table,p_object varchar2) is
1223 Begin
1224   for i in 1..p_array.count loop
1225     if p_array(i)=p_object then
1226       for j in i..p_array.count-1 loop
1227         p_array(j):=p_array(j+1);
1228       end loop;
1229       p_array.delete(p_array.count);
1230       exit;
1231     end if;
1232   end loop;
1233 Exception when others then
1234   log_n('Exception in remove_array_element '||sqlerrm);
1235   raise;
1236 End;
1237 
1238 /*
1239 handle dbms jobs for parallel loading and aggregations in 10g+
1240 we will have a global table with info on all current jobs. procedure
1241 wait on jobs will wait on jobs. jobs will communicate with the main process
1242 using dbms_pipe
1243 create job will add entries to the global table. clean job procedure will clean
1244 up the table
1245 p_process: will contain the string with the full procedure call and parameters.
1246 
1247 */
1248 procedure start_job(
1249 p_job_name varchar2,
1250 p_run_id number,
1251 p_process varchar2,
1252 p_options varchar2
1253 ) is
1254 PRAGMA AUTONOMOUS_TRANSACTION;  --we have a commit here to start dbms job
1255 --
1256 l_job_id integer;
1257 l_parallel_job parallel_job_r;
1258 Begin
1259   --should we have protection to make sure we do not launch the same job more than once? lets have it for now
1260   l_parallel_job:=get_parallel_job(p_job_name);
1261   if l_parallel_job.job_name is not null then
1262     if l_parallel_job.status <> 'success' and l_parallel_job.status <> 'error' then
1263       log_n('The same job '||p_job_name||' is currently running');
1264       raise bsc_aw_utility.g_exception;
1265     end if;
1266   end if;
1267   --create a pipe for communication
1268   create_pipe(p_job_name);
1269   if g_debug then
1270     log_n('dbms_job.submit('||p_process||')'||bsc_aw_utility.get_time);
1271   end if;
1272   dbms_job.submit(l_job_id,p_process);
1273   --add to the global array list
1274   g_parallel_jobs(g_parallel_jobs.count+1).job_name:=p_job_name;
1275   g_parallel_jobs(g_parallel_jobs.count).run_id:=p_run_id; --1,2, 3 etc
1276   g_parallel_jobs(g_parallel_jobs.count).job_id:=l_job_id;
1277   g_parallel_jobs(g_parallel_jobs.count).start_time:=get_time;
1278   g_parallel_jobs(g_parallel_jobs.count).status:='running';
1279   commit;
1280 Exception when others then
1281   log_n('Exception in start_job '||sqlerrm);
1282   raise;
1283 End;
1284 
1285 function get_parallel_job(p_job_name varchar2) return parallel_job_r is
1286 Begin
1287   for i in 1..g_parallel_jobs.count loop
1288     if g_parallel_jobs(i).job_name=p_job_name then
1289       return g_parallel_jobs(i);
1290     end if;
1291   end loop;
1292   return null;
1293 Exception when others then
1294   log_n('Exception in get_parallel_job '||sqlerrm);
1295   raise;
1296 End;
1297 
1298 procedure wait_on_jobs(p_options varchar2,p_job_status out nocopy parallel_job_tb) is
1299 Begin
1300   if g_debug then
1301     log('Wait on jobs >>'||get_time);
1302     dmp_parallel_jobs;
1303   end if;
1304   clean_up_jobs(null); --clean up done jobs
1305   if check_all_jobs_complete(g_parallel_jobs)=false then
1306     wait_on_jobs_sleep(p_options,p_job_status);
1307     /*looked at dbms_alert as a way to avoid active wait. but it looks like dbms_alert internally goes for active wait */
1308   end if;
1309   if g_debug then
1310     log_n('Wait on jobs Done >>'||get_time);
1311     dmp_parallel_jobs;
1312   end if;
1313   clean_up_jobs(null); --clean up done jobs
1314 Exception when others then
1315   log_n('Exception in wait_on_jobs '||sqlerrm);
1316   raise;
1317 End;
1318 
1319 procedure wait_on_jobs_sleep(p_options varchar2,p_job_status out nocopy parallel_job_tb) is
1320 --
1321 l_prev_time number;
1322 Begin
1323   if g_debug then
1324     log_n('wait_on_jobs_sleep');
1325   end if;
1326   loop
1327     if l_prev_time is null then
1328       l_prev_time:=g_job_wait_time_large;
1329     else
1330       l_prev_time:=g_job_wait_time_small;
1331     end if;
1332     sleep(l_prev_time,null);
1333     check_jobs(g_parallel_jobs);
1334     if check_all_jobs_complete(g_parallel_jobs) then
1335       exit;
1336     end if;
1337   end loop;
1338   p_job_status:=g_parallel_jobs;
1339 Exception when others then
1340   log_n('Exception in wait_on_jobs_sleep '||sqlerrm);
1341   raise;
1342 End;
1343 
1344 procedure check_jobs(p_parallel_jobs in out nocopy parallel_job_tb) is
1345 Begin
1346   for i in 1..p_parallel_jobs.count loop
1347     if p_parallel_jobs(i).status <> 'success' and p_parallel_jobs(i).status <> 'error' then
1348       if is_job_running(p_parallel_jobs(i).job_id)='N' then --mark this job as done
1349         update_job_status(p_parallel_jobs(i));--read from the pipe. then update the fields
1350       end if;
1351     end if;
1352   end loop;
1353 Exception when others then
1354   log_n('Exception in check_jobs '||sqlerrm);
1355   raise;
1356 End;
1357 
1358 function check_all_jobs_complete(p_parallel_jobs parallel_job_tb) return boolean is
1359 Begin
1360   for i in 1..p_parallel_jobs.count loop
1361     if p_parallel_jobs(i).status <> 'success' and p_parallel_jobs(i).status <> 'error' then
1362       return false;
1363     end if;
1364   end loop;
1365   return true;
1366 Exception when others then
1367   log_n('Exception in check_all_jobs_complete '||sqlerrm);
1368   raise;
1369 End;
1370 
1371 procedure update_job_status(p_parallel_job in out nocopy parallel_job_r) is
1372 --
1373 l_pipe_message varchar2(2000);
1374 Begin
1375   --get pipe message
1376   l_pipe_message:=get_pipe_message(p_parallel_job.job_name);
1377   if l_pipe_message is null then
1378     --the process core dumped without getting a chance to write to the pipe
1379     p_parallel_job.status:='error';
1380     p_parallel_job.sqlcode:=-20000;
1381     p_parallel_job.message:=null;
1382     p_parallel_job.end_time:=get_time;
1383   else
1384     p_parallel_job.status:=get_parameter_value(l_pipe_message,'status',',');
1385     p_parallel_job.sqlcode:=get_parameter_value(l_pipe_message,'sqlcode',','); --null for success
1386     p_parallel_job.message:=get_parameter_value(l_pipe_message,'message',','); --null for success
1387     p_parallel_job.end_time:=get_time;
1388   end if;
1389   remove_pipe(p_parallel_job.job_name);
1390 Exception when others then
1391   log_n('Exception in update_job_status '||sqlerrm);
1392   raise;
1393 End;
1394 
1395 procedure create_pipe(p_pipe_name varchar2) is
1396 l_status number;
1397 Begin
1398   remove_pipe(p_pipe_name);
1399   l_status:=dbms_pipe.create_pipe(pipename=>p_pipe_name,private=>false);
1400 Exception when others then
1401   if sqlcode=-23322 then --naming conflict
1402     if g_debug then
1403       log_n('Pipe with same name '||p_pipe_name||' exists');
1404     end if;
1405   else
1406     log_n('Exception in create_pipe '||sqlerrm);
1407     raise;
1408   end if;
1409 End;
1410 
1411 function get_pipe_message(p_pipe_name varchar2) return varchar2 is
1412 --
1413 l_status number;
1414 l_message varchar2(2000);
1415 Begin
1416   l_status:=dbms_pipe.receive_message(pipename=>p_pipe_name);
1417   if l_status=0 then
1418     dbms_pipe.unpack_message(l_message);
1419   end if;
1420   return l_message;
1421 Exception when others then
1422   log_n('Exception in get_pipe_message '||sqlerrm);
1423   raise;
1424 End;
1425 
1426 procedure send_pipe_message(p_pipe_name varchar2,p_message varchar2) is
1427 PRAGMA AUTONOMOUS_TRANSACTION;
1428 --
1429 l_status number;
1430 Begin
1431   dbms_pipe.reset_buffer;
1432   dbms_pipe.pack_message(p_message);
1433   l_status:=dbms_pipe.send_message(pipename=>p_pipe_name);
1434   commit;
1435 Exception when others then
1436   log_n('Exception in send_pipe_message '||sqlerrm);
1437   raise;
1438 End;
1439 
1440 procedure remove_pipe(p_pipe_name varchar2) is
1441 --
1442 l_status number;
1443 Begin
1444   l_status:=dbms_pipe.remove_pipe(pipename=>p_pipe_name);
1445 Exception when others then
1446   log_n('Exception in remove_pipe '||sqlerrm);
1447 End;
1448 
1449 /*
1450 we look at all_jobs and dba_jobs_running because when a job is launched, it takes some time
1451 for it to start.
1452 */
1453 function is_job_running(p_job_id number) return varchar2 is
1454 --
1455 cursor c1 is select 1 from all_jobs where job=p_job_id;
1456 l_status number;
1457 Begin
1458   open c1;
1459   fetch c1 into l_status;
1460   close c1;
1461   if l_status=1 then
1462     return 'Y';
1463   else
1464     return 'N';
1465   end if;
1466 Exception when others then
1467   log_n('Exception in is_job_running '||sqlerrm);
1468   raise;
1469 End;
1470 
1471 --for now, clean up all the jobs
1472 procedure clean_up_jobs(p_options varchar2) is
1473 l_parallel_jobs parallel_job_tb;
1474 Begin
1475   if get_parameter_value(p_options,'all',',')='Y' then
1476     g_parallel_jobs.delete;
1477   else
1478     --clean up success and error
1479     for i in 1..g_parallel_jobs.count loop
1480       if g_parallel_jobs(i).status <> 'success' and g_parallel_jobs(i).status <> 'error' then
1481         l_parallel_jobs(l_parallel_jobs.count+1):=g_parallel_jobs(i);
1482       end if;
1483     end loop;
1484     g_parallel_jobs.delete;
1485     g_parallel_jobs:=l_parallel_jobs;
1486   end if;
1487 Exception when others then
1488   log_n('Exception in clean_up_jobs '||sqlerrm);
1489   raise;
1490 End;
1491 
1492 procedure dmp_parallel_jobs is
1493 Begin
1494   log_n('dmp parallel jobs >>');
1495   for i in 1..g_parallel_jobs.count loop
1496     log('job name='||g_parallel_jobs(i).job_name||',run id='||g_parallel_jobs(i).run_id||
1497     ',job id='||g_parallel_jobs(i).job_id||',status='||g_parallel_jobs(i).status||',sqlcode='||g_parallel_jobs(i).sqlcode||
1498     ',message='||g_parallel_jobs(i).message||'(S:'||g_parallel_jobs(i).start_time||' -> E:'||g_parallel_jobs(i).end_time||')');
1499   end loop;
1500   log_n('-------------');
1501 Exception when others then
1502   log_n('Exception in dmp_parallel_jobs '||sqlerrm);
1503   raise;
1504 End;
1505 
1506 /*
1507 to launch jobs, we need to make sure that
1508 (job_queue_processes-count_jobs_running) > p_number_jobs
1509 */
1510 function can_launch_jobs(p_number_jobs number) return varchar2 is
1511 Begin
1512   /*we will enable parallel by default */
1513   if get_db_version>=10 and nvl(get_parameter_value('exclusive lock'),'N')='N'
1514   and nvl(get_parameter_value('NO PARALLEL'),'N')='N' then
1515     if p_number_jobs<=1 then
1516       return 'N';
1517     end if;
1518     return can_launch_dbms_job(p_number_jobs);
1519   end if;
1520   return 'N'; --if 9i, no jobs possible
1521 Exception when others then
1522   log_n('Exception in can_launch_jobs '||sqlerrm);
1523   raise;
1524 End;
1525 
1526 function can_launch_dbms_job(p_number_jobs number) return varchar2 is
1527 l_job_queue_processes number;
1528 l_jobs_running number;
1529 l_status varchar2(20);
1530 Begin
1531   l_status:='Y';
1532   l_job_queue_processes:=to_number(get_vparameter('job_queue_processes'));
1533   l_jobs_running:=count_jobs_running;
1534   if g_debug then
1535     log_n('can_launch_jobs,l_job_queue_processes='||l_job_queue_processes||',l_jobs_running='||l_jobs_running||', p_number_jobs='||p_number_jobs);
1536   end if;
1537   if l_status='Y' then
1538     if l_job_queue_processes is null then
1539       l_status:='N';
1540     elsif (l_job_queue_processes-l_jobs_running)<=p_number_jobs then
1541       l_status:='N';
1542     end if;
1543   end if;
1544   if l_status='Y' then
1545     /*p_number_jobs is more than 2 times the cpu count, we disable jobs */
1546     if p_number_jobs>(2*get_cpu_count) then
1547       l_status:='N';
1548     end if;
1549   end if;
1550   return l_status;
1551 Exception when others then
1552   log_n('Exception in can_launch_dbms_job '||sqlerrm);
1553   raise;
1554 End;
1555 
1556 function count_jobs_running return number is
1557 --
1558 TYPE CurTyp IS REF CURSOR;
1559 cv   CurTyp;
1560 l_count number;
1561 Begin
1562   open cv for 'select count(*) from all_scheduler_running_jobs';
1563   fetch cv into l_count;
1564   close cv;
1565   return l_count;
1566 Exception when others then
1567   if g_debug then
1568     log_n('Exception in count_jobs_running '||sqlerrm);
1569   end if;
1570   return 0;
1571 End;
1572 
1573 function get_vparameter(p_name varchar2) return varchar2 is
1574 --
1575 cursor c1 is select value from v$parameter param where name=p_name;
1576 l_value varchar2(200);
1577 Begin
1578   open c1;
1579   fetch c1 into l_value;
1580   return l_value;
1581 Exception when others then
1582   log_n('Exception in get_vparameter '||sqlerrm);
1583   raise;
1584 End;
1585 
1586 --makes a string out of the options. for dbms jobs
1587 function get_option_string return varchar2 is
1588 l_string varchar2(4000);
1589 Begin
1590   for i in 1..g_options.count loop
1591     l_string:=l_string||g_options(i).parameter;
1592     if g_options(i).value is not null then
1593       l_string:=l_string||'='||g_options(i).value;
1594     end if;
1595     l_string:=l_string||',';
1596   end loop;
1597   return l_string;
1598 Exception when others then
1599   log_n('Exception in get_option_string '||sqlerrm);
1600   raise;
1601 End;
1602 
1603 function get_session_id return number is
1604 l_sid number;
1605 Begin
1606   select mystat.sid into l_sid from v$mystat mystat where rownum=1;
1607   return l_sid;
1608 Exception when others then
1609   return userenv('SESSIONID');
1610 End;
1611 
1612 --used primarily as job_name in 10g multi threading to get a unique name
1613 function get_dbms_time return number is
1614 Begin
1615   return dbms_utility.get_time;
1616 Exception when others then
1617   log_n('Exception in get_dbms_time '||sqlerrm);
1618   raise;
1619 End;
1620 
1621 function make_string_from_list(p_list dbms_sql.varchar2_table) return varchar2 is
1622 Begin
1623   return make_string_from_list(p_list,',');
1624 Exception when others then
1625   log_n('Exception in make_string_from_list '||sqlerrm);
1626   raise;
1627 End;
1628 
1629 function make_string_from_list(p_list dbms_sql.varchar2_table,p_separator varchar2) return varchar2 is
1630 --
1631 l_string varchar2(20000);
1632 Begin
1633   l_string:=null;
1634   if p_list.count>0 then
1635     for i in 1..p_list.count loop
1636       l_string:=l_string||p_list(i)||p_separator;
1637     end loop;
1638     l_string:=substr(l_string,1,length(l_string)-1);
1639   end if;
1640   return l_string;
1641 Exception when others then
1642   log_n('Exception in make_string_from_list '||sqlerrm);
1643   raise;
1644 End;
1645 
1646 /*
1647 see if the options are part of g_options. if not, add them
1648 if p_option_value is null, add all in p_options. else add p_option_value in p_options
1649 this will also update the option value if already in g_options
1650 */
1651 procedure add_option(p_options varchar2,p_option_value varchar2,p_separator varchar2) is
1652 l_values value_tb;
1653 l_found boolean;
1654 Begin
1655   parse_parameter_values(p_options,p_separator,l_values);
1656   for i in 1..l_values.count loop
1657     if p_option_value is null or l_values(i).parameter=p_option_value then
1658       l_found:=false;
1659       for j in 1..g_options.count loop
1660         if g_options(j).parameter=l_values(i).parameter then
1661           l_found:=true;
1662           g_options(j):=l_values(i);
1663           exit;
1664         end if;
1665       end loop;
1666       if l_found=false then
1667         g_options(g_options.count+1):=l_values(i);
1668       end if;
1669     end if;
1670   end loop;
1671 Exception when others then
1672   log_n('Exception in add_option '||sqlerrm);
1673   raise;
1674 End;
1675 
1676 procedure set_option(p_parameter varchar2,p_value varchar2) is
1677 Begin
1678   for i in 1..g_options.count loop
1679     if g_options(i).parameter=p_parameter then
1680       g_options(i).value:=p_value;
1681       return;
1682     end if;
1683   end loop;
1684   g_options(g_options.count+1).parameter:=p_parameter;
1685   g_options(g_options.count).value:=p_value;
1686 Exception when others then
1687   log_n('Exception in set_option '||sqlerrm);
1688   raise;
1689 End;
1690 
1691 function get_hash_value(p_string varchar2,p_start number,p_end number) return varchar2 is
1692 l_hash_value number;
1693 Begin
1694   l_hash_value:=dbms_utility.get_hash_value(p_string,p_start,p_end);
1695   return to_char(l_hash_value);
1696 Exception when others then
1697   log_n('Exception in get_hash_value '||sqlerrm);
1698   raise;
1699 End;
1700 
1701 procedure merge_array(p_array in out nocopy dbms_sql.varchar2_table,p_values dbms_sql.varchar2_table) is
1702 Begin
1703   for i in 1..p_values.count loop
1704     if in_array(p_array,p_values(i))=false then
1705       p_array(p_array.count+1):=p_values(i);
1706     end if;
1707   end loop;
1708 Exception when others then
1709   log_n('Exception in merge_array '||sqlerrm);
1710   raise;
1711 End;
1712 
1713 procedure merge_value(p_array in out nocopy dbms_sql.varchar2_table,p_value varchar2) is
1714 Begin
1715   if p_value is not null then
1716     if in_array(p_array,p_value)=false then
1717       p_array(p_array.count+1):=p_value;
1718     end if;
1719   end if;
1720 Exception when others then
1721   log_n('Exception in merge_value '||sqlerrm);
1722   raise;
1723 End;
1724 
1725 procedure subtract_array(p_array in out nocopy dbms_sql.varchar2_table,p_values dbms_sql.varchar2_table) is
1726 l_array dbms_sql.varchar2_table;
1727 Begin
1728   if p_values.count>0 and p_array.count>0 then
1729     for i in 1..p_array.count loop
1730       l_array(i):=p_array(i);
1731     end loop;
1732     p_array.delete;
1733     for i in 1..l_array.count loop
1734       if in_array(p_values,l_array(i))=false then
1735         p_array(p_array.count+1):=l_array(i);
1736       end if;
1737     end loop;
1738   end if;
1739 Exception when others then
1740   log_n('Exception in subtract_array '||sqlerrm);
1741   raise;
1742 End;
1743 
1744 procedure merge_array(p_array in out nocopy dbms_sql.number_table,p_values dbms_sql.number_table) is
1745 Begin
1746   for i in 1..p_values.count loop
1747     if in_array(p_array,p_values(i))=false then
1748       p_array(p_array.count+1):=p_values(i);
1749     end if;
1750   end loop;
1751 Exception when others then
1752   log_n('Exception in merge_array '||sqlerrm);
1753   raise;
1754 End;
1755 
1756 procedure merge_value(p_array in out nocopy dbms_sql.number_table,p_value number) is
1757 Begin
1758   if p_value is not null then
1759     if in_array(p_array,p_value)=false then
1760       p_array(p_array.count+1):=p_value;
1761     end if;
1762   end if;
1763 Exception when others then
1764   log_n('Exception in merge_value '||sqlerrm);
1765   raise;
1766 End;
1767 
1768 procedure set_aw_trace is
1769 Begin
1770   if g_trace_set is null or g_trace_set=false then
1771     execute immediate 'alter session set sql_trace=true';
1772     execute immediate 'alter session set events=''10046 trace name context forever, level 12''';
1773     execute immediate 'alter session set events=''37395 trace name context forever, level 1''';
1774     bsc_aw_dbms_aw.execute('dotf tracefile');
1775     g_trace_set:=true;
1776   end if;
1777 Exception when others then
1778   log_n('Exception in set_aw_trace '||sqlerrm);
1779   raise;
1780 End;
1781 
1782 procedure dmp_values(p_table dbms_sql.varchar2_table,p_text varchar2) is
1783 Begin
1784   log('------');
1785   log(p_text);
1786   for i in 1..p_table.count loop
1787     log(p_table(i));
1788   end loop;
1789 Exception when others then
1790   log_n('Exception in dmp_values '||sqlerrm);
1791   raise;
1792 End;
1793 
1794 function get_sqlerror(p_sqlcode number,p_action varchar2) return sqlerror_r is
1795 Begin
1796   for i in 1..g_sqlerror.count loop
1797     if g_sqlerror(i).sql_code=p_sqlcode and g_sqlerror(i).action=p_action then
1798       return g_sqlerror(i);
1799     end if;
1800   end loop;
1801   return null;
1802 Exception when others then
1803   log_n('Exception in get_sqlerror '||sqlerrm);
1804   raise;
1805 End;
1806 
1807 procedure add_sqlerror(p_sqlcode number,p_action varchar2,p_message varchar2) is
1808 l_sqlerror sqlerror_r;
1809 Begin
1810   l_sqlerror:=get_sqlerror(p_sqlcode,p_action);
1811   if l_sqlerror.sql_code is null then
1812     g_sqlerror(g_sqlerror.count+1).sql_code:=p_sqlcode;
1813     g_sqlerror(g_sqlerror.count).action:=p_action;
1814     g_sqlerror(g_sqlerror.count).message:=p_message;
1815   end if;
1816 Exception when others then
1817   log_n('Exception in add_sqlerror '||sqlerrm);
1818   raise;
1819 End;
1820 
1821 procedure remove_sqlerror(p_sqlcode number,p_action varchar2) is
1822 l_sqlerror sqlerror_tb;
1823 Begin
1824   l_sqlerror:=g_sqlerror;
1825   g_sqlerror.delete;
1826   for i in 1..l_sqlerror.count loop
1827     if not(l_sqlerror(i).sql_code=p_sqlcode and l_sqlerror(i).action=p_action) then
1828       g_sqlerror(g_sqlerror.count+1):=l_sqlerror(i);
1829     end if;
1830   end loop;
1831 Exception when others then
1832   log_n('Exception in remove_sqlerror '||sqlerrm);
1833   raise;
1834 End;
1835 
1836 procedure remove_all_sqlerror is --remove all sqlerror
1837 Begin
1838   g_sqlerror.delete;
1839 Exception when others then
1840   log_n('Exception in remove_all_sqlerror '||sqlerrm);
1841   raise;
1842 End;
1843 
1844 function is_sqlerror(p_sqlcode number,p_action varchar2) return boolean is
1845 l_sqlerror sqlerror_r;
1846 Begin
1847   l_sqlerror:=get_sqlerror(p_sqlcode,p_action);
1848   if l_sqlerror.sql_code is null then
1849     return false;
1850   else
1851     return true;
1852   end if;
1853 Exception when others then
1854   log_n('Exception in is_sqlerror '||sqlerrm);
1855   raise;
1856 End;
1857 
1858 /*
1859 -1 : 2 rel diff
1860 0 : 2 rel same
1861 1 : 1 is in 2
1862 2: 2 is in 1
1863 */
1864 function compare_pc_relations(p_pc_1 parent_child_tb,p_pc_2 parent_child_tb) return number is
1865 --
1866 TYPE CurTyp IS REF CURSOR;
1867 cv   CurTyp;
1868 l_1_minus_2 number;
1869 l_2_minus_1 number;
1870 l_temp1 varchar2(200);
1871 l_temp2 varchar2(200);
1872 l_return_code number;
1873 Begin
1874   bsc_aw_utility.delete_table('bsc_aw_temp_pc',null);
1875   for i in 1..p_pc_1.count loop
1876     if p_pc_1(i).parent is not null and p_pc_1(i).child is not null then
1877       execute immediate 'insert into bsc_aw_temp_pc(parent,child,id) values (:1,:2,:3)' using nvl(p_pc_1(i).parent,'null'),
1878       nvl(p_pc_1(i).child,'null'),1;
1879     end if;
1880   end loop;
1881   for i in 1..p_pc_2.count loop
1882     if p_pc_2(i).parent is not null and p_pc_2(i).child is not null then
1883       execute immediate 'insert into bsc_aw_temp_pc(parent,child,id) values (:1,:2,:3)' using nvl(p_pc_2(i).parent,'null'),
1884       nvl(p_pc_2(i).child,'null'),2;
1885     end if;
1886   end loop;
1887   l_1_minus_2:=0;
1888   l_2_minus_1:=0;
1889   --
1890   l_temp1:=null;
1891   l_temp2:=null;
1892   open cv for 'select parent,child from bsc_aw_temp_pc where id=1 minus select parent,child from bsc_aw_temp_pc where id=2';
1893   fetch cv into l_temp1,l_temp2;
1894   close cv;
1895   if l_temp1 is not null then
1896     l_1_minus_2:=1;
1897   end if;
1898   if g_debug then
1899     log('1 minus 2 '||l_temp1||' '||l_temp2);
1900   end if;
1901   --
1902   l_temp1:=null;
1903   l_temp2:=null;
1904   open cv for 'select parent,child from bsc_aw_temp_pc where id=2 minus select parent,child from bsc_aw_temp_pc where id=1';
1905   fetch cv into l_temp1,l_temp2;
1906   close cv;
1907   if l_temp1 is not null then
1908     l_2_minus_1:=1;
1909   end if;
1910   if g_debug then
1911     log('2 minus 1 '||l_temp1||' '||l_temp2);
1912   end if;
1913   --
1914   if l_1_minus_2=0 and l_2_minus_1=0 then --same
1915     l_return_code:=0;
1916   elsif l_1_minus_2=0 and l_2_minus_1>0 then --1 is in 2
1917     l_return_code:=1;
1918   elsif l_1_minus_2>0 and l_2_minus_1=0 then --2 is in 1
1919     l_return_code:=2;
1920   elsif l_1_minus_2>0 and l_2_minus_1>0 then --not same
1921     l_return_code:=-1;
1922   end if;
1923   if g_debug then
1924     log('compare_pc_relations, Return code='||l_return_code);
1925   end if;
1926   return l_return_code;
1927 Exception when others then
1928   log_n('Exception in compare_pc_relations '||sqlerrm);
1929   raise;
1930 End;
1931 
1932 procedure init_is_new_value is
1933 Begin
1934   g_values.delete;
1935 Exception when others then
1936   log_n('Exception in init_is_new_value '||sqlerrm);
1937   raise;
1938 End;
1939 
1940 procedure init_is_new_value(p_index number) is
1941 Begin
1942   g_values(p_index).id:=p_index;
1943   g_values(p_index).new_values.delete;
1944 Exception when others then
1945   log_n('Exception in init_is_new_value '||sqlerrm);
1946   raise;
1947 End;
1948 
1949 --goes hand in hand with init_is_new_value
1950 function is_new_value(p_value varchar2,p_index number) return boolean is
1951 l_flag boolean;
1952 Begin
1953   l_flag:=in_array(g_values(p_index).new_values,p_value);
1954   if l_flag=false then
1955     g_values(p_index).new_values(g_values(p_index).new_values.count+1):=p_value;
1956   end if;
1957   return not(l_flag);
1958 Exception when others then
1959   log_n('Exception in is_new_value '||sqlerrm);
1960   raise;
1961 End;
1962 
1963 --goes hand in hand with init_is_new_value
1964 function is_new_value(p_value number,p_index number) return boolean is
1965 Begin
1966   return is_new_value(to_char(p_value),p_index);
1967 Exception when others then
1968   log_n('Exception in is_new_value '||sqlerrm);
1969   raise;
1970 End;
1971 
1972 function order_array(p_array dbms_sql.varchar2_table) return dbms_sql.varchar2_table is
1973 l_array dbms_sql.varchar2_table;
1974 TYPE CurTyp IS REF CURSOR;
1975 cv   CurTyp;
1976 Begin
1977   if p_array.count>0 then
1978     delete_table('bsc_aw_temp_vn',null);
1979     forall i in 1..p_array.count
1980       execute immediate 'insert into bsc_aw_temp_vn(name) values (:1)' using p_array(i);
1981     open cv for 'select name from bsc_aw_temp_vn order by name';
1982     loop
1983       fetch cv into l_array(l_array.count+1);
1984       exit when cv%notfound;
1985     end loop;
1986   end if;
1987   return l_array;
1988 Exception when others then
1989   log_n('Exception in order_array '||sqlerrm);
1990   raise;
1991 End;
1992 
1993 function make_upper(p_array dbms_sql.varchar2_table) return dbms_sql.varchar2_table is
1994 l_array dbms_sql.varchar2_table;
1995 Begin
1996   for i in 1..p_array.count loop
1997     l_array(i):=upper(p_array(i));
1998   end loop;
1999   return l_array;
2000 Exception when others then
2001   log_n('Exception in make_upper '||sqlerrm);
2002   raise;
2003 End;
2004 
2005 /*
2006 getting db locks. used for co-ordinating multiple MO sessions
2007 for now, we do not implement this. in lock management, we already do spin wait. so 2 sessions cane be started, the 2nd will spin
2008 and try to get the lock
2009 */
2010 procedure get_db_lock(p_lock_name varchar2) is
2011 l_lock_handle varchar2(200);
2012 l_flag integer;
2013 Begin
2014   l_lock_handle:=get_lock_handle(p_lock_name);
2015   l_flag:=dbms_lock.request(lockhandle=>l_lock_handle,timeout=>bsc_aw_utility.g_max_wait_time);
2016   if l_flag=1 then --timeout
2017     log('Timeout in dbms_lock.request('||p_lock_name||') ...');
2018     raise bsc_aw_utility.g_exception;
2019   end if;
2020 Exception when others then
2021   log_n('Exception in get_db_lock '||sqlerrm);
2022   raise;
2023 End;
2024 
2025 procedure release_db_lock(p_lock_name varchar2) is
2026 l_lock_handle varchar2(2000);
2027 l_flag integer;
2028 Begin
2029   l_lock_handle:=get_lock_handle(p_lock_name);
2030   l_flag:=dbms_lock.release(lockhandle=>l_lock_handle);
2031   if l_flag=3 or l_flag=5 then --error
2032     log('Exception in dbms_lock.release. Return flag='||l_flag);
2033     raise bsc_aw_utility.g_exception;
2034   end if;
2035 Exception when others then
2036   log_n('Exception in release_db_lock '||sqlerrm);
2037   raise;
2038 End;
2039 
2040 function get_lock_handle(p_lock_name varchar2) return varchar2 is
2041 l_lock_handle varchar2(2000);
2042 Begin
2043   dbms_lock.allocate_unique(lockname=>p_lock_name,lockhandle=>l_lock_handle);
2044   return l_lock_handle;
2045 Exception when others then
2046   log_n('Exception in get_lock_handle '||sqlerrm);
2047   raise;
2048 End;
2049 
2050 function get_closest_2_power_number(p_number number) return number is
2051 l_num number;
2052 Begin
2053   l_num:=1;
2054   if p_number is null or p_number<2 then
2055     return 0;
2056   end if;
2057   loop
2058     l_num:=l_num*2;
2059     if l_num>p_number then
2060       return l_num/2;
2061     end if;
2062   end loop;
2063 Exception when others then
2064   log_n('Exception in get_closest_2_power '||sqlerrm);
2065   raise;
2066 End;
2067 
2068 procedure analyze_table(p_table varchar2,p_interval number) is
2069 l_table varchar2(100);
2070 l_owner varchar2(100);
2071 l_all_tables all_tables_tb;
2072 l_analyze boolean;
2073 Begin
2074   l_table:=substr(p_table,instr(p_table,'.')+1);
2075   l_owner:=get_table_owner(p_table);
2076   l_analyze:=false;
2077   if p_interval is null or p_interval=0 then
2078     l_analyze:=true;
2079   else
2080     l_all_tables:=get_db_table_parameters(l_table,l_owner);
2081     if l_all_tables(1).last_analyzed is null then
2082       l_analyze:=true;
2083     else
2084       if (sysdate-l_all_tables(1).last_analyzed)>p_interval then
2085         l_analyze:=true;
2086       end if;
2087     end if;
2088   end if;
2089   if l_analyze then
2090     analyze_table(l_table,l_owner);
2091   end if;
2092 Exception when others then
2093   log_n('Exception in analyze_table '||sqlerrm);
2094   raise;
2095 End;
2096 
2097 procedure analyze_table(p_table varchar2,p_owner varchar2) is
2098 Begin
2099   if g_debug then
2100     log('Analyze '||p_owner||'.'||p_table||get_time);
2101   end if;
2102   dbms_stats.gather_table_stats(OWNNAME=>p_owner,TABNAME=>p_table);
2103   if g_debug then
2104     log('Done '||get_time);
2105   end if;
2106 Exception when others then
2107   log_n('Exception in analyze_table '||sqlerrm);
2108   raise;
2109 End;
2110 
2111 function get_db_table_parameters(p_table varchar2,p_owner varchar2) return all_tables_tb is
2112 l_tables all_tables_tb;
2113 cursor c1 is select * from all_tables where table_name=upper(p_table) and owner=upper(p_owner);
2114 Begin
2115   open c1;
2116   fetch c1 into l_tables(1);
2117   close c1;
2118   return l_tables;
2119 Exception when others then
2120   log_n('Exception in get_db_table_parameters '||sqlerrm);
2121   raise;
2122 End;
2123 
2124 /*given a relation and a start value, get the trim hier with all upper values*/
2125 procedure get_upper_trim_hier(p_parent_child parent_child_tb,p_seed varchar2,p_trim_parent_child in out nocopy parent_child_tb) is
2126 l_parents parent_child_tb;
2127 flag boolean;
2128 Begin
2129   get_parent_values(p_parent_child,p_seed,l_parents);
2130   for i in 1..l_parents.count loop
2131     get_upper_trim_hier(p_parent_child,l_parents(i).parent,p_trim_parent_child);
2132   end loop;
2133   if l_parents.count>0 then
2134     for i in 1..l_parents.count loop
2135       flag:=false;
2136       for j in 1..p_trim_parent_child.count loop --add only distinct list
2137         if p_trim_parent_child(j).parent=l_parents(i).parent and p_trim_parent_child(j).child=l_parents(i).child then
2138           flag:=true;
2139           exit;
2140         end if;
2141       end loop;
2142       if flag=false then
2143         p_trim_parent_child(p_trim_parent_child.count+1):=l_parents(i);
2144       end if;
2145     end loop;
2146   end if;
2147 Exception when others then
2148   log_n('Exception in get_upper_trim_hier '||sqlerrm);
2149   raise;
2150 End;
2151 
2152 /*given a relation and a start value, get the trim hier with all lower values*/
2153 procedure get_lower_trim_hier(p_parent_child parent_child_tb,p_seed varchar2,p_trim_parent_child in out nocopy parent_child_tb) is
2154 l_children parent_child_tb;
2155 flag boolean;
2156 Begin
2157   get_child_values(p_parent_child,p_seed,l_children);
2158   for i in 1..l_children.count loop
2159     get_lower_trim_hier(p_parent_child,l_children(i).child,p_trim_parent_child);
2160   end loop;
2161   if l_children.count>0 then
2162     for i in 1..l_children.count loop
2163       flag:=false;
2164       for j in 1..p_trim_parent_child.count loop --add only distinct list
2165         if p_trim_parent_child(j).parent=l_children(i).parent and p_trim_parent_child(j).child=l_children(i).child then
2166           flag:=true;
2167           exit;
2168         end if;
2169       end loop;
2170       if flag=false then
2171         p_trim_parent_child(p_trim_parent_child.count+1):=l_children(i);
2172       end if;
2173     end loop;
2174   end if;
2175 Exception when others then
2176   log_n('Exception in get_lower_trim_hier '||sqlerrm);
2177   raise;
2178 End;
2179 
2180 procedure get_parent_values(p_parent_child parent_child_tb,p_child varchar2,p_parents out nocopy parent_child_tb) is
2181 Begin
2182   for i in 1..p_parent_child.count loop
2183     if p_parent_child(i).child=p_child and p_parent_child(i).parent is not null then
2184       p_parents(p_parents.count+1):=p_parent_child(i);
2185     end if;
2186   end loop;
2187 Exception when others then
2188   log_n('Exception in get_parent_values '||sqlerrm);
2189   raise;
2190 End;
2191 
2192 procedure get_child_values(p_parent_child parent_child_tb,p_parent varchar2,p_children out nocopy parent_child_tb) is
2193 Begin
2194   for i in 1..p_parent_child.count loop
2195     if p_parent_child(i).parent=p_parent and p_parent_child(i).child is not null then
2196       p_children(p_children.count+1):=p_parent_child(i);
2197     end if;
2198   end loop;
2199 Exception when others then
2200   log_n('Exception in get_child_values '||sqlerrm);
2201   raise;
2202 End;
2203 
2204 procedure get_all_parents(p_parent_child parent_child_tb,p_child varchar2,p_parents in out nocopy dbms_sql.varchar2_table) is
2205 l_parents parent_child_tb;
2206 Begin
2207   get_parent_values(p_parent_child,p_child,l_parents);
2208   for i in 1..l_parents.count loop
2209     get_all_parents(p_parent_child,l_parents(i).parent,p_parents);
2210   end loop;
2211   if l_parents.count>0 then
2212     for i in 1..l_parents.count loop
2213       if l_parents(i).parent is not null then
2214         merge_value(p_parents,l_parents(i).parent);
2215       end if;
2216     end loop;
2217   end if;
2218 Exception when others then
2219   log_n('Exception in get_all_parents '||sqlerrm);
2220   raise;
2221 End;
2222 
2223 procedure get_all_children(p_parent_child parent_child_tb,p_parent varchar2,p_children in out nocopy dbms_sql.varchar2_table) is
2224 l_children parent_child_tb;
2225 Begin
2226   get_child_values(p_parent_child,p_parent,l_children);
2227   for i in 1..l_children.count loop
2228     get_all_children(p_parent_child,l_children(i).child,p_children);
2229   end loop;
2230   if l_children.count>0 then
2231     for i in 1..l_children.count loop
2232       if l_children(i).child is not null then
2233         merge_value(p_children,l_children(i).child);
2234       end if;
2235     end loop;
2236   end if;
2237 Exception when others then
2238   log_n('Exception in get_all_children '||sqlerrm);
2239   raise;
2240 End;
2241 
2242 /*we have a string like property1=value1,property2,property3=value3
2243 we pass new property and or new value like property2 value value2 or property 3 value 33 or property4 with value 4
2244 we update p_string with the values*/
2245 procedure update_property(p_string in out nocopy varchar2,p_parameter varchar2,p_value varchar2,p_separator varchar2) is
2246 l_values dbms_sql.varchar2_table;
2247 l_index number;
2248 Begin
2249   parse_parameter_values(p_string,p_separator,l_values);
2250   for i in 1..l_values.count loop
2251     if l_values(i)=p_parameter or instr(l_values(i),p_parameter||'=')>0 then
2252       l_index:=i;
2253       exit;
2254     end if;
2255   end loop;
2256   if l_index is null then
2257     l_index:=l_values.count+1;
2258   end if;
2259   if p_value is null then
2260     l_values(l_index):=p_parameter;
2261   else
2262     l_values(l_index):=p_parameter||'='||p_value;
2263   end if;
2264   p_string:=make_string_from_list(l_values,p_separator);  /* trailing separator*/
2265 Exception when others then
2266   log_n('Exception in update_property '||sqlerrm);
2267   raise;
2268 End;
2269 
2270 /* p_property_string contains prop1=value1,prop2=value2 etc*/
2271 procedure merge_property(p_property in out nocopy property_tb,p_property_string varchar2,p_separator varchar2) is
2272 l_values value_tb;
2273 Begin
2274   if p_property_string is null then
2275     return;
2276   end if;
2277   parse_parameter_values(p_property_string,p_separator,l_values);
2278   for i in 1..l_values.count loop
2279     merge_property(p_property,l_values(i).parameter,null,l_values(i).value);
2280   end loop;
2281 Exception when others then
2282   log_n('Exception in merge_property '||sqlerrm);
2283   raise;
2284 End;
2285 
2286 /*add/update property */
2287 procedure merge_property(p_property in out nocopy property_tb,p_property_name varchar2,p_property_type varchar2,p_property_value varchar2) is
2288 Begin
2289   for i in 1..p_property.count loop
2290     if p_property(i).property_name=p_property_name then
2291       p_property(i).property_type:=p_property_type;
2292       p_property(i).property_value:=p_property_value;
2293       exit;
2294     end if;
2295   end loop;
2296   p_property(p_property.count+1).property_name:=p_property_name;
2297   p_property(p_property.count).property_type:=p_property_type;
2298   p_property(p_property.count).property_value:=p_property_value;
2299 Exception when others then
2300   log_n('Exception in merge_property '||sqlerrm);
2301   raise;
2302 End;
2303 
2304 procedure remove_property(p_property in out nocopy property_tb,p_property_name varchar2) is
2305 l_property property_tb;
2306 Begin
2307   for i in 1..p_property.count loop
2308     if p_property(i).property_name<>p_property_name then
2309       l_property(l_property.count+1):=p_property(i);
2310     end if;
2311   end loop;
2312   p_property:=l_property;
2313 Exception when others then
2314   log_n('Exception in remove_property '||sqlerrm);
2315   raise;
2316 End;
2317 
2318 function get_property(p_property property_tb,p_property_name varchar2) return property_r is
2319 l_property property_r;
2320 Begin
2321   for i in 1..p_property.count loop
2322     if p_property(i).property_name=p_property_name then
2323       l_property:=p_property(i);
2324       exit;
2325     end if;
2326   end loop;
2327   return l_property;
2328 Exception when others then
2329   log_n('Exception in get_property '||sqlerrm);
2330   raise;
2331 End;
2332 
2333 function get_property_string(p_property property_tb) return varchar2 is
2334 l_string varchar2(8000);
2335 Begin
2336   for i in 1..p_property.count loop
2337     if p_property(i).property_value is null then
2338       l_string:=l_string||p_property(i).property_name||',';
2339     else
2340       l_string:=l_string||p_property(i).property_name||'='||p_property(i).property_value||',';
2341     end if;
2342   end loop;
2343   if l_string is not null then
2344     l_string:=substr(l_string,1,length(l_string)-1);
2345   end if;
2346   return l_string;
2347 Exception when others then
2348   log_n('Exception in get_property_string '||sqlerrm);
2349   raise;
2350 End;
2351 
2352 function get_cpu_count return number is
2353 Begin
2354   return to_number(get_vparameter('cpu_count'));
2355 Exception when others then
2356   log_n('Exception in get_cpu_count '||sqlerrm);
2357   raise;
2358 End;
2359 
2360 /*example load_stats('before load'); */
2361 procedure load_stats(p_name varchar2,p_group varchar2) is
2362 ig pls_integer;
2363 Begin
2364   for i in 1..g_ssg.count loop
2365     if g_ssg(i).group_name=p_group then
2366       ig:=i;
2367       exit;
2368     end if;
2369   end loop;
2370   if ig is null then
2371     ig:=g_ssg.count+1;
2372   end if;
2373   --
2374   g_ssg(ig).group_name:=p_group;
2375   g_ssg(ig).session_stats(g_ssg(ig).session_stats.count+1).stats_name:=p_name;
2376   g_ssg(ig).session_stats(g_ssg(ig).session_stats.count).stats_time:=sysdate;
2377   load_session_stats(g_ssg(ig).session_stats(g_ssg(ig).session_stats.count).stats);
2378   load_session_waits(g_ssg(ig).session_stats(g_ssg(ig).session_stats.count).wait_events);
2379 Exception when others then
2380   log_n('Exception in load_stats '||sqlerrm);
2381   raise;
2382 End;
2383 
2384 procedure load_session_stats(p_stats out nocopy stats_tb) is
2385 cursor c1 is select statname.name, mystat.value from v$mystat mystat,v$statname statname where mystat.statistic#=statname.statistic#
2386 order by statname.name;
2387 Begin
2388   for r1 in c1 loop
2389     p_stats(p_stats.count+1).stats_name:=r1.name;
2390     p_stats(p_stats.count).value:=r1.value;
2391   end loop;
2392 Exception when others then
2393   log_n('Exception in load_session_stats '||sqlerrm);
2394   raise;
2395 End;
2396 
2397 procedure load_session_waits(p_wait_events out nocopy wait_event_tb) is
2398 cursor c1 is select event.event,event.total_waits,event.total_timeouts,round(event.time_waited) time_waited,
2399 round(event.average_wait) average_wait,round(event.max_wait) max_wait
2400 from v$session_event event where event.sid=get_session_id order by event.event;
2401 Begin
2402   for r1 in c1 loop
2403     p_wait_events(p_wait_events.count+1).event_name:=r1.event;
2404     p_wait_events(p_wait_events.count).total_waits:=r1.total_waits;
2405     p_wait_events(p_wait_events.count).total_timeouts:=r1.total_timeouts;
2406     p_wait_events(p_wait_events.count).time_waited:=r1.time_waited;
2407     p_wait_events(p_wait_events.count).average_wait:=r1.average_wait;
2408     p_wait_events(p_wait_events.count).max_wait:=r1.max_wait;
2409   end loop;
2410 Exception when others then
2411   log_n('Exception in load_session_waits '||sqlerrm);
2412   raise;
2413 End;
2414 
2415 /*only 1 group object per group name */
2416 function get_session_stats_group(p_group varchar2) return session_stats_group_r is
2417 l_ssg session_stats_group_r;
2418 Begin
2419   for i in 1..g_ssg.count loop
2420     if g_ssg(i).group_name=p_group then
2421       l_ssg:=g_ssg(i);
2422       exit;
2423     end if;
2424   end loop;
2425   return l_ssg;
2426 Exception when others then
2427   log_n('Exception in get_session_stats_group '||sqlerrm);
2428   raise;
2429 End;
2430 
2431 function get_ssg_index(p_group varchar2) return pls_integer is
2432 Begin
2433   for i in 1..g_ssg.count loop
2434     if g_ssg(i).group_name=p_group then
2435       return i;
2436     end if;
2437   end loop;
2438   return null;
2439 Exception when others then
2440   log_n('Exception in get_ssg_index '||sqlerrm);
2441   raise;
2442 End;
2443 
2444 /*printing cleans the stats */
2445 procedure print_stats(p_group varchar2) is
2446 l_ssg pls_integer;
2447 Begin
2448   l_ssg:=get_ssg_index(p_group);
2449   if l_ssg is not null then
2450     diff_stats(g_ssg(l_ssg));
2451     diff_waits(g_ssg(l_ssg));
2452     print_stats(g_ssg(l_ssg));
2453     clean_stats(g_ssg(l_ssg));
2454   end if;
2455 Exception when others then
2456   log_n('Exception in print_stats '||sqlerrm);
2457   raise;
2458 End;
2459 
2460 procedure clean_stats(p_group varchar2) is
2461 l_ssg pls_integer;
2462 Begin
2463   l_ssg:=get_ssg_index(p_group);
2464   if l_ssg is not null then
2465     clean_stats(g_ssg(l_ssg));
2466   end if;
2467 Exception when others then
2468   log_n('Exception in clean_stats '||sqlerrm);
2469   raise;
2470 End;
2471 
2472 procedure clean_stats(p_ssg in out nocopy session_stats_group_r) is
2473 Begin
2474   p_ssg.session_stats.delete;
2475 Exception when others then
2476   log_n('Exception in clean_stats '||sqlerrm);
2477   raise;
2478 End;
2479 
2480 procedure print_stats(p_ssg session_stats_group_r) is
2481 Begin
2482   if p_ssg.group_name is not null then
2483     log('===========================Stats=============================================================');
2484     log('Stats Group : '||p_ssg.group_name);
2485     for i in 2..p_ssg.session_stats.count loop
2486       print_stats(p_ssg.session_stats(i));
2487     end loop;
2488   end if;
2489 Exception when others then
2490   log_n('Exception in print_stats '||sqlerrm);
2491   raise;
2492 End;
2493 
2494 procedure print_stats(p_session_stats session_stats_r) is
2495 Begin
2496   log('.');
2497   log('Stats       : '||p_session_stats.stats_name);
2498   log('Stats Time  : '||to_char(p_session_stats.stats_time,'MM/DD/YYYY HH24:MI:SS'));
2499   print_session_stats(p_session_stats.stats);
2500   log('.');
2501   print_session_wait(p_session_stats.wait_events);
2502   log('.');
2503 Exception when others then
2504   log_n('Exception in print_stats '||sqlerrm);
2505   raise;
2506 End;
2507 
2508 procedure print_session_stats(p_stats stats_tb) is
2509 Begin
2510   log(rpad('Stats Name',64,'-')||'Value (Diff Value)');
2511   for i in 1..p_stats.count loop
2512     log(rpad(p_stats(i).stats_name,64,'-')||p_stats(i).value||' ('||p_stats(i).diff_value||')');
2513   end loop;
2514 Exception when others then
2515   log_n('Exception in print_session_stats '||sqlerrm);
2516   raise;
2517 End;
2518 
2519 procedure print_session_wait(p_wait_events wait_event_tb) is
2520 Begin
2521   log(rpad('Wait Event',52,'-')||rpad('Total Waited (Diff)',30,'-')||rpad('Total Waits (Diff)',30,'-')||rpad('Timeouts (Diff)',20));
2522   for i in 1..p_wait_events.count loop
2523     log(rpad(p_wait_events(i).event_name,52,'-')||rpad(p_wait_events(i).time_waited||'('||p_wait_events(i).diff_time_waited||')',30,'-')||
2524     rpad(p_wait_events(i).total_waits||'('||p_wait_events(i).diff_total_waits||')',30,'-')||
2525     rpad(p_wait_events(i).total_timeouts||'('||p_wait_events(i).diff_total_timeouts||')',20));
2526   end loop;
2527 Exception when others then
2528   log_n('Exception in print_session_wait '||sqlerrm);
2529   raise;
2530 End;
2531 
2532 procedure diff_stats(p_ssg in out nocopy session_stats_group_r) is
2533 Begin
2534   for i in 2..p_ssg.session_stats.count loop
2535     diff_session_stats(p_ssg.session_stats(i).stats,p_ssg.session_stats(i-1).stats);
2536   end loop;
2537 Exception when others then
2538   log_n('Exception in diff_stats '||sqlerrm);
2539   raise;
2540 End;
2541 
2542 /*assumes stats is ordered by stats name */
2543 procedure diff_session_stats(p_new_stats in out nocopy stats_tb,p_old_stats stats_tb) is
2544 js pls_integer;
2545 flag boolean;
2546 Begin
2547   js:=1;
2548   for i in 1..p_new_stats.count loop
2549     flag:=false;
2550     for j in js..p_old_stats.count loop
2551       if p_old_stats(j).stats_name=p_new_stats(i).stats_name then
2552         flag:=true;
2553         js:=j+1;
2554         p_new_stats(i).diff_value:=p_new_stats(i).value-p_old_stats(j).value;
2555         exit;
2556       end if;
2557     end loop;
2558     if flag=false then
2559       js:=1;
2560     end if;
2561   end loop;
2562 Exception when others then
2563   log_n('Exception in diff_session_stats '||sqlerrm);
2564   raise;
2565 End;
2566 
2567 /*assumes waits are ordered by event name */
2568 procedure diff_waits(p_ssg in out nocopy session_stats_group_r) is
2569 Begin
2570   for i in 2..p_ssg.session_stats.count loop
2571     diff_session_wait(p_ssg.session_stats(i).wait_events,p_ssg.session_stats(i-1).wait_events);
2572   end loop;
2573 Exception when others then
2574   log_n('Exception in diff_waits '||sqlerrm);
2575   raise;
2576 End;
2577 
2578 procedure diff_session_wait(p_new_wait in out nocopy wait_event_tb,p_old_wait wait_event_tb) is
2579 js pls_integer;
2580 flag boolean;
2581 Begin
2582   js:=1;
2583   for i in 1..p_new_wait.count loop
2584     flag:=false;
2585     for j in js..p_old_wait.count loop
2586       if p_new_wait(i).event_name=p_old_wait(j).event_name then
2587         flag:=true;
2588         js:=j+1;
2589         p_new_wait(i).diff_total_waits:=p_new_wait(i).total_waits-p_old_wait(j).total_waits;
2590         p_new_wait(i).diff_total_timeouts:=p_new_wait(i).total_timeouts-p_old_wait(j).total_timeouts;
2591         p_new_wait(i).diff_time_waited:=p_new_wait(i).time_waited-p_old_wait(j).time_waited;
2592       end if;
2593     end loop;
2594     if flag=false then
2595       js:=1;
2596     end if;
2597   end loop;
2598 Exception when others then
2599   log_n('Exception in diff_session_wait '||sqlerrm);
2600   raise;
2601 End;
2602 
2603 procedure kill_session(p_sid number,p_serial number) is
2604 Begin
2605   execute immediate 'alter system kill session '''||p_sid||','||p_serial||'''';
2606 Exception when others then
2607   log_n('Exception in kill_session '||sqlerrm);
2608   raise;
2609 End;
2610 
2611 function get_table_count(p_table varchar2,p_where varchar2) return number is
2612 stmt varchar2(4000);
2613 TYPE RefCurTyp IS REF CURSOR;
2614 cv RefCurTyp;
2615 table_count number;
2616 Begin
2617   stmt:='select count(*) from '||p_table;
2618   if p_where is not null then
2619     stmt:=stmt||' where '||p_where;
2620   end if;
2621   if g_debug then
2622     log(stmt||get_time);
2623   end if;
2624   open cv for stmt;
2625   fetch cv into table_count;
2626   close cv;
2627   if g_debug then
2628     log('Result='||table_count||get_time);
2629   end if;
2630   return table_count;
2631 Exception when others then
2632   log_n('Exception in get_table_count '||sqlerrm);
2633   raise;
2634 End;
2635 
2636 function is_number(p_number varchar2) return boolean is
2637 l_number number;
2638 Begin
2639   l_number:=to_number(p_number);
2640   return true;
2641 Exception when others then
2642   return false;
2643 End;
2644 
2645 END BSC_AW_UTILITY;