CREATE OR REPLACE PACKAGE BODY SnapshotCreateRestore AS notmTable elemidType; uoidTable uoidType; TYPE TTYPE is REF CURSOR; CWMSEQ_INC NUMBER:= 0; NEW NUMBER:= 0; OLD NUMBER:= 1; --sochen: since cwmseq increment_by changed from 100 to 10 to save some numbers in case java elementid to be overflow DEFAULT_CWMSEQ_INC NUMBER:=10; PROCEDURE MyDebug(debugMessage VARCHAR2) IS PRAGMA AUTONOMOUS_TRANSACTION; BEGIN --insert into sochen_debug2(info) values(debugMessage); COMMIT; END MyDebug; PROCEDURE cleanAssocTable IS BEGIN delete from assoctable; END cleanAssocTable; -- WorkspaceID predicate unnecessary in tempfco (global temporary table) PROCEDURE cleanTempFCO IS BEGIN delete from tempfco; END cleanTempFCO; -- WorkspaceID predicate unnecessary in currtempfco (global temporary table) PROCEDURE cleanCurrTempFCO IS BEGIN delete from currtempfco; END cleanCurrTempFCO; PROCEDURE cleanTempTable IS BEGIN delete from temptable; END cleanTempTable; PROCEDURE cleanNOTMTable IS BEGIN SnapshotCreateRestore.notmTable.DELETE(); END cleanNOTMTable; /** * Bug 3589323. This method deals with chained associations that * occur in AssocTable while copying multiple objects at a time. */ FUNCTION traverseHashLookup(hashTable IN elemidType, elemID IN NUMBER) RETURN NUMBER IS c NUMBER; BEGIN c := elemID; loop if (hashTable.EXISTS(c)) then c := hashTable(c); else exit; end if; end loop; return c; END traverseHashLookup; -- WorkspaceID predicate unnecessary in mcmcomponent (global temporary table) FUNCTION inMCMComponent(elemID IN NUMBER) RETURN BOOLEAN IS c NUMBER; BEGIN select count(1) into c from mcmcomponent where elementid = elemID; if (c = 0) then return FALSE; else return TRUE; end if; END inMCMComponent; PROCEDURE takeSnapshot(elemID IN NUMBER,snap IN NUMBER) IS idTable elemidType; i BINARY_INTEGER:= 1; vCounter BINARY_INTEGER; vElemID cmpelement_v.elementid%TYPE; BEGIN --Bug 6653513. Using "where LEVEL>=2" in place of no predicate and "if (c.ordering >= 2" --seems to return no rows at times when using DB 10.2 with seed optimizer statistics. --I verified this using SQL*Plus using DB 10.2.0.1. Very strange. However, using --DB 10.2 with gathered statistics or DB 11.1 under any circumstances seems to work. Snapshot.debug('SnapshotCreateRestore.takeSnapshot: Object being snapshotted = ',elemID); for c in (select childid,LEVEL ordering from pctree start with childid = elemID connect by prior parentid = childid) loop if (c.ordering >= 2 and NOT(inMCMComponent(c.childid))) then idTable(c.childid):= c.childid; Snapshot.debug('SnapshotCreateRestore.takeSnapshot: parentid =',c.childid); end if; end loop; Snapshot.debug('SnapshotCreateRestore.takeSnapshot: Number of elems in idTable=',idTable.COUNT); /* * take snapshot of the component */ SnapshotGenerated.takeSnapshot(idTable,snap); if (Snapshot.isDebug()) then Snapshot.debug('SnapshotCreateRestore.takeSnapshot: ','CMPElement_X contents'); for c in (select * from cmpelement_x where snapshotid=snap) loop Snapshot.debug(' elementid = ' || c.elementid || ' name = ' || c.name || ' classname = ' || c.classname || ' uoid = ' || c.uoid, ''); end loop; end if; /* * take a snapshot of the namespace table */ insert into fcofoldernamespacestorage select cmp.workspaceID,snap,1,1, cmp.parentID, cmp.domain, cmp.name, cmp.isPhys, cmp.elementid, cmp.aggregateParent, cmp.languageISOID from cmpallfolderfconames cmp,temptable t where cmp.workspaceID = t.workspaceID and cmp.elementid = t.elementid; /* * take snapshot of association tables */ insert into pctreestorage select /*+ LEADING(t) USE_NL_WITH_INDEX(p ALLPCTREE_PK) */ t.workspaceID,snap,t.compuoid, p.parentid,p.childid,p.parentrole,p.childrole from temptable t, allpctree p where t.workspaceID = p.workspaceID and t.elementid = p.childid; insert into intralinkstorage select /*+ LEADING(t) USE_NL_WITH_INDEX(i ALLINTRALINK_PK) */ t.workspaceID,snap,t.compuoid, i.linkfrom,i.linkto,i.linkfromrole,i.linktorole from allintralink i,temptable t where i.workspaceID = t.workspaceID and i.linkfrom = t.elementid; insert into interlinkstorage select /*+ LEADING(t) USE_NL_WITH_INDEX(i ALLINTERLINK_PK) */ t.workspaceID,snap,t.compuoid, i.linkfrom,i.linkto,i.linkfromrole,i.linktorole from allinterlink i,temptable t where i.workspaceID = t.workspaceID and i.linkfrom = t.elementid; delete from changelog; END takeSnapshot; -- WorkspaceID predicate unnecessary in _v views and tempfco (global temporary table) PROCEDURE restoreParentage(snap IN NUMBER) IS notmVal NUMBER; BEGIN delete from tempfco t where exists ( select 1 from firstclassobject_v f where f.uoid = t.uoid ); if (Snapshot.isDebug()) then for c in (select uoid,elementid from tempfco) loop Snapshot.debug('SnapshotCreateRestore.restoreParentage: elementid = ',c.elementid); end loop; end if; insert into cmpallfolderfconames select workspaceID,parentid,domain,name,isphys,f.elementid,aggregateparent,languageisoid from fcofoldernamespacestorage f,tempfco t where f.elementid = t.elementid and f.snapshotid = snap and t.type = FCOPARENTS; Snapshot.debug('SnapshotCreateRestore.restoreParentage: ','inserting pctree parents'); insert into pctree select workspaceID,parentid,childid,parentrole,childrole from pctreestorage p,tempfco t where p.childid = t.elementid and p.snapshotid = snap and t.type = FCOPARENTS; Snapshot.debug('SnapshotCreateRestore.restoreParentage: ','inserting interlink parents'); insert into interlink select workspaceID,linkfrom,linkto,linkfromrole,linktorole from interlinkstorage i,tempfco t where i.linkfrom = t.elementid and i.snapshotid = snap and t.type = FCOPARENTS; Snapshot.debug('SnapshotCreateRestore.restoreParentage: ','inserting intralink parents'); insert into intralink select workspaceID,linkfrom,linkto,linkfromrole,linktorole from intralinkstorage i,tempfco t where i.linkfrom = t.elementid and i.snapshotid = snap and t.type = FCOPARENTS; SnapshotGenerated.restoreParentage(snap); END restoreParentage; PROCEDURE insertIntoCurrentRepos(snap IN NUMBER,compid IN NUMBER, restoreParents IN BOOLEAN,selfOnly IN NUMBER) IS BEGIN if (Snapshot.isDebug()) then Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: ','tempfco contents'); for c in (select elementid from tempfco where type = FCOCHILDREN or type = ITEMSETS) loop Snapshot.debug('tempfco: compid = ' || compid || ', elementid = ',c.elementid); end loop; end if; if (Snapshot.isDebug()) then --This debug gets expensive unless the repository is extremely small. --Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: ','cmpallfolderfconames contents'); --for c in (select parentID,domain,name,isPhys,elementid,aggregateParent, -- languageISOID -- from cmpallfolderfconames) loop -- Snapshot.debug('cmpallfolderfconames: existingInCurrentRepos: parentID = ' -- || c.parentID || ' domain = ' || c.domain || ' name = ' -- || c.name || ' isPhys = ' || c.isPhys || ' lang = ' -- || c.languageISOID || ' elementid = ', c.elementid); --end loop; Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: ','fcofoldernamespacestorage contents'); for c in (select parentID,domain,name,isPhys,elementid,aggregateParent, languageISOID from fcofoldernamespacestorage where elementid in ( select compid from dual union select elementid from tempfco where type = FCOCHILDREN or type = ITEMSETS ) and snapshotid = snap) loop Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos namespace: parentID = ' || c.parentID || ' domain = ' || c.domain || ' name = ' || c.name || ' isPhys = ' || c.isPhys || ' lang = ' || c.languageISOID || ' elementid = ', c.elementid); end loop; -- FCOFOLDERNS_PK = (workspaceID,parentID,domain,name,isPhys,languageISOID) Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: ','cmpallfolderfconames conflicts'); for c in (select s.parentID,s.domain,s.name,s.isPhys,s.elementid,s.aggregateParent, s.languageISOID from fcofoldernamespacestorage s, cmpallfolderfconames n where s.elementid in ( select compid from dual union select elementid from tempfco where (type = FCOCHILDREN or type = ITEMSETS) and (selfOnly = Snapshot.CASCADE_SNAPSHOT) ) and s.parentID = n.parentID and s.domain = n.domain and s.name = n.name and s.isPhys = n.isPhys and s.languageISOID = n.languageISOID and s.snapshotid = snap) loop Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: namespace parentID = ' || c.parentID || ' domain = ' || c.domain || ' name = ' || c.name || ' isPhys = ' || c.isPhys || ' lang = ' || c.languageISOID || ' elementid = ', c.elementid); end loop; end if; /* * insert into cmpallfolderfconames the version namespace entries */ insert into cmpallfolderfconames select workspaceID,parentID,domain,name,isPhys,elementid,aggregateParent,languageISOID from fcofoldernamespacestorage where elementid in ( select compid from dual union select elementid from tempfco where (type = FCOCHILDREN or type = ITEMSETS) and (selfOnly = Snapshot.CASCADE_SNAPSHOT) ) and snapshotid = snap; if (Snapshot.isDebug()) then Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: ','pctree conflicts'); -- AllPCTree_PK = (workspaceID,childid) for c in (select p.parentid,p.childid,p.parentrole,p.childrole from pctreestorage p, tempfco t, pctree r where p.compuoid = t.uoid and p.snapshotid = snap and t.type = FCOCHILDREN and p.childid = r.childid and selfOnly = Snapshot.CASCADE_SNAPSHOT union select p.parentid,p.childid,p.parentrole,p.childrole from pctreestorage p, pctree r where p.childid = compid and p.snapshotid = snap and p.childid = r.childid) loop Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: pctree parentID = ' || c.parentid || ' childID = ' || c.childid || ' parentRole = ' || c.parentRole || ' childRole = ', c.childrole); end loop; end if; Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: ','inserting pctree'); insert into pctree ( select workspaceID,parentid,childid,parentrole,childrole from pctreestorage p, tempfco t where p.compuoid = t.uoid and p.snapshotid = snap and t.type = FCOCHILDREN and selfOnly = Snapshot.CASCADE_SNAPSHOT union select workspaceID,parentid,childid,parentrole,childrole from pctreestorage p where p.childid = compid and p.snapshotid = snap ); Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: ','inserting intralink'); -- AllIntraLink_PK primary key (workspaceID,linkfrom,linktorole,linkfromrole) insert into intralink ( select workspaceID,linkfrom,linkto,linkfromrole,linktorole from intralinkstorage i, tempfco t where i.compuoid = t.uoid and i.snapshotid = snap and t.type = FCOCHILDREN and selfOnly = Snapshot.CASCADE_SNAPSHOT union select workspaceID,linkfrom,linkto,linkfromrole,linktorole from intralinkstorage i where i.linkfrom = compid and i.snapshotid = snap ); Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: ','inserting interlink'); -- AllInterLink_PK = (workspaceID,linkfrom,linktorole,linkfromrole) insert into interlink ( select workspaceID,linkfrom,linkto,linkfromrole,linktorole from interlinkstorage i, tempfco t where i.compuoid = t.uoid and i.snapshotid = snap and t.type = FCOCHILDREN and selfOnly = Snapshot.CASCADE_SNAPSHOT union select workspaceID,linkfrom,linkto,linkfromrole,linktorole from interlinkstorage i where i.linkfrom = compid and i.snapshotid = snap ); if (restoreParents) then Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: ','inserting parentage'); restoreParentage(snap); end if; Snapshot.debug('SnapshotCreateRestore.insertIntoCurrentRepos: ','inserting heavy snapshot'); SnapshotGenerated.insertIntoCurrentRepos(snap,compid); delete from changelog; END insertIntoCurrentRepos; PROCEDURE deleteFromCurrentRepos(currentElemID IN NUMBER,cascade IN NUMBER) IS i BINARY_INTEGER:= 0; elemidTable elemidType; BEGIN Snapshot.debug('SnapshotCreateRestore.deleteFromCurrentRepos: currentElemID = ', currentElemID); for c in (select distinct elementid,uoid,notm,level from firstclassobject_v start with elementid=currentElemID connect by prior elementid = owningfolder order by level) loop elemidTable(i):= c.elementid; uoidTable(i):= c.uoid; notmTable(i):= c.notm+1; i:= i+1; Snapshot.debug('SnapshotCreateRestore.deleteFromCurrentRepos: c.elementid = ', c.elementid); exit when NOT(cascade = Snapshot.CASCADE_SNAPSHOT); end loop; forall indx in 0..i-1 insert into currtempfco(elementid,uoid,type) values (elemidTable(indx),uoidTable(indx),FCOCHILDREN); insert into currtempfco(elementid,uoid) select itemset.elementid,itemset.uoid from cmpitemset_v itemset,currtempfco t where t.elementid = itemset.firstclassobject; -- Bug 8282412: After Tahoe redefined CMPPhysicalObject as an FCO, physical objects not getting deleted prior to restore. insert into currtempfco(elementid,uoid) select phyobj.elementid,phyobj.uoid from cmpphysicalobject_v phyobj,currtempfco t where t.elementid = phyobj.logicalobject; if (Snapshot.isDebug()) then Snapshot.debug('SnapshotCreateRestore.deleteFromCurrentRepos: ', 'currtempfco contents'); for c in (select elementid,type from currtempfco) loop Snapshot.debug('currtempfco: elementid = ' || c.elementid || ' , type = ', c.type); end loop; end if; --This debug gets expensive unless the repository is extremely small. It should also include isPhys,Parent,Domain! --if (Snapshot.isDebug()) then -- Snapshot.debug('SnapshotCreateRestore.deleteFromCurrentRepos: ','cmpallfolderfconames contents'); -- for c in (select name,elementid from cmpallfolderfconames) loop -- Snapshot.debug('cmpallfolderfconames: name = ' || c.name || ' elementid = ',c.elementid); -- end loop; --end if; /* For Paris, cmpelement_v and secondclassobject_v are no longer updatable, so do this... */ if (cascade = Snapshot.CASCADE_SNAPSHOT) then delete /*+ use_nl(fco) index(fco, idx_FCOElementid)*/ from firstclassobject_v fco where exists (select 1 from currtempfco currfco where currfco.elementid = fco.elementid); /* For Paris, secondclassobject_v is no longer updatable, so do this... (hint avoids FTS)*/ delete /*+ use_nl(sco) index(sco, idx_SCOElementid)*/ from CMPSCOElement_v sco where exists (select 1 from currtempfco fco where fco.elementid = sco.firstclassobject); delete /*+ use_nl(sco) index(sco, idx_SCOCfgElementid)*/ from CMPSCOCfgElement_v sco where exists (select 1 from currtempfco fco where fco.elementid = sco.firstclassobject); delete /*+ use_nl(sco) index(sco, idx_SCOMapElementid)*/ from CMPSCOMapElement_v sco where exists (select 1 from currtempfco fco where fco.elementid = sco.firstclassobject); delete /*+ use_nl(sco) index(sco, idx_SCOPrpElementid)*/ from CMPSCOPrpElement_v sco where exists (select 1 from currtempfco fco where fco.elementid = sco.firstclassobject); else /* For Paris, cmpelement_v and secondclassobject_v are no longer updatable, so do this... */ delete from CMPFCOElement_v where elementid = currentElemID; delete from CMPSCOElement_v where elementid = currentElemID; delete from CMPSCOCfgElement_v where elementid = currentElemID; delete from CMPSCOMapElement_v where elementid = currentElemID; delete from CMPSCOPrpElement_v where elementid = currentElemID; delete from CMPSYSElement_v where elementid = currentElemID; delete from CMPSCOElement_v where firstclassobject = currentElemID; delete from CMPSCOCfgElement_v where firstclassobject = currentElemID; delete from CMPSCOMapElement_v where firstclassobject = currentElemID; delete from CMPSCOPrpElement_v where firstclassobject = currentElemID; end if; /* * delete the rows from cmpallfolderfconames */ delete from cmpallfolderfconames cmp where exists ( select 1 from currtempfco t where t.elementid = cmp.elementid ); SnapshotTrigger.syncAssociationTables(); cleanCurrTempFCO(); END deleteFromCurrentRepos; PROCEDURE reconcileAssociations(versionIDTable IN elemidType, currentIDTable IN elemidType,hashTable IN OUT elemidType,snap IN NUMBER, traverseHashFirst IN BOOLEAN) IS c NUMBER; BEGIN if (traverseHashFirst and versionIDTable.COUNT > 0) then -- Bug 3589323. Support multi-object copy. for i in 0..versionIDTable.LAST loop c:= versionIDTable(i); if (hashTable.EXISTS(c)) then hashTable(c):= traverseHashLookup(hashTable,c); end if; end loop; end if; if (snap = 0) then -- namespace table. -- A disabled ORDERED hint was used previously. Ordering small snapshots on -- (assoctable, cmpallfolderfconames) for NL works, but not big ones. -- All assoctable rows are deleted after each paste or restore operation, -- so dynamic sampling is indicated here to assist the optimizer. -- Due to WS in Tahoe, now optimizer chooses extra nested loop->FTS avoids for c in (select /*+ full (a) */ cmp.rowid,elementid,parentid,aggregateparent from assoctable a,cmpallfolderfconames cmp where cmp.workspaceID = a.workspaceID and a.oldID = cmp.elementid) loop if (hashTable.EXISTS(c.elementid)) then update cmpallfolderfconames set elementid = hashTable(c.elementid) where rowid = c.rowid; end if; if (hashTable.EXISTS(c.parentid)) then update cmpallfolderfconames set parentid = hashTable(c.parentid) where rowid = c.rowid; end if; if (hashTable.EXISTS(c.aggregateparent)) then update cmpallfolderfconames set aggregateparent = hashTable(c.aggregateparent) where rowid = c.rowid; end if; end loop; if (versionIDTable.COUNT > 0) then -- intralink forall i in 0..versionIDTable.LAST update /*+ index(intralink idx_intralink_linkfrom)*/ intralink set linkfrom = currentIDTable(i) where linkfrom = versionIDTable(i); forall i in 0..versionIDTable.LAST update /*+ index(intralink idx_intralink_linkto)*/ intralink set linkto = currentIDTable(i) where linkto = versionIDTable(i); -- interlink forall i in 0..versionIDTable.LAST update /*+ index(interlink idx_interlink_linkfrom)*/ interlink set linkfrom = currentIDTable(i) where linkfrom = versionIDTable(i); forall i in 0..versionIDTable.LAST update /*+ index(interlink idx_interlink_linkto)*/ interlink set linkto = currentIDTable(i) where linkto = versionIDTable(i); end if; -- pctree. -- A disabled ORDERED hint was used previously. Ordering small snapshots on -- (assoctable, pctree) for NL works, but not big ones. -- All assoctable rows are deleted after each paste or restore operation, -- so dynamic sampling is indicated here to assist the optimizer. -- Due to WS in Tahoe, now optimizer chooses extra nested loop->FTS avoids for c in (select /*+ full (a) */ p.rowid,parentid,childid from assoctable a, pctree p where p.workspaceID = a.workspaceID and p.childid = a.oldID) loop if (hashTable.EXISTS(c.parentid)) then if (Snapshot.isDebug()) then Snapshot.debug('Parentid: Updating current ' || c.parentid || ' with ', hashTable(c.parentid)); end if; update pctree set parentid = hashTable(c.parentid) where rowid = c.rowid; end if; if (hashTable.EXISTS(c.childid)) then if (Snapshot.isDebug()) then Snapshot.debug('Childid: Updating current ' || c.childid || ' with ', hashTable(c.childid)); end if; update pctree set childid = hashTable(c.childid) where rowid = c.rowid; end if; end loop; else if (versionIDTable.COUNT > 0) then forall i in 0..versionIDTable.LAST update /*+ index(tempfco, idx_TempFCO_ElemId)*/ tempfco set elementid = currentIDTable(i) where elementid = versionIDTable(i); end if; -- namespace storage. -- A disabled ORDERED hint was used previously. Ordering small snapshots on -- (assoctable, fcofoldernamespacestorage) for NL works, but not big ones. -- All assoctable rows are deleted after each paste or restore operation, -- so dynamic sampling is indicated here to assist the optimizer. -- Due to WS in Tahoe, now optimizer chooses extra nested loop->FTS avoids for c in (select /*+ full (a) */ cmp.rowid,elementid,parentid,aggregateparent from assoctable a,fcofoldernamespacestorage cmp where cmp.workspaceID = a.workspaceID and cmp.snapshotid = snap and a.oldID = cmp.elementid) loop if (hashTable.EXISTS(c.elementid)) then update fcofoldernamespacestorage set elementid = hashTable(c.elementid) where rowid = c.rowid; end if; if (hashTable.EXISTS(c.parentid)) then update fcofoldernamespacestorage set parentid = hashTable(c.parentid) where rowid = c.rowid; end if; if (hashTable.EXISTS(c.aggregateparent)) then update fcofoldernamespacestorage set aggregateparent = hashTable(c.aggregateparent) where rowid = c.rowid; end if; end loop; -- lwcontext does not need to be updated since the diff is the -- only service relying on this and diff does not work on element ids if (versionIDTable.COUNT > 0) then -- intralink storage forall i in 0..versionIDTable.LAST update /*+ index(intralinkstorage idx_intralink_s_linkfrom)*/ intralinkstorage set linkfrom = currentIDTable(i) where linkfrom = versionIDTable(i) and snapshotid = snap; forall i in 0..versionIDTable.LAST update /*+ index(intralinkstorage idx_intralink_s_linkto)*/ intralinkstorage set linkto = currentIDTable(i) where linkto = versionIDTable(i) and snapshotid = snap; -- interlink storage forall i in 0..versionIDTable.LAST update /*+ index(interlinkstorage idx_interlink_s_linkfrom)*/ interlinkstorage set linkfrom = currentIDTable(i) where linkfrom = versionIDTable(i) and snapshotid = snap; forall i in 0..versionIDTable.LAST update /*+ index(interlinkstorage idx_interlink_s_linkto)*/ interlinkstorage set linkto = currentIDTable(i) where linkto = versionIDTable(i) and snapshotid = snap; end if; -- pctree storage -- An enabled ORDERED hint was used previously. Ordering small snapshots on -- (assoctable, pctreestorage) for NL works, but not big ones. -- All assoctable rows are deleted after each paste or restore operation, -- and so are pctreestorage rows (for copy snapshots, not ordinary ones) -- so dynamic sampling is indicated here to assist the optimizer. -- Due to WS in Tahoe, now optimizer chooses extra nested loop->FTS avoids for c in (select /*+ full (a) */ p.rowid,parentid,childid from assoctable a, pctreestorage p where p.workspaceID = a.workspaceID and p.snapshotid = snap and a.oldID = p.childid) loop if (hashTable.EXISTS(c.parentid)) then if (Snapshot.isDebug()) then Snapshot.debug('Parentid: Updating versioned ' || c.parentid || ' with ', hashTable(c.parentid)); end if; update pctreestorage set parentid = hashTable(c.parentid) where rowid = c.rowid; end if; if (hashTable.EXISTS(c.childid)) then if (Snapshot.isDebug()) then Snapshot.debug('Childid: Updating versioned ' || c.childid || ' with ', hashTable(c.childid)); end if; update pctreestorage set childid = hashTable(c.childid) where rowid = c.rowid; end if; end loop; end if; Snapshot.debug('SnapshotCreateRestore.reconcileAssociations: hashTable.COUNT', hashTable.COUNT); if (Snapshot.isDebug() and hashTable.COUNT > 0) then for i in hashTable.FIRST..hashTable.LAST loop if (hashTable.EXISTS(i)) then Snapshot.debug('SnapshotCreateRestore.reconcileAssociations: ' || 'hashTable(' || i || ')=','' || hashTable(i)); end if; end loop; end if; if (Snapshot.isDebug()) then for c in (select elementid,notm from tempfco) loop Snapshot.debug('SnapshotCreateRestore.reconcileAssociations: ' || 'tempfco.elementid = ',c.elementid); end loop; end if; SnapshotGenerated.reconcileAssociations(hashTable,snap); END reconcileAssociations; PROCEDURE updateSnapshotRows(snap IN NUMBER,currentElemID IN OUT NUMBER, versionElemID IN OUT NUMBER) IS versionID NUMBER; currentID NUMBER; versionIDTable elemidType; allIdsTable elemidType; currentIDTable elemidType; hashTable elemidType; i BINARY_INTEGER:= 0; /* * The select from cmpwbproject specifically is necessary * because the * */ cursor c is select a.elementid versionID,b.elementid currentID from cmpwbproject_x a, cmpwbproject_v b where a.snapshotid = snap and b.uoid = a.uoid union all select a.elementid versionID,b.elementid currentID from cmpelement_x a, cmpelement_v b where a.snapshotid = snap and b.uoid = a.uoid; /* // This looks elegant, but isn't performing well. Use basic join! union all select a.elementid versionID,b.elementid currentID from ( select uoid,elementid from cmpelement_x cmp where snapshotid = snap ) a, ( select uoid,elementid from cmpelement_v ) b where a.uoid = b.uoid; */ /* * all the objects in the snapshot need to be updated * regardless of the contents of tempfco */ cursor d is select elementid from cmpelement_x where snapshotid = snap; BEGIN Snapshot.debug('SnapshotCreateRestore.updateSnapshotRows: ','tempfco contents'); if (Snapshot.isDebug()) then for c in (select elementid,type from tempfco) loop Snapshot.debug('updateSnapshotRows: elementid = ' || c.elementid || ' type = ',c.type); end loop; end if; open c; loop fetch c into versionID,currentID; exit when c%NOTFOUND; Snapshot.debug('SnapshotCreateRestore.updateSnapshotRows: versionID = ',versionID); Snapshot.debug('SnapshotCreateRestore.updateSnapshotRows: currentID = ',currentID); /* * update the tempfco to reflect that this object already exists */ update /*+ index(tempfco, idx_TempFCO_ElemId)*/ tempfco set elementid = currentID, notm = OLD where elementid = versionID; if (NOT(versionID = currentID)) then versionIDTable(i):= versionID; currentIDTable(i):= currentID; hashTable(versionID):= currentID; i:= i+1; end if; end loop; i:= 0; open d; loop fetch d into versionID; exit when d%NOTFOUND; allIdsTable(i):= versionID; Snapshot.debug('SnapshotCreateRestore.updateSnapshotRows: allIdsTable(i) = ',versionID); i:= i+1; end loop; if (allIdsTable.COUNT > 0) then forall j in allIdsTable.FIRST..allIdsTable.LAST insert into assoctable(oldID) values (allIdsTable(j)); end if; if (i > 0) then reconcileAssociations(versionIDTable,currentIDTable,hashTable,snap,FALSE); end if; Snapshot.debug('SnapshotCreateRestore.updateSnapshotRows: after reconcile',''); END updateSnapshotRows; /** * This method handles views where a paste either flags the need for, * or must perform, additional business rules processing. For now: * 1) CMPProfile should be flagged. [Requested by RGONZALE] * 2) CMPRecord used in a single record format CMPWBFile must have same names as the file. [Bug 3973955] * 3) CMPGenerationResult associated with an imported CMPFunctionCategory must have a similar name. [Bug 4263404] * This means _SPEC or _BODY, where is the name of the new pkg. * 4) CMPFunction must have its signature updated to begin with its name. [Bug 4192514] * 5) CMPWBMIVDefinition should be set editable. [Bug 4581022] * 6) CMPLocation should be set unregistered, deletable, renamable [Bug 4569425] * Note: Due to bug 4970027, customerrenamable=0 means true. Switch to 1 post-Paris (OWB 10.1.2.0.2). * 7) Copies of pre-defined public CMPFunction and CMPFunctionCategory should be deletable [Bug 5044290] * 8) CMPNamedConfiguration/Usage should be set deletable, renamable, and editable. [Bug 5084620] * 9) CMPLocation should be editable, otherwise OMBCOPY fails on rename step. [Bug 5100298] * Strangely enough, this issue did not prevent rename from the UI. * @param uoidStr uoid of the root component * @param snap snapshot id * @param theClass the class of the FCO * @param elemID the elementid of the root component */ PROCEDURE applyPasteNewCopyRules(uoidStr IN VARCHAR2, snap IN NUMBER, theClass IN VARCHAR2, elemID IN NUMBER, pasteType IN NUMBER) IS theName VARCHAR2(255); theLogicalName VARCHAR2(4000); theFunctionCat NUMBER(9); recClassLen NUMBER(9); recCount NUMBER(9); BEGIN if (snap = 0) then if (theClass = 'CMPLogicalLocation' or theClass = 'CMPRuntimeLocation') then update cmplocation_v set registered = 0, customerdeletable = 1, customerrenamable = 0, editable = 1, seeded = 0 where elementid = elemID; end if; if (theClass = 'CMPNamedConfiguration') then update cmpnamedconfiguration_v set customerdeletable = 1, customerrenamable = 0, editable = 1, seeded = 0 where elementid = elemID; update cmpnamedconfigurationusage_v set customerdeletable = 1, customerrenamable = 0, editable = 1, seeded = 0 where owningfolder = elemID; end if; if (theClass = 'CMPWBMIVDefinition') then update cmpwbmivdefinition_v set editable = 1 where elementid = elemID; end if; if (theClass = 'CMPProfile') then update cmpprofile_v set imported = 1 where elementid = elemID; end if; if (theClass = 'CMPFunction') then update cmpfunction_v set signature = (name||' '||substr(signature,instr(signature,'('))) where elementid = elemID; update cmpfunction_v set customerdeletable = 1, editable = 1, seeded = 0 where elementid = elemID and seeded = 1; end if; if (theClass = 'CMPFunctionCategory') then theName := null; theLogicalName := null; BEGIN select name,logicalName into theName,theLogicalName from cmpfunctioncategory_v where elementid = elemID and categorytype = 'TYPE_IMPORTED_PACKAGE'; EXCEPTION when NO_DATA_FOUND then null; END; if (theName is not null) then update cmpgenerationresult_v set name = theName||'_SPEC', logicalname = theLogicalName||'_SPEC' where firstclassobject = elemID and substr(name,-5,5) = '_SPEC'; update cmpgenerationresult_v set name = theName||'_BODY', logicalname = theLogicalName||'_BODY' where firstclassobject = elemID and substr(name,-5,5) = '_BODY'; end if; theFunctionCat := null; BEGIN select elementid into theFunctionCat from cmpfunctioncategory_v where elementid = elemID and seeded = 1; EXCEPTION when NO_DATA_FOUND then null; END; if (theFunctionCat is not null) then update cmpfunctioncategory_v set customerdeletable = 1, editable = 1, seeded = 0 where elementid = elemID and seeded = 1; update cmpfunction_v set customerdeletable = 1, editable = 1, seeded = 0 where owningfolder = theFunctionCat and functioncategory = theFunctionCat and seeded = 1; end if; end if; if (theClass = 'CMPWBFile') then theName := null; theLogicalName := null; recClassLen := 0; recCount := 0; select name,logicalname,recordclassifierlength into theName,theLogicalName,recClassLen from cmpwbfile_v where elementid = elemID; select count(*) into recCount from cmprecord_v where owningfile = elemID; if ((recCount > 1) or (recClassLen > 0)) then null; elsif (theName is not null) then update cmprecord_v set name = theName, logicalname = theLogicalName where owningfile = elemID; end if; end if; -- Bug 6653513, 6994664: Catch any other general seeded/readonly cases -- Bug 8502681. Not all seeded objects set seeded = 1, so make all copies editable update cmpfcoelement_v set customerdeletable = 1, editable = 1, seeded = 0 where elementid = elemID and (seeded = 1 or editable = 0); update firstclassobject_v set customerdeletable = 1, editable = 1, seeded = 0 where owningfolder = elemID and (seeded = 1 or editable = 0); update cmpscoelement_v set customerdeletable = 1, editable = 1, seeded = 0 where firstclassobject = elemID and (seeded = 1 or editable = 0); update cmpscocfgelement_v set customerdeletable = 1, editable = 1, seeded = 0 where firstclassobject = elemID and (seeded = 1 or editable = 0); update cmpscomapelement_v set customerdeletable = 1, editable = 1, seeded = 0 where firstclassobject = elemID and (seeded = 1 or editable = 0); update cmpscoprpelement_v set customerdeletable = 1, editable = 1, seeded = 0 where firstclassobject = elemID and (seeded = 1 or editable = 0); else if (theClass = 'CMPLogicalLocation' or theClass = 'CMPRuntimeLocation') then update cmplocation_x set registered = 0, customerdeletable = 1, customerrenamable = 0, editable = 1, seeded = 0 where snapshotid = snap and uoid = uoidStr; end if; if (theClass = 'CMPNamedConfiguration') then update cmpnamedconfiguration_x set customerdeletable = 1, customerrenamable = 0, editable = 1, seeded = 0 where snapshotid = snap and uoid = uoidStr; update cmpnamedconfigurationusage_x set customerdeletable = 1, customerrenamable = 0, editable = 1, seeded = 0 where snapshotid = snap and owningfolder = (select elemID from cmpnamedconfiguration_x where snapshotid = snap and uoid = uoidStr); end if; if (theClass = 'CMPWBMIVDefinition') then update cmpwbmivdefinition_x set editable = 1 where snapshotid = snap and uoid = uoidStr; end if; if (theClass = 'CMPProfile') then update cmpprofile_x set imported = 1 where snapshotid = snap and uoid = uoidStr; end if; if (theClass = 'CMPFunction') then update cmpfunction_x set signature = (name||' '||substr(signature,instr(signature,'('))) where snapshotid = snap and uoid = uoidStr; update cmpfunction_x set customerdeletable = 1, editable = 1, seeded = 0 where snapshotid = snap and uoid = uoidStr and seeded = 1; end if; if (theClass = 'CMPFunctionCategory') then theName := null; theLogicalName := null; BEGIN select name,logicalName into theName,theLogicalName from cmpfunctioncategory_x where snapshotid = snap and uoid = uoidStr and categorytype = 'TYPE_IMPORTED_PACKAGE'; EXCEPTION when NO_DATA_FOUND then null; END; if (theName is not null) then update cmpgenerationresult_x set name = theName||'_SPEC', logicalname = theLogicalName||'_SPEC' where snapshotid = snap and firstclassobject = elemID and substr(name,-5,5) = '_SPEC'; update cmpgenerationresult_x set name = theName||'_BODY', logicalname = theLogicalName||'_BODY' where snapshotid = snap and firstclassobject = elemID and substr(name,-5,5) = '_BODY'; end if; theFunctionCat := null; BEGIN select elementid into theFunctionCat from cmpfunctioncategory_x where snapshotid = snap and uoid = uoidStr and seeded = 1; EXCEPTION when NO_DATA_FOUND then null; END; if (theFunctionCat is not null) then update cmpfunctioncategory_x set customerdeletable = 1, editable = 1, seeded = 0 where snapshotid = snap and uoid = uoidStr and seeded = 1; update cmpfunction_x set customerdeletable = 1, editable = 1, seeded = 0 where snapshotid = snap and owningfolder = theFunctionCat and functioncategory = theFunctionCat and seeded = 1; end if; end if; if (theClass = 'CMPWBFile') then theName := null; theLogicalName := null; recClassLen := 0; recCount := 0; select name,logicalname,recordclassifierlength into theName,theLogicalName,recClassLen from cmpwbfile_x where snapshotid = snap and uoid = uoidStr; select count(*) into recCount from cmprecord_x where snapshotid = snap and owningfile = elemID; if ((recCount > 1) or (recClassLen > 0)) then null; elsif (theName is not null) then update cmprecord_x set name = theName, logicalname = theLogicalName where snapshotid = snap and owningfile = elemID; end if; end if; -- Bug 6653513, 6994664: Catch any other general seeded/readonly cases -- Bug 8502681. Not all seeded objects set seeded = 1, so make all copies editable update cmpfcoelement_x set customerdeletable = 1, editable = 1, seeded = 0 where snapshotid = snap and uoid = uoidStr and (seeded = 1 or editable = 0); update firstclassobject_x set customerdeletable = 1, editable = 1, seeded = 0 where snapshotid = snap and (seeded = 1 or editable = 0) and owningfolder = (select elemID from firstclassobject_x where snapshotid = snap and uoid = uoidStr); update cmpscoelement_x set customerdeletable = 1, editable = 1, seeded = 0 where snapshotid = snap and (seeded = 1 or editable = 0) and firstclassobject = (select elemID from firstclassobject_x where snapshotid = snap and uoid = uoidStr); update cmpscocfgelement_x set customerdeletable = 1, editable = 1, seeded = 0 where snapshotid = snap and (seeded = 1 or editable = 0) and firstclassobject = (select elemID from firstclassobject_x where snapshotid = snap and uoid = uoidStr); update cmpscomapelement_x set customerdeletable = 1, editable = 1, seeded = 0 where snapshotid = snap and (seeded = 1 or editable = 0) and firstclassobject = (select elemID from firstclassobject_x where snapshotid = snap and uoid = uoidStr); update cmpscoprpelement_x set customerdeletable = 1, editable = 1, seeded = 0 where snapshotid = snap and (seeded = 1 or editable = 0) and firstclassobject = (select elemID from firstclassobject_x where snapshotid = snap and uoid = uoidStr); end if; END applyPasteNewCopyRules; FUNCTION resetParent(uoidStr IN VARCHAR2,snap IN NUMBER, newParent IN NUMBER, pasteType IN NUMBER, srcPlatformId IN NUMBER, tgtPlatformId IN NUMBER, isPasteNewCopy IN BOOLEAN) RETURN NUMBER IS elemID NUMBER; oldParent NUMBER; theClass VARCHAR2(255); theParentClass VARCHAR2(255); theParentType VARCHAR2(255); leaveFCOInstalledModuleNull BOOLEAN; BEGIN --ServerLog.open('e:\Work\Mcm','log.txt'); --if (NOT(ServerLog.isOpen())) then -- ServerLog.open('d:\temp','Snapshot.log'); --end if; Snapshot.debug('resetParent: snap = ' || snap || ' newParent = ' || newParent || ' uoidStr = ', uoidStr); /* For Paris, cmprelation_v, cmprelation_x are no longer updatable, so must update CMPFCORel..., CMPSCOCfgRel... views */ leaveFCOInstalledModuleNull := FALSE; if (snap = 0) then BEGIN select distinct elementid, aggregateparent,classname into elemID,oldParent,theClass from cmpcopyobject_v where uoid = uoidStr; EXCEPTION WHEN TOO_MANY_ROWS THEN -- handle, for example, cases like functions within packages. In these cases the 'duplicate' -- row derived from CMPRelation will have an aggregateparent (installedmodule) value of null -- which should be ignored. The row from FirstClassObject is the one to select. -- Other cases: When copying a module function into a package, must select the 'duplicate' -- where aggregateparent differs from newParent, but if copying within a package, parent is the same. elemID := null; if (Snapshot.isDebug()) then Snapshot.debug('SnapshotCreateRestore.resetParent: ', 'cmpcopyobject_v contents'); end if; for c in (select distinct elementid, aggregateparent,classname from cmpcopyobject_v where uoid = uoidStr and aggregateparent is not null) loop if (Snapshot.isDebug()) then Snapshot.debug('cmpcopyobject_v: elementid = ' || c.elementid || ' aggregateParent = ' || c.aggregateParent || ' className = ', c.classname); end if; if ((elemID is null) or (c.aggregateParent != newParent)) then elemID := c.elementid; oldParent := c.aggregateParent; theClass := c.classname; end if; end loop; END; -- handle, for example, cases like functions within packages. These must leave installedModule null -- if newParent is a CMPFunctionCategory. Otherwise it is FunctionCategory that must be left null. if (newParent = 0) then theParentClass := ''; theParentType := ''; else select classname,strongtypename into theParentClass,theParentType from firstclassobject_v where elementid = newParent; end if; if (theParentClass = 'CMPFunctionCategory') then leaveFCOInstalledModuleNull := TRUE; end if; -- if (NOT leaveFCOInstalledModuleNull) then update CMPFCORelation_v set installedmodule = newParent where elementid = elemID; end if; update cmpinstalledmodule_v set owningproject = newParent where elementid = elemID; update CMPSCOCfgRelation_v set installedmodule = newParent where elementid = elemID; -- bug 7524397: don't reset owningfolder for physical objects update firstclassobject_v set owningfolder = decode(newParent,0,null,newParent) where elementid = elemID and classname not in ('CMPPhysicalMap','CMPPhysicalObject'); -- dereference NamedConfiguration of PhysicalObject when paste is across Projects [Bug 5390587] -- Tahoe: Now PhysicalObjects are FCOs, not SCOs, so inter-proj/plat operations must explicitly delete -- them from associated LogicalObjects, or specific owning config (if NamedConfiguration paste). -- Note: physical objects are processed last so, for copy/paste cases, their new LogicalObject or NamedConfiguration -- association won't be set in time for a selective delete to work. Luckily, this is a cut/paste. if ((pasteType = INTERPROJECT) or (pasteType = INTERPLATFORM) or (pasteType = INTERPROJPLAT)) then delete from cmpphysicalobject_v where logicalobject = elemID; end if; if ((pasteType = INTERPROJECT) and (theClass = 'CMPNamedConfiguration')) then delete from cmpphysicalobject_v where namedconfiguration = elemID; end if; -- handle views where the model stores parent in multiple columns if (theClass = 'CMPBusinessRuleDefinition') then update cmpbusinessruledefinition_v set owningmodule = newParent where elementid = elemID; elsif (theClass = 'CMPCatalog') then update cmpcatalog_v set owningproject = newParent where elementid = elemID; elsif (theClass = 'CMPCube') then update cmpcube_v set installedmodule = newParent where elementid = elemID; elsif (theClass = 'CMPDimension') then update cmpdimension_v set installedmodule = newParent where elementid = elemID; elsif (theClass = 'CMPDrillPath') then update cmpdrillpath_v set intelligenceschema = newParent where elementid = elemID; elsif (theClass = 'CMPFunction') then if (theParentClass = 'CMPFunctionCategory') then update cmpfunction_v set functioncategory = newParent, installedmodule = null where elementid = elemID; elsif (theParentClass != 'CMPFunctionCategory') then update cmpfunction_v set functioncategory = null, installedmodule = newParent where elementid = elemID; end if; elsif (theClass = 'CMPFunctionCategory') then update cmpfunctioncategory_v set installedmodule = newParent where elementid = elemID; elsif (theClass = 'CMPIntelligenceBusArea') then update cmpintelligencebusarea_v set intelligenceschema = newParent where elementid = elemID; elsif (theClass = 'CMPLOVItemClass') then update cmplovitemclass_v set intelligenceschema = newParent where elementid = elemID; elsif (theClass = 'CMPMap') then update cmpmap_v set installedmodule = newParent where elementid = elemID; --Bug 6883668: Adjust strongtypename for certain cross-platform cases. if ((pasteType = INTERPLATFORM) or (pasteType = INTERPROJPLAT)) then update cmpmap_v set strongtypename = decode(theParentType, 'oracle.wh.repos.impl.application.KMMapModule', 'oracle.wh.repos.impl.mapping.CMPKMMap', 'oracle.wh.repos.impl.application.OracleNativeModule', 'oracle.wh.repos.impl.mapping.CMPBatchMap', strongtypename) where elementid = elemID; end if; --Bug 8533660: Null out CMPPhysicalObject ACLContainers (unused, but improperly maintained) elsif (theClass = 'CMPPhysicalMap' or theClass = 'CMPPhysicalObject') then update cmpphysicalobject_v set aclcontainer = null where elementid = elemID; elsif (theClass = 'CMPPLSCollection') then update cmpplscollection_v set functioncategory = newParent where elementid = elemID; elsif (theClass = 'CMPPLSRecord') then update cmpplsrecord_v set functioncategory = newParent where elementid = elemID; elsif (theClass = 'CMPProcess') then update cmpprocess_v set owningpackage = newParent where elementid = elemID; elsif (theClass = 'CMPProcessPackage') then update cmpprocesspackage_v set processinstalledmodule = newParent where elementid = elemID; elsif (theClass = 'CMPProgramGroup') then update cmpprogramgroup_v set owningproject = newParent where elementid = elemID; elsif (theClass = 'CMPPublicSubMap') then if (theParentClass = 'CMPSubMapLibrary') then update cmppublicsubmap_v set library = newParent, owningproject = null where elementid = elemID; elsif (theParentClass = 'CMPWBProject') then update cmppublicsubmap_v set library = null, owningproject = newParent where elementid = elemID; end if; elsif (theClass = 'CMPSubMapLibrary') then update cmpsubmaplibrary_v set owningproject = newParent where elementid = elemID; elsif (theClass = 'CMPRefCursorType') then update cmprefcursortype_v set functioncategory = newParent where elementid = elemID; elsif (theClass = 'CMPSQLCollection') then update cmpsqlcollection_v set owningmodule = newParent where elementid = elemID; elsif (theClass = 'CMPTaskFlow') then update cmptaskflow_v set owninginstalledmodule = newParent, customerrenamable = 0 where elementid = elemID; elsif (theClass = 'CMPUserFolder') then if (theParentClass = 'CMPUserFolder') then update cmpuserfolder_v set owningmodule = null, parentfolder = newParent where elementid = elemID; elsif (theParentClass = 'CMPSubMapLibrary') then update cmpuserfolder_v set owningmodule = null, parentfolder = null where elementid = elemID; else update cmpuserfolder_v set owningmodule = newParent, parentfolder = null where elementid = elemID; end if; end if; update cmpallfolderfconames set aggregateparent = newParent, parentid = newParent where elementid = elemID; if (isPasteNewCopy) then applyPasteNewCopyRules(uoidStr, snap, theClass, elemID, pasteType); end if; -- handle itemsets, but skip any physical objects [bug 7524397] if (oldParent is not null and theClass != 'CMPPhysicalObject' and theClass != 'CMPPhysicalMap') then --Snapshot.debug('Updating Cur Parentid of Childid: ' || elemID || ' with ', -- newParent); update cmpallfolderfconames set parentID = newParent where parentid = oldParent and aggregateparent = elemID; update pctree set parentid = newParent where parentid = oldParent and childid = elemID; end if; if ((pasteType = INTERPLATFORM) or (pasteType = INTERPROJPLAT)) then SnapshotDataTypeService.resetDataTypes(elemID, srcPlatformId, tgtPlatformId); end if; else BEGIN select distinct elementid, aggregateparent,classname into elemID,oldParent,theClass from cmpcopyobject_x where snapshotid = snap and uoid = uoidStr; EXCEPTION WHEN TOO_MANY_ROWS THEN -- handle, for example, cases like functions within packages. In these cases the 'duplicate' -- row derived from CMPRelation will have an aggregateparent (installedmodule) value of null -- which should be ignored. The row from FirstClassObject is the one to select. -- Other cases: When copying a module function into a package, must select the 'duplicate' -- where aggregateparent differs from newParent, but if copying within a package, parent is the same. elemID := null; if (Snapshot.isDebug()) then Snapshot.debug('SnapshotCreateRestore.resetParent: ', 'cmpcopyobject_x contents'); end if; for c in (select distinct elementid, aggregateparent,classname from cmpcopyobject_x where snapshotid = snap and uoid = uoidStr and aggregateparent is not null) loop if (Snapshot.isDebug()) then Snapshot.debug('cmpcopyobject_x: elementid = ' || c.elementid || ' aggregateParent = ' || c.aggregateParent || ' className = ', c.classname); end if; if ((elemID is null) or (c.aggregateParent != newParent)) then elemID := c.elementid; oldParent := c.aggregateParent; theClass := c.classname; end if; end loop; END; -- handle, for example, cases like functions within packages. These must leave installedModule null -- if newParent is a CMPFunctionCategory. Otherwise it is FunctionCategory that must be left null. -- Note: even here in the '_x' view section, parentClass is looked up from the firstclassobject_v view. if (newParent = 0) then theParentClass := ''; theParentType := ''; else select classname,strongtypename into theParentClass,theParentType from firstclassobject_v where elementid = newParent; end if; if (theParentClass = 'CMPFunctionCategory') then leaveFCOInstalledModuleNull := TRUE; end if; -- if (NOT leaveFCOInstalledModuleNull) then update CMPFCORelation_x set installedmodule = newParent where snapshotid = snap and uoid = uoidStr; end if; update cmpinstalledmodule_x set owningproject = newParent where snapshotid = snap and uoid = uoidStr; update CMPSCOCfgRelation_x set installedmodule = newParent where snapshotid = snap and uoid = uoidStr; -- bug 7524397: don't reset owningfolder for physical objects update firstclassobject_x set owningfolder = decode(newParent,0,null,newParent) where snapshotid = snap and uoid = uoidStr and classname not in ('CMPPhysicalMap','CMPPhysicalObject'); -- dereference NamedConfiguration of PhysicalObject when paste is across Projects [Bug 5390587] -- Tahoe: Now PhysicalObjects are FCOs, not SCOs, so inter-proj/plat operations must explicitly delete -- them from associated LogicalObjects, or specific owning config (if NamedConfiguration paste). -- Note: physical objects are processed last so, for copy/paste cases, their new LogicalObject or NamedConfiguration -- association won't be set in time for a selective delete to work, but OK to delete all -- physical objects in the snapshot as an alternative. if ((pasteType = INTERPROJECT) or (pasteType = INTERPLATFORM) or (pasteType = INTERPROJPLAT)) then delete from cmpphysicalobject_x where snapshotid = snap; -- where snapshotid = snap and logicalobject in -- (select elementid from firstclassobject_x -- where snapshotid = snap and uoid = uoidStr); end if; if ((pasteType = INTERPROJECT) and (theClass = 'CMPNamedConfiguration')) then delete from cmpphysicalobject_x where snapshotid = snap; -- where snapshotid = snap and namedconfiguration in -- (select elementid from firstclassobject_x -- where snapshotid = snap and uoid = uoidStr); end if; -- handle views where the model stores parent in multiple columns if (theClass = 'CMPBusinessRuleDefinition') then update cmpbusinessruledefinition_x set owningmodule = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPCatalog') then update cmpcatalog_x set owningproject = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPCube') then update cmpcube_x set installedmodule = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPDimension') then update cmpdimension_x set installedmodule = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPDrillPath') then update cmpdrillpath_x set intelligenceschema = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPFunction') then if (theParentClass = 'CMPFunctionCategory') then update cmpfunction_x set functioncategory = newParent, installedmodule = null where snapshotid = snap and uoid = uoidStr; elsif (theParentClass != 'CMPFunctionCategory') then update cmpfunction_x set functioncategory = null, installedmodule = newParent where snapshotid = snap and uoid = uoidStr; end if; elsif (theClass = 'CMPFunctionCategory') then update cmpfunctioncategory_x set installedmodule = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPIntelligenceBusArea') then update cmpintelligencebusarea_x set intelligenceschema = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPLOVItemClass') then update cmplovitemclass_x set intelligenceschema = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPMap') then update cmpmap_x set installedmodule = newParent where snapshotid = snap and uoid = uoidStr; --Bug 6883668: Adjust strongtypename for certain cross-platform cases. if ((pasteType = INTERPLATFORM) or (pasteType = INTERPROJPLAT)) then update cmpmap_x set strongtypename = decode(theParentType, 'oracle.wh.repos.impl.application.KMMapModule', 'oracle.wh.repos.impl.mapping.CMPKMMap', 'oracle.wh.repos.impl.application.OracleNativeModule', 'oracle.wh.repos.impl.mapping.CMPBatchMap', strongtypename) where snapshotid = snap and uoid = uoidStr; end if; --Bug 8533660: Null out CMPPhysicalObject ACLContainers (unused, but improperly maintained) elsif (theClass = 'CMPPhysicalMap' or theClass = 'CMPPhysicalObject') then update cmpphysicalobject_x set aclcontainer = null where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPPLSCollection') then update cmpplscollection_x set functioncategory = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPPLSRecord') then update cmpplsrecord_x set functioncategory = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPProcess') then update cmpprocess_x set owningpackage = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPProcessPackage') then update cmpprocesspackage_x set processinstalledmodule = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPProgramGroup') then update cmpprogramgroup_x set owningproject = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPPublicSubMap') then if (theParentClass = 'CMPSubMapLibrary') then update cmppublicsubmap_x set library = newParent, owningproject = null where snapshotid = snap and uoid = uoidStr; elsif (theParentClass = 'CMPWBProject') then update cmppublicsubmap_x set library = null, owningproject = newParent where snapshotid = snap and uoid = uoidStr; end if; elsif (theClass = 'CMPSubMapLibrary') then update cmpsubmaplibrary_x set owningproject = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPRefCursorType') then update cmprefcursortype_x set functioncategory = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPSQLCollection') then update cmpsqlcollection_x set owningmodule = newParent where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPTaskFlow') then update cmptaskflow_x set owninginstalledmodule = newParent, customerrenamable = 0 where snapshotid = snap and uoid = uoidStr; elsif (theClass = 'CMPUserFolder') then if (theParentClass = 'CMPUserFolder') then update cmpuserfolder_x set owningmodule = null, parentfolder = newParent where snapshotid = snap and uoid = uoidStr; elsif (theParentClass = 'CMPSubMapLibrary') then update cmpuserfolder_x set owningmodule = null, parentfolder = null where snapshotid = snap and uoid = uoidStr; else update cmpuserfolder_x set owningmodule = newParent, parentfolder = null where snapshotid = snap and uoid = uoidStr; end if; end if; update fcofoldernamespacestorage set aggregateparent = newParent, parentid = newParent where snapshotid = snap and elementid = elemID; if (isPasteNewCopy) then applyPasteNewCopyRules(uoidStr, snap, theClass, elemID, pasteType); end if; -- handle itemsets, but skip any physical objects [bug 7524397] if (oldParent is not null and theClass != 'CMPPhysicalObject' and theClass != 'CMPPhysicalMap') then --Snapshot.debug('Updating Ver Parentid of Childid: ' || elemID || ' with ', -- newParent); update fcofoldernamespacestorage set parentID = newParent where parentid = oldParent and aggregateparent = elemID and snapshotid = snap; update pctreestorage set parentid = newParent where snapshotid = snap and parentid = oldParent and childid = elemID; end if; if ((pasteType = INTERPLATFORM) or (pasteType = INTERPROJPLAT)) then SnapshotDataTypeService.resetDataTypes(uoidStr, snap, srcPlatformId, tgtPlatformId); end if; end if; if (oldParent is null) then oldParent := 0; end if; return oldParent; END resetParent; FUNCTION resetParent(uoidStr IN VARCHAR2,snap IN NUMBER, newParent IN NUMBER, pasteType IN NUMBER, srcPlatformId IN NUMBER, tgtPlatformId IN NUMBER) RETURN NUMBER IS oldParent NUMBER; BEGIN oldParent:= resetParent(uoidStr, snap, newParent, pasteType, srcPlatformId, tgtPlatformId, FALSE); return oldParent; END resetParent; /** * This method builds an association lookup that can substitute * the old element ids with the new sequence generated ids * @param uoidStr uoid of the root component * @param snap snapshot id */ PROCEDURE buildAssocTable(uoidStr IN VARCHAR2, snap IN NUMBER) IS baseSeq NUMBER; i NUMBER; BEGIN BEGIN if (CWMSEQ_INC = 0) then select increment_by into CWMSEQ_INC from user_sequences where sequence_name = 'CWMSEQ'; end if; EXCEPTION when NO_DATA_FOUND then CWMSEQ_INC := DEFAULT_CWMSEQ_INC; --100; END; i:= CWMSEQ_INC; /* * Bug 7524397: Include physical objects by matching on uoid, not compuoid, in join. */ for c in ( select workspaceid, elementid from cmpuserconfigtemplateset_x where snapshotid = snap and uoid = uoidStr union all select workspaceid, elementid from cmpwbmivdefinition_x where snapshotid = snap and uoid = uoidStr union all select workspaceid, elementid from cmpwbproject_x where snapshotid = snap and uoid = uoidStr union all select workspaceid, elementid from cmpelement_x cmp where snapshotid = snap and exists ( select 1 from tempfco t where (type = FCOPARENTS or type = FCOCHILDREN) and ((t.uoid = cmp.compuoid) or (t.uoid = cmp.uoid and cmp.classname in ('CMPPhysicalObject', 'CMPPhysicalMap'))) ) ) loop if (NOT(i < CWMSEQ_INC)) then i := 0; select cwmseq.nextval into baseSeq from dual; end if; insert into assoctable values (c.workspaceid,c.elementid,baseSeq+i,sys_guid()); i:= i+1; end loop; if (Snapshot.isDebug()) then Snapshot.debug('SnapshotCreateRestore.buildAssocTable: ','tempfco contents'); for c in (select elementid,uoid,notm,type from tempfco) loop Snapshot.debug('buildAssocTable->tempfco: elementid = ' || c.elementid || ' uoid = ' || c.uoid || ' notm = ' || c.notm || ' type = ', c.type); end loop; Snapshot.debug('SnapshotCreateRestore.buildAssocTable: ','snapshot contents'); for c in (select elementid, compuoid from cmpelement_x where snapshotid = snap) loop Snapshot.debug('buildAssocTable->snapshot: elementid = ' || c.elementid || ' compuoid = ', c.compuoid); end loop; Snapshot.debug('SnapshotCreateRestore.buildAssocTable: ','assoctable contents'); for c in (select oldid, newid,uoid from assoctable) loop Snapshot.debug('buildAssocTable: oldid = ' || c.oldid || ' newid = ' || c.newid || ' uoid = ', c.uoid); end loop; end if; END buildAssocTable; PROCEDURE setNewAssociations(snap IN NUMBER, currentElemID IN OUT NUMBER, versionElemID IN OUT NUMBER) IS versionIDTable elemidType; currentIDTable elemidType; hashTable elemidType; i BINARY_INTEGER:= 0; BEGIN Snapshot.debug('SnapshotCreateRestore.setNewAssociations: ', ''); Snapshot.debug('SnapshotCreateRestore.setNewAssociations: currentElemID = ', currentElemID); Snapshot.debug('SnapshotCreateRestore.setNewAssociations: versionElemID = ', versionElemID); for c in (select oldID,newID from assoctable) loop Snapshot.debug('SnapshotCreateRestore.setNewAssociations: versionID = ', c.oldID); Snapshot.debug('SnapshotCreateRestore.setNewAssociations: currentID = ', c.newID); if (NOT(c.newID = c.oldID)) then versionIDTable(i):= c.oldID; currentIDTable(i):= c.newID; hashTable(c.oldID):= c.newID; i:= i+1; end if; end loop; reconcileAssociations(versionIDTable,currentIDTable,hashTable,snap,TRUE); BEGIN Snapshot.debug('setNewAssociations checking: select newID into currentElemID from assoctable where oldID =', currentElemID); select newID into currentElemID from assoctable where oldID = currentElemID; Snapshot.debug('setNewAssociations checking: select newID into versionElemID from assoctable where oldID =', versionElemID); select newID into versionElemID from assoctable where oldID = versionElemID; /* * This is for multiple pastes. The current element id is the id of the source * but the stored copy element ids get updated for each paste, so the * current element id needs to be updated to that of the new object. * Same is true for mcmcomponent which gets loaded by the client in order * to sync the cache. */ EXCEPTION when NO_DATA_FOUND then Snapshot.debug('setNewAssociations hits NO_DATA_FOUND',''); update mcmcomponent set elementid = versionElemID where elementid = currentElemID; select newID into currentElemID from assoctable where oldID = versionElemID; END; END setNewAssociations; /** * Helper function for populating the "temporary" variable * @param snap snapshot id to restore from * @param versionElemID root elementid of the component or folder to be snapshotted */ PROCEDURE populateTempFCOSelfOnly(snap IN NUMBER, versionElemID IN NUMBER) IS BEGIN insert into tempfco(elementid,uoid,notm,type) ( select elementid, uoid,NEW,FCOCHILDREN from cmpelement_x where elementid = versionElemID and snapshotid = snap ); if (Snapshot.isDebug()) then for c in (select elementid,uoid,type from tempfco) loop Snapshot.debug('populateTempFCOSelfOnly: elementid = ' || c.elementid || ' uoid = ' || c.uoid || ' type = ', c.type); end loop; end if; END populateTempFCOSelfOnly; PROCEDURE populateTempFCO(snap IN NUMBER, versionElemID IN NUMBER, selfOnly IN NUMBER) IS BEGIN Snapshot.debug('SnapshotCreateRestore.populateTempFCO: ', ''); Snapshot.debug('SnapshotCreateRestore.populateTempFCO: versionElemID = ', versionElemID); if (selfOnly = Snapshot.NON_CASCADE_SNAPSHOT) then populateTempFCOSelfOnly(snap,versionElemID); return; end if; /* * get UOIDs of all FCOs of the component and the itemset * uoids(for namespace) and label as either * FCOCHILDREN or FCOPARENT of object being restored */ insert into tempfco(elementid,uoid,notm,type) ( select distinct elementid,uoid,NEW,FCOPARENTS from firstclassobject_x where snapshotid = snap start with elementid = versionElemID connect by prior owningfolder = elementid ); delete from tempfco where elementid = versionElemID and type=FCOPARENTS; insert into tempfco(elementid,uoid,notm,type) ( select distinct elementid,uoid,NEW,FCOCHILDREN from firstclassobject_x where snapshotid = snap start with elementid = versionElemID connect by prior elementid = owningfolder ); /* * remove the component itself from FCOPARENTS */ delete from tempfco where elementid = versionElemID; /* * this kind of insertion is for getting the component itself * so it can handle both FCO and SCO */ insert into tempfco(elementid,uoid,notm,type) ( select elementid, uoid,NEW,FCOCHILDREN from cmpelement_x where elementid = versionElemID and snapshotid = snap ); insert into tempfco(elementid,uoid,notm,type) ( select distinct itemset.elementid, itemset.uoid,NEW,ITEMSETS from cmpitemset_x itemset, tempfco t where t.elementid = itemset.firstclassobject and itemset.snapshotid = snap ); if (Snapshot.isDebug()) then for c in (select elementid,uoid,type from tempfco) loop Snapshot.debug('populateTempFCO: elementid = ' || c.elementid || ' uoid = ' || c.uoid || ' type = ', c.type); end loop; end if; END populateTempFCO; /** * Updates the NOTMs for the current repository when doing a restore * @param restoreNew flag for restore as new */ PROCEDURE updateNOTM(restoreOper IN NUMBER) IS BEGIN Snapshot.debug('SnapshotCreateRestore.updateNOTM: ', ''); /* * update the NOTM values of all first class objects * so other sessions will know that a sync is required */ if (notmTable.COUNT > 0 and restoreOper = Snapshot.RESTORE_SNAPSHOT) then forall i in 0..notmTable.LAST update firstclassobject_v set NOTM = notmTable(i) where uoid = uoidTable(i); end if; END updateNOTM; PROCEDURE adjustFCOFolderRef(oldUoidStr IN VARCHAR2, newUoidStr IN VARCHAR2) IS vOldID cmpelement_v.elementid%TYPE; vNewID cmpelement_v.elementid%TYPE; vClass cmpelement_v.classname%TYPE; vFirst BOOLEAN; BEGIN vOldID := null; vNewID := null; vClass := null; vFirst := TRUE; --Find FCOFolderRefs for both the old and new FCO. Only update the new one. --Note: new Ref is created with the same encoded name as the original Ref. for c in (select cmp.rowid, cmp.fco from cmpfcofolderreference_v cmp where cmp.name = ('R'||substr(oldUoidStr,4))) loop if (vFirst = TRUE) then vFirst := FALSE; BEGIN --Determine elementId of the FCO copy. select elementId, className into vNewID,vClass from firstclassobject_v where uoid = newUoidStr; EXCEPTION when NO_DATA_FOUND then --Unlikely, FCO represented by newUoidStr should have just been created Snapshot.debug('SnapshotCreateRestore.adjustFCOFolderRef: Cannot find FCO copy by UOID = ',newUoidStr); exit; END; if (vClass = 'CMPUserFolder') then --Only process ordinary FCOs, not user folders. exit; end if; BEGIN --Determine elementId of the original FCO. select elementId into vOldID from firstclassobject_v where uoid = oldUoidStr; EXCEPTION when NO_DATA_FOUND then --Unlikely, FCO represented by oldUoidStr should still exist Snapshot.debug('SnapshotCreateRestore.adjustFCOFolderRef: Cannot find original FCO by UOID = ',oldUoidStr); exit; END; end if; if (c.fco = vOldID) then null; -- Skip the original else BEGIN -- Skip any that point to an existing FCO select classname into vClass from firstclassobject_v where elementId = c.fco; EXCEPTION when NO_DATA_FOUND then update cmpfcofolderreference_v set fco = vNewID, uoid = ('R'||substr(newUoidStr,4)) where rowid = c.rowid; exit; END; end if; end loop; END adjustFCOFolderRef; /** * Updates the current repos with new UOIDs * @param restoreNew flag for restore as new */ PROCEDURE updateCurrentRepos(restoreOper IN NUMBER) IS BEGIN Snapshot.debug('SnapshotCreateRestore.updateCurrentRepos: ', ''); if (restoreOper = Snapshot.RESTORE_NEW) then /* For Paris, cmpelement_v is no longer updatable, so must update CMPFCO..., CMPSCO..., and CMPSYS... views */ update CMPFCOElement_v cmp set cmp.notm = 1, cmp.uoid = (select uoid from assoctable a where a.newID = cmp.elementid) where exists (select 1 from assoctable a where cmp.elementid = a.newID); update CMPSCOelement_v cmp set cmp.notm = 1, cmp.uoid = (select uoid from assoctable a where a.newID = cmp.elementid) where exists (select 1 from assoctable a where cmp.elementid = a.newID); update CMPSCOCfgelement_v cmp set cmp.notm = 1, cmp.uoid = (select uoid from assoctable a where a.newID = cmp.elementid) where exists (select 1 from assoctable a where cmp.elementid = a.newID); update CMPSCOmapelement_v cmp set cmp.notm = 1, cmp.uoid = (select uoid from assoctable a where a.newID = cmp.elementid) where exists (select 1 from assoctable a where cmp.elementid = a.newID); update CMPSCOprpelement_v cmp set cmp.notm = 1, cmp.uoid = (select uoid from assoctable a where a.newID = cmp.elementid) where exists (select 1 from assoctable a where cmp.elementid = a.newID); update CMPSYSElement_v cmp set cmp.notm = 1, cmp.uoid = (select uoid from assoctable a where a.newID = cmp.elementid) where exists (select 1 from assoctable a where cmp.elementid = a.newID); end if; END updateCurrentRepos; /** * Restores a snapshot to the current repository * @param uoidStr uoid of the component or folder to be restored * @param snap snapshot id from which to restore * @param restoreParents flag to indicate parent restore * @param restoreOper flag to indicate restore type (ordinary or copy/paste) * @param restoreNew flag to indicate restore as new * @param newParent elementid of the new parent user folder if to be restored as new * @param nsNewParent elementid of the new parent if to be restored as new * @param firstInGroup flag to indicate uoidStr is only the first in a multi-object copy set. * @param pasteType flag to indicate paste is across projects or not. [Bug 5390587] * @param pastedUOID uoid assigned to the new pasted copy of the current object in a multi-object copy set.. * @return error code, 0 if successful */ FUNCTION restore(uoidStr IN VARCHAR2,snap IN NUMBER,restoreParents IN BOOLEAN, restoreOper IN NUMBER default Snapshot.RESTORE_SNAPSHOT, newParent IN NUMBER default 0,firstInGroup IN BOOLEAN, pasteType IN NUMBER, srcPlatformId IN NUMBER, tgtPlatformId IN NUMBER, pastedUOID OUT VARCHAR2) RETURN NUMBER IS existsInRepos BOOLEAN:= TRUE; oldParent cmpelement_v.elementid%TYPE; /* * cmpstorage element id */ currentElemID cmpelement_v.elementid%TYPE:= 0; versionElemID cmpelement_v.elementid%TYPE:= 0; insertElemID cmpelement_v.elementid%TYPE:= 0; vClass cmpelement_v.classname%TYPE; cascade NUMBER; selfOnly NUMBER; vEditable NUMBER; vSeeded NUMBER; i BINARY_INTEGER:= 1; BEGIN /* SOCHEN: add here since clean temp fco should be called anyway at the end of this procedure, but may not called due to any exception. Hence add here to make sure it is cleaned at the beginning of the procedure */ cleanTempFCO(); BEGIN select elementid into currentElemID from cmpelement_v where uoid = uoidStr; EXCEPTION when NO_DATA_FOUND then existsInRepos:= FALSE; END; /* * Restore must not depend on element id, only on uoid */ BEGIN select elementid,editable,seeded into versionElemID,vEditable,vSeeded from cmpelement_x where uoid = uoidStr and snapshotid = snap; EXCEPTION when NO_DATA_FOUND then Snapshot.debug('SnapshotCreateRestore.restore:', 'returning FALSE'); SnapshotError.handleFatalSnapshotError(uoidStr, snap, SnapshotError.VERSION_OBJECT_DOES_NOT_EXIST); return SnapshotError.VERSION_OBJECT_DOES_NOT_EXIST; END; /* * Bug 8221714: Skip restore processing if object is seeded and not editable */ if ((restoreOper = Snapshot.RESTORE_SNAPSHOT) and (vSeeded = 1) and (vEditable = 0)) then return 0; end if; /* * if the object to be restored was created as cascade at snapshot time * then restore as cascade; if not, restore as no cascade */ BEGIN select iscascade,classname into cascade,vClass from snapshotstoretable where snapshotid = snap and uoid = uoidStr; Snapshot.debug('SnapshotCreateRestore.restore: cascade = ', cascade); EXCEPTION when NO_DATA_FOUND then cascade:= 0; vClass:= null; END; /* * populate temp fco * bug 7230545: avoid duplicate processing of PhysicalObjects under NamedConfigurations * bug 7448023: avoid duplicate processing of any FCO under a "cascaded" Folder */ if (cascade = Snapshot.NON_CASCADE_SNAPSHOT) then if (vClass = 'CMPNamedConfiguration' or vClass = 'CMPTaskFlow') then selfOnly := Snapshot.NON_CASCADE_SNAPSHOT; end if; else selfOnly := Snapshot.CASCADE_SNAPSHOT; end if; populateTempFCO(snap,versionElemID,selfOnly); /* * update object and association ids */ if (restoreOper = Snapshot.RESTORE_SNAPSHOT) then updateSnapshotRows(snap,currentElemID,versionElemID); end if; /* * delete from the current repository */ if (existsInRepos and restoreOper = Snapshot.RESTORE_SNAPSHOT) then deleteFromCurrentRepos(currentElemID,cascade); end if; if (restoreOper = Snapshot.RESTORE_NEW) then buildAssocTable(uoidStr,snap); setNewAssociations(snap,currentElemID,versionElemID); oldParent:= resetParent(uoidStr,snap,newParent,pasteType,srcPlatformId,tgtPlatformId,TRUE); Snapshot.debug('SnapshotCreateRestore.restore: oldParent = ', oldParent); end if; BEGIN -- Bug 3589323. Added "firstInGroup or !RESTORE_NEW" condition so that a multi-object copy -- will use an ElemID that matches ID reassign by buildAssocTable/setNewAssociations. if (existsInRepos and (firstInGroup or (restoreOper != Snapshot.RESTORE_NEW))) then Snapshot.debug('SnapshotCreateRestore.restore: currentElemID = ', currentElemID); insertElemID := currentElemID; else Snapshot.debug('SnapshotCreateRestore.restore: versionElemID = ', versionElemID); insertElemID := versionElemID; end if; -- Bug 3589323. Set OUT parameter with value of pasted UOID. Needed for multi-object copy. if (restoreOper = Snapshot.RESTORE_NEW) then select uoid into pastedUOID from assoctable where newid = insertElemID; end if; insertIntoCurrentRepos(snap,insertElemID,restoreParents,selfOnly); EXCEPTION when DUP_VAL_ON_INDEX then SnapshotError.handleRestoreSnapshotError(uoidStr, snap, SnapshotError.NAMESPACE_ON_RESTORE); return SnapshotError.NAMESPACE_ON_RESTORE; END; updateNOTM(restoreOper); updateCurrentRepos(restoreOper); -- Verify if this resetParent does anything (since insertIntoCurrentRepos just called above). -- Was this previously needed to support multiple paste of the same object back when the -- original snapshot was re-used? That's no longer the case; each paste takes a fresh snapshot. if (restoreOper = Snapshot.RESTORE_NEW) then oldParent:= resetParent(uoidStr,snap,oldParent,pasteType,srcPlatformId,tgtPlatformId); end if; if (restoreOper = Snapshot.RESTORE_SNAPSHOT and NOT(Snapshot.isModelConsistent(snap)=Snapshot.CONSISTENT)) then ModelService.cleanProperties(); end if; cleanTempFCO(); cleanNOTMTable(); if (NOT(restoreOper = Snapshot.RESTORE_NEW)) then cleanAssocTable(); null; end if; return 0; END restore; FUNCTION restore(uoidStr IN VARCHAR2,snap IN NUMBER,restoreParents IN BOOLEAN, restoreOper IN NUMBER default Snapshot.RESTORE_SNAPSHOT, newParent IN NUMBER default 0) RETURN NUMBER IS retValue NUMBER; pastedUOID cmpelement_v.uoid%TYPE; BEGIN retValue:= restore(uoidStr,snap,restoreParents,restoreOper,newParent,FALSE, INTRAPROJPLAT,0,0,pastedUOID); return retValue; END restore; /** * This method to be called for creating copies * @param snap snapshotid that must be less than 0 for * partition pruning to work */ PROCEDURE copy(snap IN NUMBER) IS retVal NUMBER; BEGIN retVal:= Snapshot.getSnapshotID('TEMP_CUTCOPYPASTE_'||ABS(snap), Snapshot.PERSISTENT_SNAPSHOT,null, Snapshot.HEAVY_SNAPSHOT, Snapshot.RESTORE_NEW,snap); for c in (select elementid from mcmcomponent) loop Snapshot.storeComponentRows(c.elementid,Snapshot.CURRENT_SNAPSHOT, Snapshot.CASCADE_SNAPSHOT); takeSnapshot(c.elementid,snap); delete from temptable; end loop; --ServerLog.close(); END copy; /** * This method to be called for creating copies * @param snap snapshotid that must be less than 0 for * partition pruning to work * @param newParent elementid of the new parent to paste to * @param nsNewParent elementid of the new parent if to be restored as new */ PROCEDURE paste(snap IN NUMBER,newParent IN NUMBER,nsNewParent IN NUMBER, pasteType IN NUMBER, srcPlatformId IN NUMBER, tgtPlatformId IN NUMBER) IS retVal NUMBER; cnt NUMBER; parent NUMBER; firstInGroup BOOLEAN; checkTheClass BOOLEAN; pastedUOID cmpelement_v.uoid%TYPE; theClass cmpelement_v.classname%TYPE; BEGIN firstInGroup:=TRUE; checkTheClass:=FALSE; --if (NOT(ServerLog.isOpen())) then -- ServerLog.open('/data/temp','Snapshot.log'); --end if; if (Snapshot.isDebug()) then Snapshot.debug('SnapshotCreateRestore.paste:','mcmcomponent contents before paste'); for c in (select elementid,uoid from mcmcomponent) loop Snapshot.debug('SnapshotCreateRestore.paste: elementid = ' || c.elementid || ' uoid = ',c.uoid); end loop; end if; --Bug 7444225: Filter out Functions for inter-platform pastes. if ((pasteType = INTERPLATFORM) or (pasteType = INTERPROJPLAT)) then delete from cmpscoelement_x where snapshotid = snap and firstclassobject in (select elementid from cmpfunction_x where snapshotid = snap); delete from cmpscocfgelement_x where snapshotid = snap and firstclassobject in (select elementid from cmpfunction_x where snapshotid = snap); delete from cmpscomapelement_x where snapshotid = snap and firstclassobject in (select elementid from cmpfunction_x where snapshotid = snap); delete from cmpscoprpelement_x where snapshotid = snap and firstclassobject in (select elementid from cmpfunction_x where snapshotid = snap); delete from cmpfunction_x where snapshotid = snap; end if; if (newParent != nsNewParent) then checkTheClass:=TRUE; end if; --Tahoe: --Guarantee processing of user folders before ordinary FCOs. The new FCOFolderRef should --exist (created by insertIntoCurrentRepos for folder parent) before its new referenced FCO. --When the new FCO is available, update these new ref attributes: fco, name, fcofqn. --Tahoe: --Guarantee processing of physical objects last. The new logical object should exist. for c in (select m.uoid,decode(f.classname,'CMPUserFolder',0, 'CMPPhysicalMap',2,'CMPPhysicalObject',2,1) porder from mcmcomponent m, firstclassobject_v f where f.elementid = m.elementid order by porder) loop parent:= nsNewParent; if (checkTheClass) then select classname into theClass from firstclassobject_v f where f.uoid = c.uoid; if (theClass = 'CMPUserFolder') then parent:= newParent; end if; end if; retVal:= restore(c.uoid,snap,FALSE,Snapshot.RESTORE_NEW,parent, firstInGroup,pasteType,srcPlatformId,tgtPlatformId,pastedUOID); Snapshot.debug('SnapshotCreateRestore.paste: retVal = ',retVal); Snapshot.debug('SnapshotCreateRestore.paste: pastedUOID = ',pastedUOID); firstInGroup:= FALSE; adjustFCOFolderRef(c.uoid, pastedUOID); update mcmcomponent m set m.uoid = pastedUOID where m.uoid = c.uoid; end loop; if (Snapshot.isDebug()) then Snapshot.debug('SnapshotCreateRestore.paste:','mcmcomponent contents after paste'); for c in (select elementid,uoid from mcmcomponent) loop Snapshot.debug('SnapshotCreateRestore.paste: elementid = ' || c.elementid || ' uoid = ',c.uoid); end loop; select count(1) into cnt from cmpelement_v where uoid = pastedUOID; Snapshot.debug('SnapshotCreateRestore.paste: cnt = ',cnt); end if; --Bug 3589323. The following SQL picks up a new object's uoid correctly for a single-object copy, --but mcmcomponent uoid should come from newest association for each object in a multi-object copy. --update mcmcomponent m set uoid = -- (select uoid from assoctable a where m.elementid = a.oldid); cleanAssocTable(); --ServerLog.close(); END paste; --sochen PROCEDURE addSecurityInfoForRecycle(snap IN NUMBER) IS aclcursor TTYPE; allACLContainers SEC_INTEGERLIST :=SEC_INTEGERLIST(); theACL number; theElemId number; BEGIN --MyDebug('1.come to add sec info for recycle, snpaid:'||snap); for c in (select elementid from mcmcomponent) loop --for cascade down open aclcursor for select ACLCONTAINER from firstclassobject_v start with elementid = c.elementid connect by prior elementid = owningfolder; loop begin fetch aclcursor into theACL; exit when aclcursor%NOTFOUND; --MyDebug('2.add sec info for recycle: aclId:'||theACL); if (theACL IS NULL) then null; --do nothing else allACLContainers.EXTEND; allACLContainers(allACLContainers.COUNT):= theACL; --allACLUOIDs.EXTEND; --allACLUOIDs(allACLUOIDs.COUNT):=theACLUOID; end if; end; end loop; close aclcursor; --for cascade up open aclcursor for select ACLCONTAINER , elementid from firstclassobject_v start with elementid = c.elementid connect by prior owningfolder = elementid; loop begin fetch aclcursor into theACL, theElemId; exit when aclcursor%NOTFOUND; if (theACL is NULL) then null; else if (theElemId = c.elementid) then null; --prevent from dulicate ... else allACLContainers.EXTEND; allACLContainers(allACLContainers.COUNT):=theACL; --allACLUOIDs.EXTEND; --allACLUOIDs(allACLUOIDs.COUNT):=theACLUOID; end if; end if; end; end loop; close aclcursor; end loop; -- now insert the acl info into mcmcomponent if (allACLContainers.COUNT > 0) then for i IN allACLContainers.FIRST..allACLContainers.LAST LOOP --MyDebug('3. add sec for recycle:'||'insert into mcmcomponent(elementid) values('||allACLContainers(i)||')'); insert into mcmcomponent(elementid, cascade,type ) values (allACLContainers(i),0,0); end loop; end if; EXCEPTION WHEN OTHERS THEN raise_application_error(-20001, 'OWB has encountered database exception:'||SUBSTR(SQLERRM, 1, 200)); END addSecurityInfoForRecycle; /** * This method to be called for creating snapshots for the recycle bin * @param snap snapshotid that must be less than 0 for * partition pruning to work */ PROCEDURE recycle(snap IN NUMBER) IS retVal NUMBER; userRecycleBin VARCHAR2(255); BEGIN select upper(sys_context('userenv', 'session_user')) into userRecycleBin from dual; retVal:= Snapshot.getSnapshotID('TEMP_RECYCLEBIN_'||ABS(snap), Snapshot.PERSISTENT_SNAPSHOT,userRecycleBin,Snapshot.HEAVY_SNAPSHOT, Snapshot.UNDELETE,snap); --sochen: update the mcmcomponent table to have security info addSecurityInfoForRecycle(snap); for c in (select elementid from mcmcomponent) loop delete from temptable; Snapshot.storeComponentRows(c.elementid, Snapshot.CURRENT_SNAPSHOT, Snapshot.CASCADE_SNAPSHOT); retVal:= Snapshot.insertSnapshotStore(c.elementid, snap,'', Snapshot.HEAVY_SNAPSHOT,Snapshot.CASCADE_SNAPSHOT); takeSnapshot(c.elementid, snap); end loop; delete from temptable; END recycle; --loop up in fco_x plus snapid PROCEDURE addSecurityInfoForUndelete(snap IN NUMBER) IS aclcursor TTYPE; allACLContainers SEC_STRINGLIST :=SEC_STRINGLIST(); theACL number; theACLUOID varchar2(200); isCascadeUp boolean; existing number; theElemUOID varchar2(200); BEGIN --MyDebug('400. spc: come to add sec for undelete, snap id:'||snap); for c in (select uoid, cascade from mcmcomponent) loop if (c.cascade = 0) then isCascadeUp := FALSE; else isCascadeUp := TRUE; end if; Snapshot.debug('SnapshotCreateRestore.addSecurityInfoForUndelete: uoid = ',c.uoid); Snapshot.debug('SnapshotCreateRestore.addSecurityInfoForUndelete: isCascadeUp = ',c.cascade); --MyDebug('401. come to add sec for undelete, c.cascadeUp is:'||c.cascade||',c.uoid is:'||c.uoid); --for cascade down(always) open aclcursor for select aclcontainer from firstclassobject_x where snapshotid = snap start with uoid = c.uoid and snapshotid = snap connect by prior elementid = owningfolder and snapshotid = snap; loop begin fetch aclcursor into theACL; exit when aclcursor%NOTFOUND; --MyDebug('402: found id of the acl id is:'||theACL); Snapshot.debug('SnapshotCreateRestore.addSecurityInfoForUndelete: theACL.1 = ',theACL); if (theACL IS NULL) then --Bug 7330114. ClassDefinitions under WS have null ACL null; --do nothing else select uoid into theACLUOID from firstclassobject_x where elementid = theACL and snapshotid = snap; --MyDebug('403: found uoid of the acl id is:'||theACLUOID); Snapshot.debug('SnapshotCreateRestore.addSecurityInfoForUndelete: theACLUOID.1 = ',theACLUOID); if (theACLUOID IS NULL) then null; --do nothing else allACLContainers.EXTEND; allACLContainers(allACLContainers.COUNT):= theACLUOID; end if; end if; end; end loop; close aclcursor; --for cascade up if isCascadeUp is true if (isCascadeUp = TRUE) then open aclcursor for select aclcontainer,uoid from firstclassobject_x where snapshotid = snap start with uoid = c.uoid and snapshotid = snap connect by prior owningfolder = elementid and snapshotid = snap; loop begin fetch aclcursor into theACL,theElemUOID; exit when aclcursor%NOTFOUND; Snapshot.debug('SnapshotCreateRestore.addSecurityInfoForUndelete: theACL.2 = ',theACL); Snapshot.debug('SnapshotCreateRestore.addSecurityInfoForUndelete: theElemUOID = ',theElemUOID); if (theACL IS NULL) then --Bug 7330114. ClassDefinitions under WS have null ACL null; --do nothing else select uoid into theACLUOID from firstclassobject_x where elementid = theACL and snapshotid = snap; Snapshot.debug('SnapshotCreateRestore.addSecurityInfoForUndelete: theACLUOID.2 = ',theACLUOID); if (theACLUOID IS NULL) then null; --do nothing else select count(*) into existing from firstclassobject_v where uoid = theACLUOID; if (existing >0) then exit;--in repository else if (theElemUOID =c.uoid) then null; --prevent duplicate else allACLContainers.EXTEND; allACLContainers(allACLContainers.COUNT):= theACLUOID; end if; end if; end if; end if; end; end loop; close aclcursor; end if; end loop; -- now insert the acl info into mcmcomponent if (allACLContainers.COUNT > 0) then for i IN allACLContainers.FIRST..allACLContainers.LAST LOOP --MyDebug('404.add sec for undelete:'||'insert into mcmcomponent(uoid, cascade) values('||allACLContainers(i)||',0)'); insert into mcmcomponent(uoid, cascade) values(allACLContainers(i),0); end loop; end if; EXCEPTION WHEN OTHERS THEN raise_application_error(-20001, 'OWB has encountered database exception:'||SUBSTR(SQLERRM, 1, 200)); END addSecurityInfoForUndelete; /** * This method to be called for undeleting snapshots from the recycle bin * @param snap snapshotid that must be less than 0 for * partition pruning to work */ PROCEDURE undelete(snap IN NUMBER) IS retVal NUMBER; cascadeUp BOOLEAN; BEGIN /* * Bug 8282412: Also, must treat undelete from recycle bin same as an * ordinary restore in terms of physical object processing order. */ addSecurityInfoForUndelete(snap); for c in (select m.uoid, decode(f.classname,'CMPPhysicalMap',1,'CMPPhysicalObject',1,0) porder from mcmcomponent m, firstclassobject_x f where f.snapshotid = snap and f.uoid = m.uoid order by porder) loop retVal:= restore(c.uoid,snap,TRUE,Snapshot.UNDELETE); end loop; END undelete; PROCEDURE resolveNSIssues(snap IN NUMBER, elemID IN NUMBER, newPhysName IN VARCHAR2,newLogName IN VARCHAR2,newNSName IN VARCHAR2, newDomain IN VARCHAR2) IS BEGIN /* For Paris, cmpelement_v is no longer updatable, so must update CMPFCO..., CMPSCO..., and CMPSYS... views */ if (snap = 0) then if (newPhysName is not null) then update cmpallfolderfconames set name = newNSName,domain = newDomain where isPhys = 1 and elementid = elemID; update CMPFCOElement_v set name = newPhysName where elementid = elemID; update CMPSCOelement_v set name = newPhysName where elementid = elemID; update CMPSCOCfgelement_v set name = newPhysName where elementid = elemID; update CMPSCOmapelement_v set name = newPhysName where elementid = elemID; update CMPSCOprpelement_v set name = newPhysName where elementid = elemID; update CMPSYSElement_v set name = newPhysName where elementid = elemID; end if; if (newLogName is not null) then update cmpallfolderfconames set name = newNSName,domain = newDomain where isPhys = 2 and elementid = elemID; update CMPFCOElement_v set logicalname = newLogName where elementid = elemID; update CMPSCOelement_v set logicalname = newLogName where elementid = elemID; update CMPSCOCfgelement_v set logicalname = newLogName where elementid = elemID; update CMPSCOmapelement_v set logicalname = newLogName where elementid = elemID; update CMPSCOprpelement_v set logicalname = newLogName where elementid = elemID; update CMPSYSElement_v set logicalname = newLogName where elementid = elemID; end if; else if (newPhysName is not null) then update fcofoldernamespacestorage set name = newNSName,domain = newDomain where snapshotid = snap and isPhys = 1 and elementid = elemID; update CMPFCOElement_x set name = newPhysName where snapshotid = snap and elementid = elemID; update CMPSCOelement_x set name = newPhysName where snapshotid = snap and elementid = elemID; update CMPSCOCfgelement_x set name = newPhysName where snapshotid = snap and elementid = elemID; update CMPSCOmapelement_x set name = newPhysName where snapshotid = snap and elementid = elemID; update CMPSCOprpelement_x set name = newPhysName where snapshotid = snap and elementid = elemID; update CMPSYSElement_x set name = newPhysName where snapshotid = snap and elementid = elemID; end if; if (newLogName is not null) then update fcofoldernamespacestorage set name = newNSName,domain = newDomain where snapshotid = snap and isPhys = 2 and elementid = elemID; update CMPFCOElement_x set logicalname = newLogName where snapshotid = snap and elementid = elemID; update CMPSCOelement_x set logicalname = newLogName where snapshotid = snap and elementid = elemID; update CMPSCOCfgelement_x set logicalname = newLogName where snapshotid = snap and elementid = elemID; update CMPSCOmapelement_x set logicalname = newLogName where snapshotid = snap and elementid = elemID; update CMPSCOprpelement_x set logicalname = newLogName where snapshotid = snap and elementid = elemID; update CMPSYSElement_x set logicalname = newLogName where snapshotid = snap and elementid = elemID; end if; end if; END resolveNSIssues; FUNCTION validateNamespace(elemID IN NUMBER,platformId IN NUMBER) RETURN NUMBER IS platformName cmpelement_v.name%TYPE; nameMaxLength NUMBER; BEGIN BEGIN select name into platformName from cmpplatform_v where elementid = platformId; EXCEPTION when NO_DATA_FOUND then return 1; END; nameMaxLength := NamespaceRules.getNameMaxLength(platformName); for fco in ( select elementid, name from firstclassobject_v start with elementid = elemID connect by prior elementid = owningfolder ) loop if (length(fco.name) > nameMaxLength) then return 0; end if; if (NamespaceRules.isReservedWord(platformName, fco.name) = 1) then return 0; end if; for sco in ( select name from secondclassobject_V where firstclassobject = fco.elementid ) loop if (length(sco.name) > nameMaxLength) then return 0; end if; if (NamespaceRules.isReservedWord(platformName, sco.name) = 1) then return 0; end if; end loop; end loop; return 1; END validateNamespace; END SnapshotCreateRestore; /