DBA Data[Home] [Help]

PACKAGE BODY: APPS.WF_MAINTENANCE

Source


1 package body WF_MAINTENANCE as
2  /* $Header: wfmtn9b.pls 120.20.12020000.2 2012/07/13 20:42:04 alsosa ship $ */
3 
4 g_CommitCounter NUMBER := 0;
5 g_docommit BOOLEAN := FALSE;
6 
7 -- Types for bulk operations
8 type itemRec is record
9  ( item_type varchar2(8),
10    item_key  varchar2(240)
11  );
12 
13 type itemActRec is record
14  ( item_type        varchar2(8),
15    item_key         varchar2(240),
16    process_activity number
17  );
18 
19 type procActRec is record
20  ( process_item_type varchar2(8),
21    process_name      varchar2(30),
22    process_version   number,
23    instance_label    varchar2(30),
24    instance_id       number
25  );
26 
27 type itemTblType is table of itemRec index by binary_integer;
28 type itemActTblType is table of itemActRec index by binary_integer;
29 type procActTblType is table of procActRec index by binary_integer;
30 type numTblType is table of number index by binary_integer;
31 type rowIdTblType is table of rowid index by binary_integer;
32 
33 itemTbl itemTblType;
34 itemActTbl itemActTblType;
35 procActTbl procActTblType;
36 numTbl numTblType;
37 rowIdTbl rowIdTblType;
38 
39 procedure PerformCommit;
40 
41 -- procedure PropagateChangedName
42 --   Locates all occurrences of an old username and changes to
43 --   the new username.
44 --
45 -- IN:
46 --   OldName - Old Username we are changing from.
47 --   NewName - New Username we are changing to.
48 --   CommitFrequency - Number of updates we perform before commit.
49 --
50 procedure PropagateChangedName(
51   OldName in varchar2,
52   NewName in varchar2,
53   docommit in BOOLEAN )
54 
55 is
56 
57 l_oldname VARCHAR2(320); -- Local Variable of OldName
58 l_newname VARCHAR2(320); -- Local Variable of NewName
59 l_pname VARCHAR2(50) := 'WF_MAINT_COMPLETED_ITEMS';
60 l_pvalue varchar2(10);
61 l_size number := 5000;
62 
63 l_items number;
64 l_ias   number;
65 l_iash  number;
66 l_ntfs  number;
67 l_pas   number;
68 l_rr    number;
69 l_rra   number;
70 l_coms  number;
71 l_ra    number;
72 l_wa    number; --counter of WorlistAccess changes for the user
73 
74 
75 -- Setting up cursors for tables that would store a role name.
76 -- Some tables have columns named 'READ_ROLE' and 'WRITE_ROLE' that
77 -- are not currently used, so they are not included.
78 
79 cursor cItems (l_oldname varchar2) is
80 select ITEM_TYPE, ITEM_KEY
81 from   WF_ITEMS
82 where  OWNER_ROLE = l_oldname;
83 
84 cursor cItems2 (l_oldname varchar2) is
85 select ITEM_TYPE, ITEM_KEY
86 from   WF_ITEMS
87 where  OWNER_ROLE = l_oldname
88 and    END_DATE IS NULL;
89 
90 cursor cItemActivityStatuses (l_oldname varchar2) is
91 select ITEM_TYPE, ITEM_KEY, PROCESS_ACTIVITY
92 from   WF_ITEM_ACTIVITY_STATUSES
93 where  ASSIGNED_USER =  l_oldname;
94 
95 cursor cItemActivityStatuses2 (l_oldname varchar2) is
96 select WIAS.ITEM_TYPE, WIAS.ITEM_KEY, WIAS.PROCESS_ACTIVITY
97 from   WF_ITEM_ACTIVITY_STATUSES WIAS, WF_ITEMS WI
98 where  WIAS.ITEM_TYPE = wi.item_type
99 and    WIAS.ITEM_KEY = wi.item_key
100 and    WI.END_DATE IS NULL
101 and    WIAS.ASSIGNED_USER = l_oldname;
102 
103 cursor cItemActivityStatuses_H (l_oldname varchar2) is
104 select ITEM_TYPE, ITEM_KEY, PROCESS_ACTIVITY
105 from   WF_ITEM_ACTIVITY_STATUSES_H
106 where  ASSIGNED_USER =  l_oldname;
107 
108 cursor cItemActivityStatuses_H2 (l_oldname varchar2) is
109 select WIASH.ITEM_TYPE, WIASH.ITEM_KEY, WIASH.PROCESS_ACTIVITY
110 from   WF_ITEM_ACTIVITY_STATUSES_H WIASH, WF_ITEMS WI
111 where  WIASH.ITEM_TYPE = wi.item_type
112 and    WIASH.ITEM_KEY = wi.item_key
113 and    WI.END_DATE IS NULL
114 and    WIASH.ASSIGNED_USER =  l_oldname;
115 
116 cursor cNotifications (l_oldname varchar2) is
117 select NOTIFICATION_ID
118 from   WF_NOTIFICATIONS
119 where  RECIPIENT_ROLE     = l_oldname
120 or     ORIGINAL_RECIPIENT = l_oldname
121 or     more_info_role     = l_oldname
122 or     from_role          = l_oldname
123 or     responder          = l_oldname;
124 
125 -- Only notifications belonging to active items
126 cursor cNotifications2 (l_oldname varchar2) is
127 select NOTIFICATION_ID
128 from   WF_NOTIFICATIONS WN
129 where  (WN.RECIPIENT_ROLE = l_oldname
130 or     WN.ORIGINAL_RECIPIENT = l_oldname
131 or     WN.MORE_INFO_ROLE = l_oldname
132 or     WN.FROM_ROLE = l_oldname
133 or     WN.RESPONDER = l_oldname)
134 and (exists (select '1'
135             from   WF_ITEM_ACTIVITY_STATUSES WIAS, WF_ITEMS WI
136             where  WIAS.NOTIFICATION_ID = WN.NOTIFICATION_ID
137             and    WIAS.NOTIFICATION_ID is not null
138             and    WIAS.ITEM_TYPE = WI.ITEM_TYPE
139             and    WIAS.ITEM_KEY = WI.ITEM_KEY
140             and    WI.END_DATE IS NULL)
141   or exists (select '1'
142             from   WF_ITEM_ACTIVITY_STATUSES_H WIASH, WF_ITEMS WI
143             where  WIASH.NOTIFICATION_ID = WN.NOTIFICATION_ID
144             and    WIASH.NOTIFICATION_ID is not null
145             and    WIASH.ITEM_TYPE = WI.ITEM_TYPE
146             and    WIASH.ITEM_KEY = WI.ITEM_KEY
147             and    WI.END_DATE IS NULL));
148 
149 cursor cProcessActivities (l_oldname varchar2) is
150 select PROCESS_ITEM_TYPE, PROCESS_NAME, PROCESS_VERSION,
151        INSTANCE_LABEL, INSTANCE_ID
152 from   WF_PROCESS_ACTIVITIES
153 where  PERFORM_ROLE = l_oldname;
154 
155 cursor cRoutingRules (l_oldname varchar2) is
156 select RULE_ID
157 from   WF_ROUTING_RULES
158 where  ROLE = l_oldname
159 or     ACTION_ARGUMENT = l_oldname;
160 
161 cursor cRoutingRuleAttributes (l_oldname varchar2) is
162 select ra.ROWID
163 from   WF_ROUTING_RULE_ATTRIBUTES ra
164 where  ra.TEXT_VALUE = l_oldname
165 and    exists
166        (select null
167         from   wf_message_attributes ma
168         where  ma.name=ra.name
169         and    ma.type='ROLE');
170 
171 cursor cWfComments (l_oldname varchar2) is
172 select rowid
173 from   wf_comments
174 where  from_role = l_oldname
175 or     to_role = l_oldname
176 or     proxy_role = l_oldname;
177 
178 -- Only notifications belonging to active items
179 cursor cWfComments2 (l_oldname varchar2) is
180 select WC.ROWID
181 from   WF_COMMENTS WC
182 where (WC.FROM_ROLE = l_oldname
183 or     WC.TO_ROLE = l_oldname
184 or     WC.PROXY_ROLE = l_oldname)
185 and (exists (select '1'
186             from   WF_ITEM_ACTIVITY_STATUSES WIAS, WF_ITEMS WI
187             where  WIAS.NOTIFICATION_ID = WC.NOTIFICATION_ID
188             and    WIAS.NOTIFICATION_ID is not null
189             and    WIAS.ITEM_TYPE = WI.ITEM_TYPE
190             and    WIAS.ITEM_KEY = WI.ITEM_KEY
191             and    WI.END_DATE IS NULL)
192   or exists (select '1'
193             from   WF_ITEM_ACTIVITY_STATUSES_H WIASH, WF_ITEMS WI
194             where  WIASH.NOTIFICATION_ID = WC.NOTIFICATION_ID
195             and    WIASH.NOTIFICATION_ID is not null
196             and    WIASH.ITEM_TYPE = WI.ITEM_TYPE
197             and    WIASH.ITEM_KEY = WI.ITEM_KEY
198             and    WI.END_DATE IS NULL));
199 
200 cursor cRoleAttributes (l_oldname varchar2) is
201 select wiav.rowid
202 from   wf_item_attribute_values wiav, wf_item_attributes wia
203 where  wia.type = 'ROLE'
204 and    wia.item_type = wiav.item_type
205 and    wia.name = wiav.name
206 and    wiav.text_value = l_oldname;
207 
208 cursor cRoleAttributes2 (l_oldname varchar2) is
209 select wiav.rowid
210 from   wf_item_attribute_values wiav, wf_item_attributes wia
211 where  wia.type = 'ROLE'
212 and    wia.item_type = wiav.item_type
213 and    wia.name = wiav.name
214 and    wiav.text_value = l_oldname
215 and exists (select '1'
216             from  WF_ITEMS WI
217             where WI.ITEM_TYPE = WIAV.ITEM_TYPE
218             and   WI.ITEM_KEY = WIAV.ITEM_KEY
219             and   WI.END_DATE IS NULL);
220 
221 l_roleInfoTAB WF_DIRECTORY.wf_local_roles_tbl_type;
222 
223 cursor cWorklistAccess is
224 select fg.rowid
225 from   FND_GRANTS fg
226 where  fg.GRANTEE_TYPE='USER'
227 and    fg.GRANTEE_ORIG_SYSTEM in ('FND_USR', 'PER')
228 and    fg.PROGRAM_NAME = 'WORKFLOW_UI'
229 and    fg.PARAMETER1=PropagateChangedName.OldName;
230 
231 begin
232 l_newname := upper(substrb(NewName,1,320));
233 l_oldname := upper(substrb(OldName,1,320));
234 
235 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
236   wf_log_pkg.string(wf_log_pkg.level_procedure, 'wf.plsql.wf_maintenance.propagateChangedName',
237                     'Changing old user '||l_oldname||' to new '||l_newname);
238 end if;
239 
240 g_docommit := docommit;
241 
242 
243 /* We check to be sure that old name no longer exists (IE: the name was
244    changed).  If it is we can go ahead and effect the change.
245 
246    If the old name is still active and somewhere else in the directory services
247    we can't change it, so we have to raise the error that the name still
248    exists.
249 
250    We then check to be sure the new name is active and ready to receive
251    the records from the old name.
252 */
253 
254  WF_DIRECTORY.GetRoleInfo2(l_oldName, l_roleInfoTAB);
255 
256  if (l_roleInfoTAB(1).display_name is not NULL) then
257   if not (WF_DIRECTORY.ChangeLocalUsername(l_oldname, l_newname, FALSE)) then
258     WF_CORE.Token('ROLE', l_oldname);
259     WF_CORE.Token('PROCEDURE', 'PropagateChangedName');
260     WF_CORE.Token('PARAMETER', 'OldName');
261     WF_CORE.Raise('WFMTN_ACTIVEROLE');
262     return;
263   end if;
264  end if;
265 
266  WF_DIRECTORY.GetRoleInfo2(l_newname, l_roleInfoTAB);
267 
268  if  (l_roleInfoTAB(1).display_name is null) then
269    WF_CORE.Token('ROLE', l_newname);
270    WF_CORE.Raise('WFNTF_ROLE');
271    return;
272  end if;
273 
274 
275 /* We will now start looping through the cursors and updating OldName
276    to NewName
277 */
278 l_pvalue := FND_PROFILE.value(l_pname);
279 -- This profile is shipped only for 12.1.X and above at this point. If not
280 -- available, continue to update all records as always.
281 if (l_pvalue is null or l_pvalue = 'Y') then
282 
283   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
284     wf_log_pkg.string(wf_log_pkg.level_statement, 'wf.plsql.wf_maintenance.propagateChangedName',
285                       'Updating all WF data');
286   end if;
287 
288   open cItems(l_oldname);
289   loop
290     fetch cItems bulk collect into itemTbl limit l_size;
291     if (itemTbl.count = 0) then
292       exit;
293     end if;
294 
295     forall i in itemTbl.first..itemTbl.last
296       update wf_items
297       set    owner_role = l_newname
298       where  item_type = itemTbl(i).item_type
299       and    item_key  = itemTbl(i).item_key;
300 
301     commit;
302     itemTbl.delete;
303   end loop;
304   l_items := cItems%rowcount;
305   close cItems;
306 
307   open cItemActivityStatuses(l_oldname);
308   loop
309     fetch cItemActivityStatuses bulk collect into itemActTbl limit l_size;
310     if (itemActTbl.count = 0) then
311       exit;
312     end if;
313 
314     forall i in itemActTbl.first..itemActTbl.last
315       update WF_ITEM_ACTIVITY_STATUSES
316       set    ASSIGNED_USER = l_newname
317       where  ITEM_TYPE = itemActTbl(i).item_type
318       and    ITEM_KEY = itemActTbl(i).item_key
319       and    PROCESS_ACTIVITY = itemActTbl(i).process_activity;
320 
321     commit;
322     itemActTbl.delete;
323   end loop;
324   l_ias := cItemActivityStatuses%rowcount;
325   close cItemActivityStatuses;
326 
327   open cItemActivityStatuses_H(l_oldname);
328   loop
329     fetch cItemActivityStatuses_H bulk collect into itemActTbl limit l_size;
330     if (itemActTbl.count = 0) then
331       exit;
332     end if;
333 
334     forall i in itemActTbl.first..itemActTbl.last
335       update WF_ITEM_ACTIVITY_STATUSES_H
336       set    ASSIGNED_USER = l_newname
337       where  ITEM_TYPE = itemActTbl(i).item_type
338       and    ITEM_KEY = itemActTbl(i).item_key
339       and    PROCESS_ACTIVITY = itemActTbl(i).process_activity;
340 
341     commit;
342     itemActTbl.delete;
343   end loop;
344   l_iash := cItemActivityStatuses_H%rowcount;
345   close cItemActivityStatuses_H;
346 
347   open cNotifications (l_oldname);
348   loop
349     fetch cNotifications bulk collect into numTbl limit l_size;
350     if (numTbl.count = 0) then
351       exit;
352     end if;
353 
354     forall i in numTbl.first..numTbl.last
355       update WF_NOTIFICATIONS
356       set    RECIPIENT_ROLE = decode(RECIPIENT_ROLE, l_oldname, l_newname, RECIPIENT_ROLE),
357              ORIGINAL_RECIPIENT = decode(ORIGINAL_RECIPIENT, l_oldname, l_newname, ORIGINAL_RECIPIENT),
358              FROM_ROLE = decode(FROM_ROLE, l_oldname, l_newname, FROM_ROLE),
359              RESPONDER = decode(RESPONDER, l_oldname, l_newname, RESPONDER),
360              MORE_INFO_ROLE = decode(MORE_INFO_ROLE, l_oldname, l_newname, MORE_INFO_ROLE)
361       where  NOTIFICATION_ID = numTbl(i);
362     commit;
363 
364     numTbl.delete;
365   end loop;
366   l_ntfs := cNotifications%rowcount;
367   close cNotifications;
368 
369   open cWfComments(l_oldname);
370   loop
371     fetch cWfComments bulk collect into rowIdTbl limit l_size;
372     if (rowIdTbl.count = 0) then
373       exit;
374     end if;
375 
376     forall i in rowIdTbl.first..rowIdTbl.last
377       update WF_COMMENTS
378       set    FROM_ROLE = decode(FROM_ROLE, l_oldname, l_newname, FROM_ROLE),
379              FROM_USER = decode(FROM_ROLE, l_oldname, l_roleInfoTAB(1).display_name, FROM_USER),
380              TO_ROLE = decode(TO_ROLE, l_oldname, l_newname, TO_ROLE),
381              TO_USER = decode(TO_ROLE, l_oldname, l_roleInfoTAB(1).display_name, TO_USER),
382              PROXY_ROLE = decode(PROXY_ROLE, l_oldname, l_newname, PROXY_ROLE)
383       where rowid = rowIdTbl(i);
384     commit;
385 
386     rowIdTbl.delete;
387   end loop;
388   l_coms := cWfComments%rowcount;
389   close cWfComments;
390 
391   open cRoleAttributes(l_oldname);
392   loop
393     fetch cRoleAttributes bulk collect into rowIdTbl limit l_size;
394     if (rowIdTbl.count = 0) then
395       exit;
396     end if;
397 
398     forall i in rowIdTbl.first..rowIdTbl.last
399       update WF_ITEM_ATTRIBUTE_VALUES
400       set    TEXT_VALUE = l_newname
401       where  rowid = rowIdTbl(i);
402     commit;
403 
404     rowIdTbl.delete;
405   end loop;
406   l_ra := cRoleAttributes%rowcount;
407   close cRoleAttributes;
408 
409 else   -- End profile = 'Y'
410 
411   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
412     wf_log_pkg.string(wf_log_pkg.level_statement, 'wf.plsql.wf_maintenance.propagateChangedName',
413                       'Updating only Active WF data');
414   end if;
415 
416   open cItems2(l_oldname);
417   loop
418     fetch cItems2 bulk collect into itemTbl limit l_size;
419     if (itemTbl.count = 0) then
420       exit;
421     end if;
422 
423     forall i in itemTbl.first..itemTbl.last
424       update wf_items
425       set    owner_role = l_newname
426       where  item_type = itemTbl(i).item_type
427       and    item_key  = itemTbl(i).item_key;
428     commit;
429 
430     itemTbl.delete;
431   end loop;
432   l_items := cItems2%rowcount;
433   close cItems2;
434 
435   open cItemActivityStatuses2(l_oldname);
436   loop
437     fetch cItemActivityStatuses2 bulk collect into itemActTbl limit l_size;
438     if (itemActTbl.count = 0) then
439       exit;
440     end if;
441 
442     forall i in itemActTbl.first..itemActTbl.last
443       update WF_ITEM_ACTIVITY_STATUSES
444       set    ASSIGNED_USER = l_newname
445       where  ITEM_TYPE = itemActTbl(i).item_type
446       and    ITEM_KEY = itemActTbl(i).item_key
447       and    PROCESS_ACTIVITY = itemActTbl(i).process_activity;
448     commit;
449 
450     itemActTbl.delete;
451   end loop;
452   l_ias := cItemActivityStatuses2%rowcount;
453   close cItemActivityStatuses2;
454 
455   open cItemActivityStatuses_H2(l_oldname);
456   loop
457     fetch cItemActivityStatuses_H2 bulk collect into itemActTbl limit l_size;
458     if (itemActTbl.count = 0) then
459       exit;
460     end if;
461 
462     forall i in itemActTbl.first..itemActTbl.last
463       update WF_ITEM_ACTIVITY_STATUSES_H
464       set    ASSIGNED_USER = l_newname
465       where  ITEM_TYPE = itemActTbl(i).item_type
466       and    ITEM_KEY = itemActTbl(i).item_key
467       and    PROCESS_ACTIVITY = itemActTbl(i).process_activity;
468     commit;
469 
470     itemActTbl.delete;
471   end loop;
472   l_iash := cItemActivityStatuses_H2%rowcount;
473   close cItemActivityStatuses_H2;
474 
475   open cNotifications2 (l_oldname);
476   loop
477     fetch cNotifications2 bulk collect into numTbl limit l_size;
478     if (numTbl.count = 0) then
479       exit;
480     end if;
481 
482     forall i in numTbl.first..numTbl.last
483       update WF_NOTIFICATIONS
484       set    RECIPIENT_ROLE = decode(RECIPIENT_ROLE, l_oldname, l_newname, RECIPIENT_ROLE),
485              ORIGINAL_RECIPIENT = decode(ORIGINAL_RECIPIENT, l_oldname, l_newname, ORIGINAL_RECIPIENT),
486              FROM_ROLE = decode(FROM_ROLE, l_oldname, l_newname, FROM_ROLE),
487              RESPONDER = decode(RESPONDER, l_oldname, l_newname, RESPONDER),
488              MORE_INFO_ROLE = decode(MORE_INFO_ROLE, l_oldname, l_newname, MORE_INFO_ROLE)
489       where  NOTIFICATION_ID = numTbl(i);
490     commit;
491 
492     numTbl.delete;
493   end loop;
494   l_ntfs := cNotifications2%rowcount;
495   close cNotifications2;
496 
497   open cWfComments2(l_oldname);
498   loop
499     fetch cWfComments2 bulk collect into rowIdTbl limit l_size;
500     if (rowIdTbl.count = 0) then
501       exit;
502     end if;
503 
504     forall i in rowIdTbl.first..rowIdTbl.last
505       update WF_COMMENTS
506       set    FROM_ROLE = decode(FROM_ROLE, l_oldname, l_newname, FROM_ROLE),
507              FROM_USER = decode(FROM_ROLE, l_oldname, l_roleInfoTAB(1).display_name, FROM_USER),
508              TO_ROLE = decode(TO_ROLE, l_oldname, l_newname, TO_ROLE),
509              TO_USER = decode(TO_ROLE, l_oldname, l_roleInfoTAB(1).display_name, TO_USER),
510              PROXY_ROLE = decode(PROXY_ROLE, l_oldname, l_newname, PROXY_ROLE)
511       where rowid = rowIdTbl(i);
512     commit;
513 
514     rowIdTbl.delete;
515   end loop;
516   l_coms := cWfComments2%rowcount;
517   close cWfComments2;
518 
519   open cRoleAttributes2(l_oldname);
520   loop
521     fetch cRoleAttributes2 bulk collect into rowIdTbl limit l_size;
522     if (rowIdTbl.count = 0) then
523       exit;
524     end if;
525 
526     forall i in rowIdTbl.first..rowIdTbl.last
527       update WF_ITEM_ATTRIBUTE_VALUES
528       set    TEXT_VALUE = l_newname
529       where  rowid = rowIdTbl(i);
530     commit;
531 
532     rowIdTbl.delete;
533   end loop;
534   l_ra := cRoleAttributes2%rowcount;
535   close cRoleAttributes2;
536 
537 end if; -- End profile = 'N'
538 
539 open cProcessActivities(l_oldname);
540 loop
541   fetch cProcessActivities bulk collect into procActTbl limit l_size;
542   if (procActTbl.count = 0) then
543     exit;
544   end if;
545 
546   forall i in procActTbl.first..procActTbl.last
547     update WF_PROCESS_ACTIVITIES
548     set    PERFORM_ROLE = l_newname
549     where  PROCESS_ITEM_TYPE = procActTbl(i).process_item_type
550     and    PROCESS_NAME = procActTbl(i).process_name
551     and    PROCESS_VERSION = procActTbl(i).process_version
552     and    INSTANCE_LABEL = procActTbl(i).instance_label
553     and    INSTANCE_ID = procActTbl(i).instance_id;
554   commit;
555 
556   procActTbl.delete;
557 end loop;
558 l_pas := cProcessActivities%rowcount;
559 close cProcessActivities;
560 
561 open cRoutingRules(l_oldname);
562 loop
563   fetch cRoutingRules bulk collect into numTbl limit l_size;
564   if (numTbl.count = 0) then
565     exit;
566   end if;
567 
568   forall i in numTbl.first..numTbl.last
569     update WF_ROUTING_RULES
570     set    ROLE = l_newname
571     where  RULE_ID = numTbl(i)
572     and    ROLE = l_oldname;
573   commit;
574 
575   forall i in numTbl.first..numTbl.last
576     update WF_ROUTING_RULES
577     set    ACTION_ARGUMENT = l_newname
578     where  RULE_ID = numTbl(i)
579     and    ACTION_ARGUMENT = l_oldname;
580   commit;
581 
582   numTbl.delete;
583 end loop;
584 l_rr := cRoutingRules%rowcount;
585 close cRoutingRules;
586 
587 open cRoutingRuleAttributes(l_oldname);
588 loop
589   fetch cRoutingRuleAttributes bulk collect into rowIdTbl limit l_size;
590   if (rowIdTbl.count = 0) then
591     exit;
592   end if;
593 
594   forall i in rowIdTbl.first..rowIdTbl.last
595     update wf_routing_rule_attributes
596     set    text_value = l_newname
597     where  rowid = rowIdTbl(i);
598   commit;
599 
600   rowIdTbl.delete;
601 end loop;
602 l_rra := cRoutingRuleAttributes%rowcount;
603 close cRoutingRuleAttributes;
604 
605 commit;
606 
607 open cWorklistAccess;
608 LOOP
609   FETCH cWorklistAccess BULK COLLECT INTO rowIdTbl LIMIT l_size;
610   if (rowIdTbl.count = 0) then
611     exit;
612   end if;
613   FORALL i IN rowIdTbl.FIRST..rowIdTbl.LAST
614   UPDATE fnd_grants fg
615   SET    fg.parameter1=PropagateChangedName.NewName
616   WHERE  fg.ROWID=rowIdTbl(i);
617   COMMIT;
618   rowIdTbl.DELETE;
619 end LOOP;
620 l_wa := cWorklistAccess%ROWCOUNT;
621 CLOSE cWorklistAccess;
622 
623 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
624   wf_log_pkg.string(wf_log_pkg.level_statement, 'wf.plsql.wf_maintenance.propagateChangedName',
625                     'Updated Records: WF_ITEMS:'||l_items||', WF_IAS:'||l_ias||', WF_IASH:'
626                      ||l_iash||', WF_NTFS:'||l_ntfs||', WF_COMMENTS:'||l_coms);
627   wf_log_pkg.string(wf_log_pkg.level_statement, 'wf.plsql.wf_maintenance.propagateChangedName',
628                     'Updated Records: WF_PROC_ACTS:'||l_pas||', WF_ROUTING_RULES:'||l_rr
629                     ||', WF_ROUTING_RULE_ATTRS:' ||l_rra||', WF_ITEM_ATTR_VALUES:'||l_ra
630                     ||', WORKLIST_ACCESS:'||l_wa);
631 end if;
632 
633 exception
634  when others then
635    WF_CORE.Context('WF_MAINTENANCE', 'PropagateChangedName', OldName, NewName);
636    raise;
637 end PropagateChangedName;
638 
639 -- procedure PerformCommit (private)
640 --   Decides if commit should occur and commits.
641 --
642 -- IN:
643 --   No Parameters.
644 --
645 procedure PerformCommit
646 
647 IS
648 BEGIN
649 if (g_docommit) then
650  g_commitCounter := g_commitCounter +1;
651  if (g_commitCounter >= WF_MAINTENANCE.g_CommitFrequency) then
652     commit;
653     g_commitCounter := 0;
654  end if;
655 end if;
656 
657 END PerformCommit;
658 
659 -- Procedure FixWURAEffectiveDates (private)
660 -- As part of fix 9184359. Scan table WF_USER_ROLE_ASSIGNMENTS for rows with
661 -- null effective start/end dates and will set them according the the
662 -- values of the other date columns
663 -- IN: No p_maxRows. This parameter comes from main procedure ValidateUserRoles
664 --
665 procedure FixWURAEffectiveDates (p_maxRows IN NUMBER, p_username IN VARCHAR2,
666                                  p_rolename IN VARCHAR2)
667 IS
668 --  TYPE WURARecord is RECORD (l_rowid ROWID,
669 --       start_date date, end_date date, u_start_date date, u_end_date date,
670 --       r_start_date date, r_end_date date, ar_start_date date, ar_end_date date,
671 --       e_start_date date, e_end_date date);
672 --  TYPE WURATab is table of WURARecord index by BINARY_INTEGER;
673   TYPE dateTab is table of date index by binary_integer;
674   l_start_dateTab dateTab;
675   l_end_dateTab dateTab;
676   l_u_start_dateTab dateTab;
677   l_u_end_dateTab dateTab;
678   l_r_start_dateTab dateTab;
679   l_r_end_dateTab dateTab;
680   l_ar_start_dateTab dateTab;
681   l_ar_end_dateTab dateTab;
682   l_e_start_dateTab dateTab;
683   l_e_end_dateTab dateTab;
684   TYPE rowidTab is table of rowid index by binary_integer;
685   l_rowidTab rowidTab;
686   cursor c_nullEffectiveDates is
687   select ROWID, start_date, end_date, user_start_date, user_end_date,
688          role_start_date, role_end_date,
689          assigning_role_start_date, assigning_role_end_date, null, null
690   from   WF_USER_ROLE_ASSIGNMENTS WURA
691   where  (WURA.USER_NAME = p_username or p_username is null)
692   and    (WURA.ROLE_NAME = p_rolename or p_rolename is null)
693   and    (WURA.EFFECTIVE_START_DATE is null
694   or     WURA.EFFECTIVE_END_DATE is null);
695 BEGIN
696   open c_nullEffectiveDates;
697   <<NullEffectiveDates>>
698   loop
699     fetch c_nullEffectiveDates
700     bulk collect
701     into l_rowidTab, l_start_dateTab, l_end_dateTab, l_u_start_dateTab,
702          l_u_end_dateTab, l_r_start_dateTab, l_r_end_dateTab, l_ar_start_dateTab,
703          l_ar_end_dateTab, l_e_start_dateTab, l_e_end_dateTab
704     limit p_maxRows;
705     if l_rowidTab.COUNT > 0 then
706         for i in l_rowidTab.FIRST..l_rowidTab.LAST loop
707           WF_ROLE_HIERARCHY.Calculate_Effective_Dates(l_start_dateTab(i),
708                                                       l_end_dateTab(i),
709                                                       l_u_start_dateTab(i),
710                                                       l_u_end_dateTab(i),
711                                                       l_r_start_dateTab(i),
712                                                       l_r_end_dateTab(i),
713                                                       l_ar_start_dateTab(i),
714                                                       l_ar_end_dateTab(i),
715                                                       l_e_start_dateTab(i),
716                                                       l_e_end_dateTab(i));
717         end loop;
718         begin
719           forall j in l_rowidTab.FIRST.. l_rowidTab.LAST
720             update WF_USER_ROLE_ASSIGNMENTS WURA
721             set    WURA.EFFECTIVE_START_DATE=l_e_start_dateTab(j),
722                    WURA.EFFECTIVE_END_DATE  =l_e_end_dateTab(j)
723             where  WURA.ROWID=l_rowidTab(j);
724         exception
725           when others then
726             if c_nullEffectiveDates%ISOPEN then
727               close c_nullEffectiveDates;
728             end if;
729             raise;
730         end;
731     end if;
732     if l_rowidTab.COUNT < p_maxRows then
733       exit NullEffectiveDates;
734     end if;
735   end loop NullEffectiveDates;
736   close c_nullEffectiveDates;
737 exception
738   when others then
739     if c_nullEffectiveDates%ISOPEN then
740       close c_nullEffectiveDates;
741     end if;
742     raise;
743 END FixWURAEffectiveDates;
744 
745 -- procedure FixLUREffectiveDates (private)
746 --   Fix incorrect Effective_End_Date in WF_LOCAL_USER_ROLES as pert of bug 8423138
747 --
748 -- IN:
749 --   No p_maxRows. This parameter comes from main procedure ValidateUserRoles
750 --
751 procedure FixLUREffectiveDates(p_maxRows IN NUMBER, p_username IN VARCHAR2,
752                                p_rolename IN VARCHAR2)
753 is
754   TYPE idTab   IS TABLE OF ROWID INDEX BY BINARY_INTEGER;
755   TYPE dateTab IS TABLE OF DATE INDEX BY BINARY_INTEGER;
756 
757   type nameTab is table of varchar2(100) index by binary_integer;
758 
759   l_LURTab idTab;
760   l_URAEffectiveStartDate dateTab;
761   l_URAEffectiveEndDate dateTab;
762 
763   cursor c_invalidEffectiveDates is
764   select lur.rowid,
765          ura.effective_start_date,ura.effective_end_date
766   from   wf_local_user_roles lur,
767          (select user_name, role_name, min(effective_start_date) effective_start_date,
768                  max (effective_end_date) effective_end_date
769             from wf_user_role_assignments group by user_name, role_name) ura
770   where  ura.user_name = lur.user_name
771     and  ura.role_name = lur.role_name
772     and  (URA.USER_NAME=p_username or p_username is null)
773     and  (URA.ROLE_NAME=p_rolename or p_rolename is null)
774     and  (ura.effective_start_date <> lur.effective_start_date or
775           ura.effective_end_date <> lur.effective_end_date);
776 
777 begin
778   <<InvalidEffectiveDates>>
779   loop
780     open c_invalidEffectiveDates;
781     fetch c_invalidEffectiveDates bulk collect
782       into  l_LURTab,
783             l_URAEffectiveStartDate,
784             l_URAEffectiveEndDate
785       limit p_maxRows;
786     close c_invalidEffectiveDates;
787     if (l_LURTab.COUNT > 0) then
788       begin
789         forall i in l_LURTab.FIRST..l_LURTab.LAST
790           update WF_LOCAL_USER_ROLES
791           set    EFFECTIVE_START_DATE=l_URAEffectiveStartDate(i),
792                  EFFECTIVE_END_DATE=l_URAEffectiveEndDate(i)
793           where  ROWID = l_LURTab(i);
794       exception
795         when others then
796           if (c_invalidEffectiveDates%ISOPEN) then
797             close c_invalidEffectiveDates;
798           end if;
799         raise;
800       end;
801     end if;
802     if (l_LURTab.COUNT < p_maxRows) then
803       exit InvalidEffectiveDates;
804     end if;
805   end loop InvalidEffectiveDates;
806   exception
807     when others then
808       if c_invalidEffectiveDates%ISOPEN then
809         close c_invalidEffectiveDates;
810       end if;
811       raise;
812 end FixLUREffectiveDates;
813 
814 ------------------------------------------------------------------------------
815 /*
816 ** ValidateUserRoles - Validates and corrects denormalized user and role
817 **                     information in user/role relationships.
818 */
819 PROCEDURE ValidateUserRoles(p_BatchSize in NUMBER,
820                             p_username in varchar2,
821                             p_rolename in varchar2,
822                             p_check_dangling in BOOLEAN,
823                             p_check_missing_ura in BOOLEAN,
824                             p_UpdateWho in BOOLEAN,
825                             p_parallel_processes in number) is
826 
827   ColumnsMissing      EXCEPTION;
828   TooManyRows         EXCEPTION;
829 
830   pragma exception_init(ColumnsMissing, -904);
831   pragma exception_init(TooManyRows, -1422);
832 
833   TYPE charTab IS TABLE OF VARCHAR2(1) INDEX BY BINARY_INTEGER;
834   TYPE dateTab IS TABLE OF DATE 	  INDEX BY BINARY_INTEGER;
835   TYPE numTab  IS TABLE OF NUMBER	  INDEX BY BINARY_INTEGER;
836   TYPE idTab   IS TABLE OF ROWID 	  INDEX BY BINARY_INTEGER;
837   TYPE origTab IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER;
838   TYPE ownerTAGTAB  IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
839 
840   l_roleSrcTAB 	        WF_DIRECTORY.roleTable;
841   l_userSrcTAB 	        WF_DIRECTORY.userTable;
842   l_roleDestTAB 	WF_DIRECTORY.roleTable;
843   l_userDestTAB         WF_DIRECTORY.userTable;
844   l_rowIDTAB            idTab;
845   l_rowIDSrcTAB         idTab;
846   l_rowIDDestTAB        idTab;
847   l_stgIDTAB            idTab;
848   l_userStartSrcTAB     dateTab;
849   l_roleStartSrcTAB     dateTab;
850   l_userEndSrcTAB       dateTab;
851   l_roleEndSrcTAB       dateTab;
852   l_effStartSrcTAB      dateTab;
853   l_effEndSrcTAB        dateTab;
854   l_AssignTAB           charTab;
855   l_userStartDestTAB    dateTab;
856   l_roleStartDestTAB	dateTab;
857   l_userEndDestTAB      dateTab;
858   l_roleEndDestTAB 	dateTab;
859   l_effStartDestTAB     dateTab;
860   l_effEndDestTAB	dateTab;
861   l_relIDTAB	        numTab;
862   l_maxRows	        number;
863   l_userOrigIDSrcTAB    numTab;
864   l_roleOrigIDSrcTAB    numTab;
865   l_userOrigIDDestTAB   numTab;
866   l_roleOrigIDDEstTAB   numTab;
867   l_userOrigSrcTAB	origTab;
868   l_roleOrigSrcTAB      origTab;
869   l_userOrigDestTAB	origTab;
870   l_roleOrigDestTAB     origTab;
871   l_assigningRoleSrcTAB WF_DIRECTORY.roleTable;
872   l_asgStartSrcTAB	dateTab;
873   l_asgEndSrcTAB        dateTab;
874   l_startSrcTAB         dateTab;
875   l_endSrcTAB           dateTab;
876 
877   l_startDestTAB        dateTab;
878   l_endDestTAB          dateTab;
879   l_partTAB             numTab;
880   l_userID              number;
881   l_empID               number;
882 
883   sumTabIndex           number;
884   ur_index              number;
885   l_eIndex              number;
886 
887   l_activeAssigned      boolean;
888   l_updateDateTAB       dateTAB;
889   l_createDateTAB       dateTAB;
890   l_updatedByTAB        numTAB;
891   l_updateLoginTAB      numTAB;
892   l_createdByTAB        numTAB;
893   l_parentOrigTAB       origTAB;
894   l_parentOrigIDTAB     numTAB;
895   l_ownerTAGS           ownerTAGTAB;
896   -- <bug 6823723>
897   l_sql                 varchar2(6000);
898   l_defaultParProc      number;
899   l_parallelProc        varchar2(5);
900 
901   result number;
902   l_lockhandle varchar2(200);
903 
904   -- Bug 6752821. Each cursor will have three more variations depending
905   -- on wheather a username and/or rolename is specified
906   -- cursor named %1 used when both username and rolename are provided
907   -- cursor named %2 used when only username is provided
908   -- cursor named %3 used when only rolename is provided
909   -- cursor named %4 used when none are provided
910 
911   -- Missing records in WF_USER_ROLE_ASSIGNMENTS
912   -- Using same cursor parameter names as Procedures' param names.
913   cursor c_missing_user_role_asg(p_username varchar2, p_rolename varchar2 ) is
914     select user_name, role_name, -1, start_date, expiration_date,
915            created_by, creation_date, last_updated_by, last_update_date,
916            last_update_login, user_start_date, role_start_date,
917            user_end_date, role_end_date, partition_id,
918            effective_start_date, effective_end_date, user_orig_system,
919            user_orig_system_id, role_orig_system, role_orig_system_id,
920            parent_orig_system, parent_orig_system_id, owner_tag
921     from wf_local_user_roles wur
922     where (p_username IS NULL OR wur.user_name=p_username)
923 	   and   (p_rolename IS NULL OR wur.role_name=p_rolename)
924 	   and   not exists (select null
925                       from wf_user_role_assignments wura
926                       where wura.user_name = wur.user_name
927                       and wura.role_name = wur.role_name
928                       and (p_username is null OR wura.user_name = p_username)
929                       and (p_rolename is null or wura.role_name = p_rolename)
930                       );
931 
932 
933   -- Invalid and Duplicated records in the (FND_USR) partition
934   -- For bug 6752821: no need to consider role_name, it does not intervene,
935   -- no (FND_RESP) partition is considered.
936   cursor c_invalid_fnd_users (p_username varchar2) is
937     select wu.rowid, wu.orig_system old_orig_system,
938            wu.orig_system_id old_orig_system_id,
939            decode(nvl(fu.employee_id, -1),-1,'FND_USR','PER') new_orig_system,
940            nvl(fu.employee_id, fu.user_id)
941     from   wf_local_roles partition (FND_USR) wu,
942            fnd_user fu
943     where  wu.name = fu.user_name
944    	and    (p_username is null or wu.name = p_username)
945     and    (wu.orig_system <> decode(nvl(fu.employee_id, -1),-1,'FND_USR','PER')
946             or wu.orig_system_id <> nvl(fu.employee_id, fu.user_id)
947            );
948 
949 
950 	  -- Records with invalid or duplicate FND_USR/PER references
951   -- in WF_LOCAL_USER_ROLES
952   -- For bug 6752821: no need for cursors %2 and %3 as role_name does not intervene,
953   -- no (FND_RESP) partition is considered.
954 
955   cursor c_invalOrigSys (p_username varchar2) is
956    select wu.orig_system, wu.orig_system_id,
957           wur.role_orig_system, wur.role_orig_system_id,
958           wur.partition_id, wur.rowid
959    from   wf_local_user_roles wur,
960           wf_local_roles partition (FND_USR) wu
961    where  (p_username is null or wu.name = p_username )
962    and    wu.name = wur.user_name
963    and    wur.user_orig_system in ('FND_USR','PER')
964    and    (wur.user_orig_system <> wu.orig_system
965           or  wur.user_orig_system_id <> wu.orig_system_id
966              --check for role_orig_system in case of self-reference
967           or (wur.partition_id=1
968               and (wur.role_orig_system <> wu.orig_system
969                     or  wur.role_orig_system_id <> wu.orig_system_id)
970               )
971           );
972 
973 
974 
975   --We will correct the orig_system, orig_system_id information for any
976   --incorrect fnd_usr/per user/role records.  This is processed after the
977   --fnd_usr/per records in wf_local_roles are validated. The dates will be
978   --resolved in when c_userRoleAssignments are resolved.
979   -- For bug 6752821: no need to consider rolename as this check is for self-reference
980 
981   cursor c_userSelfReference (p_username varchar2) is
982     select wura.rowid, wur.rowid, wu.start_date, wu.expiration_date,
983            wu.orig_system, wu.orig_system_id
984     from   wf_local_user_roles partition (FND_USR) wur,
985            wf_local_roles partition (FND_USR) wu,
986            wf_user_role_assignments partition (FND_USR)  wura
987     --Equi-joins to select the proper relationships between the tables
988     where  (p_username is null OR wura.user_name = p_username)
989 	   and    wura.partition_id = wu.partition_id
990     and    wura.partition_id = wu.partition_id
991     and    wur.user_name = wu.name
992     and    wur.role_name = wu.name
993     and    wura.assigning_role = wu.name
994     and    wura.user_name = wu.name
995     and    wura.role_name = wu.name
996     --Criteria to select records that need to be corrected, beginning with
997     --broad checks (if effective dates are null, no reason to check further)
998     --and working down to more specific checks between the orig_system/id
999     and    ((wur.effective_start_date is null or
1000              wur.effective_end_date is null or
1001              wura.effective_start_date is null or
1002              wura.effective_end_date is null)
1003       or    ((wur.user_orig_system <> wu.orig_system) or
1004              (wur.user_orig_system_id <> wu.orig_system_id) or
1005              (wur.role_orig_system <> wu.orig_system) or
1006              (wur.role_orig_system_id <> wu.orig_system_id))
1007       or    (wura.user_orig_system is null or wura.role_orig_system is null or
1008              wura.user_orig_system_id is null or
1009              wura.user_orig_system_id is null)
1010       or    (wura.user_orig_system <> wu.orig_system)
1011       or    (wura.user_orig_system_id <> wu.orig_system_id)
1012       or    (wura.role_orig_system <> wu.orig_system)
1013       or    (wura.role_orig_system_id <> wu.orig_system_id)
1014       or    (wu.start_date is null and
1015               (wur.start_date is not null or
1016                wur.user_start_date is not null or
1017                wur.role_start_date is not null or
1018                wur.effective_start_date <> to_date(1,'J')))
1019       or    (wu.start_date is not null and
1020               (wur.start_date is null or wur.user_start_date is null or
1021                wur.role_start_date is null or wur.start_date <> wu.start_date or
1022                wur.user_start_date <> wu.start_date or
1023                wur.role_start_date <> wu.start_date or
1024                wur.effective_start_date <> wu.start_date))
1025       or    (wu.expiration_date is null and
1026               (wur.expiration_date is not null or
1027                wur.user_end_date is not null or wur.role_end_date is not null or
1028                wur.effective_end_date <> to_date('9999/01/01','YYYY/MM/DD')))
1029       or    (wu.expiration_date is not null and
1030               (wur.expiration_date is null or wur.user_end_date is null or
1031                wur.role_end_date is null or
1032                wur.expiration_date <> wu.expiration_date or
1033                wur.user_end_date <> wu.expiration_date or
1034                wur.role_end_date <> wu.expiration_date or
1035                wur.effective_end_date <> wu.expiration_date)));
1036 
1037   --Now we will correct other user/role relationships, including the user
1038   --orig_system/id information of any record that an fnd_usr/per may be
1039   --participating in.
1040   cursor c_UserRoleAssignments (p_username varchar2, p_rolename varchar2) is
1041     select rowid, wura_id,wur_id,role_name,user_name,
1042       assigning_role, start_date, end_Date,role_start_date,
1043       role_end_date, user_start_date,user_end_date,
1044       role_orig_system,role_orig_system_id,
1045       user_orig_system, user_orig_system_id,
1046       assigning_role_start_date, assigning_role_end_date,
1047       effective_start_date, effective_end_date,
1048       relationship_id
1049    from wf_ur_validate_stg
1050 	  where (p_username is null OR user_name = p_username)
1051 	  and   (p_rolename is null OR role_name = p_rolename)
1052    order by  ROLE_NAME, USER_NAME;
1053 
1054   -- Dangling records
1055   CURSOR dangling_UR_refs (p_username varchar2 , p_rolename varchar2) is
1056     select rowid
1057     from   wf_local_user_roles
1058     where  (p_username IS NULL OR user_name= p_username )
1059     AND    (p_rolename IS NULL OR role_name = p_rolename)
1060     AND    ( not exists (select null from wf_local_roles
1061                          WHERE name= user_name
1062                          AND (p_username IS NULL OR name= p_username)
1063                         )
1064            or  not EXISTS (select null from wf_local_roles
1065                             WHERE NAME = role_name
1066                             AND (p_rolename IS NULL OR name= p_rolename)
1067                            )
1068            );
1069 
1070 
1071   -- Same from user_role_assignments
1072   CURSOR dangling_URA_refs (p_username varchar2, p_rolename varchar2) is
1073     select rowid
1074     from   wf_user_role_assignments
1075     where  (p_username IS NULL OR user_name = p_username )
1076 	   and    (p_rolename IS NULL OR role_name = p_rolename )
1077     -- Either user name or role name NOT in wf_local_roles
1078     and    (user_name not in (select name from wf_local_roles
1079                               WHERE (p_username is null or name = p_username)
1080                               )
1081             -- Check RoleName
1082             or     role_name not in (select name from wf_local_roles
1083                                      WHERE (p_rolename IS NULL OR NAME = p_rolename)
1084                                      )
1085            );
1086 
1087 
1088   l_modulePkg varchar2(240) := 'WF_MAINTENANCE.ValidateUserRoles';
1089 
1090 begin
1091 -- Log only
1092 -- BINDVAR_SCAN_IGNORE[2]
1093   WF_LOG_PKG.String(WF_LOG_PKG.LEVEL_PROCEDURE, l_modulePkg,
1094                      'Begin ValidateUserRoles('||p_batchSize||')');
1095   --First validate the inbound parameter(s)
1096   if (p_BatchSize is NULL or (p_BatchSize < 1)) then
1097     l_MaxRows := 10000;
1098   else
1099     l_MaxRows := p_BatchSize;
1100   end if;
1101 
1102   -- Acquire a session lock to ensure that only one instance of the program is
1103   -- running at a time.
1104   dbms_lock.allocate_unique('WF_MAINTENANCE.ValidateUserRoles',l_lockhandle);
1105 
1106   if (dbms_lock.request(lockhandle=>l_lockhandle,
1107                         lockmode=>dbms_lock.x_mode,
1108                         timeout=>0) <> 0) then
1109    wf_core.raise('WF_LOCK_FAIL');
1110   end if;
1111 
1112   if (p_check_dangling is not null and p_check_dangling) then
1113   --Validate that the users and roles who participate in user/role
1114   --relationships actually exist.
1115   begin
1116     <<Dangling_UR_Reference>>
1117     loop
1118       open dangling_UR_refs (p_username, p_rolename) ;
1119       fetch dangling_UR_refs bulk collect into l_rowIDTAB limit l_maxRows;
1120       close dangling_UR_refs;
1121 
1122       if (l_rowIDTAB.COUNT > 0) then
1123         forall i in l_rowIDTAB.FIRST..l_rowIDTAB.LAST
1124           DELETE from WF_LOCAL_USER_ROLES
1125           WHERE  rowid = l_rowIDTAB(i);
1126           commit;
1127       end if;
1128 
1129       if (l_rowIDTAB.COUNT < l_maxRows) then
1130         exit Dangling_UR_Reference;
1131       end if;
1132     end loop Dangling_UR_Reference;
1133   exception
1134     when others then
1135       if dangling_UR_refs%ISOPEN then
1136         close dangling_UR_refs;
1137       end if;
1138 
1139       raise;
1140   end;
1141   --Truncate the rowid tab.
1142   l_rowIDTAB.DELETE;
1143   begin
1144     <<Dangling_URA_Reference>>
1145     loop
1146       open dangling_URA_refs (p_username, p_rolename) ;
1147       fetch dangling_URA_refs bulk collect into l_rowIDTAB limit l_maxRows;
1148       close dangling_URA_refs;
1149 
1150       if (l_rowIDTAB.COUNT > 0) then
1151         forall i in l_rowIDTAB.FIRST..l_rowIDTAB.LAST
1152           DELETE from WF_USER_ROLE_ASSIGNMENTS
1153           WHERE  rowid = l_rowIDTAB(i);
1154           commit;
1155       end if;
1156 
1157       if (l_rowIDTAB.COUNT < l_maxRows) then
1158         exit Dangling_URA_Reference;
1159       end if;
1160     end loop Dangling_URA_Reference;
1161   exception
1162     when others then
1163       if dangling_URA_refs%ISOPEN then
1164         close dangling_URA_refs;
1165       end if;
1166 
1167       raise;
1168   end;
1169   --Truncate the rowid tab.
1170   l_rowIDTAB.DELETE;
1171  end if;
1172 
1173    if (p_check_missing_ura is not null and p_check_missing_ura) then
1174     --Validate that the users and roles who participate in user/role
1175     --relationships actually exist.
1176     begin
1177       <<Missing_URA_Reference>>
1178       loop
1179         l_userSrcTAB.DELETE;
1180         open c_missing_user_role_asg (p_username, p_rolename);
1181         fetch c_missing_user_role_asg bulk collect into l_userSrcTAB,
1182               l_roleSrcTAB, l_relIDTAB, l_startSrcTAB, l_endSrcTAB,
1183               l_createdByTAB, l_createDateTAB, l_updatedByTAB, l_updateDateTAB,
1184               l_updateLoginTAB, l_userStartSrcTAB, l_roleStartSrcTAB,
1185               l_userEndSrcTAB, l_roleEndSrcTAB, l_partTAB, l_effStartSrcTAB,
1186               l_effEndSrcTAB, l_userOrigSrcTAB, l_userOrigIDSrcTAB,
1187               l_roleOrigSrcTAB, l_roleOrigIDSrcTAB, l_parentOrigTAB,
1188               l_parentOrigIDTAB, l_ownerTAGS
1189               limit l_maxRows;
1190         close c_missing_user_role_asg;
1191 
1192 
1193         if (l_userSrcTAB.COUNT > 0) then
1194           begin
1195             forall i in l_userSrcTAB.FIRST..l_userSrcTAB.LAST save exceptions
1196 
1197               insert into WF_USER_ROLE_ASSIGNMENTS (USER_NAME,
1198                 ROLE_NAME, RELATIONSHIP_ID, ASSIGNING_ROLE, START_DATE,
1199                 END_DATE, CREATED_BY, CREATION_DATE, LAST_UPDATED_BY,
1200                 LAST_UPDATE_DATE, LAST_UPDATE_LOGIN, USER_START_DATE,
1201                 ROLE_START_DATE, ASSIGNING_ROLE_START_DATE, USER_END_DATE,
1202                 ROLE_END_DATE, ASSIGNING_ROLE_END_DATE, PARTITION_ID,
1203                 EFFECTIVE_START_DATE, EFFECTIVE_END_DATE, USER_ORIG_SYSTEM,
1204                 USER_ORIG_SYSTEM_ID, ROLE_ORIG_SYSTEM, ROLE_ORIG_SYSTEM_ID,
1205                 PARENT_ORIG_SYSTEM, PARENT_ORIG_SYSTEM_ID, OWNER_TAG)
1206                 values (l_userSrcTAB(i), l_roleSrcTAB(i), l_relIDTAB(i),
1207                  l_roleSrcTAB(i), l_startSrcTAB(i), l_endSrcTAB(i),
1208                  l_createdByTAB(i), l_createDateTAB(i), l_updatedByTAB(i),
1209                  l_updateDateTAB(i), l_updateLoginTAB(i), l_userStartSrcTAB(i),
1210                  l_roleStartSrcTAB(i), l_roleStartSrcTAB(i), l_userEndSrcTAB(i),
1211                  l_roleEndSrcTAB(i), l_roleEndSrcTAB(i), l_partTAB(i),
1212                  l_effStartSrcTAB(i), l_effEndSrcTAB(i), l_userOrigSrcTAB(i),
1213                  l_userOrigIDSrcTAB(i), l_roleOrigSrcTAB(i),
1214                  l_roleOrigIDSrcTAB(i), l_parentOrigTAB(i),
1215                  l_parentOrigIDTAB(i), l_ownerTAGS(i));
1216               commit;
1217           exception
1218             when others then
1219               for j in 1..sql%bulk_exceptions.count loop
1220                 if (sql%bulk_exceptions(j).ERROR_CODE = 1) then
1221                   --Ignore a dup_val_on_index.  That just means that the
1222                   --user/role name combination was already assigned during this
1223                   --job.
1224                   null;
1225                 else
1226                   raise;
1227                 end if;
1228               end loop;
1229           end;
1230         end if;
1231 
1232         if (l_userSrcTAB.COUNT < l_maxRows) then
1233           exit Missing_URA_Reference;
1234         end if;
1235       end loop Missing_URA_Reference;
1236     exception
1237       when others then
1238         if c_missing_user_role_asg%ISOPEN then
1239           close c_missing_user_role_asg;
1240         end if;
1241 
1242         raise;
1243     end;
1244   end if;
1245 
1246   --Now we will correct any invalid fnd_usr records in WF_LOCAL_ROLES.  This
1247   --orig_system can have errors because we routinely have to change the
1248   --orig_system, orig_system_id whenever a user is associated or dis-associated
1249   --with an employee.
1250   begin
1251     <<fnd_usr_loop>>
1252     loop
1253       --Clear the l_rowIDTAB before the next iteration
1254       l_rowIDTAB.DELETE;
1255       open  c_invalid_fnd_users (p_username);
1256       fetch c_invalid_fnd_users bulk collect into l_rowIDTAB, l_userOrigSrcTAB,
1257             l_userOrigIDSrcTAB, l_userOrigDestTAB, l_userOrigIDDestTAB
1258             limit l_maxRows;
1259       close c_invalid_fnd_users;
1260 
1261       if (l_rowIDTAB.count > 0) then
1262         begin
1263           forall i in l_rowIDTAB.FIRST..l_rowIDTAB.LAST save exceptions
1264             UPDATE WF_LOCAL_ROLES
1265             SET    orig_system = l_userOrigDestTAB(i),
1266                    orig_system_id = l_userOrigIDDestTAB(i)
1267             WHERE  rowid = l_rowIDTAB(i);
1268         exception
1269           when others then
1270             for j in 1..sql%bulk_exceptions.count loop
1271               l_eIndex := sql%bulk_exceptions(j).ERROR_INDEX;
1272               delete from wf_local_roles
1273               where  rowid = l_rowIDTAB(l_eIndex);
1274             end loop;
1275         end;
1276         commit;
1277       end if;
1278       if (l_rowIDTab.count < l_maxRows) then
1279         commit;
1280         exit fnd_usr_loop;
1281       end if;
1282     end loop fnd_usr_loop;
1283   exception
1284     when others then
1285       if c_invalid_fnd_users%ISOPEN then
1286         close c_invalid_fnd_users;
1287       end if;
1288 
1289       raise;
1290   end; --End of duplicate/invalid FND_USR/PER user correction.
1291 
1292   -- Now we correct the FND_USR/PER orig_system values on the user side
1293   -- of user/role assignments as well as user-self-references in
1294   -- WF_LOCAL_USER_ROLES
1295 
1296   begin
1297   <<inval_orig_sys_loop>>
1298     loop
1299       --Clear the l_rowIDTAB before the next iteration
1300       l_rowIDTAB.DELETE;
1301 
1302       open  c_invalOrigSys (p_username) ;
1303       fetch c_invalOrigSys bulk collect into l_userOrigSrcTAB,
1304         l_userOrigIDSrcTAB, l_roleOrigSrcTAB, l_roleOrigIDSrcTAB,
1305         l_partTAB,l_rowIDTAB
1306         limit l_maxRows;
1307       close c_invalOrigSys;
1308 
1309 
1310       if (l_rowIDTAB.count > 0) then
1311           for i in  l_rowIDTAB.FIRST..l_rowIDTAB.LAST loop
1312             -- check whether this is a case of user=role
1313            if l_partTAB(i) = 1 then
1314               -- set the role_orig_system values as well.
1315               l_roleOrigSrcTAB(i) := l_userOrigSrcTAB(i);
1316               l_roleOrigIDSrcTAB(i) := l_userOrigIDSrcTAB(i);
1317            end if;
1318           end loop;
1319           --perform the bulk update.. delete duplicates in case of
1320           -- dup_val_on_index Exception.
1321           begin
1322           forall i in l_rowIDTAB.FIRST..l_rowIDTAB.LAST save exceptions
1323             UPDATE WF_LOCAL_USER_ROLES
1324             SET    user_orig_system = l_userOrigSrcTAB(i),
1325                    user_orig_system_id = l_userOrigIDSrcTAB(i),
1326                    role_orig_system = l_roleOrigSrcTAB(i),
1327                    role_orig_system_id = l_roleOrigIDSrcTAB(i)
1328             WHERE  rowid = l_rowIDTAB(i);
1329            exception
1330             when others then
1331              for j in 1..sql%bulk_exceptions.count loop
1332               if (sql%bulk_exceptions(j).ERROR_CODE = 1) then
1333                l_eIndex := sql%bulk_exceptions(j).ERROR_INDEX;
1334                delete from wf_local_user_roles
1335                where  rowid = l_rowIDTAB(l_eIndex);
1336               end if;
1337              end loop;
1338            end;
1339            commit;
1340       end if;
1341       if (l_rowIDTab.count < l_maxRows) then
1342         commit;
1343         exit inval_orig_sys_loop;
1344       end if;
1345     end loop inval_orig_sys_loop;
1346   exception
1347     when others then
1348       if c_invalOrigSys%ISOPEN then
1349         close c_invalOrigSys;
1350       end if;
1351 
1352       raise;
1353   end; --End of duplicate/invalid FND_USR/PER correction in WF_LOCAL_USER_ROLES.
1354 
1355   --Next, we correct the corrupt self-reference records in
1356   --wf_user_role_Assignments and wf_local_user_Roles.
1357   begin
1358   <<self_refer_loop>>
1359   loop
1360     --We will commit on each loop cycle to prevent fetch across commits, we will
1361     --close and reopen the cursor on each fetch.  This would mean that we are
1362     --pulling more than 10000 if we loop more than once and would rather have
1363     --a performance impact here than encounter rollback segment problems.
1364     --The where criteria of the cursor will not re-select the updated rows so
1365     --we do not have to worry about retaining a position.
1366 
1367     open c_userSelfReference (p_username);
1368     fetch c_userSelfReference
1369     bulk collect into l_rowIDTAB, l_rowIDSrcTAB, l_startSrcTAB,
1370                     l_endSrcTAB, l_userOrigSrcTAB, l_userOrigIDSrcTAB
1371     limit l_maxRows;
1372     close c_userSelfReference;
1373 
1374     --We now have pl/sql tables in memory that we can update with the new
1375     --values. So we loop through them and begin the processing.
1376     if (l_rowIDTAB.COUNT < 1) then
1377       exit self_refer_loop;
1378     end if;
1379 
1380     --We now have a complete series of pl/sql tables with
1381     --all of the start/end dates and calculated effective start/end dates
1382     --We can then issue the bulk  update.
1383     begin
1384      if (p_UpdateWho is not null and p_UpdateWho) then
1385       forall tabIndex in l_rowIDTAB.FIRST..l_rowIDTAB.LAST save exceptions
1386         update  WF_USER_ROLE_ASSIGNMENTS
1387         set     ROLE_START_DATE = l_StartSrcTAB(tabIndex),
1388                 ROLE_END_DATE = l_EndSrcTAB(tabIndex),
1389                 USER_START_DATE = l_StartSrcTAB(tabIndex),
1390                 USER_END_DATE = l_EndSrcTAB(tabIndex),
1391                 START_DATE    = l_StartSrcTAB(tabIndex),
1392                 END_DATE      = l_EndSrcTAB(tabIndex),
1393                 EFFECTIVE_START_DATE = nvl(l_StartSrcTAB(tabIndex),
1394                                            to_date(1,'J')),
1395                 EFFECTIVE_END_DATE = nvl(l_EndSrcTAB(tabIndex),
1396                                          to_date('9999/01/01', 'YYYY/MM/DD')),
1397                 ASSIGNING_ROLE_START_DATE = l_StartSrcTAB(tabIndex),
1398                 ASSIGNING_ROLE_END_DATE = l_EndSrcTAB(tabIndex),
1399                 USER_ORIG_SYSTEM=l_userOrigSrcTAB(tabIndex),
1400                 ROLE_ORIG_SYSTEM=l_userOrigSrcTAB(tabIndex),
1401                 USER_ORIG_SYSTEM_ID=l_userOrigIDSrcTAB(tabIndex),
1402                 ROLE_ORIG_SYSTEM_ID=l_userOrigIDSrcTAB(tabIndex),
1403                 LAST_UPDATED_BY = FND_GLOBAL.USER_ID,
1404                 LAST_UPDATE_DATE = SYSDATE,
1405                 LAST_UPDATE_LOGIN  = FND_GLOBAL.LOGIN_ID
1406         where   rowid = l_rowIDTAB(tabIndex);
1407      else --donot touch the WHO columns. This is default behavior
1408       forall tabIndex in l_rowIDTAB.FIRST..l_rowIDTAB.LAST save exceptions
1409         update  WF_USER_ROLE_ASSIGNMENTS
1410         set     ROLE_START_DATE = l_StartSrcTAB(tabIndex),
1411                 ROLE_END_DATE = l_EndSrcTAB(tabIndex),
1412                 USER_START_DATE = l_StartSrcTAB(tabIndex),
1413                 USER_END_DATE = l_EndSrcTAB(tabIndex),
1414                 START_DATE    = l_StartSrcTAB(tabIndex),
1415                 END_DATE      = l_EndSrcTAB(tabIndex),
1416                 EFFECTIVE_START_DATE = nvl(l_StartSrcTAB(tabIndex),
1417                                            to_date(1,'J')),
1418                 EFFECTIVE_END_DATE = nvl(l_EndSrcTAB(tabIndex),
1419                                          to_date('9999/01/01', 'YYYY/MM/DD')),
1420                 ASSIGNING_ROLE_START_DATE = l_StartSrcTAB(tabIndex),
1421                 ASSIGNING_ROLE_END_DATE = l_EndSrcTAB(tabIndex),
1422                 USER_ORIG_SYSTEM=l_userOrigSrcTAB(tabIndex),
1423                 ROLE_ORIG_SYSTEM=l_userOrigSrcTAB(tabIndex),
1424                 USER_ORIG_SYSTEM_ID=l_userOrigIDSrcTAB(tabIndex),
1425                 ROLE_ORIG_SYSTEM_ID=l_userOrigIDSrcTAB(tabIndex)
1426         where   rowid = l_rowIDTAB(tabIndex);
1427      end if;
1428     exception
1429        when others then
1430          for j in 1..sql%bulk_exceptions.count loop
1431            if (sql%bulk_exceptions(j).ERROR_CODE = 1) then
1432              --If update violates dup_val_on_index, we can simply delete.
1433              l_eIndex := sql%bulk_exceptions(j).ERROR_INDEX;
1434              delete from wf_user_role_assignments
1435              where rowid = l_rowIDTAB(l_eIndex);
1436            else
1437              raise;
1438            end if;
1439          end loop;
1440      end;
1441 
1442      --Commit work to save rollback
1443      commit;
1444 
1445      -- update WF_LOCAL_USER_ROLES
1446      begin
1447       if (p_UpdateWho is not null and p_UpdateWho) then
1448        forall tabIndex in l_rowIDSrcTAB.FIRST..l_rowIDSrcTAB.LAST save exceptions
1449         update wf_local_user_roles partition (FND_USR)
1450         set     ROLE_START_DATE = l_StartSrcTAB(tabIndex),
1451                 ROLE_END_DATE = l_EndSrcTAB(tabIndex),
1452                 USER_START_DATE = l_StartSrcTAB(tabIndex),
1453                 USER_END_DATE = l_EndSrcTAB(tabIndex),
1454                 START_DATE    = l_StartSrcTAB(tabIndex),
1455                 EXPIRATION_DATE  = l_EndSrcTAB(tabIndex),
1456                 EFFECTIVE_START_DATE = nvl(l_StartSrcTAB(tabIndex),
1457                                            to_date(1,'J')),
1458                 EFFECTIVE_END_DATE = nvl(l_EndSrcTAB(tabIndex),
1459                                          to_date('9999/01/01', 'YYYY/MM/DD')),
1460                 LAST_UPDATED_BY = FND_GLOBAL.USER_ID,
1461                 LAST_UPDATE_DATE = SYSDATE,
1462                 LAST_UPDATE_LOGIN  = FND_GLOBAL.LOGIN_ID
1463          where  rowid = l_rowIDSrcTAB(tabIndex);
1464       else  --donot touch the WHO columns. This is default behavior
1465        forall tabIndex in l_rowIDSrcTAB.FIRST..l_rowIDSrcTAB.LAST save exceptions
1466         update wf_local_user_roles partition (FND_USR)
1467         set     ROLE_START_DATE = l_StartSrcTAB(tabIndex),
1468                 ROLE_END_DATE = l_EndSrcTAB(tabIndex),
1469                 USER_START_DATE = l_StartSrcTAB(tabIndex),
1470                 USER_END_DATE = l_EndSrcTAB(tabIndex),
1471                 START_DATE    = l_StartSrcTAB(tabIndex),
1472                 EXPIRATION_DATE  = l_EndSrcTAB(tabIndex),
1473                 EFFECTIVE_START_DATE = nvl(l_StartSrcTAB(tabIndex),
1474                                            to_date(1,'J')),
1475                 EFFECTIVE_END_DATE = nvl(l_EndSrcTAB(tabIndex),
1476                                          to_date('9999/01/01', 'YYYY/MM/DD'))
1477          where  rowid = l_rowIDSrcTAB(tabIndex);
1478        end if;
1479       end;
1480 
1481     if (l_rowIDTAB.COUNT < l_maxRows) then --Last batch, no need to refetch
1482       commit;
1483       exit self_refer_loop;
1484     else
1485       -- reset the ROWID Table before the next set of fetch
1486       l_rowIDTAB.DELETE;
1487       commit;
1488     end if;
1489   end loop self_refer_loop;
1490   exception
1491    when others then
1492      if (c_userSelfReference%isOpen) then
1493        close c_userSelfReference;
1494      end if;
1495 
1496      raise;
1497   end; --end of self-reference fix
1498 
1499   commit;--commit the self reference records
1500 
1501   -- reset the PL/SQL tables before we fetch the user-role cursor
1502   l_rowIDTAB.delete;
1503   l_rowIDSrcTAB.delete;
1504   l_startSrcTAB.delete;
1505   l_endSrcTAB.delete;
1506   l_userOrigSrcTAB.delete;
1507   l_userOrigIDSrcTAB.delete;
1508 
1509   --Initialize the sumTabIndex counter.
1510   sumTabIndex := 0;
1511 
1512   --Enable parallel DML
1513   execute IMMEDIATE 'alter session enable parallel dml';
1514 
1515   --truncate the stage table now
1516   WF_DDL.TruncateTable('WF_UR_VALIDATE_STG',WF_CORE.Translate('WF_SCHEMA'),
1517                        FALSE);
1518 
1519   -- <bug 6823723>
1520   select min(to_number(value))
1521   into   l_defaultParProc
1522   from   v$parameter
1523   where  name in ('parallel_max_servers','cpu_count');
1524 
1525   if ((p_parallel_processes is NULL) or (p_parallel_processes < 1) or
1526       (mod(p_parallel_processes, 1) <> 0) or (p_parallel_processes > l_defaultParProc)
1527       ) then
1528     l_parallelProc := to_char(l_defaultParProc) ;
1529   else
1530     l_parallelProc := to_char(p_parallel_processes);
1531   end if;
1532   -- </bug 6823723>
1533 
1534   -- populate the stage table
1535   -- bug 6823723. Now inserting as a dynamic DML to include the number of parallel processes
1536   l_sql :=
1537   'INSERT /*+ append parallel(WF_UR_VALIDATE_STG,'|| l_parallelProc ||') */
1538   INTO WF_UR_VALIDATE_STG (WURA_ID, WUR_ID , ROLE_NAME , USER_NAME ,
1539   ASSIGNING_ROLE , START_DATE , END_DATE , ROLE_START_DATE, ROLE_END_DATE
1540   , USER_START_DATE , USER_END_DATE , ROLE_ORIG_SYSTEM ,
1541   ROLE_ORIG_SYSTEM_ID , USER_ORIG_SYSTEM , USER_ORIG_SYSTEM_ID ,
1542   ASSIGNING_ROLE_START_DATE , ASSIGNING_ROLE_END_DATE ,
1543   EFFECTIVE_START_DATE , EFFECTIVE_END_DATE , RELATIONSHIP_ID )
1544   SELECT /*+ ordered parallel(WURA,'|| l_parallelProc ||') parallel(WR,'|| l_parallelProc ||
1545           ') parallel (wu,'|| l_parallelProc ||')
1546              parallel (WAR,'|| l_parallelProc ||') parallel(WUR,'|| l_parallelProc ||') */
1547          WURA.ROWID, WUR.ROWID, WURA.ROLE_NAME, WURA.USER_NAME,
1548          WURA.ASSIGNING_ROLE,
1549          DECODE(WURA.USER_NAME, WURA.ROLE_NAME, WU.START_DATE,
1550                 WURA.START_DATE) START_DATE,
1551          DECODE(WURA.USER_NAME, WURA.ROLE_NAME, WU.EXPIRATION_DATE,
1552                 WURA.END_DATE) END_DATE,
1553          WR.START_DATE, WR.EXPIRATION_DATE, WU.START_DATE,
1554          WU.EXPIRATION_DATE, WR.ORIG_SYSTEM, WR.ORIG_SYSTEM_ID,
1555          WU.ORIG_SYSTEM, WU.ORIG_SYSTEM_ID, WAR.START_DATE,
1556          WAR.EXPIRATION_DATE,
1557          GREATEST(NVL(WURA.START_DATE, TO_DATE(1,''J'')),
1558                   NVL(WURA.USER_START_DATE, TO_DATE(1,''J'')),
1559                   NVL(WURA.ROLE_START_DATE, TO_DATE(1,''J'')),
1560                   NVL(WURA.ASSIGNING_ROLE_START_DATE,
1561                       TO_DATE(1,''J''))) EFFECTIVE_START_DATE,
1562          LEAST(NVL(WURA.END_DATE, TO_DATE(''9999/01/01'', ''YYYY/MM/DD'')),
1563                NVL(WURA.USER_END_DATE, TO_DATE(''9999/01/01'', ''YYYY/MM/DD'')),
1564                NVL(WURA.ROLE_END_DATE, TO_DATE(''9999/01/01'', ''YYYY/MM/DD'')),
1565                NVL(WURA.ASSIGNING_ROLE_END_DATE,
1566                    TO_DATE(''9999/01/01'', ''YYYY/MM/DD''))) EFFECTIVE_END_DATE,
1567          WURA.RELATIONSHIP_ID
1568     FROM
1569          WF_USER_ROLE_ASSIGNMENTS WURA,
1570          WF_LOCAL_USER_ROLES WUR ,
1571          WF_LOCAL_ROLES WAR,
1572          WF_LOCAL_ROLES WU,
1573          WF_LOCAL_ROLES WR
1574    WHERE WURA.PARTITION_ID = WAR.PARTITION_ID
1575      AND WURA.ASSIGNING_ROLE=WAR.NAME
1576      AND WURA.USER_NAME= WUR.USER_NAME
1577      AND WURA.ROLE_NAME=WUR.ROLE_NAME
1578      AND WUR.USER_NAME = WU.NAME
1579      AND WUR.USER_ORIG_SYSTEM=WU.ORIG_SYSTEM
1580      AND WUR.USER_ORIG_SYSTEM_ID= WU.ORIG_SYSTEM_ID
1581      AND WUR.ROLE_NAME = WR.NAME
1582      AND WUR.ROLE_ORIG_SYSTEM= WR.ORIG_SYSTEM
1583      AND WUR.ROLE_ORIG_SYSTEM_ID= WR.ORIG_SYSTEM_ID
1584      AND WUR.PARTITION_ID = WR.PARTITION_ID
1585      AND WUR.PARTITION_ID <> 1
1586      AND WAR.PARTITION_ID <> 1
1587      AND ( ( WUR.EFFECTIVE_START_DATE IS NULL or
1588              WUR.EFFECTIVE_END_DATE IS NULL or
1589              WURA.EFFECTIVE_START_DATE IS NULL or
1590              WURA.EFFECTIVE_END_DATE IS NULL )
1591       OR ( WURA.EFFECTIVE_START_DATE <> GREATEST(NVL(WURA.START_DATE,
1592          TO_DATE(1,''J'')), NVL(WURA.USER_START_DATE, TO_DATE(1,''J'')), NVL(
1593          WURA.ROLE_START_DATE, TO_DATE(1,''J'')), NVL(
1594          WURA.ASSIGNING_ROLE_START_DATE, TO_DATE(1,''J''))) )
1595       OR ( WURA.EFFECTIVE_END_DATE <> LEAST(NVL(WURA.END_DATE, TO_DATE(
1596          ''9999/01/01'', ''YYYY/MM/DD'')), NVL(WURA.USER_END_DATE, TO_DATE(
1597          ''9999/01/01'', ''YYYY/MM/DD'')) , NVL(WURA.ROLE_END_DATE, TO_DATE(
1598          ''9999/01/01'', ''YYYY/MM/DD'')), NVL(WURA.ASSIGNING_ROLE_END_DATE,
1599          TO_DATE(''9999/01/01'', ''YYYY/MM/DD''))))
1600       OR (WURA.USER_NAME = WURA.ROLE_NAME and
1601           (nvl(wura.start_date, to_date(1,''J'')) <>
1602            nvl(wu.start_date, to_date(1,''J'')) or
1603            nvl(wura.end_date, to_date(''9999/01/01'', ''YYYY/MM/DD'')) <>
1604            nvl(wu.expiration_date, to_date(''9999/01/01'', ''YYYY/MM/DD''))))
1605       OR ( ( WUR.ASSIGNMENT_TYPE IS NULL )
1606       OR WUR.ASSIGNMENT_TYPE NOT IN (''D'', ''I'', ''B'') )
1607       OR ( WURA.USER_ORIG_SYSTEM IS NULL
1608       OR WURA.ROLE_ORIG_SYSTEM IS NULL
1609       OR WURA.USER_ORIG_SYSTEM_ID IS NULL
1610       OR WURA.ROLE_ORIG_SYSTEM_ID IS NULL )
1611       OR ( WURA.USER_ORIG_SYSTEM <> WU.ORIG_SYSTEM
1612       OR WURA.USER_ORIG_SYSTEM_ID <> WU.ORIG_SYSTEM_ID
1613       OR WURA.ROLE_ORIG_SYSTEM <> WR.ORIG_SYSTEM
1614       OR WURA.ROLE_ORIG_SYSTEM_ID <> WR.ORIG_SYSTEM_ID )
1615       OR ( ( WU.START_DATE IS NULL
1616      AND ( WUR.USER_START_DATE IS NOT NULL
1617       OR WURA.USER_START_DATE IS NOT NULL ) )
1618       OR ( WU.START_DATE IS NOT NULL
1619      AND ( WUR.USER_START_DATE IS NULL
1620       OR WUR.USER_START_DATE <> WU.START_DATE
1621       OR WURA.USER_START_DATE IS NULL
1622       OR WURA.USER_START_DATE <> WU.START_DATE ) )
1623       OR ( WU.EXPIRATION_DATE IS NULL
1624      AND ( WUR.USER_END_DATE IS NOT NULL
1625       OR WURA.USER_END_DATE IS NOT NULL ) )
1626       OR ( WU.EXPIRATION_DATE IS NOT NULL
1627      AND ( WUR.USER_END_DATE IS NULL
1628       OR WUR.USER_END_DATE <> WU.EXPIRATION_DATE
1629       OR WURA.USER_END_DATE IS NULL
1630       OR WURA.USER_END_DATE <> WU.EXPIRATION_DATE ) ) )
1631       OR ( ( WR.START_DATE IS NULL
1632      AND ( WUR.ROLE_START_DATE IS NOT NULL
1633       OR WURA.ROLE_START_DATE IS NOT NULL ) )
1634       OR ( WR.START_DATE IS NOT NULL
1635      AND ( WUR.ROLE_START_DATE IS NULL
1636       OR WUR.ROLE_START_DATE <> WR.START_DATE
1637       OR WURA.ROLE_START_DATE IS NULL
1638       OR WURA.ROLE_START_DATE <> WR.START_DATE ) )
1639       OR ( WR.EXPIRATION_DATE IS NULL
1640      AND ( WUR.ROLE_END_DATE IS NOT NULL
1641       OR WURA.ROLE_END_DATE IS NOT NULL ) )
1642       OR ( WR.EXPIRATION_DATE IS NOT NULL
1643      AND ( WUR.ROLE_END_DATE IS NULL
1644       OR WUR.ROLE_END_DATE <> WR.EXPIRATION_DATE
1645       OR WURA.ROLE_END_DATE IS NULL
1646       OR WURA.ROLE_END_DATE <> WR.EXPIRATION_DATE ) ) )
1647       OR ( ( WAR.START_DATE IS NULL
1648      AND WURA.ASSIGNING_ROLE_START_DATE IS NOT NULL )
1649       OR ( WAR.START_DATE IS NOT NULL
1650      AND ( WURA.ASSIGNING_ROLE_START_DATE IS NULL
1651       OR WURA.ASSIGNING_ROLE_START_DATE <> WAR.START_DATE ) )
1652       OR ( WAR.EXPIRATION_DATE IS NULL
1653      AND WURA.ASSIGNING_ROLE_END_DATE IS NOT NULL )
1654       OR ( WAR.EXPIRATION_DATE IS NOT NULL
1655      AND ( WURA.ASSIGNING_ROLE_END_DATE IS NULL
1656       OR WURA.ASSIGNING_ROLE_END_DATE <> WAR.EXPIRATION_DATE ) ) ) )' ;
1657 
1658     execute IMMEDIATE l_sql;
1659     commit;
1660     execute IMMEDIATE 'alter session disable parallel dml';
1661 
1662   -- ALSOSA. Current progress
1663   OPEN c_UserRoleAssignments(p_username, p_rolename);
1664 
1665   <<outer_loop>>
1666   loop
1667     fetch c_UserRoleAssignments
1668     bulk collect into l_stgIDTAB, l_rowIDTAB, l_rowIDSrcTAB, l_roleSrcTAB,
1669                         l_userSrcTAB, l_assigningRoleSrcTAB, l_startSrcTAB,
1670                         l_endSrcTAB, l_roleStartSrcTAB, l_roleEndSrcTAB,
1671                         l_userStartSrcTAB, l_userEndSrcTAB, l_roleOrigSrcTAB,
1672                         l_roleOrigIDSrcTAB,l_userOrigSrcTAB, l_userOrigIDSrcTAB,
1673                         l_asgStartSrcTAB, l_asgEndSrcTAB, l_effStartSrcTAB,
1674                         l_effEndSrcTAB, l_relIDTAB
1675                         limit l_maxRows;
1676 
1677 
1678     --We now have pl/sql tables in memory that we can update with the new
1679     --values. So we loop through them and begin the processing.
1680     if (l_rowIDTAB.COUNT < 1) then
1681       exit outer_loop;
1682     end if;
1683 
1684     --We now have a complete series of pl/sql tables with
1685     --all of the start/end dates and calculated effective start/end dates
1686     --We can then issue the bulk  update..
1687     if (p_UpdateWho is not null and p_UpdateWho) then
1688      forall tabIndex in l_rowIDTAB.FIRST..l_rowIDTAB.LAST
1689       update  WF_USER_ROLE_ASSIGNMENTS
1690       set     ROLE_START_DATE = l_roleStartSrcTAB(tabIndex),
1691               ROLE_END_DATE = l_roleEndSrcTAB(tabIndex),
1692               USER_START_DATE = l_userStartSrcTAB(tabIndex),
1693               USER_END_DATE = l_userEndSrcTAB(tabIndex),
1694               START_DATE = l_startSrcTAB(tabIndex),
1695               END_DATE = l_endSRcTAB(tabIndex),
1696               EFFECTIVE_START_DATE = l_effStartSrcTAB(tabIndex),
1697               EFFECTIVE_END_DATE = l_effEndSrcTAB(tabIndex),
1698               ASSIGNING_ROLE_START_DATE = l_asgStartSrcTAB(tabIndex),
1699               ASSIGNING_ROLE_END_DATE = l_asgEndSrcTAB(tabIndex),
1700               USER_ORIG_SYSTEM=l_userOrigSrcTAB(tabIndex),
1701               ROLE_ORIG_SYSTEM=l_roleOrigSrcTAB(tabIndex),
1702               USER_ORIG_SYSTEM_ID=l_userOrigIDSrcTAB(tabIndex),
1703               ROLE_ORIG_SYSTEM_ID=l_roleOrigIDSrcTAB(tabIndex),
1704               LAST_UPDATED_BY = FND_GLOBAL.USER_ID,
1705               LAST_UPDATE_DATE = SYSDATE,
1706               LAST_UPDATE_LOGIN  = FND_GLOBAL.LOGIN_ID
1707       where   rowid = l_rowIDTAB(tabIndex);
1708    else --Donot touch WHO columns. This is default behavior
1709     forall tabIndex in l_rowIDTAB.FIRST..l_rowIDTAB.LAST
1710       update  WF_USER_ROLE_ASSIGNMENTS
1711       set     ROLE_START_DATE = l_roleStartSrcTAB(tabIndex),
1712               ROLE_END_DATE = l_roleEndSrcTAB(tabIndex),
1713               USER_START_DATE = l_userStartSrcTAB(tabIndex),
1714               USER_END_DATE = l_userEndSrcTAB(tabIndex),
1715               START_DATE = l_startSrcTAB(tabIndex),
1716               END_DATE = l_endSRcTAB(tabIndex),
1717               EFFECTIVE_START_DATE = l_effStartSrcTAB(tabIndex),
1718               EFFECTIVE_END_DATE = l_effEndSrcTAB(tabIndex),
1719               ASSIGNING_ROLE_START_DATE = l_asgStartSrcTAB(tabIndex),
1720               ASSIGNING_ROLE_END_DATE = l_asgEndSrcTAB(tabIndex),
1721               USER_ORIG_SYSTEM=l_userOrigSrcTAB(tabIndex),
1722               ROLE_ORIG_SYSTEM=l_roleOrigSrcTAB(tabIndex),
1723               USER_ORIG_SYSTEM_ID=l_userOrigIDSrcTAB(tabIndex),
1724               ROLE_ORIG_SYSTEM_ID=l_roleOrigIDSrcTAB(tabIndex)
1725       where   rowid = l_rowIDTAB(tabIndex);
1726    end if;
1727 
1728     --We will reloop through the assignment pl/sql tables and populate the
1729     --summary pl/sql tables.
1730     <<summarize_assignments>>
1731     for tabIndex in l_rowIDTAB.FIRST..l_rowIDTAB.LAST loop
1732       --we need to insert into summary table if this is the first
1733       --record to be inserted or, we have a new user/role combination
1734       --in the assignment table, which hasnt yet been inserted into the
1735       --summary table
1736       if ((l_roleDestTab.COUNT < 1) or
1737           (l_rowIDSrcTAB(tabIndex) <> l_rowIDDestTAB(sumTabIndex))) then
1738         -- before inserting, check whether the summarytable has
1739         -- grown too large
1740         if sumTabIndex >= l_maxRows then
1741           --limit reached for summary table, so perform
1742           --the bulk update and clear off the table.
1743           --We need to perform the bulk update here in addition to
1744           --bulk update after exit from the loop, so that clearing
1745           --the summary table will not lose user/role effective date
1746           --information when duplicate user/role
1747           --combinations are spread across multiple groups
1748           if (p_UpdateWho is not null and p_UpdateWho) then
1749             forall destTabIndex in l_roleDestTab.FIRST..l_roleDestTab.LAST
1750               UPDATE WF_LOCAL_USER_ROLES wur
1751               SET    ROLE_START_DATE = l_roleStartDestTAB(destTabIndex),
1752                    ROLE_END_DATE   = l_roleEndDestTAB(destTabIndex),
1753                    USER_START_DATE = l_userStartDestTAB(destTabIndex),
1754                    USER_END_DATE = l_userEndDestTAB(destTabIndex),
1755                    START_DATE = l_startDestTAB(destTabIndex),
1756                    EXPIRATION_DATE = l_endDestTAB(destTabIndex),
1757                    EFFECTIVE_START_DATE = l_effStartDestTAB(destTabIndex),
1758                    EFFECTIVE_END_DATE = l_effEndDestTAB(destTabIndex),
1759                    ASSIGNMENT_TYPE = l_assignTAB(destTabIndex),
1760                    LAST_UPDATED_BY = FND_GLOBAL.USER_ID,
1761                    LAST_UPDATE_LOGIN = FND_GLOBAL.Login_Id,
1762                    LAST_UPDATE_DATE  = SYSDATE
1763               WHERE rowid = l_rowIDDestTAB(destTabIndex);
1764           else --Do not touch WHO columns. This is default behavior
1765            forall destTabIndex in l_roleDestTab.FIRST..l_roleDestTab.LAST
1766             UPDATE WF_LOCAL_USER_ROLES wur
1767             SET    ROLE_START_DATE = l_roleStartDestTAB(destTabIndex),
1768                    ROLE_END_DATE   = l_roleEndDestTAB(destTabIndex),
1769                    USER_START_DATE = l_userStartDestTAB(destTabIndex),
1770                    USER_END_DATE = l_userEndDestTAB(destTabIndex),
1771                    START_DATE = l_startDestTAB(destTabIndex),
1772                    EXPIRATION_DATE = l_endDestTAB(destTabIndex),
1773                    EFFECTIVE_START_DATE = l_effStartDestTAB(destTabIndex),
1774                    EFFECTIVE_END_DATE = l_effEndDestTAB(destTabIndex),
1775                    ASSIGNMENT_TYPE = l_assignTAB(destTabIndex)
1776              WHERE rowid = l_rowIDDestTAB(destTabIndex);
1777           end if;
1778           l_roleStartDestTAB.DELETE;
1779           l_roleEndDestTAB.DELETE;
1780           l_userStartDestTAB.DELETE;
1781           l_userEndDestTAB.DELETE;
1782           l_effStartDestTAB.DELETE;
1783           l_effEndDestTAB.DELETE;
1784           l_assignTAB.DELETE;
1785           l_startDestTAB.DELETE;
1786           l_endDestTAB.DELETE;
1787           l_roleDestTAB.DELETE;
1788           l_userDestTAB.DELETE;
1789           l_userOrigDestTAB.DELETE;
1790           l_userOrigIDDestTAB.DELETE;
1791           l_roleOrigDestTAB.DELETE;
1792           l_roleOrigIDDestTAB.DELETE;
1793           l_rowIDDestTAB.DELETE;
1794 
1795           sumTabIndex := 0;
1796         end if;	--sumTabIndex >= l_maxRows
1797 
1798         --now perform the insert
1799         sumTabIndex := sumTabIndex + 1;
1800         l_RoleDestTAB(sumTabIndex)       := l_roleSrcTAB(tabIndex);
1801         l_UserDestTAB(sumTabIndex)       := l_userSRcTAB(tabIndex);
1802         l_userOrigDestTAB(sumTabIndex)   := l_userOrigSrcTAB(tabIndex);
1803         l_userOrigIDDestTAB(sumTabIndex) := l_userOrigIDSrcTAB(tabIndex);
1804         l_roleOrigDestTAB(sumTabIndex)   := l_roleOrigSrcTAB(tabIndex);
1805         l_roleOrigIDDestTAB(sumTabIndex) := l_roleOrigIDSrcTAB(tabIndex);
1806         l_roleStartDestTAB(sumTabIndex)  := l_roleStartSrcTAB(tabIndex);
1807         l_roleEndDestTAB(sumTabIndex)    := l_roleEndSrcTAB(tabIndex);
1808         l_userStartDestTAB(sumTabIndex)  := l_userStartSrcTAB(tabIndex);
1809         l_userEndDestTAB(sumTabIndex)    := l_userEndSrcTAB(tabIndex);
1810         l_effStartDestTAB(sumTabIndex)   := l_effStartSrcTAB(tabIndex);
1811         l_effEndDestTAB(sumTabIndex)     := l_effEndSrcTAB(tabIndex);
1812         l_rowIDDestTAB(sumTabIndex)      := l_rowIDSrcTAB(TabIndex);
1813 
1814         --Check to see if the assignment is active.
1815         if (l_effEndSrcTAB(tabIndex) > trunc(SYSDATE) and
1816             l_effStartSrcTab(tabIndex) <= trunc(SYSDATE)) then
1817           l_activeAssigned := TRUE;
1818         else
1819           l_activeAssigned := FALSE;
1820         end if;
1821 
1822         --Determine the initial assignment_type.
1823         if  l_relIDTAB(tabIndex) = -1 then
1824           l_AssignTAB(sumTabIndex):='D';
1825           l_startDestTAB(sumTabIndex)    :=l_startSrcTAB(tabIndex);
1826           l_endDestTAB(sumTabIndex)      :=l_endSrcTAB(tabIndex);
1827         else
1828           l_AssignTAB(sumTabIndex):='I';
1829           l_startDestTAB(sumTabIndex)    :=null;
1830           l_endDestTAB(sumTabIndex)      :=null;
1831         end if;
1832       else  --Record is already in the summary table so update effective dates
1833       if l_effStartSrcTAB(tabIndex) < l_effStartDestTAB(sumTabIndex) then
1834         l_effStartDestTAB(sumTabIndex) := l_effStartSrcTAB(tabIndex);
1835       end if;
1836 
1837       if l_effEndSrcTAB(tabIndex) > l_effEndDestTAB(sumTabIndex) then
1838         l_effEndDestTAB(sumTabIndex) := l_effEndSrcTAB(tabIndex);
1839       end if;
1840 
1841       -- if this is a direct assignment then we need to set the start
1842       -- and end dates
1843       if l_relIDTAB(tabIndex) = -1 then
1844          l_startDestTAB(sumTabIndex)    :=l_startSrcTAB(tabIndex);
1845          l_endDestTAB(sumTabIndex)      :=l_endSrcTAB(tabIndex);
1846       end if;
1847 
1848       --if the assignment type in summary table is Direct and
1849       --we encountered an inherited assignment in the Assignment table
1850       --or if the assignment type in summary table is inherited and we
1851       --encountered a direct assignment in the Assignment table
1852       --update the assignment_Type to Both
1853 
1854       if (l_effEndSrcTAB(tabIndex) > trunc(SYSDATE) and
1855           l_effStartSrcTAB(tabIndex) <= trunc(SYSDATE)) then
1856         --This is an active assignment so we need to determine if an
1857         --active assignment was already used in calculating assignment_type
1858         if (l_activeAssigned) then
1859           --An active assignment was already used in the calculation so this
1860           --assignment will be used to determine if and existing 'D' or 'I'
1861           --should be changed into a 'B'
1862           if (((l_AssignTAB(sumTabIndex) = 'D') and
1863                (l_relIDTAB(tabIndex) <> -1)) or
1864                ((l_AssignTAB(sumTabIndex) = 'I') and
1865                (l_relIDTAB(tabIndex) = -1))) then
1866 
1867             l_AssignTAB(sumTabIndex) := 'B';
1868           end if;
1869         else
1870           --This is the first active assignment, so set the initial value
1871           --Determine the initial assignment_type.
1872           if  l_relIDTAB(tabIndex) = -1 then
1873             l_AssignTAB(sumTabIndex):='D';
1874             l_startDestTAB(sumTabIndex)    :=l_startSrcTAB(tabIndex);
1875             l_endDestTAB(sumTabIndex)      :=l_endSrcTAB(tabIndex);
1876           else
1877             l_AssignTAB(sumTabIndex):='I';
1878             l_startDestTAB(sumTabIndex)    :=null;
1879             l_endDestTAB(sumTabIndex)      :=null;
1880           end if;
1881 
1882           --Now set l_activeAssigned to TRUE.
1883           l_activeAssigned := TRUE;
1884         end if;
1885       else
1886         --This is an expired assignment, so we will set the assignment_type
1887         --only if we have not already initialized/modified with an
1888         --active assignment.
1889         if NOT (l_activeAssigned) then
1890           if  l_relIDTAB(tabIndex) = -1 then
1891             l_AssignTAB(sumTabIndex):='D';
1892             l_startDestTAB(sumTabIndex)    :=l_startSrcTAB(tabIndex);
1893             l_endDestTAB(sumTabIndex)      :=l_endSrcTAB(tabIndex);
1894           else
1895             l_AssignTAB(sumTabIndex):='I';
1896             l_startDestTAB(sumTabIndex)    :=null;
1897             l_endDestTAB(sumTabIndex)      :=null;
1898           end if;
1899         end if;
1900       end if;
1901     end if;
1902   end loop summarize_assignments;
1903 
1904     --Check to see if we have the last batch and do not need to re-fetch
1905     if (l_rowIDTAB.COUNT < l_maxRows) then
1906       commit;
1907       exit outer_loop;
1908     else
1909       -- reset the ROWID Table before the next set of fetch
1910       l_rowIDTAB.DELETE;
1911       commit;
1912     end if;
1913   end loop outer_loop;
1914 
1915   --when we reach here, we need to bulk update the leftover records,
1916   --if any, in the summary table.
1917 
1918   if (l_roleDestTAB.COUNT) > 0 then
1919    if (p_UpdateWho is not null and p_UpdateWho) then
1920     forall destTabIndex in l_roleDestTab.FIRST..l_roleDestTab.LAST
1921       UPDATE WF_LOCAL_USER_ROLES wur
1922       SET    ROLE_START_DATE = l_roleStartDestTAB(destTabIndex),
1923              ROLE_END_DATE   = l_roleEndDestTAB(destTabIndex),
1924              USER_START_DATE = l_userStartDestTAB(destTabIndex),
1925              USER_END_DATE = l_userEndDestTAB(destTabIndex),
1926              EFFECTIVE_START_DATE = l_effStartDestTAB(destTabIndex),
1927              EFFECTIVE_END_DATE = l_effEndDestTAB(destTabIndex),
1928              START_DATE = l_startDestTAB(destTabIndex),
1929              EXPIRATION_DATE = l_endDestTAB(destTabIndex),
1930              ASSIGNMENT_TYPE = l_assignTAB(destTabIndex),
1931              LAST_UPDATED_BY = FND_GLOBAL.USER_ID,
1932              LAST_UPDATE_LOGIN = FND_GLOBAL.Login_Id,
1933              LAST_UPDATE_DATE  = SYSDATE
1934        WHERE rowid = l_rowIDDestTAB(destTabIndex);
1935    else --Do not touch WHO columns. This is default behavior.
1936     forall destTabIndex in l_roleDestTab.FIRST..l_roleDestTab.LAST
1937       UPDATE WF_LOCAL_USER_ROLES wur
1938       SET    ROLE_START_DATE = l_roleStartDestTAB(destTabIndex),
1939              ROLE_END_DATE   = l_roleEndDestTAB(destTabIndex),
1940              USER_START_DATE = l_userStartDestTAB(destTabIndex),
1941              USER_END_DATE = l_userEndDestTAB(destTabIndex),
1942              EFFECTIVE_START_DATE = l_effStartDestTAB(destTabIndex),
1943              EFFECTIVE_END_DATE = l_effEndDestTAB(destTabIndex),
1944              START_DATE = l_startDestTAB(destTabIndex),
1945              EXPIRATION_DATE = l_endDestTAB(destTabIndex),
1946              ASSIGNMENT_TYPE = l_assignTAB(destTabIndex)
1947        WHERE rowid = l_rowIDDestTAB(destTabIndex);
1948    end if;
1949   end if;
1950 
1951   commit; --Commit final work.
1952 
1953   --close the cursor now
1954    if (c_userRoleAssignments%ISOPEN) then
1955      close c_userRoleAssignments;
1956    end if;
1957 
1958   -- Bug 9184359
1959   FixWURAEffectiveDates(l_maxRows , p_username, p_rolename);
1960 
1961   -- Bug 8423138
1962   FixLUREffectiveDates(l_maxRows, p_username, p_rolename);
1963 
1964   --release lock
1965   if (dbms_lock.release(l_lockhandle) <> 0) then
1966    wf_core.raise('WF_LOCK_FAIL');
1967   end if;
1968 
1969 exception
1970   when others then
1971     result := dbms_lock.release(l_lockhandle);
1972     if (c_userRoleAssignments%ISOPEN) then
1973       close c_userRoleAssignments;
1974     end if;
1975 
1976     raise;
1977 end;
1978 
1979   /*
1980   ** GetUsernameChangeCounts
1981   **   Described in package specification.
1982   */
1983   function GetUsernameChangeCounts(p_name VARCHAR2) RETURN wfcount_tab pipelined is
1984     --l_wfcount_tab wfcount_tab;
1985     l_wfcount_tab wfcount_type;
1986     l_roleInfoTAB WF_DIRECTORY.wf_local_roles_tbl_type;
1987     l_partitionID WF_DIRECTORY_PARTITIONS.PARTITION_ID%TYPE;
1988     l_partitionName WF_DIRECTORY_PARTITIONS.ORIG_SYSTEM%TYPE;
1989     l_pvalue varchar2(10) := FND_PROFILE.value('WF_MAINT_COMPLETED_ITEMS');
1990   begin
1991     -- First etermine if the username actually exists
1992     WF_DIRECTORY.GetRoleInfo2(p_name, l_roleInfoTAB);
1993     if l_roleInfoTAB(1).DISPLAY_NAME is null then
1994       l_wfcount_tab := null;
1995     else
1996       l_wfcount_tab.USER_NAME:=p_name;
1997 
1998       -- Determine the entries in FND_GRANTS associated to this role.
1999       select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2000       from   FND_GRANTS fg
2001       where  fg.GRANTEE_TYPE='USER'
2002       and    fg.GRANTEE_ORIG_SYSTEM in ('FND_USR', 'PER')
2003       and    fg.PROGRAM_NAME = 'WORKFLOW_UI'
2004       and    fg.PARAMETER1=p_name;
2005       l_wfcount_tab.TABLE_NAME :='FND_GRANTS';
2006       pipe ROW (l_wfcount_tab);
2007 
2008       -- Determine the workflow processes owned by this role. Can be any role.
2009       if (l_pvalue is null or l_pvalue = 'Y') then
2010         select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2011         from   WF_ITEMS
2012         where  OWNER_ROLE = p_name;
2013       else
2014         select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2015         from   WF_ITEMS
2016         where  OWNER_ROLE = p_name
2017         and    END_DATE is null;
2018       end if;
2019       l_wfcount_tab.TABLE_NAME :='WF_ITEMS';
2020       pipe ROW (l_wfcount_tab);
2021 
2022       -- Determine rows to change in WF_ITEM_ACTIVITY_STATUSES
2023       if (l_pvalue is null or l_pvalue = 'Y') then
2024         select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2025         from   WF_ITEM_ACTIVITY_STATUSES WIAS
2026         where  ASSIGNED_USER =  p_name;
2027       else
2028         select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2029         from   WF_ITEM_ACTIVITY_STATUSES WIAS
2030         where  exists (select '1'
2031                        from WF_ITEMS WI
2032                        where  WI.ITEM_TYPE=WIAS.ITEM_TYPE and
2033                               WI.ITEM_KEY=WIAS.ITEM_KEY and
2034                               WI.END_DATE is null) and
2035                ASSIGNED_USER =  p_name;
2036       end if;
2037       l_wfcount_tab.TABLE_NAME :='WF_ITEM_ACTIVITY_STATUSES';
2038       pipe ROW (l_wfcount_tab);
2039 
2040       -- Determine rows to change in WF_ITEM_ACTIVITY_STATUSES_H
2041       if (l_pvalue is null or l_pvalue = 'Y') then
2042         select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2043         from   WF_ITEM_ACTIVITY_STATUSES_H WIASH
2044         where  ASSIGNED_USER =  p_name;
2045       else
2046         select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2047         from   WF_ITEM_ACTIVITY_STATUSES_H WIASH
2048         where  exists (select '1'
2049                        from WF_ITEMS WI
2050                        where  WI.ITEM_TYPE=WIASH.ITEM_TYPE and
2051                               WI.ITEM_KEY=WIASH.ITEM_KEY and
2052                               WI.END_DATE is null) and
2053                ASSIGNED_USER =  p_name;
2054       end if;
2055       l_wfcount_tab.TABLE_NAME :='WF_ITEM_ACTIVITY_STATUSES_H';
2056       pipe ROW (l_wfcount_tab);
2057 
2058       -- Determine rows to change in WF_NOTIFICATIONS
2059       if (l_pvalue is null or l_pvalue = 'Y') then
2060         select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2061         from   WF_NOTIFICATIONS WN
2062         where  RECIPIENT_ROLE        = p_name
2063                 or ORIGINAL_RECIPIENT = p_name
2064                 or more_info_role     = p_name
2065                 or from_role          = p_name
2066                 or responder          = p_name;
2067       else
2068         select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2069         from   WF_NOTIFICATIONS WN
2070         where  (exists (select '1'
2071                 from   WF_ITEM_ACTIVITY_STATUSES WIAS, WF_ITEMS WI
2072                 where  WIAS.NOTIFICATION_ID = WN.NOTIFICATION_ID
2073                 and    WIAS.ITEM_TYPE = WI.ITEM_TYPE
2074                 and    WIAS.ITEM_KEY = WI.ITEM_KEY
2075                 and    WI.END_DATE IS NULL)
2076           or exists (select '1'
2077                 from   WF_ITEM_ACTIVITY_STATUSES_H WIASH, WF_ITEMS WI
2078                 where  WIASH.NOTIFICATION_ID = WN.NOTIFICATION_ID
2079                 and    WIASH.ITEM_TYPE = WI.ITEM_TYPE
2080                 and    WIASH.ITEM_KEY = WI.ITEM_KEY
2081                 and    WI.END_DATE IS NULL))
2082         and    (RECIPIENT_ROLE        = p_name
2083                 or ORIGINAL_RECIPIENT = p_name
2084                 or more_info_role     = p_name
2085                 or from_role          = p_name
2086                 or responder          = p_name);
2087       end if;
2088       l_wfcount_tab.TABLE_NAME := 'WF_NOTIFICATIONS';
2089       pipe ROW (l_wfcount_tab);
2090 
2091       -- Determine rows to change in WF_PROCESS_ACTIVITIES
2092       select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2093       from   WF_PROCESS_ACTIVITIES
2094       where  PERFORM_ROLE = p_name;
2095       l_wfcount_tab.TABLE_NAME := 'WF_PROCESS_ACTIVITIES';
2096       pipe ROW (l_wfcount_tab);
2097 
2098       -- Determine rows to change in WF_ROUTING_RULES. Applies to users only
2099       if (l_pvalue is null or l_pvalue = 'Y') then
2100         if l_roleInfoTAB(1).ORIG_SYSTEM in ('PER','FND_USR') then
2101           select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2102           from   WF_ROUTING_RULES
2103           where  ROLE = p_name or ACTION_ARGUMENT = p_name;
2104         else
2105           l_wfcount_tab.REC_CNT := 0;
2106         end if;
2107       else
2108         if l_roleInfoTAB(1).ORIG_SYSTEM in ('PER','FND_USR') then
2109           select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2110           from   WF_ROUTING_RULES
2111           where  (ROLE = p_name or ACTION_ARGUMENT = p_name)
2112             and  BEGIN_DATE<=SYSDATE
2113             and  (END_DATE is null or END_DATE>=SYSDATE);
2114         else
2115           l_wfcount_tab.REC_CNT := 0;
2116         end if;
2117 	  end if;
2118       l_wfcount_tab.TABLE_NAME := 'WF_ROUTING_RULES';
2119       pipe ROW (l_wfcount_tab);
2120 
2121       -- Determine rows to change in WF_ROUTING_RULE_ATTRIBUTES. Applies to users only
2122       if (l_pvalue is null or l_pvalue = 'Y') then
2123         if l_roleInfoTAB(1).ORIG_SYSTEM in ('PER','FND_USR') then
2124           select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2125           from   WF_ROUTING_RULE_ATTRIBUTES ra, WF_ROUTING_RULES wrr
2126           where  wrr.RULE_ID=ra.RULE_ID
2127           and    ra.TEXT_VALUE = p_name
2128           and    exists
2129            (select '1'
2130             from   WF_MESSAGE_ATTRIBUTES ma
2131             where  ma.NAME=ra.NAME
2132             and    ma.TYPE='ROLE');
2133         else
2134           l_wfcount_tab.REC_CNT := 0;
2135         end if;
2136       else
2137         if l_roleInfoTAB(1).ORIG_SYSTEM in ('PER','FND_USR') then
2138           select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2139           from   WF_ROUTING_RULE_ATTRIBUTES ra, WF_ROUTING_RULES wrr
2140           where  wrr.BEGIN_DATE<=SYSDATE
2141           and    (wrr.END_DATE is null or wrr.END_DATE>=SYSDATE)
2142           and    wrr.RULE_ID=ra.RULE_ID
2143           and    ra.TEXT_VALUE = p_name
2144           and    exists
2145            (select '1'
2146             from   WF_MESSAGE_ATTRIBUTES ma
2147             where  ma.NAME=ra.NAME
2148             and    ma.TYPE='ROLE');
2149         else
2150           l_wfcount_tab.REC_CNT := 0;
2151         end if;
2152 
2153       end if;
2154       l_wfcount_tab.TABLE_NAME := 'WF_ROUTING_RULE_ATTRIBUTES';
2155       pipe ROW (l_wfcount_tab);
2156 
2157       -- Determine rows to change in WF_COMMENTS Applies to users only
2158       if (l_pvalue is null or l_pvalue = 'Y') then
2159         if l_roleInfoTAB(1).ORIG_SYSTEM in ('PER','FND_USR') then
2160           select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2161           from   WF_COMMENTS WC
2162           where (WC.FROM_ROLE = p_name
2163           or     WC.TO_ROLE = p_name
2164           or     WC.PROXY_ROLE = p_name)
2165           and (exists (select '1'
2166                 from   WF_ITEM_ACTIVITY_STATUSES WIAS, WF_ITEMS WI
2167                 where  WIAS.NOTIFICATION_ID = WC.NOTIFICATION_ID
2168                 and    WIAS.ITEM_TYPE = WI.ITEM_TYPE
2169                 and    WIAS.ITEM_KEY = WI.ITEM_KEY
2170                 and    WI.END_DATE IS NULL)
2171           or exists (select '1'
2172                 from   WF_ITEM_ACTIVITY_STATUSES_H WIASH, WF_ITEMS WI
2173                 where  WIASH.NOTIFICATION_ID = WC.NOTIFICATION_ID
2174                 and    WIASH.ITEM_TYPE = WI.ITEM_TYPE
2175                 and    WIASH.ITEM_KEY = WI.ITEM_KEY
2176                 and    WI.END_DATE IS NULL));
2177         else
2178           l_wfcount_tab.REC_CNT := 0;
2179         end if;
2180       else
2181         if l_roleInfoTAB(1).ORIG_SYSTEM in ('PER','FND_USR') then
2182           select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2183           from   WF_COMMENTS WC
2184           where  WC.FROM_ROLE = p_name
2185           or     WC.TO_ROLE = p_name
2186           or     WC.PROXY_ROLE = p_name;
2187         else
2188           l_wfcount_tab.REC_CNT := 0;
2189         end if;
2190       end if;
2191       l_wfcount_tab.TABLE_NAME := 'WF_COMMENTS';
2192       pipe ROW (l_wfcount_tab);
2193 
2194       -- Determine rows to change in WF_ITEM_ATTRIBUTE_VALUES. Can be any role.
2195       if (l_pvalue is null or l_pvalue = 'Y') then
2196         select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2197         from   WF_ITEM_ATTRIBUTE_VALUES WIAV, WF_ITEM_ATTRIBUTES WIA
2198         where  WIA.type = 'ROLE'
2199         and    WIA.ITEM_TYPE = WIAV.ITEM_TYPE
2200         and    WIA.NAME = WIAV.NAME
2201         and    WIAV.TEXT_VALUE = p_name;
2202       else
2203         select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2204         from   WF_ITEM_ATTRIBUTE_VALUES WIAV, WF_ITEM_ATTRIBUTES WIA
2205         where  WIA.type = 'ROLE'
2206         and    WIA.ITEM_TYPE = WIAV.ITEM_TYPE
2207         and    WIA.NAME = WIAV.NAME
2208         and    WIAV.TEXT_VALUE = p_name
2209         and    exists (select '1'
2210                        from   WF_ITEMS WI
2211                        where  WI.ITEM_TYPE=WIAV.ITEM_TYPE
2212                          and  WI.ITEM_KEY=WIAV.ITEM_KEY
2213                          and  WI.END_DATE is null);
2214       end if;
2215       l_wfcount_tab.TABLE_NAME := 'WF_ITEM_ATTRIBUTE_VALUES';
2216       pipe ROW (l_wfcount_tab);
2217 
2218       -- Now check what happens with the WFDS tables:
2219       WF_DIRECTORY.assignPartition(l_roleInfoTAB(1).ORIG_SYSTEM, l_partitionID, l_partitionName);
2220       -- Determine rows to change in WF_LOCAL_ROLES. Can be any role
2221       select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2222       from    WF_LOCAL_ROLES
2223       WHERE   NAME = p_name
2224       AND     PARTITION_ID = l_partitionID
2225       AND     ORIG_SYSTEM = l_roleInfoTAB(1).ORIG_SYSTEM
2226       AND     ORIG_SYSTEM_ID = l_roleInfoTAB(1).ORIG_SYSTEM_ID;
2227       l_wfcount_tab.TABLE_NAME := 'WF_LOCAL_ROLES';
2228       pipe ROW (l_wfcount_tab);
2229 
2230       -- Determine rows to change in WF_LOCAL_USER_ROLES. Can be any role
2231       select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2232       from   WF_LOCAL_USER_ROLES
2233       WHERE  (ROLE_NAME = p_name
2234       AND    ROLE_ORIG_SYSTEM = l_roleInfoTAB(1).ORIG_SYSTEM
2235       AND    ROLE_ORIG_SYSTEM_ID = l_roleInfoTAB(1).ORIG_SYSTEM_ID)
2236              OR
2237              (USER_NAME = p_name
2238       AND    USER_ORIG_SYSTEM = l_roleInfoTAB(1).ORIG_SYSTEM
2239       AND    USER_ORIG_SYSTEM_ID = l_roleInfoTAB(1).ORIG_SYSTEM_ID);
2240       l_wfcount_tab.TABLE_NAME := 'WF_LOCAL_USER_ROLES';
2241       pipe ROW (l_wfcount_tab);
2242 
2243       -- Determine rows to change in WF_USER_ROLE_ASSIGNMENTS. Can be any role
2244       select nvl(count(1), 0) into l_wfcount_tab.REC_CNT
2245       from   WF_USER_ROLE_ASSIGNMENTS
2246       WHERE  (ROLE_NAME = p_name
2247       AND    ROLE_ORIG_SYSTEM = l_roleInfoTAB(1).ORIG_SYSTEM
2248       AND    ROLE_ORIG_SYSTEM_ID = l_roleInfoTAB(1).ORIG_SYSTEM_ID)
2249              OR
2250              (USER_NAME = p_name
2251       AND    USER_ORIG_SYSTEM = l_roleInfoTAB(1).ORIG_SYSTEM
2252       AND    USER_ORIG_SYSTEM_ID = l_roleInfoTAB(1).ORIG_SYSTEM_ID);
2253       l_wfcount_tab.TABLE_NAME := 'WF_USER_ROLE_ASSIGNMENTS';
2254       pipe ROW (l_wfcount_tab);
2255 
2256       -- Determine rows to change in WF_ROLE_HIERARCHIES. Applies to roles only
2257       if l_roleInfoTAB(1).ORIG_SYSTEM NOT in ('PER','FND_USR') then
2258         select sum (a.detail) into l_wfcount_tab.REC_CNT
2259         from (select nvl(count(1), 0) as detail
2260               from    WF_ROLE_HIERARCHIES
2261               WHERE   SUPER_NAME = p_name
2262               AND     SUPERIOR_PARTITION_ID = l_partitionID
2263               union
2264               select nvl(count(1), 0) as detail
2265               from    WF_ROLE_HIERARCHIES
2266               WHERE   SUB_NAME = p_name
2267               AND     PARTITION_ID = l_partitionID) a;
2268       else
2269         l_wfcount_tab.REC_CNT := 0;
2270       end if;
2271       l_wfcount_tab.TABLE_NAME := 'WF_ROLE_HIERARCHIES';
2272       pipe ROW (l_wfcount_tab);
2273     end if;
2274     return;
2275   exception
2276     when others then
2277       return;
2278   end GetUsernameChangeCounts;
2279 
2280 end WF_MAINTENANCE;