[Home] [Help]
PACKAGE BODY: APPS.FND_UMS_ANALYSIS_ENGINE
Source
1 package body fnd_ums_analysis_engine as
2 /* $Header: AFUMSAEB.pls 120.1 2005/07/02 04:20:36 appldev noship $ */
3
4 -- define the newline character
5
6 NEWLINE varchar2(3);
7
8 -- initial engine mode
9
10 MODE_NOT_CALLED constant varchar2(30) := 'ENGINE_NOT_CALLED';
11
12 -- Global APPL_TOP Id. Should be replaced with AD_PATCH.GLOBAL_APPL_TOP_ID
13
14 GLOBAL_APPL_TOP_ID constant number := -1;
15
16 -- bugfix release statuses:
17
18 RSTATUS_IN_PROGRESS constant varchar2(30) := 'IN_PROGRESS';
19 RSTATUS_RELEASED constant varchar2(30) := 'RELEASED';
20 RSTATUS_RELEASED_HIGH_PRIORITY constant varchar2(30) := 'RELEASED_HIGH_PRIORITY';
21 RSTATUS_SUPERSEDED constant varchar2(30) := 'SUPERSEDED';
22 RSTATUS_OBSOLETED constant varchar2(30) := 'OBSOLETED';
23
24 -- patch types:
25
26 -- US patch with UMS metadata
27
28 PATCH_TYPE_US_UMS constant varchar2(30) := 'US_UMS';
29
30 -- US patch without UMS metadata
31
32 PATCH_TYPE_US_NON_UMS constant varchar2(30) := 'US_NON_UMS';
33
34 -- NLS patch (no UMS metadata)
35 -- Implicitly prereqs the US patch of the same bug number.
36
37 PATCH_TYPE_NLS_PATCH constant varchar2(30) := 'NLS_PATCH';
38
39 -- NLS bugfix (no UMS metadata)
40 -- NLS bugfix is a fix for translation bug. There is no US patch for
41 -- the same bug number. Language code is prefixed with 'NLS_'.
42
43 PATCH_TYPE_NLS_BUGFIX constant varchar2(30) := 'NLS_BUGFIX';
44
45 -- replacement types:
46 -- see get_replacement_bugfix_guid() for more details.
47
48 REPLACEMENT_ORIGINAL constant varchar2(30) := 'ORIGINAL_REPLACEMENT';
49 REPLACEMENT_FIRST_NON_OBSOLETE constant varchar2(30) := 'FIRST_NON_OBSOLETE_REPLACEMENT';
50 REPLACEMENT_LAST_NON_OBSOLETE constant varchar2(30) := 'LAST_NON_OBSOLETE_REPLACEMENT';
51
52 -- bugfix application statuses:
53
54 -- bugfix has not been applied
55
56 APP_STATUS_NOT_APPLIED constant varchar2(30) := 'NOT_APPLIED';
57
58 -- bugfix is implicitly applied; all its files and all its prereqs
59 -- (or their equivalent) are applied
60
61 APP_STATUS_IMPLICITLY_APPLIED constant varchar2(30) := 'IMPLICITLY_APPLIED';
62
63 -- bugfix has been explicitly applied
64
65 APP_STATUS_EXPLICITLY_APPLIED constant varchar2(30) := 'EXPLICITLY_APPLIED';
66
67 -- bugfix has been effectively applied
68
69 APP_STATUS_EFFECTIVELY_APPLIED constant varchar2(30) := 'EFFECTIVELY_APPLIED';
70
71 -- Equivalency Results for Post Processing Algorithm
72
73 EQUIVALENCY_TERMINATED constant varchar2(30) := 'EQUIVALENCY_TERMINATED';
74 EQUIVALENCY_IN_PROGRESS constant varchar2(30) := 'EQUIVALENCY_IN_PROGRESS';
75 EQUIVALENCY_COMPLETED_NONE constant varchar2(30) := 'EQUIVALENCY_COMPLETED_NONE';
76 EQUIVALENCY_COMPLETED_REQUIRED constant varchar2(30) := 'EQUIVALENCY_COMPLETED_REQUIRED';
77 EQUIVALENCY_COMPLETED_MERGED constant varchar2(30) := 'EQUIVALENCY_COMPLETED_MERGED';
78 EQUIVALENCY_COMPLETED_APPLIED constant varchar2(30) := 'EQUIVALENCY_COMPLETED_APPLIED';
79
80 -- maximum number of calls to get_equivalency_result() function
81
82 MAX_GET_EQUIVALENCY_CALL_COUNT constant number := 5000;
83
84 -- Report symbols
85
86 SYMBOL_OBSOLETED constant varchar2(10) := '*';
87 SYMBOL_MISSING constant varchar2(10) := '!';
88 SYMBOL_APPLIED constant varchar2(10) := '+';
89 SYMBOL_NO_INFORMATION constant varchar2(10) := '?';
90 SYMBOL_NOT_APPLIED constant varchar2(10) := '-';
91
92 -- raise_application_error codes
93
94 ERROR_AD_IS_PATCH_APPLIED constant number := -20001;
95 ERROR_AD_IS_FILE_COPIED constant number := -20002;
96 ERROR_AD_SET_PATCH_STATUS constant number := -20003;
97
98 ERROR_UMS_OTHERS constant number := -20100;
99 ERROR_UMS_REPLACEMENT_TYPE constant number := -20101;
100 ERROR_UMS_PATCH_TYPE constant number := -20104;
101 ERROR_UMS_ARRAY_NAME constant number := -20105;
102 ERROR_UMS_ENGINE_NOT_CALLED constant number := -20107;
103 ERROR_UMS_ILLEGAL_STATE constant number := -20108;
104 ERROR_UMS_MISSING_DATA constant number := -20111;
105 ERROR_UMS_INVALID_ENGINE_MODE constant number := -20113;
106 ERROR_UMS_INVALID_BUG_LIST constant number := -20114;
107 ERROR_UMS_INVALID_APPL_TOP_ID constant number := -20115;
108
109 -- the maximum size of a piece of the report
110
111 MAX_REPORT_SIZE constant number := 32000;
112
113 -- Generic use array types
114
115 type BINARY_INTEGER_ARRAY is table of binary_integer index by binary_integer;
116 type VARCHAR2_ARRAY is table of varchar2(32000) index by binary_integer;
117
118 -- Arrays for bulk fetching
119
120 type BUGFIX_GUID_ARRAY is table of fnd_ums_bugfixes.bugfix_guid%TYPE index by binary_integer;
121 type RELATION_TYPE_ARRAY is table of fnd_ums_bugfix_relationships.relation_type%TYPE index by binary_integer;
122
123 -- a bugfix in the dependency graph
124
125 type bugfix is record
126 (-- primary key
127 bugfix_index binary_integer,
128
129 -- attributes from FND_UMS_BUGFIXES
130 bugfix_guid fnd_ums_bugfixes.bugfix_guid%type,
131 release_name fnd_ums_bugfixes.release_name%type,
132 bug_number fnd_ums_bugfixes.bug_number%type,
133 download_mode fnd_ums_bugfixes.download_mode%type,
134 application_short_name fnd_ums_bugfixes.application_short_name%type,
135 release_status fnd_ums_bugfixes.release_status%type,
136 type fnd_ums_bugfixes.type%type,
137 abstract fnd_ums_bugfixes.abstract%type,
138
139 -- attributes passed in
140 language_code varchar2(30),
141
142 -- derived attributes
143 patch_type varchar2(30),
144 ad_application_status varchar2(30),
145 bugfix_id varchar2(60),
146 merged boolean,
147
148 -- attributes used during prereq check
149 replacement_chain_tag number,
150 application_status varchar2(30),
151 required boolean,
152
153 -- post processing equivalency properties,
154 equivalency_result varchar2(30),
155 equivalency_path varchar2(32000),
156 equivalent_bugfix_index binary_integer);
157
158 type BUGFIX_ARRAY is table of bugfix index by binary_integer;
159
160 -- Input passed to Analysis Engine.
161
162 type input_bug is record
163 (bug_number number,
164 language_code varchar2(30));
165
166 type INPUT_BUG_ARRAY is table of input_bug index by binary_integer;
167
168 type replacement_chain is record
169 (bugfix_count number,
170 bugfix_indexes binary_integer_array);
171
172 type globals_record is record
173 (-- the one-based array of report pieces
174 report_count number,
175 report VARCHAR2_ARRAY,
176
177 -- the number of top-level bugfixes
178 top_level_bugfix_count number,
179 top_level_bugfix_indexes BINARY_INTEGER_ARRAY,
180
181 -- obsolete top-level bugfix exists flag
182 obs_top_level_bugfix_exists boolean,
183
184 -- the number of bugfixes
185 bugfix_count number,
186
187 -- the required bugfixes
188 required_bugfix_count number,
189 required_bugfix_indexes BINARY_INTEGER_ARRAY,
190
191 -- the prereq list
192 prereq_list varchar2(32000),
193
194 -- the depth of the recursion used for indenting the debug output
195 indent_level number,
196
197 -- the mode
198 engine_mode varchar2(30),
199
200 -- the root cause error message
201 root_cause_error_message varchar2(32000),
202
203 -- the unhandled exception depth
204 exception_depth number,
205
206 -- the APPL_TOP id
207 appl_top_id number,
208
209 -- the debug flag
210 debug_on boolean,
211
212 -- replacement chain cycle detection counter
213 replacement_chain_tag_counter number,
214
215 -- number of calls to get_equivalency_result() function
216 get_equivalency_call_count number,
217
218 -- engine return status
219 status varchar2(30));
220
221 -- Global Variables
222
223 g_globals globals_record;
224
225 g_bugfixes BUGFIX_ARRAY;
226
227 g_arcs_revision varchar2(32000);
228
229 --------------------------------------------------------------------------------
230 -- Returns TRUE iff analyze_dependencies (engine) is called.
231 --
232 -- return: TRUE iff analyze_dependencies (engine) is called; FALSE otherwise.
233 --------------------------------------------------------------------------------
234 function is_engine_called
235 return boolean
236 is
237 l_return boolean;
238 begin
239 if (g_globals.engine_mode = MODE_NOT_CALLED) then
240 l_return := false;
241 else
242 l_return := true;
243 end if;
244
245 return l_return;
246 end is_engine_called;
247
248 --------------------------------------------------------------------------------
249 -- Gets the relation type as text.
250 --
251 -- p_relation_type - the relation type
252 --
253 -- return: the relation type as text
254 --------------------------------------------------------------------------------
255 function get_relation_type_as_text(p_relation_type in varchar2)
256 return varchar2
257 is
258 l_text varchar2(30);
259 begin
260 if (p_relation_type = fnd_ums_loader.REL_TYPE_PREREQS) then
261 l_text := 'Prereqs';
262 elsif (p_relation_type = fnd_ums_loader.REL_TYPE_INDIRECTLY_PREREQS) then
263 l_text := 'Indirectly Prereqs';
264 elsif (p_relation_type = fnd_ums_loader.REL_TYPE_INCLUDES) then
265 l_text := 'Includes';
266 elsif (p_relation_type = fnd_ums_loader.REL_TYPE_INDIRECTLY_INCLUDES) then
267 l_text := 'Indirectly Includes';
268 elsif (p_relation_type = fnd_ums_loader.REL_TYPE_REPLACED_BY) then
269 l_text := 'Replaced by';
270 else
271 l_text := p_relation_type;
272 end if;
273
274 return l_text;
275 end get_relation_type_as_text;
276
277 --------------------------------------------------------------------------------
278 -- Appends a line to the report.
279 --
280 -- p_text - the text to append to the report
281 --------------------------------------------------------------------------------
282 procedure append_to_report(p_text in varchar2)
283 is
284 begin
285 if (lengthb(g_globals.report(g_globals.report_count)) +
286 lengthb(p_text) + lengthb(NEWLINE) > MAX_REPORT_SIZE) then
287 -- appending the text to the current piece of the report would exceed its
288 -- maximum allowed size so initialize the next piece of the report
289
290 g_globals.report_count := g_globals.report_count + 1;
291 g_globals.report(g_globals.report_count) := '';
292 end if;
293
294 g_globals.report(g_globals.report_count) := g_globals.report(g_globals.report_count) ||
295 rtrim(p_text, NEWLINE) || NEWLINE;
296 end append_to_report;
297
298 --------------------------------------------------------------------------------
299 -- Logs a message to the global report if in DEBUG mode. Indents the line
300 -- according to the value of g_globals.indent_level.
301 --
302 -- p_text - the text to log
303 --------------------------------------------------------------------------------
304 procedure debug_to_report(p_text in varchar2)
305 is
306 l_text varchar2(2000);
307 begin
308 if (g_globals.debug_on) then
309 -- indent the line according to indent_level
310
311 l_text := lpad(p_text, length(p_text) + 3*g_globals.indent_level);
312
313 append_to_report(l_text);
314 end if;
315 exception
316 when others then
317 null;
318 end debug_to_report;
319
320 --------------------------------------------------------------------------------
321 -- Logs unhandled exception info to the report.
322 --
323 -- p_method - name of the method reporting exception
324 --------------------------------------------------------------------------------
325 procedure exception_to_report
326 is
327 begin
328 append_to_report(' ');
329 append_to_report(rpad('=', 80, '='));
330
331 -- Root cause of the problem
332 append_to_report(g_globals.root_cause_error_message);
333
334 append_to_report(' ');
335 append_to_report('----- Error Message Stack -----');
336 append_to_report(dbms_utility.format_error_stack());
337
338 if (g_globals.debug_on) then
339 append_to_report(' ');
340 append_to_report(dbms_utility.format_call_stack());
341 end if;
342
343 append_to_report(rpad('=', 80, '='));
344 exception
345 when others then
346 null;
347 end exception_to_report;
348
349 --------------------------------------------------------------------------------
350 -- Converts boolean to char.
351 --
352 -- p_boolean - boolean variable
353 --
354 -- return: Char representation of boolean variable.
355 --------------------------------------------------------------------------------
356 function boolean_to_char(p_boolean in boolean)
357 return varchar2
358 is
359 l_return varchar2(100);
360 begin
361 if (p_boolean is null) then
362 l_return := 'NULL';
363 elsif (p_boolean) then
364 l_return := 'TRUE';
365 else
366 l_return := 'FALSE';
367 end if;
368
369 return l_return;
370
371 end boolean_to_char;
372
373 --------------------------------------------------------------------------------
374 -- Returns formatted method call
375 --
376 -- p_method - name of the method
377 -- p_arg1..5 - method arguments
378 --
379 -- return: formatted method call
380 --------------------------------------------------------------------------------
381 function get_formatted_method_call(p_method in varchar2,
382 p_arg1 in varchar2 default null,
383 p_arg2 in varchar2 default null,
384 p_arg3 in varchar2 default null,
385 p_arg4 in varchar2 default null,
386 p_arg5 in varchar2 default null)
387 return varchar2
388 is
389 l_method varchar2(32000);
390 begin
391 l_method := p_method || '(';
392
393 if (p_arg1 is not null) then
394 l_method := l_method || p_arg1;
395 end if;
396
397 if (p_arg2 is not null) then
398 l_method := l_method || ', ' || p_arg2;
399 end if;
400
401 if (p_arg3 is not null) then
402 l_method := l_method || ', ' || p_arg3;
403 end if;
404
405 if (p_arg4 is not null) then
406 l_method := l_method || ', ' || p_arg4;
407 end if;
408
409 if (p_arg5 is not null) then
410 l_method := l_method || ', ' || p_arg5;
411 end if;
415 return l_method;
412
413 l_method := l_method || ')';
414
416
417 exception
418 when others then
419 return p_method;
420 end get_formatted_method_call;
421
422 --------------------------------------------------------------------------------
423 -- Returns formatted error.
424 --
425 -- p_line0 - The first line that goes after ORA error number
426 -- p_line1..5 - optional lines to be indented
427 --
428 -- return: formatted error message
429 --------------------------------------------------------------------------------
430 function get_formatted_error(p_line0 in varchar2,
431 p_line1 in varchar2 default null,
432 p_line2 in varchar2 default null,
433 p_line3 in varchar2 default null,
434 p_line4 in varchar2 default null,
435 p_line5 in varchar2 default null)
436 return varchar2
437 is
438 l_error_text varchar2(32000);
439 l_newline_indent varchar2(2000);
440 begin
441 --
442 -- 12345678901
443 -- ORA-xxxxx: <p_line0>
444 -- <p_line1>
445 -- <p_line2>
446 --
447
448 l_newline_indent := NEWLINE || rpad(' ', 11, ' ');
449
450 l_error_text := p_line0;
451
452 if (p_line1 is not null) then
453 l_error_text := l_error_text || l_newline_indent || p_line1;
454 end if;
455
456 if (p_line2 is not null) then
457 l_error_text := l_error_text || l_newline_indent || p_line2;
458 end if;
459
460 if (p_line3 is not null) then
461 l_error_text := l_error_text || l_newline_indent || p_line3;
462 end if;
463
464 if (p_line4 is not null) then
465 l_error_text := l_error_text || l_newline_indent || p_line4;
466 end if;
467
468 if (p_line5 is not null) then
469 l_error_text := l_error_text || l_newline_indent || p_line5;
470 end if;
471
472 return l_error_text;
473
474 end get_formatted_error;
475
476 --------------------------------------------------------------------------------
477 -- Raises formatted application error.
478 --
479 -- p_error_code - error code
480 -- p_error_text - error text
481 --------------------------------------------------------------------------------
482 procedure raise_formatted_error(p_error_code in number,
483 p_error_text in varchar2)
484 is
485 l_error_text varchar2(32000);
486 begin
487 l_error_text := p_error_text || NEWLINE || dbms_utility.format_error_stack();
488
489 raise_application_error(p_error_code, l_error_text);
490
491 exception
492 when others then
493 --
494 -- Store the root cause of the problem. This will be presented to
495 -- user as the main cause of the exception. Rest of the exception is
496 -- basically the call stack trace.
497 --
498 if (g_globals.exception_depth = 0) then
499 g_globals.root_cause_error_message := dbms_utility.format_error_stack();
500 end if;
501
502 g_globals.exception_depth := g_globals.exception_depth + 1;
503
504 if (g_globals.debug_on) then
505 exception_to_report();
506 end if;
507
508 raise;
509 end raise_formatted_error;
510
511 --------------------------------------------------------------------------------
512 -- Raises formatted error for 'when others then' block
513 --
514 -- p_method - name of the method
515 -- p_arg1..5 - method arguments
516 --------------------------------------------------------------------------------
517 procedure raise_others_error(p_method in varchar2,
518 p_arg1 in varchar2 default null,
519 p_arg2 in varchar2 default null,
520 p_arg3 in varchar2 default null,
521 p_arg4 in varchar2 default null,
522 p_arg5 in varchar2 default null)
523 is
524 l_error_text varchar2(32000);
525 begin
526 l_error_text := get_formatted_method_call(p_method,
527 p_arg1,
528 p_arg2,
529 p_arg3,
530 p_arg4,
531 p_arg5);
532
533 l_error_text := l_error_text || ' raised exception.';
534
535 raise_formatted_error(ERROR_UMS_OTHERS, l_error_text);
536
537 -- No exception handling here
538 end raise_others_error;
539
540 --------------------------------------------------------------------------------
541 -- Sorts required bugfixes
542 --------------------------------------------------------------------------------
543 procedure sort_required_bugfixes
544 is
545 l_tmp_index binary_integer;
546 l_min_index binary_integer;
547 l_min_bug_number number;
548 begin
549 -- use selection sort algorithm
550
551 for i in 0 .. g_globals.required_bugfix_count - 1 loop
552 l_min_index := i;
556
553 l_min_bug_number := g_bugfixes(g_globals.required_bugfix_indexes(i)).bug_number;
554
555 for j in i + 1 .. g_globals.required_bugfix_count - 1 loop
557 if (g_bugfixes(g_globals.required_bugfix_indexes(j)).bug_number < l_min_bug_number) then
558 l_min_index := j;
559 l_min_bug_number := g_bugfixes(g_globals.required_bugfix_indexes(j)).bug_number;
560 end if;
561
562 end loop;
563
564 if (l_min_index <> i) then
565 l_tmp_index := g_globals.required_bugfix_indexes(i);
566 g_globals.required_bugfix_indexes(i) := g_globals.required_bugfix_indexes(l_min_index);
567 g_globals.required_bugfix_indexes(l_min_index) := l_tmp_index;
568 end if;
569 end loop;
570
571 exception
572 when others then
573 raise_others_error('sort_required_bugfixes');
574 end sort_required_bugfixes;
575
576 --------------------------------------------------------------------------------
577 -- Generates a comma seperated list of required bugfixes.
578 --------------------------------------------------------------------------------
579 function compute_prereq_list
580 return varchar2
581 is
582 l_prereq_list varchar2(32000);
583 begin
584 l_prereq_list := '';
585
586 -- sort required bugfixes
587
588 sort_required_bugfixes();
589
590 for i in 0 .. g_globals.required_bugfix_count - 1 loop
591
592 if (i > 0) then
593 l_prereq_list := l_prereq_list || ',';
594 end if;
595
596 l_prereq_list := l_prereq_list || g_bugfixes(g_globals.required_bugfix_indexes(i)).bug_number;
597 end loop;
598
599 return l_prereq_list;
600
601 exception
602 when others then
603 raise_others_error('compute_prereq_list');
604 end compute_prereq_list;
605
606 --------------------------------------------------------------------------------
607 -- Prints array details.
608 --
609 -- p_array_name - the array name 'Potenatial Prereqs', 'Required Bugfixes', etc.
610 -- p_arg1 - optional argument, used for title, prompt etc.
611 --------------------------------------------------------------------------------
612 procedure debug_array_to_report(p_array_name in varchar2,
613 p_arg1 in varchar2 default null)
614 is
615 l_heading varchar2(2000);
616
617 procedure debug_bugfix_to_report(p_bugfix_index in binary_integer,
618 p_debug_application_status in boolean,
619 p_debug_top_level in boolean)
620 is
621 l_bugfix bugfix;
622 l_debug varchar2(32000);
623 begin
624 l_bugfix := g_bugfixes(p_bugfix_index);
625
626 l_debug := lpad(l_bugfix.bugfix_id, 13) ||
627 ' ' || rpad(l_bugfix.release_status, 18);
628
629 if (p_debug_application_status) then
630 l_debug := l_debug || ' ' || rpad(l_bugfix.application_status, 18);
631 end if;
632
633 if (p_debug_top_level) then
634 if (l_bugfix.merged) then
635 l_debug := l_debug || ' MERGED';
636 else
637 l_debug := l_debug || ' NOT_MERGED';
638 end if;
639 end if;
640
641 debug_to_report(l_debug);
642
643 exception
644 when others then
645 raise_others_error('debug_bugfix_to_report',
646 g_bugfixes(p_bugfix_index).bug_number,
647 boolean_to_char(p_debug_application_status),
648 boolean_to_char(p_debug_top_level));
649 end debug_bugfix_to_report;
650
651 begin
652 if (p_arg1 is null) then
653 l_heading := p_array_name || ': ';
654 else
655 l_heading := p_array_name || ' (' || p_arg1 || '): ';
656 end if;
657
658 if (p_array_name = 'Top Level Bugfixes') then
659 debug_to_report(' ');
660 debug_to_report(l_heading || g_globals.top_level_bugfix_count);
661 debug_to_report('--------------------------------------------------');
662
663 for i in 0..g_globals.top_level_bugfix_count - 1 loop
664 debug_bugfix_to_report(p_bugfix_index => i,
665 p_debug_application_status => true,
666 p_debug_top_level => false);
667
668 end loop; -- top level bugfixes
669
670 elsif (p_array_name = 'Required Bugfixes') then
671
672 debug_to_report(' ');
673 debug_to_report(l_heading || g_globals.required_bugfix_count);
674 debug_to_report('--------------------------------------------------');
675
676 for i in 0 .. g_globals.required_bugfix_count - 1 loop
677 debug_bugfix_to_report(p_bugfix_index => g_globals.required_bugfix_indexes(i),
678 p_debug_application_status => true,
679 p_debug_top_level => true);
680 end loop; -- required bugfixes
681
682 else
683 raise_formatted_error(ERROR_UMS_ARRAY_NAME,
684 get_formatted_error('UMS Code Error in debug_array_to_report()',
685 'Unexpected array name: ' || p_array_name));
686 end if;
687
688 exception
689 when others then
690 raise_others_error('debug_array_to_report',
691 p_array_name,
692 p_arg1);
693 end debug_array_to_report;
694
695 --------------------------------------------------------------------------------
696 -- Creates the bugfix in cache.
697 --
698 -- p_release_name - the release name
699 -- p_bug_number - the bug number
700 -- p_language_code - the language code
701 --
702 -- return: the bugfix index
703 --------------------------------------------------------------------------------
704 function create_bugfix(p_release_name in varchar2,
705 p_bug_number in number,
706 p_language_code in varchar2)
707 return binary_integer
708 is
709 l_bugfix bugfix;
710 l_bugfix_index binary_integer;
711 begin
712 if (p_language_code <> 'US') then
713
714 -- NLS patch or NLS bugfix
715
716 l_bugfix.bugfix_guid := null;
717 l_bugfix.release_name := p_release_name;
718 l_bugfix.bug_number := p_bug_number;
719 l_bugfix.download_mode := fnd_ums_loader.DL_MODE_NONE;
720 l_bugfix.application_short_name := null;
721 l_bugfix.release_status := RSTATUS_RELEASED;
722 l_bugfix.type := fnd_ums_loader.BUGFIX_TYPE_BUGFIX;
723 l_bugfix.bugfix_id := p_bug_number || ':' || p_language_code;
724
725 if (p_language_code like 'NLS_%') then
726 l_bugfix.patch_type := PATCH_TYPE_NLS_BUGFIX;
727 l_bugfix.abstract := '<NLS Bugfix for language: ' ||
728 substr(p_language_code,5) || '>';
729 else
730 l_bugfix.patch_type := PATCH_TYPE_NLS_PATCH;
731 l_bugfix.abstract := '<NLS Patch for language: ' ||
732 p_language_code || '>';
733 end if;
734
735 else
736 -- a 'US' bugfix
737 l_bugfix.bugfix_id := p_bug_number;
738
739 begin
740 select 'AFUMSAEB.pls : $Revision: 120.1 $ : create_bugfix' arcs_revision,
741 bugfix_guid,
742 release_name,
743 bug_number,
744 download_mode,
745 application_short_name,
746 release_status,
747 type,
748 abstract
749 into g_arcs_revision,
750 l_bugfix.bugfix_guid,
751 l_bugfix.release_name,
752 l_bugfix.bug_number,
753 l_bugfix.download_mode,
754 l_bugfix.application_short_name,
755 l_bugfix.release_status,
756 l_bugfix.type,
757 l_bugfix.abstract
758 from fnd_ums_bugfixes
759 where release_name = p_release_name
760 and bug_number = p_bug_number
761 and download_mode <> fnd_ums_loader.DL_MODE_NONE;
762
763 l_bugfix.patch_type := PATCH_TYPE_US_UMS;
764 exception
765 when no_data_found then
766
767 -- non-UMS US bugfix.
768
769 l_bugfix.patch_type := PATCH_TYPE_US_NON_UMS;
770
771 l_bugfix.bugfix_guid := null;
772 l_bugfix.release_name := p_release_name;
773 l_bugfix.bug_number := p_bug_number;
774 l_bugfix.download_mode := fnd_ums_loader.DL_MODE_NONE;
775 l_bugfix.application_short_name := null;
776 l_bugfix.release_status := RSTATUS_RELEASED;
777 l_bugfix.type := fnd_ums_loader.BUGFIX_TYPE_BUGFIX;
778 l_bugfix.abstract := '<Patch for language: US>';
779 end;
780 end if;
781
782 -- get ad_application_status
783 begin
784 if (l_bugfix.patch_type in (PATCH_TYPE_NLS_PATCH,
785 PATCH_TYPE_NLS_BUGFIX)) then
786
787 l_bugfix.ad_application_status := ad_patch.NOT_APPLIED;
788 else
789 -- a 'US' bugfix
790 -- get bugfix application status from AD
791
792 begin
793 l_bugfix.ad_application_status := ad_patch.is_patch_applied(
794 p_appl_top_id => g_globals.appl_top_id,
795 p_release_name => l_bugfix.release_name,
796 p_bug_number => l_bugfix.bug_number);
797 exception
798 when others then
799 raise_formatted_error(ERROR_AD_IS_PATCH_APPLIED,
800 get_formatted_error('Error in AD_PATCH',
804 l_bugfix.release_name || ''',',
801 'ad_patch.is_patch_applied(p_appl_top_id => ' ||
802 g_globals.appl_top_id || ',',
803 ' p_release_name => ''' ||
805 ' p_bug_number => ' ||
806 l_bugfix.bug_number || ')'));
807 end;
808 end if;
809 end;
810
811 if (l_bugfix.ad_application_status = ad_patch.EXPLICITLY_APPLIED) then
812 l_bugfix.application_status := APP_STATUS_EXPLICITLY_APPLIED;
813
814 elsif (l_bugfix.ad_application_status = ad_patch.IMPLICITLY_APPLIED) then
815 l_bugfix.application_status := APP_STATUS_IMPLICITLY_APPLIED;
816
817 else
818 l_bugfix.application_status := APP_STATUS_NOT_APPLIED;
819
820 end if;
821
822 -- Common initialization
823
824 l_bugfix.language_code := p_language_code;
825 l_bugfix.required := false;
826 l_bugfix.merged := false;
827 l_bugfix.replacement_chain_tag := null;
828 l_bugfix.equivalency_result := null;
829 l_bugfix.equivalency_path := null;
830 l_bugfix.equivalent_bugfix_index := null;
831
832 -- Bugfix record is ready, assign the primary key.
833
834 l_bugfix_index := g_globals.bugfix_count;
835
836 g_globals.bugfix_count := g_globals.bugfix_count + 1;
837
838 l_bugfix.bugfix_index := l_bugfix_index;
839
840 g_bugfixes(l_bugfix_index) := l_bugfix;
841
842 return l_bugfix.bugfix_index;
843
844 exception
845 when others then
846 raise_others_error('create_bugfix',
847 p_release_name,
848 p_bug_number,
849 p_language_code);
850 end create_bugfix;
851
852 --------------------------------------------------------------------------------
853 -- Gets the bugfix. If the bugfix does not exist, a new one is created. This
854 -- function is useful if you only need a handle to the bugfix for read access.
855 -- Since the returned bugfix is a copy of the one in the global array, it is
856 -- not useful for write access.
857 --
858 -- p_release_name - the release name
859 -- p_bug_number - the bug number
860 -- p_language_code - the language code
861 --
862 -- return: the bugfix
863 --------------------------------------------------------------------------------
864 function get_bugfix(p_release_name in varchar2,
865 p_bug_number in number,
866 p_language_code in varchar2)
867 return bugfix
868 is
869 l_bugfix bugfix;
870 l_bugfix_index binary_integer;
871 l_found boolean;
872 begin
873 l_found := false;
874
875 for i in reverse 0 .. g_globals.bugfix_count - 1 loop
876 if (g_bugfixes(i).release_name = p_release_name and
877 g_bugfixes(i).bug_number = p_bug_number and
878 g_bugfixes(i).language_code = p_language_code) then
879 l_bugfix := g_bugfixes(i);
880 l_found := true;
881
882 exit;
883 end if;
884 end loop;
885
886 if (not l_found) then
887 l_bugfix_index := create_bugfix(p_release_name,
888 p_bug_number,
889 p_language_code);
890 l_bugfix := g_bugfixes(l_bugfix_index);
891 end if;
892
893 return l_bugfix;
894
895 exception
896 when others then
897 raise_others_error('get_bugfix',
898 p_release_name,
899 p_bug_number,
900 p_language_code);
901 end get_bugfix;
902
903 --------------------------------------------------------------------------------
904 -- Gets the bugfix for UMS bugfixes.
905 --
906 -- p_bugfix_guid - the bugfix guid
907 --
908 -- return: the bugfix
909 --------------------------------------------------------------------------------
910 function get_bugfix(p_bugfix_guid in fnd_ums_bugfixes.bugfix_guid%type)
911 return bugfix
912 is
913 l_release_name fnd_ums_bugfixes.release_name%type;
914 l_bug_number fnd_ums_bugfixes.bug_number%type;
915 l_bugfix_index binary_integer;
916 l_bugfix bugfix;
917 l_found boolean;
918 begin
919 l_found := false;
920
921 for i in reverse 0 .. g_globals.bugfix_count - 1 loop
922 if (g_bugfixes(i).bugfix_guid = p_bugfix_guid) then
923 l_bugfix := g_bugfixes(i);
924 l_found := true;
925
926 exit;
927 end if;
928 end loop;
929
930 if (not l_found) then
931 -- Check UMS table
932 begin
933 select 'AFUMSAEB.pls : $Revision: 120.1 $ : get_bugfix' arcs_revision,
934 release_name,
935 bug_number
936 into g_arcs_revision,
937 l_release_name,
938 l_bug_number
939 from fnd_ums_bugfixes
940 where bugfix_guid = p_bugfix_guid;
941 exception
942 when no_data_found then
943 raise_formatted_error(ERROR_UMS_MISSING_DATA,
944 get_formatted_error('No data found in FND_UMS_BUGFIXES',
945 'for bugfix guid ' || p_bugfix_guid));
946 end;
950 'US');
947
948 l_bugfix_index := create_bugfix(l_release_name,
949 l_bug_number,
951 l_bugfix := g_bugfixes(l_bugfix_index);
952
953 end if;
954
955 return l_bugfix;
956
957 exception
958 when others then
959 raise_others_error('get_bugfix',
960 p_bugfix_guid);
961 end get_bugfix;
962
963 --------------------------------------------------------------------------------
964 -- Sets/unsets required state of a bugfix
965 --
966 -- p_bugfix_index - bugfix index
967 -- p_required - required state of a bugfix
968 --------------------------------------------------------------------------------
969 procedure set_bugfix_required(p_bugfix_index in binary_integer,
970 p_required in boolean)
971 is
972 l_required boolean;
973 begin
974 l_required := g_bugfixes(p_bugfix_index).required;
975
976 if (l_required) then
977 if (not p_required) then
978 --
979 -- REQUIRED --> NOT REQUIRED
980 --
981 -- remove it from required bugfixes
982 for i in 0 .. g_globals.required_bugfix_count - 1 loop
983 if (g_globals.required_bugfix_indexes(i) = p_bugfix_index) then
984
985 g_globals.required_bugfix_indexes(i) :=
986 g_globals.required_bugfix_indexes(g_globals.required_bugfix_count - 1);
987 g_globals.required_bugfix_count := g_globals.required_bugfix_count - 1;
988
989 exit; -- from the loop
990 end if;
991 end loop;
992 end if;
993 else
994 if (p_required) then
995 --
996 -- NOT REQUIRED --> REQUIRED
997 --
998 -- add it to required bugfixes
999 g_globals.required_bugfix_indexes(g_globals.required_bugfix_count) := p_bugfix_index;
1000 g_globals.required_bugfix_count := g_globals.required_bugfix_count + 1;
1001 end if;
1002 end if;
1003
1004 g_bugfixes(p_bugfix_index).required := p_required;
1005
1006 exception
1007 when others then
1008 raise_others_error('set_bugfix_required',
1009 g_bugfixes(p_bugfix_index).bug_number,
1010 boolean_to_char(p_required));
1011 end set_bugfix_required;
1012
1013 --------------------------------------------------------------------------------
1014 -- Gets the replacement bugfix guid.
1015 --
1016 -- p_bugfix_guid - the bugfix guid
1017 --
1018 -- return: the replacement bugfix guid or null if there is no replacement
1019 --------------------------------------------------------------------------------
1020 function get_replacement_bugfix_guid(p_bugfix_guid in fnd_ums_bugfixes.bugfix_guid%type)
1021 return fnd_ums_bugfixes.bugfix_guid%type
1022 is
1023 l_replacement_bugfix_guid fnd_ums_bugfixes.bugfix_guid%type;
1024 begin
1025 begin
1026 select 'AFUMSAEB.pls : $Revision: 120.1 $ : get_replacement_bugfix_guid' arcs_revision,
1027 related_bugfix_guid
1028 into g_arcs_revision,
1029 l_replacement_bugfix_guid
1030 from fnd_ums_bugfix_relationships
1031 where bugfix_guid = p_bugfix_guid
1032 and relation_type = fnd_ums_loader.REL_TYPE_REPLACED_BY;
1033 exception
1034 when no_data_found then
1035 -- there is no replacement
1036
1037 l_replacement_bugfix_guid := null;
1038 end;
1039
1040 return l_replacement_bugfix_guid;
1041
1042 exception
1043 when others then
1044 raise_others_error('get_replacement_bugfix_guid',
1045 get_bugfix(p_bugfix_guid).bug_number);
1046 end get_replacement_bugfix_guid;
1047
1048 --------------------------------------------------------------------------------
1049 -- Returns the replacement chain of a bugfix up to
1050 -- the end of the chain
1051 --
1052 -- p_bugfix_index - the bugfix index
1053 -- px_replacement_chain - the replacement chain
1054 --------------------------------------------------------------------------------
1055 procedure get_full_replacement_chain(p_bugfix_index in binary_integer,
1056 px_replacement_chain in out nocopy replacement_chain)
1057 is
1058 l_bugfix bugfix;
1059 l_bugfix_guid fnd_ums_bugfixes.bugfix_guid%type;
1060 begin
1061 px_replacement_chain.bugfix_count := 0;
1062
1063 g_globals.replacement_chain_tag_counter := g_globals.replacement_chain_tag_counter + 1;
1064
1065 l_bugfix := g_bugfixes(p_bugfix_index);
1066 l_bugfix_guid := l_bugfix.bugfix_guid;
1067
1068 loop
1069 px_replacement_chain.bugfix_indexes(px_replacement_chain.bugfix_count) := l_bugfix.bugfix_index;
1070 px_replacement_chain.bugfix_count := px_replacement_chain.bugfix_count + 1;
1071
1072 -- check for cyclic replacement chain
1073
1074 if (l_bugfix.replacement_chain_tag = g_globals.replacement_chain_tag_counter) then
1075 px_replacement_chain.bugfix_count := px_replacement_chain.bugfix_count - 1;
1076 exit; -- from chain loop
1077 else
1078 -- tag it
1079 g_bugfixes(l_bugfix.bugfix_index).replacement_chain_tag := g_globals.replacement_chain_tag_counter;
1080 end if;
1081
1085 -- the end of the replacement chain has been reached
1082 l_bugfix_guid := get_replacement_bugfix_guid(l_bugfix_guid);
1083
1084 if (l_bugfix_guid is null) then
1086
1087 exit; -- from chain loop
1088 end if;
1089
1090 -- next bugfix in the chain
1091
1092 l_bugfix := get_bugfix(l_bugfix_guid);
1093 end loop;
1094
1095 exception
1096 when others then
1097 raise_others_error('get_full_replacement_chain',
1098 g_bugfixes(p_bugfix_index).bug_number);
1099 end get_full_replacement_chain;
1100
1101 --------------------------------------------------------------------------------
1102 -- Gets the replacement bugfix guid.
1103 --
1104 -- p_bugfix_guid - the bugfix guid
1105 -- p_replacement_type - type of the replacement.
1106 --
1107 -- return: the replacement bugfix guid or null if there is no replacement
1108 --
1109 -- OR OR OR OR
1110 -- Aobs ------> A1 ------> A2obs ------> A3 ------> A4obs
1111 --
1112 -- p_bugfix_guid p_replacement_type return
1113 -- ------------- ------------------------------- --------
1114 -- Aobs REPLACEMENT_ORIGINAL A1
1115 -- Aobs REPLACEMENT_FIRST_NON_OBSOLETE A1
1116 -- Aobs REPLACEMENT_LAST_NON_OBSOLETE A3
1117 --
1118 -- A1 REPLACEMENT_ORIGINAL A2obs
1119 -- A1 REPLACEMENT_FIRST_NON_OBSOLETE A3
1120 -- A1 REPLACEMENT_LAST_NON_OBSOLETE A3
1121 --
1122 -- A2obs REPLACEMENT_ORIGINAL A3
1123 -- A2obs REPLACEMENT_FIRST_NON_OBSOLETE A3
1124 -- A2obs REPLACEMENT_LAST_NON_OBSOLETE A3
1125 --
1126 -- A3 REPLACEMENT_ORIGINAL A4obs
1127 -- A3 REPLACEMENT_FIRST_NON_OBSOLETE null
1128 -- A3 REPLACEMENT_LAST_NON_OBSOLETE null
1129 --
1130 -- A4obs REPLACEMENT_ORIGINAL null
1131 -- A4obs REPLACEMENT_FIRST_NON_OBSOLETE null
1132 -- A4obs REPLACEMENT_LAST_NON_OBSOLETE null
1133 --
1134 --------------------------------------------------------------------------------
1135 function get_replacement_bugfix_guid(p_bugfix_guid in fnd_ums_bugfixes.bugfix_guid%type,
1136 p_replacement_type in varchar2)
1137 return fnd_ums_bugfixes.bugfix_guid%type
1138 is
1139 l_replacement_bugfix_guid fnd_ums_bugfixes.bugfix_guid%type;
1140 l_bugfix bugfix;
1141 l_replacement_chain replacement_chain;
1142 begin
1143 l_replacement_bugfix_guid := null;
1144
1145 l_bugfix := get_bugfix(p_bugfix_guid);
1146
1147 get_full_replacement_chain(l_bugfix.bugfix_index, l_replacement_chain);
1148
1149 if (p_replacement_type = REPLACEMENT_ORIGINAL) then
1150
1151 for i in 1 .. l_replacement_chain.bugfix_count - 1 loop
1152 if (i = 1) then
1153 l_replacement_bugfix_guid := g_bugfixes(l_replacement_chain.bugfix_indexes(i)).bugfix_guid;
1154 exit;
1155 end if;
1156 end loop;
1157
1158 elsif (p_replacement_type = REPLACEMENT_FIRST_NON_OBSOLETE) then
1159
1160 for i in 1 .. l_replacement_chain.bugfix_count - 1 loop
1161 if (g_bugfixes(l_replacement_chain.bugfix_indexes(i)).release_status <> RSTATUS_OBSOLETED) then
1162 l_replacement_bugfix_guid := g_bugfixes(l_replacement_chain.bugfix_indexes(i)).bugfix_guid;
1163 exit;
1164 end if;
1165 end loop;
1166
1167 elsif (p_replacement_type = REPLACEMENT_LAST_NON_OBSOLETE) then
1168
1169 for i in reverse 1 .. l_replacement_chain.bugfix_count - 1 loop
1170 if (g_bugfixes(l_replacement_chain.bugfix_indexes(i)).release_status <> RSTATUS_OBSOLETED) then
1171 l_replacement_bugfix_guid := g_bugfixes(l_replacement_chain.bugfix_indexes(i)).bugfix_guid;
1172 exit;
1173 end if;
1174 end loop;
1175
1176 else
1177 raise_formatted_error(ERROR_UMS_REPLACEMENT_TYPE,
1178 get_formatted_error('UMS Code Error in get_replacement_bugfix_guid()',
1179 'Unexpected replacement type: ' || p_replacement_type));
1180 end if;
1181
1182 return l_replacement_bugfix_guid;
1183
1184 exception
1185 when others then
1186 raise_others_error('get_replacement_bugfix_guid',
1187 get_bugfix(p_bugfix_guid).bug_number,
1188 p_replacement_type);
1189 end get_replacement_bugfix_guid;
1190
1191 --------------------------------------------------------------------------------
1192 procedure check_bugfix_required(p_bugfix_index in binary_integer,
1193 p_relation_type in varchar2,
1194 p_related_bugfix_index in binary_integer)
1195 is
1196 l_debug_bugfix bugfix;
1197 l_related_bugfix bugfix;
1198 begin
1199 l_related_bugfix := g_bugfixes(p_related_bugfix_index);
1200
1201 if (g_globals.debug_on) then
1202 l_debug_bugfix := g_bugfixes(p_bugfix_index);
1203
1204 debug_to_report('Checking (' || l_debug_bugfix.bugfix_id || ' ' ||
1205 p_relation_type || ' ' ||
1206 l_related_bugfix.bugfix_id || ')');
1207 g_globals.indent_level := g_globals.indent_level + 1;
1208 end if;
1209
1213 debug_to_report('Bugfix ' ||
1210 if (l_related_bugfix.application_status in (APP_STATUS_EXPLICITLY_APPLIED,
1211 APP_STATUS_IMPLICITLY_APPLIED)) then
1212 if (g_globals.debug_on) then
1214 l_related_bugfix.bug_number ||
1215 ' is ' || l_related_bugfix.application_status || ', so it is not required.');
1216 end if;
1217 else
1218 if (g_globals.debug_on) then
1219 debug_to_report('Bugfix ' ||
1220 l_related_bugfix.bug_number ||
1221 ' is not applied, so it is required.');
1222 end if;
1223
1224 --
1225 -- This bugfix is required.
1226 --
1227 set_bugfix_required(p_related_bugfix_index, true);
1228 end if;
1229
1230 if (g_globals.debug_on) then
1231 g_globals.indent_level := g_globals.indent_level - 1;
1232 end if;
1233
1234 exception
1235 when others then
1236 raise_others_error('check_bugfix_required',
1237 g_bugfixes(p_bugfix_index).bug_number,
1238 p_relation_type,
1239 g_bugfixes(p_related_bugfix_index).bug_number);
1240 end check_bugfix_required;
1241
1242 --------------------------------------------------------------------------------
1243 procedure check_bugfix_prereqs(p_bugfix_index in binary_integer)
1244 is
1245 --
1246 -- order by is added to get reproducible results in RT.
1247 --
1248 cursor l_prereqs(p_bugfix_guid fnd_ums_bugfixes.bugfix_guid%type) is
1249 select 'AFUMSAEB.pls : $Revision: 120.1 $ : check_bugfix_prereqs' arcs_revision,
1250 fubr.related_bugfix_guid,
1251 fubr.relation_type
1252 from fnd_ums_bugfix_relationships fubr,
1253 fnd_ums_bugfixes fub
1254 where fubr.bugfix_guid = p_bugfix_guid
1255 --
1256 -- - Direct/Indirect Prereq links are followed
1257 --
1258 -- fubr.related_bugfix
1259 -- /|\
1260 -- |
1261 -- |P/P'
1262 -- |
1263 -- |
1264 -- fubr.bugfix
1265 --
1266 and fubr.relation_type in (fnd_ums_loader.REL_TYPE_PREREQS,
1267 fnd_ums_loader.REL_TYPE_INDIRECTLY_PREREQS)
1268 and fub.bugfix_guid = fubr.related_bugfix_guid
1269 order by decode(fubr.relation_type,
1270 fnd_ums_loader.REL_TYPE_INDIRECTLY_PREREQS, 1,
1271 fnd_ums_loader.REL_TYPE_PREREQS, 2,
1272 99),
1273 fub.bug_number;
1274
1275 l_bugfix bugfix;
1276 l_related_bugfix bugfix;
1277 begin
1278 l_bugfix := g_bugfixes(p_bugfix_index);
1279
1280 if (g_globals.debug_on) then
1281 debug_to_report('BEGIN bugfix ' || l_bugfix.bugfix_id);
1282
1283 g_globals.indent_level := g_globals.indent_level + 1;
1284
1285 debug_to_report('release status = ' || l_bugfix.release_status);
1286 debug_to_report('AD application status = ' || l_bugfix.ad_application_status);
1287 end if;
1288
1289 if (l_bugfix.patch_type = PATCH_TYPE_NLS_PATCH) then
1290 -- NLS Patch. Create a Prereq link on the fly to the 'US' version of
1291 -- the same bugfix.
1292
1293 l_related_bugfix := get_bugfix(p_release_name => l_bugfix.release_name,
1294 p_bug_number => l_bugfix.bug_number,
1295 p_language_code => 'US');
1296
1297 if (g_globals.debug_on) then
1298 debug_to_report('NLS Patch: need to check US patch and its prereqs.');
1299 end if;
1300
1301 check_bugfix_required(l_bugfix.bugfix_index,
1302 fnd_ums_loader.REL_TYPE_PREREQS,
1303 l_related_bugfix.bugfix_index);
1304
1305 if (g_bugfixes(l_related_bugfix.bugfix_index).required) then
1306 check_bugfix_prereqs(l_related_bugfix.bugfix_index);
1307 end if;
1308
1309 elsif (l_bugfix.patch_type = PATCH_TYPE_NLS_BUGFIX) then
1310 -- NLS bugfix
1311
1312 if (g_globals.debug_on) then
1313 debug_to_report('NLS Bugfix: there is nothing to do.');
1314 end if;
1315
1316 elsif (l_bugfix.patch_type = PATCH_TYPE_US_NON_UMS) then
1317 -- US patch without metadata
1318
1319 if (g_globals.debug_on) then
1320 debug_to_report('US, Non-UMS Patch: there is nothing to do.');
1321 end if;
1322
1323 elsif (l_bugfix.patch_type = PATCH_TYPE_US_UMS) then
1324 -- US patch with metadata
1325
1326 if (g_globals.debug_on) then
1327 debug_to_report('US Patch: need to check prereqs.');
1328 end if;
1329
1330 for l_prereq in l_prereqs(l_bugfix.bugfix_guid) loop
1331 l_related_bugfix := get_bugfix(l_prereq.related_bugfix_guid);
1332
1333 check_bugfix_required(l_bugfix.bugfix_index,
1334 l_prereq.relation_type,
1335 l_related_bugfix.bugfix_index);
1336 end loop;
1337 else
1338 raise_formatted_error(ERROR_UMS_PATCH_TYPE,
1339 get_formatted_error('UMS Code Error: ',
1340 'Unexpected patch type: ' || l_bugfix.patch_type));
1341 end if;
1342
1346 end if;
1343 if (g_globals.debug_on) then
1344 g_globals.indent_level := g_globals.indent_level - 1;
1345 debug_to_report('END bugfix ' || l_bugfix.bugfix_id);
1347
1348 exception
1349 when others then
1350 raise_others_error('check_bugfix_prereqs',
1351 g_bugfixes(p_bugfix_index).bug_number);
1352 end check_bugfix_prereqs;
1353
1354 --------------------------------------------------------------------------------
1355 function get_equivalency_result(p_bugfix_index in binary_integer,
1356 p_incoming_path in varchar2)
1357 return varchar2
1358 is
1359 cursor l_equivalents(p_bugfix_guid fnd_ums_bugfixes.bugfix_guid%type) is
1360 select alias_bugfix_guid,
1361 alias_relation_type
1362 from (select fubr.related_bugfix_guid alias_bugfix_guid,
1363 fubr.relation_type alias_relation_type
1364 from fnd_ums_bugfix_relationships fubr
1365 where fubr.bugfix_guid = p_bugfix_guid
1366 and fubr.relation_type = fnd_ums_loader.REL_TYPE_REPLACED_BY
1367 union
1368 select fubr.bugfix_guid alias_bugfix_guid,
1369 fubr.relation_type alias_relation_type
1370 from fnd_ums_bugfix_relationships fubr
1371 where fubr.related_bugfix_guid = p_bugfix_guid
1372 and fubr.relation_type in (fnd_ums_loader.REL_TYPE_INCLUDES,
1373 fnd_ums_loader.REL_TYPE_INDIRECTLY_INCLUDES)) rels,
1374 fnd_ums_bugfixes fub
1375 where 'AFUMSAEB.pls : $Revision: 120.1 $ : get_equivalency_result' is not null
1376 and rels.alias_bugfix_guid = fub.bugfix_guid
1377 order by decode(alias_relation_type,
1378 fnd_ums_loader.REL_TYPE_REPLACED_BY, 1,
1379 fnd_ums_loader.REL_TYPE_INDIRECTLY_INCLUDES, 2,
1380 fnd_ums_loader.REL_TYPE_INCLUDES, 3,
1381 99),
1382 fub.bug_number;
1383
1384 l_bugfix_guids BUGFIX_GUID_ARRAY;
1385 l_relation_types RELATION_TYPE_ARRAY;
1386
1387 l_bugfix bugfix;
1388 l_equivalent_bugfix bugfix;
1389 l_vc2 varchar2(32000);
1390 l_equivalency_result varchar2(30);
1391 begin
1392 -- Since this function is called, increment the call count
1393
1394 g_globals.get_equivalency_call_count := g_globals.get_equivalency_call_count + 1;
1395
1396 if (g_globals.get_equivalency_call_count > MAX_GET_EQUIVALENCY_CALL_COUNT) then
1397 g_bugfixes(p_bugfix_index).equivalency_result := EQUIVALENCY_TERMINATED;
1398 g_bugfixes(p_bugfix_index).equivalency_path := null;
1399 g_bugfixes(p_bugfix_index).equivalent_bugfix_index := null;
1400
1401 goto done;
1402 end if;
1403
1404 l_bugfix := g_bugfixes(p_bugfix_index);
1405
1406 if (l_bugfix.equivalency_result is null) then
1407 -- This is the first time this bugfix is visited.
1408
1409 null;
1410 elsif (l_bugfix.equivalency_result = EQUIVALENCY_TERMINATED) then
1411 -- This bugfix was terminated, it needs to be re-visited.
1412
1413 null;
1414 elsif (l_bugfix.equivalency_result = EQUIVALENCY_IN_PROGRESS) then
1415 -- An equivalency cycle exists.
1416
1417 goto done;
1418 elsif (l_bugfix.equivalency_result in (EQUIVALENCY_COMPLETED_NONE,
1419 EQUIVALENCY_COMPLETED_REQUIRED,
1420 EQUIVALENCY_COMPLETED_MERGED,
1421 EQUIVALENCY_COMPLETED_APPLIED)) then
1422 -- Equivalency visitation was complete for this bugfix.
1423
1424 goto done;
1425 end if;
1426
1427 if (g_globals.debug_on) then
1428 debug_to_report(p_incoming_path ||
1429 ', ' || g_bugfixes(p_bugfix_index).equivalency_result);
1430 end if;
1431
1432 -- This bugfix needs to be processed for equivalency check
1433
1434 if (l_bugfix.application_status in (APP_STATUS_EXPLICITLY_APPLIED,
1435 APP_STATUS_IMPLICITLY_APPLIED)) then
1436 g_bugfixes(p_bugfix_index).equivalency_result := EQUIVALENCY_COMPLETED_APPLIED;
1437 g_bugfixes(p_bugfix_index).equivalency_path := null;
1438 g_bugfixes(p_bugfix_index).equivalent_bugfix_index := p_bugfix_index;
1439
1440 goto done;
1441 end if;
1442
1443 if (l_bugfix.merged) then
1444 g_bugfixes(p_bugfix_index).equivalency_result := EQUIVALENCY_COMPLETED_MERGED;
1445 g_bugfixes(p_bugfix_index).equivalency_path := null;
1446 g_bugfixes(p_bugfix_index).equivalent_bugfix_index := p_bugfix_index;
1447
1448 goto done;
1449 end if;
1450
1451 g_bugfixes(p_bugfix_index).equivalency_result := EQUIVALENCY_IN_PROGRESS;
1452
1453 open l_equivalents(l_bugfix.bugfix_guid);
1454
1455 fetch l_equivalents bulk collect into l_bugfix_guids, l_relation_types
1456 limit MAX_GET_EQUIVALENCY_CALL_COUNT + 1 - g_globals.get_equivalency_call_count;
1457
1458 close l_equivalents;
1459
1460 for i in 1 .. l_bugfix_guids.count loop
1461 l_equivalent_bugfix := get_bugfix(l_bugfix_guids(i));
1462
1463 if (l_relation_types(i) = fnd_ums_loader.REL_TYPE_REPLACED_BY) then
1464 l_vc2 := ' -OR-> ';
1465 elsif (l_relation_types(i) = fnd_ums_loader.REL_TYPE_INCLUDES) then
1469 end if;
1466 l_vc2 := ' <-I- ';
1467 elsif (l_relation_types(i) = fnd_ums_loader.REL_TYPE_INDIRECTLY_INCLUDES) then
1468 l_vc2 := ' <-I''- ';
1470 l_vc2 := l_vc2 || l_equivalent_bugfix.bug_number;
1471
1472 l_equivalency_result := get_equivalency_result(l_equivalent_bugfix.bugfix_index,
1473 p_incoming_path || l_vc2);
1474
1475 if (l_equivalency_result = EQUIVALENCY_TERMINATED) then
1476 g_bugfixes(p_bugfix_index).equivalency_result := l_equivalency_result;
1477 g_bugfixes(p_bugfix_index).equivalency_path := null;
1478 g_bugfixes(p_bugfix_index).equivalent_bugfix_index := null;
1479
1480 goto done;
1481 elsif (l_equivalency_result in (EQUIVALENCY_COMPLETED_REQUIRED,
1482 EQUIVALENCY_COMPLETED_MERGED,
1483 EQUIVALENCY_COMPLETED_APPLIED)) then
1484
1485 g_bugfixes(p_bugfix_index).equivalency_result := l_equivalency_result;
1486 g_bugfixes(p_bugfix_index).equivalency_path :=
1487 l_vc2 || g_bugfixes(l_equivalent_bugfix.bugfix_index).equivalency_path;
1488 g_bugfixes(p_bugfix_index).equivalent_bugfix_index :=
1489 g_bugfixes(l_equivalent_bugfix.bugfix_index).equivalent_bugfix_index;
1490
1491 goto done;
1492 end if;
1493 end loop;
1494
1495 if (l_bugfix.required) then
1496 g_bugfixes(p_bugfix_index).equivalency_result := EQUIVALENCY_COMPLETED_REQUIRED;
1497 g_bugfixes(p_bugfix_index).equivalency_path := null;
1498 g_bugfixes(p_bugfix_index).equivalent_bugfix_index := p_bugfix_index;
1499
1500 goto done;
1501 end if;
1502
1503 g_bugfixes(p_bugfix_index).equivalency_result := EQUIVALENCY_COMPLETED_NONE;
1504 g_bugfixes(p_bugfix_index).equivalency_path := null;
1505 g_bugfixes(p_bugfix_index).equivalent_bugfix_index := null;
1506
1507 goto done;
1508
1509 <<done>>
1510 if (g_globals.debug_on) then
1511 debug_to_report(p_incoming_path ||
1512 ', ' || g_bugfixes(p_bugfix_index).equivalency_result);
1513 end if;
1514
1515 return g_bugfixes(p_bugfix_index).equivalency_result;
1516 exception
1517 when others then
1518 raise_others_error('get_equivalency_result',
1519 g_bugfixes(p_bugfix_index).bug_number,
1520 p_incoming_path);
1521 end get_equivalency_result;
1522
1523 --------------------------------------------------------------------------------
1524 -- Equivalency Removal
1525 -- A required bugfix can be removed if
1526 -- -- it or one of its equivalents is applied, or
1527 -- -- it or one of its equivalents is merged, or
1528 -- -- one of its equivalents is also a required bugfix.
1529 --
1530 -- Equivalency: Bugfix 2 is equivalent to Bugfix 1 if
1531 -- -- Bugfix 2 replaces Bugfix 1 or one of its equivalents, or
1532 -- -- Bugfix 2 includes Bugfix 1 or one of its equivalents
1533 --
1534 --
1535 -- In following pictures Bugfix 2 is equivalent to Bugfix 1.
1536 --
1537 -- -- Bugfix 2 replaces Bugfix 1
1538 --
1539 -- 1 -----> 2
1540 --
1541 -- -- Bugfix 2 includes Bugfix 1
1542 --
1543 -- 1
1544 -- /|\
1545 -- |
1546 -- I |
1547 -- |
1548 -- 2
1549 --
1550 -- -- Bugfix 2 replaces one of Bugfix 1's equivalents
1551 --
1552 -- 1 -----> 3 -----> 2
1553 --
1554 --
1555 -- 1
1556 -- /|\
1557 -- |
1558 -- I |
1559 -- |
1560 -- 3 -----> 2
1561 --
1562 --
1563 -- 1
1564 -- \_
1565 -- \_
1566 -- \_
1567 -- \
1568 -- 3 -----> 2
1569 --
1570 -- -- Bugfix 2 includes one of Bugfix 1's equivalents
1571 --
1572 -- 1 -----> 3
1573 -- /|\
1574 -- |
1575 -- | I
1576 -- |
1577 -- 2
1578 --
1579 --
1580 -- 1
1581 -- /|\
1582 -- |
1583 -- I |
1584 -- |
1585 -- 3
1586 -- /|\
1587 -- |
1588 -- I |
1589 -- |
1590 -- 2
1591 --
1592 --
1593 -- 1
1594 -- \_
1595 -- \_
1596 -- \_
1597 -- \
1598 -- 3
1599 -- /|\
1600 -- |
1601 -- I |
1602 -- |
1603 -- 2
1604 --
1605 --------------------------------------------------------------------------------
1606 procedure do_equivalency_removal
1607 is
1608 l_required_bugfix_count binary_integer;
1609 l_required_bugfix_indexes BINARY_INTEGER_ARRAY;
1610
1611 l_bugfix_index binary_integer;
1612 l_equivalency_result varchar2(30);
1613 begin
1614 -- Copy current required bugfix indexes to a local array
1615
1619 end loop;
1616 l_required_bugfix_count := g_globals.required_bugfix_count;
1617 for i in 0 .. g_globals.required_bugfix_count - 1 loop
1618 l_required_bugfix_indexes(i) := g_globals.required_bugfix_indexes(i);
1620
1621 for i in 0 .. l_required_bugfix_count - 1 loop
1622
1623 l_bugfix_index := l_required_bugfix_indexes(i);
1624
1625 if (g_globals.debug_on) then
1626 if (i > 0) then
1627 debug_to_report('');
1628 end if;
1629 debug_to_report('Post processing ' || g_bugfixes(l_bugfix_index).bug_number);
1630 g_globals.indent_level := g_globals.indent_level + 1;
1631 end if;
1632
1633 -- Get equivalency result of this bugfix
1634
1635 g_globals.get_equivalency_call_count := 0;
1636
1637 l_equivalency_result := get_equivalency_result(l_bugfix_index,
1638 g_bugfixes(l_bugfix_index).bug_number);
1639
1640 if (g_globals.debug_on) then
1641 debug_to_report('Number of get_equivalency_result() calls : ' || g_globals.get_equivalency_call_count);
1642 end if;
1643
1644 if (((l_equivalency_result = EQUIVALENCY_COMPLETED_REQUIRED) and
1645 (g_bugfixes(l_bugfix_index).equivalent_bugfix_index <> l_bugfix_index)) or
1646 (l_equivalency_result in (EQUIVALENCY_COMPLETED_MERGED,
1647 EQUIVALENCY_COMPLETED_APPLIED))) then
1648
1649 set_bugfix_required(l_bugfix_index, false);
1650
1651 if (g_globals.debug_on) then
1652 debug_to_report('Equivalency Removal: ' ||
1653 g_bugfixes(l_bugfix_index).bugfix_id ||
1654 ' is not required since it has an ' ||
1655 l_equivalency_result || ' equivalent bugfix.');
1656 debug_to_report('Equivalency Path : ' ||
1657 g_bugfixes(l_bugfix_index).bug_number ||
1658 g_bugfixes(l_bugfix_index).equivalency_path);
1659 end if; -- debug
1660 end if;
1661
1662 if (g_globals.debug_on) then
1663 g_globals.indent_level := g_globals.indent_level - 1;
1664 end if;
1665 end loop; -- init_required_bugfix_indexes
1666
1667 exception
1668 when others then
1669 raise_others_error('do_equivalency_removal');
1670 end do_equivalency_removal;
1671
1672 --------------------------------------------------------------------------------
1673 procedure post_process_required_bugfixes
1674 is
1675 l_count number;
1676 begin
1677 if (g_globals.required_bugfix_count > 0) then
1678 if (g_globals.debug_on) then
1679 l_count := g_globals.required_bugfix_count;
1680 debug_to_report(' ');
1681 debug_to_report('Post processing required bugfixes');
1682 debug_to_report('--------------------------------------------------');
1683 end if;
1684
1685 do_equivalency_removal();
1686
1687 if (g_globals.debug_on) then
1688 l_count := l_count - g_globals.required_bugfix_count;
1689
1690 debug_to_report('--------------------------------------------------');
1691 if (l_count = 0) then
1692 debug_to_report('Nothing was removed from the required bugfixes list.');
1693 else
1694 if (l_count = 1) then
1695 debug_to_report('1 bugfix was removed from the required bugfixes list.');
1696 else
1697 debug_to_report(l_count || ' bugfixes were removed from the required bugfixes list.');
1698 end if;
1699 debug_array_to_report('Required Bugfixes');
1700 end if;
1701 end if;
1702 end if;
1703 exception
1704 when others then
1705 raise_others_error('post_process_required_bugfixes');
1706 end post_process_required_bugfixes;
1707
1708 --------------------------------------------------------------------------------
1709 -- Gets the return status.
1710 --
1711 -- return: the return status
1712 --------------------------------------------------------------------------------
1713 function get_return_status
1714 return varchar2
1715 is
1716 l_status varchar2(30);
1717 l_all_top_level_bugs_applied boolean;
1718 l_missing_top_level_bug_info boolean;
1719 begin
1720 l_status := null;
1721
1722 -- STATUS_ERROR
1723 -- Code doesn't come here in case of error.
1724
1725 -- STATUS_OBSOLETED
1726
1727 if (g_globals.obs_top_level_bugfix_exists) then
1728 -- there is an obsolete top-level bugfix
1729
1730 l_status := STATUS_OBSOLETED;
1731 goto done;
1732 end if;
1733
1734 -- STATUS_MISSING
1735
1736 if (g_globals.required_bugfix_count > 0) then
1737 -- there is a missing prereq
1738
1739 l_status := STATUS_MISSING;
1740 goto done;
1741 end if;
1742
1743 -- STATUS_APPLIED
1744
1745 l_all_top_level_bugs_applied := true;
1746
1747 for i in 0 .. g_globals.top_level_bugfix_count - 1 loop
1748 if (g_bugfixes(i).application_status <> APP_STATUS_EXPLICITLY_APPLIED) then
1749 l_all_top_level_bugs_applied := false;
1750 exit;
1751 end if;
1752 end loop;
1753
1754 if (l_all_top_level_bugs_applied) then
1758 goto done;
1755 -- all top-level bugfixes are already applied
1756
1757 l_status := STATUS_APPLIED;
1759 end if;
1760
1761 -- STATUS_NO_INFORMATION
1762
1763 l_missing_top_level_bug_info := false;
1764
1765 for i in 0 .. g_globals.top_level_bugfix_count - 1 loop
1766 if ((g_bugfixes(i).application_status <> APP_STATUS_EXPLICITLY_APPLIED) and
1767 (g_bugfixes(i).patch_type = PATCH_TYPE_US_NON_UMS)) then
1768 l_missing_top_level_bug_info := true;
1769 exit;
1770 end if;
1771 end loop;
1772
1773 if (l_missing_top_level_bug_info) then
1774 -- at least one un-applied top-level bugfix is a US_NON_UMS bugfix
1775
1776 l_status := STATUS_NO_INFORMATION;
1777 goto done;
1778 end if;
1779
1780 -- STATUS_READY;
1781
1782 -- none of the top-level bugfixes is obsolete
1783 -- nothing is missing
1784 -- at least one bugfix is unapplied
1785 -- none of the unapplied top-level bugfixes is US_NON_UMS
1786
1787 l_status := STATUS_READY;
1788
1789 <<done>>
1790 return l_status;
1791
1792 exception
1793 when others then
1794 raise_others_error('get_return_status');
1795 end get_return_status;
1796
1797 --------------------------------------------------------------------------------
1798 -- Prints information about the bugfix.
1799 --
1800 -- p_symbol - symbol
1801 -- p_bugfix_index - bugfix index
1802 --------------------------------------------------------------------------------
1803 procedure report_one_bugfix(p_symbol in varchar2,
1804 p_bugfix_index in binary_integer)
1805 is
1806 l_bugfix bugfix;
1807 l_replacement_bugfix_guid fnd_ums_bugfixes.bugfix_guid%type;
1808 l_replacement_bugfix bugfix;
1809 begin
1810 l_bugfix := g_bugfixes(p_bugfix_index);
1811
1812 -- write the symbol, bugfix id, application short name, and abstract
1813 append_to_report('');
1814 append_to_report(p_symbol || ' ' || l_bugfix.bugfix_id || ' ' ||
1815 l_bugfix.application_short_name || ': ' || l_bugfix.abstract);
1816
1817 if (l_bugfix.release_status = RSTATUS_OBSOLETED) then
1818 append_to_report(' Action required: This patch is obsoleted, please use a replacement patch instead.');
1819
1820 l_replacement_bugfix_guid := get_replacement_bugfix_guid(l_bugfix.bugfix_guid,
1821 REPLACEMENT_LAST_NON_OBSOLETE);
1822
1823 if (l_replacement_bugfix_guid is not null) then
1824 l_replacement_bugfix := get_bugfix(l_replacement_bugfix_guid);
1825
1826 append_to_report(' Latest replacement: ' ||
1827 l_replacement_bugfix.bugfix_id || ' ' ||
1828 l_replacement_bugfix.application_short_name || ': ' ||
1829 l_replacement_bugfix.abstract);
1830 end if;
1831 end if;
1832
1833 if (g_globals.debug_on) then
1834 append_to_report(' Release status: ' || l_bugfix.release_status);
1835 append_to_report(' Application status: ' || l_bugfix.application_status);
1836 end if;
1837
1838 exception
1839 when others then
1840 raise_others_error('report_one_bugfix',
1841 p_symbol,
1842 g_bugfixes(p_bugfix_index).bug_number);
1843 end report_one_bugfix;
1844
1845 --------------------------------------------------------------------------------
1846 -- Produces the report
1847 --------------------------------------------------------------------------------
1848 procedure produce_report
1849 is
1850 l_bugfix bugfix;
1851 l_symbol varchar2(10);
1852 l_symbol_obsoleted_used boolean := false;
1853 l_symbol_missing_used boolean := false;
1854 l_symbol_applied_used boolean := false;
1855 l_symbol_no_information_used boolean := false;
1856 l_symbol_not_applied_used boolean := false;
1857 begin
1858 -- Output the facts about analyzed bugfixes
1859
1860 -- obsoleted top level bugfixes (UMS)
1861 -- required bugfixes (UMS)
1862 -- applied top level bugfixes (UMS or non-UMS)
1863 -- not applied, no information top level bugfixes (non-UMS)
1864 -- not applied top level bugfixes (UMS)
1865
1866 for i in 0 .. g_globals.required_bugfix_count - 1 loop
1867
1868 l_symbol := SYMBOL_MISSING;
1869 l_symbol_missing_used := true;
1870
1871 report_one_bugfix(l_symbol, g_globals.required_bugfix_indexes(i));
1872 end loop;
1873
1874 -- top level bugfixes (obsoleted, applied or not applied)
1875
1876 for i in 0 .. g_globals.top_level_bugfix_count - 1 loop
1877 l_bugfix := g_bugfixes(i);
1878
1879 if (not l_bugfix.required) then
1880
1881 if (l_bugfix.release_status = RSTATUS_OBSOLETED) then
1882 -- flag the bugfix as obsoleted
1883
1884 l_symbol := SYMBOL_OBSOLETED;
1885 l_symbol_obsoleted_used := true;
1886
1887 elsif (l_bugfix.application_status = APP_STATUS_EXPLICITLY_APPLIED) then
1888 -- flag the bugfix as being already applied
1889
1890 l_symbol := SYMBOL_APPLIED;
1891 l_symbol_applied_used := true;
1892
1893 elsif (l_bugfix.patch_type = PATCH_TYPE_US_NON_UMS) then
1897 l_symbol_no_information_used := true;
1894 -- flag the bugfix as not having UMS metadata
1895
1896 l_symbol := SYMBOL_NO_INFORMATION;
1898
1899 else
1900 -- flag the bugfix as not applied
1901
1902 l_symbol := SYMBOL_NOT_APPLIED;
1903 l_symbol_not_applied_used := true;
1904
1905 end if;
1906
1907 report_one_bugfix(l_symbol, l_bugfix.bugfix_index);
1908 end if;
1909 end loop;
1910
1911 -- print the legend
1912
1913 if (l_symbol_missing_used or
1914 l_symbol_obsoleted_used or
1915 l_symbol_applied_used or
1916 l_symbol_no_information_used or
1917 l_symbol_not_applied_used) then
1918
1919 append_to_report('');
1920 append_to_report('Symbol Legend');
1921 append_to_report('-------------');
1922
1923 if (l_symbol_missing_used) then
1924 append_to_report(SYMBOL_MISSING || ': Unapplied prerequisite patch.');
1925 append_to_report(' This prerequisite patch must be applied together with the current patch(es).');
1926 append_to_report(' Please merge this patch with the current patch(es) and apply them together.');
1927 end if;
1928
1929 if (l_symbol_obsoleted_used) then
1930 append_to_report(SYMBOL_OBSOLETED || ': Obsoleted patch.');
1931 append_to_report(' An obsoleted patch cannot be applied.');
1932 append_to_report(' Please apply its replacement instead.');
1933 end if;
1934
1935 if (l_symbol_applied_used) then
1936 append_to_report(SYMBOL_APPLIED || ': Applied patch.');
1937 append_to_report(' This patch is already applied and is about to be re-applied.');
1938 end if;
1939
1940 if (l_symbol_no_information_used) then
1941 append_to_report(SYMBOL_NO_INFORMATION || ': Patch without prerequisite check information.');
1942 append_to_report(' This patch is about to be applied. However, it does not have a prerequisite');
1943 append_to_report(' check information file. Please check its README for any prerequisites.');
1944 append_to_report(' If there are any that have not been applied, please apply them first.');
1945 end if;
1946
1947 if (l_symbol_not_applied_used) then
1948 append_to_report(SYMBOL_NOT_APPLIED || ': Patch with prerequisite check information.');
1949 append_to_report(' This patch is about to be applied.');
1950 end if;
1951
1952 append_to_report('');
1953 end if;
1954
1955 exception
1956 when others then
1957 raise_others_error('produce_report');
1958 end produce_report;
1959
1960 --------------------------------------------------------------------------------
1961 -- Parses the comma-separated list of bug numbers and language codes
1962 -- and extracts them into an array.
1963 --
1964 -- p_bug_list - the comma-separated list of bug numbers and language codes
1965 -- x_bug_count - the number of bugs
1966 -- x_bug_array - the array of bug numbers and language codes
1967 --------------------------------------------------------------------------------
1968 procedure parse_bug_numbers(p_bug_list in varchar2,
1969 x_bug_count out nocopy number,
1970 x_bug_array out nocopy input_bug_array)
1971 is
1972 l_pos number;
1973 l_bug_count number;
1974 l_bug_list varchar2(32000);
1975 l_vc2 varchar2(2000);
1976 l_bug_number number;
1977 l_language_code varchar2(2000);
1978 l_error_message varchar2(2000);
1979 begin
1980 l_bug_count := 0;
1981 l_bug_list := Ltrim(Rtrim(p_bug_list,' '),' ');
1982
1983 if (l_bug_list is null) then
1984 l_error_message := 'Empty bug number and language code list.';
1985 goto return_error;
1986 end if;
1987
1988 --
1989 -- In case of trailing comma ',', adding space will force loop to go one
1990 -- more iteration and ':' is missing error will be displayed.
1991 --
1992 l_bug_list := l_bug_list || ' ';
1993
1994 while l_bug_list is not null loop
1995 l_pos := instr(l_bug_list, ',');
1996
1997 if (l_pos = 0) then
1998 l_pos := length(l_bug_list) + 1;
1999 end if;
2000
2001 l_vc2 := substr(l_bug_list, 1, l_pos - 1);
2002 l_vc2 := ltrim(rtrim(l_vc2, ' '), ' ');
2003 l_bug_list := substr(l_bug_list, l_pos + 1);
2004
2005 -- now we have '<bug_number>:<language_code>'
2006
2007 l_pos := nvl(instr(l_vc2, ':'), 0);
2008
2009 if (l_pos = 0) then
2010 l_error_message := 'Incorrect syntax in ''' || l_vc2 ||
2011 '''. '':'' is missing.';
2012 goto return_error;
2013 end if;
2014
2015 -- get the bug_number.
2016
2017 declare
2018 l_tmp varchar2(2000);
2019 begin
2020 l_tmp := substr(l_vc2, 1, l_pos - 1);
2021 l_bug_number := to_number(l_tmp);
2022 if l_bug_number is null then
2023 l_error_message := 'Incorrect syntax in ''' || l_vc2 ||
2024 '''. <bug_number> is missing.';
2025 goto return_error;
2026 end if;
2027 exception
2028 when others then
2029 l_error_message := 'Incorrect syntax in ''' || l_vc2 ||
2033
2030 '''. <bug_number> is not a number.';
2031 goto return_error;
2032 end;
2034 -- get the language_code.
2035
2036 begin
2037 l_language_code := substr(l_vc2, l_pos + 1);
2038 l_language_code := ltrim(l_language_code, ' ');
2039
2040 if l_language_code is null then
2041 l_error_message := 'Incorrect syntax in ''' || l_vc2 ||
2042 '''. Language code is missing.';
2043 goto return_error;
2044 end if;
2045 end;
2046
2047 x_bug_array(l_bug_count).bug_number := l_bug_number;
2048 x_bug_array(l_bug_count).language_code := l_language_code;
2049 l_bug_count := l_bug_count + 1;
2050 end loop;
2051
2052 x_bug_count := l_bug_count;
2053 return;
2054
2055 <<return_error>>
2056 raise_formatted_error(ERROR_UMS_INVALID_BUG_LIST,
2057 get_formatted_error('Syntax error in p_bug_numbers argument of UMS analysis engine call.',
2058 l_error_message,
2059 'The correct syntax is ' || '''<bug_number>:<language_code>[,<bug_number>:<language_code>]'''));
2060 exception
2061 when others then
2062 raise_others_error('parse_bug_numbers', p_bug_list);
2063 end parse_bug_numbers;
2064
2065 --------------------------------------------------------------------------------
2066 -- Initializes the globals
2067 --
2068 -- p_appl_top_id - APPL_TOP id
2069 -- p_release_name - release name
2070 -- p_bug_numbers - bug numbers
2071 -- p_mode - engine mode
2072 --------------------------------------------------------------------------------
2073 procedure init_globals(p_appl_top_id in number,
2074 p_release_name in varchar2,
2075 p_bug_numbers in varchar2,
2076 p_mode in varchar2)
2077 is
2078 begin
2079 g_globals.appl_top_id := p_appl_top_id;
2080 g_globals.indent_level := 0;
2081 g_globals.top_level_bugfix_count := 0;
2082 g_globals.bugfix_count := 0;
2083 g_globals.required_bugfix_count := 0;
2084 g_globals.report_count := 1;
2085 g_globals.report(1) := '';
2086 g_globals.replacement_chain_tag_counter := 0;
2087 g_globals.obs_top_level_bugfix_exists := false;
2088 g_globals.status := null;
2089 g_globals.exception_depth := 0;
2090 g_globals.prereq_list := null;
2091
2092 if (p_mode = MODE_NORMAL) then
2093 g_globals.debug_on := false;
2094 elsif (p_mode = MODE_DEBUG) then
2095 g_globals.debug_on := true;
2096 else
2097 raise_formatted_error(ERROR_UMS_INVALID_ENGINE_MODE,
2098 get_formatted_error('UMS analysis engine was not called properly.',
2099 p_mode || ' is not a valid UMS analysis engine mode.',
2100 'Valid modes are: ' || MODE_NORMAL || ', ' || MODE_DEBUG));
2101 end if;
2102
2103 g_globals.engine_mode := p_mode;
2104
2105 -- get APPL_TOP info, and report it
2106
2107 declare
2108 l_appl_top_name varchar2(100);
2109 l_applications_system_name varchar2(100);
2110 begin
2111 begin
2112 select 'AFUMSAEB.pls : $Revision: 120.1 $ : init_globals' arcs_revision,
2113 name, applications_system_name
2114 into g_arcs_revision,
2115 l_appl_top_name, l_applications_system_name
2116 from ad_appl_tops
2117 where appl_top_id = p_appl_top_id;
2118 exception
2119 when no_data_found then
2120 if (p_appl_top_id = GLOBAL_APPL_TOP_ID) then
2121 l_appl_top_name := 'GLOBAL APPL_TOP';
2122 else
2123 l_appl_top_name := 'APPL_TOP_ID ' || p_appl_top_id || ' does not exist.';
2124 end if;
2125 l_applications_system_name := l_appl_top_name;
2126 end;
2127
2128 append_to_report('Running UMS analysis engine with the following parameters:');
2129 append_to_report('');
2130 append_to_report('p_appl_top_id = ' || p_appl_top_id);
2131 append_to_report(' appl_top_name = ' || l_appl_top_name);
2132 append_to_report(' applications_system_name = ' || l_applications_system_name);
2133 append_to_report('p_release_name = ' || p_release_name);
2134 append_to_report('p_bug_numbers = ' || p_bug_numbers);
2135 append_to_report('p_mode = ' || p_mode);
2136 exception
2137 when no_data_found then
2138 raise_formatted_error(ERROR_UMS_INVALID_APPL_TOP_ID,
2139 get_formatted_error('UMS analysis engine was called with an invalid appl_top_id.',
2140 'The appl_top_id ' || p_appl_top_id || ' does not exist.'));
2141 end;
2142
2143 -- parse the bug numbers and the language codes
2144
2145 declare
2146 l_bugfix bugfix;
2147
2148 l_input_bug_count number;
2149 l_input_bug_array input_bug_array;
2150 begin
2151 parse_bug_numbers(p_bug_numbers, l_input_bug_count, l_input_bug_array);
2152
2153 -- create top-level bugfixes in the global cache.
2154
2155 for i in 0 .. l_input_bug_count - 1 loop
2156 l_bugfix := get_bugfix(p_release_name,
2157 l_input_bug_array(i).bug_number,
2158 l_input_bug_array(i).language_code);
2159
2163 g_globals.obs_top_level_bugfix_exists := true;
2160 g_bugfixes(l_bugfix.bugfix_index).merged := true;
2161
2162 if (l_bugfix.release_status = RSTATUS_OBSOLETED) then
2164 end if;
2165 end loop;
2166
2167 g_globals.top_level_bugfix_count := g_globals.bugfix_count;
2168
2169 for i in 0 .. g_globals.top_level_bugfix_count - 1 loop
2170 g_globals.top_level_bugfix_indexes(i) := i;
2171 end loop;
2172
2173 if (g_globals.debug_on) then
2174 debug_array_to_report('Top Level Bugfixes');
2175 end if;
2176 end;
2177
2178 exception
2179 when others then
2180 raise_others_error('init_globals',
2181 p_appl_top_id,
2182 p_release_name,
2183 p_bug_numbers,
2184 p_mode);
2185 end init_globals;
2186
2187 --------------------------------------------------------------------------------
2188 procedure get_removable_obs_required(px_obs_required_bugfix_index in out nocopy binary_integer,
2189 px_replacement_bugfix_index in out nocopy binary_integer)
2190 is
2191 l_bugfix bugfix;
2192 l_replacement_bugfix bugfix;
2193 l_replacement_bugfix_guid fnd_ums_bugfixes.bugfix_guid%type;
2194 begin
2195 px_obs_required_bugfix_index := null;
2196 px_replacement_bugfix_index := null;
2197
2198 -- Loop over required bugfixes
2199
2200 for i in 0 .. g_globals.required_bugfix_count - 1 loop
2201
2202 l_bugfix := g_bugfixes(g_globals.required_bugfix_indexes(i));
2203
2204 if (l_bugfix.release_status = RSTATUS_OBSOLETED) then
2205
2206 -- See if this bugfix has a first non obsolete bugfix
2207
2208 l_replacement_bugfix_guid := get_replacement_bugfix_guid(l_bugfix.bugfix_guid,
2209 REPLACEMENT_FIRST_NON_OBSOLETE);
2210
2211 if (l_replacement_bugfix_guid is not null) then
2212
2213 l_replacement_bugfix := get_bugfix(l_replacement_bugfix_guid);
2214
2215 -- This obsolete required bugfix is removable.
2216
2217 px_obs_required_bugfix_index := l_bugfix.bugfix_index;
2218 px_replacement_bugfix_index := l_replacement_bugfix.bugfix_index;
2219
2220 exit; -- from the required bugfix loop
2221 end if;
2222 end if;
2223 end loop;
2224
2225 exception
2226 when others then
2227 raise_others_error('get_removable_obs_required');
2228 end get_removable_obs_required;
2229
2230 --------------------------------------------------------------------------------
2231 procedure get_rid_of_obsolete_prereqs
2232 is
2233 l_obs_required_bugfix_index binary_integer;
2234 l_replacement_bugfix_index binary_integer;
2235 begin
2236 if (g_globals.required_bugfix_count > 0) then
2237 -- Try to get rid of obsolete prereqs
2238
2239 get_removable_obs_required(l_obs_required_bugfix_index,
2240 l_replacement_bugfix_index);
2241
2242 if (l_obs_required_bugfix_index is not null) then
2243 if (g_globals.debug_on) then
2244 debug_to_report(' ');
2245 debug_to_report('Trying to get rid of obsolete prereqs:');
2246 debug_to_report('--------------------------------------------------');
2247 end if;
2248 end if;
2249
2250 while (l_obs_required_bugfix_index is not null) loop
2251
2252 -- We have a removable obsolete required bugfix
2253
2254 if (g_globals.debug_on) then
2255 debug_to_report('Obsolete Prereq:' || g_bugfixes(l_obs_required_bugfix_index).bugfix_id);
2256 debug_to_report('Replacement :' || g_bugfixes(l_replacement_bugfix_index).bugfix_id);
2257 debug_to_report(' ');
2258 end if;
2259
2260 -- perform the dependency analysis
2261
2262 check_bugfix_prereqs(l_replacement_bugfix_index);
2263
2264 set_bugfix_required(l_replacement_bugfix_index, true);
2265
2266 set_bugfix_required(l_obs_required_bugfix_index, false);
2267
2268 if (g_globals.debug_on) then
2269 debug_array_to_report('Required Bugfixes');
2270 end if;
2271
2272 get_removable_obs_required(l_obs_required_bugfix_index,
2273 l_replacement_bugfix_index);
2274 end loop;
2275 end if;
2276 exception
2277 when others then
2278 raise_others_error('get_rid_of_obsolete_prereqs');
2279 end get_rid_of_obsolete_prereqs;
2280
2281 --------------------------------------------------------------------------------
2282 procedure check_top_level_bugfix_prereqs
2283 is
2284 begin
2285 if (g_globals.debug_on) then
2286 debug_to_report(' ');
2287 debug_to_report('Checking prereqs of top level bugfixes:');
2288 debug_to_report('--------------------------------------------------');
2289 end if;
2290
2291 for i in 0 .. g_globals.top_level_bugfix_count - 1 loop
2292 check_bugfix_prereqs(g_globals.top_level_bugfix_indexes(i));
2293 end loop;
2294
2295 if (g_globals.debug_on) then
2296 debug_array_to_report('Required Bugfixes');
2297 end if;
2298 exception
2299 when others then
2300 raise_others_error('check_top_level_bugfix_prereqs');
2301 end check_top_level_bugfix_prereqs;
2302
2303 --------------------------------------------------------------------------------
2304 procedure analyze_dependencies(p_appl_top_id in number,
2305 p_release_name in varchar2,
2306 p_bug_numbers in varchar2,
2307 p_mode in varchar2,
2308 x_status out nocopy varchar2)
2309 is
2310 begin
2311 init_globals(p_appl_top_id, p_release_name, p_bug_numbers, p_mode);
2312
2313 -- check for top-level obsoleted bugfixes
2314
2315 if (g_globals.obs_top_level_bugfix_exists) then
2316 goto done;
2317 end if;
2318
2319 -- check prereqs of top level bugfixes
2320
2321 check_top_level_bugfix_prereqs();
2322
2323 -- get rid of obsolete prereqs
2324
2325 get_rid_of_obsolete_prereqs();
2326
2327 -- post process required bugfixes
2328
2329 post_process_required_bugfixes();
2330
2331 <<done>>
2332 -- get the return status
2333
2334 g_globals.status := get_return_status();
2335 g_globals.prereq_list := compute_prereq_list();
2336
2337 -- produce the report
2338
2339 produce_report();
2340
2341 x_status := g_globals.status;
2342 exception
2343 when others then
2344 begin
2345 raise_others_error('analyze_dependencies',
2346 p_appl_top_id,
2347 p_release_name,
2348 p_bug_numbers,
2349 p_mode);
2350 exception
2351 when others then
2352 g_globals.status := STATUS_ERROR;
2353 x_status := g_globals.status;
2354 exception_to_report();
2355 end;
2356 end analyze_dependencies;
2357
2358 --------------------------------------------------------------------------------
2359 function get_prereq_list
2360 return varchar2
2361 is
2362 begin
2363 if (not is_engine_called()) then
2364
2365 raise_formatted_error(ERROR_UMS_ENGINE_NOT_CALLED,
2366 get_formatted_error('State error in get_prereq_list()',
2367 'analyze_dependencies() must be called first.'));
2368
2369 elsif (g_globals.status in (STATUS_OBSOLETED, STATUS_ERROR)) then
2370
2371 raise_formatted_error(ERROR_UMS_ILLEGAL_STATE,
2372 get_formatted_error('State error in get_prereq_list()',
2373 'Prereq list is not defined in ' || STATUS_OBSOLETED ||
2374 ' and ' || STATUS_ERROR || ' statuses.'));
2375
2376 end if;
2377
2378 return g_globals.prereq_list;
2379 exception
2380 when others then
2381 begin
2382 raise_others_error('get_prereq_list');
2383 exception
2384 when others then
2385 exception_to_report();
2386 raise;
2387 end;
2388 end get_prereq_list;
2389
2390 --------------------------------------------------------------------------------
2391 function get_report_count return number
2392 is
2393 begin
2394 return g_globals.report_count;
2395 end get_report_count;
2396
2397 --------------------------------------------------------------------------------
2398 function get_report(i in number) return varchar2
2399 is
2400 begin
2401 return g_globals.report(i);
2402 end get_report;
2403
2404 begin
2405 NEWLINE := fnd_ums_loader.newline();
2406 g_globals.engine_mode := MODE_NOT_CALLED;
2407 end fnd_ums_analysis_engine;