📄 copyhelper.cpp
字号:
COrderEntry* pCreator = NULL;
for(int j = m_Links.GetSize(); --j >= 0; )
{
DECLARE_GET_pLink(j);
if(IsEqual(pLink, pEntry))
{
ASSERT(!pCreator);
pCreator = pLink;
}
else if(pLink->GetTblSlaveTo() == pEntry->GetTblSlaveTo()
&& !pLink->IsForked() && !IsSerialLink(pLink))
{
ASSERT(!pLink->IsPassed());
return postpone;
}
}
pEntry->SetPassed();
if(pCreator && !pCreator->IsPassed())
{
ShowProgress();
pCreator->SetPassed();
}
BOOL bResult = GoDownstairs(pEntry->m_CopyIterator, pEntry);
return bResult? handled : error;
}
BOOL CTblCopyHelper::HasVirginXLinks(CTableId pTblTo, int nCount)
{
if(0 > nCount)
{
ASSERT(FALSE); return FALSE;
}
for(int i = m_XLinks.GetSize() ; --i >= 0; )
{
DECLARE_GET_pXLink(i);
if(!pXLink->IsPassed() && pXLink->GetTblSlaveTo() == pTblTo
&& !pXLink->IsSelfLink()
&& (!pXLink->IsByReference() || HasVirginXLinks(pXLink->GetTblMasterTo(), nCount-1)))
{
#ifdef _DEBUG
g_arrVirginXLinks.Add(pXLink->GetTblMasterTo().GetTableName() + _T("\"-\"") + pXLink->GetTblSlaveTo().GetTableName());
#endif// _DEBUG
return TRUE;
}
}
return FALSE;
}
COrderLink* CTblCopyHelper::GetSelfLink(CTableId pTblTo)
{
COrderLink* pSelfLink = NULL;
for(int i = m_Links.GetSize(); --i >= 0; )
{
DECLARE_GET_pLink(i);
if(pLink->GetTblMasterTo() == pTblTo && pLink->IsSelfLink())
{
ASSERT(NULL == pSelfLink);
pSelfLink = pLink;
#ifndef _DEBUG
break;
#endif//_DEBUG
}
}
return pSelfLink;
}
typedef std::set<Identity, std::less<Identity>, cached_alloc<Identity> > CCachedLongSet;
bool IdToPresents(CMapIdentities* pSubstId, Identity lIdToFind, CCachedLongSet& rIdCache)
{
if(pSubstId->IsEmpty())
return false;
if(rIdCache.empty())
{
llmap::const_iterator iterEnd = end(*pSubstId);
for(llmap::const_iterator iter = begin(*pSubstId)
; iter != iterEnd
; ++iter)
{
rIdCache.insert(iter->second);
}
}
return IsValid(lIdToFind) && (rIdCache.end() != rIdCache.find(lIdToFind));
}
bool CTblCopyHelper::IsPassed(CTableId pTblTo)
{
for(int i = m_Links.GetSize(); --i >= 0; )
{
DECLARE_GET_pLink(i);
if(pLink->GetTblSlaveTo() == pTblTo && !pLink->IsPassed())
return false;
}
typedef CMultiSetEntries::const_iterator CIterator;
COrderVariantKey key(pTblTo);
std::pair<CIterator, CIterator>
range(m_WorkFlowEntries.equal_range(static_cast<COrderVariant*>(&key)));
for(CMultiSetEntries::const_iterator iter = range.first
; iter != range.second
; ++iter)
{
COrderEntry* pEntry = static_cast<COrderEntry*>(*iter);
CHECK_ADDRESS(pEntry);
ASSERT(pEntry->GetTblSlaveTo() == pTblTo);
if(!pEntry->IsPassed())
return false;
}
return true;
}
void CTblCopyHelper::MarkRelatedXLinksPassed(CTableId pTblTo)
{
if(IsPassed(pTblTo))
for(int i = m_XLinks.GetSize(); --i >= 0; )
{
DECLARE_GET_pXLink(i);
if(pXLink->GetTblMasterTo() == pTblTo)
{
pXLink->SetPassed();
}
}
}
//////////////////////////////////////////////////////////////
struct CDownstairsContext
{
Identity m_lPKTo;
CMapIdentities* m_pSubstParentId;
bool m_bConvert;
CDownstairsContext()
{
m_lPKTo = ID_NOT_DEF;
m_pSubstParentId = NULL;
m_bConvert = false;
}
};
class CTblCopyHelperDownstairs : public CTblCopyHelper
{
template<typename T, typename C, typename H>
friend void TransferData(T* pHolder, const C& rContext, COrderVariant* pVar,
int nCount, bool bForceAdd, CMapIdentities* pSubstId, H& rIdHandler);
bool DoConvertAndFilter(COrderVariant* pVar, CMapIdentities* pSubstId,
const CDownstairsContext& rContext)
{
if(pVar->HasPrimaryKey())
{
Identity lId = pVar->GetPrimaryKeyFrom();
if(IsValid(lId) && pSubstId->Lookup(lId, lId))
return false;
}
CDBTable* pTblTo = pVar->GetTblCopyTo();
size_t nFieldOffset = pVar->GetFieldOffset();
for(int i = m_Entries.GetSize(); --i >= 0; )
{
DECLARE_GET_pEntry(i);
if(pEntry->GetTblCopyTo() == pTblTo
&& !pEntry->m_CopyIterator.ByPK())
{
if(nFieldOffset != pEntry->GetFieldOffset()
&& pEntry->GetFieldSlaveFrom() != pEntry->GetIteratorValueFrom())
return false;
pEntry->SetFieldSlaveTo(pEntry->GetIteratorValueTo());
}
}
Identity lPkTo;
if(IsValid(rContext.m_lPKTo))
lPkTo = rContext.m_lPKTo; // Has priority to entries
else if(rContext.m_pSubstParentId)
{
VERIFY(rContext.m_pSubstParentId->Lookup(pVar->GetFieldSlaveFrom(), lPkTo));
}
if (IsValid(lPkTo))
pVar->SetFieldSlaveTo(lPkTo);
if(rContext.m_bConvert)
pVar->Convert();
return true;
}
void DoAddDropRecord(COrderVariant* pVar, bool& bUpdate)
{
VERIFY(pVar->GetTblCopyTo()->AddRecord(FALSE));
bUpdate = true;
}
};
//////////////////////////////////////////////////////////////
BOOL CTblCopyHelper::GoDownstairs(CCopyIterator CopyIterator,
COrderVariant* pTwinTables)
{
int i;
CDBTable* pTblTo = pTwinTables->GetTblCopyTo();
CMapIdentities* pSubstParentId = NULL;
CMapIdentities* pSubstId = m_mapTbl2MapId.GetAtNew(pTwinTables->GetTblSlaveTo());
// We should mark related Xlinks as passed anyway
MarkRelatedXLinksPassed(pTwinTables->GetTblSlaveTo());
COrderLink* pSelfLink = NULL;
CSubstRecArrayPtr arrOutpSubstRec = new CSubstRecArray;
int nPrevCount = 0;
const bool bHasPrimaryKey = pTwinTables->HasPrimaryKey();
bool bNextSubType = false;
CCachedLongSet IdCache(std::less<Identity>(), m_LongMapMemCache);
pTwinTables->FirstSubType();
do
{
DWORD dwFilterType = pTwinTables->GetFilterType();
ASSERT(dwFilterType != 0);
LeaveKind eLeaveData = pTwinTables->GetLeaveData();
do
{
PumpPaintMsg();
for(int nValue = CopyIterator.GetSize(); --nValue >= 0; )
{
bool bForceAdd = (CopyIterator.ByPK() || lkLeaveData == eLeaveData)
&& !pTwinTables->IsUpdateDestination()
|| fltUniqueIndex == dwFilterType && lkLeaveUnique != eLeaveData;
if(CopyIterator.ByPK())
{
if(!pTwinTables->FindByPrimaryKeyFrom(CopyIterator.GetValueFrom(nValue)))
continue;
if(!bNextSubType && lkLeaveData != eLeaveData
&& pTblTo->HasUniqueFilter() && !pTwinTables->IsUpdateDestination())
{
pTwinTables->CopyData();
if(!GoUpstairs(pTblTo, EXTRA_SPACE))
return FALSE;
SetDefValues(pTwinTables);
pTwinTables->CorrectTableData();
if(pTwinTables->FindMatchByUI())
{
if(HasSameDatabases() && bHasPrimaryKey
&& pTblTo->GetPrimaryKey() == pTwinTables->GetPrimaryKeyFrom())
continue;
else
if (!pTblTo->DeleteRecord())
bForceAdd = false;
}
}
}
else
{
bool bRestart = false;
pTblTo->InitData();
// First iterate thru sibling entries - both in and out
for(i = m_Entries.GetSize(); --i >= 0; )
{
DECLARE_GET_pEntry(i);
if(pEntry->GetTblCopyTo() == pTblTo)
{
ASSERT(pEntry == pTwinTables || fltNoFilter != pEntry->GetFilterType());
if(pEntry->m_CopyIterator.ByPK())
{
if(!pEntry->IsPassed())
{// Substitute CopyIterator and restart iteration
VERIFY(m_mapTbl2MapId.Lookup(pTwinTables->GetTblMasterTo(),
pSubstParentId));
CopyIterator = pEntry->m_CopyIterator;
nValue = CopyIterator.GetSize();
dwFilterType = pEntry->GetFilterType();
bRestart = true;
pEntry->SetPassed();
break;
}
}
else
{
pEntry->SetFieldSlaveFrom(pEntry->GetIteratorValueFrom());
pEntry->SetFieldSlaveTo(pEntry->GetIteratorValueTo());
pEntry->SetPassed();
}
}
}
if(bRestart)
continue;
if(dwFilterType != fltNoFilter)
pTwinTables->SetFieldSlaveFrom(CopyIterator.GetValueFrom(nValue)); // Has priority to entries
pTwinTables->SetFieldSlaveTo(CopyIterator.GetValueTo(nValue));
// Remove garbage
// Important: garbage should be removable - enable cascade deletes
if(!bNextSubType && lkDeleteAll == eLeaveData)
{
DWORD filter = (dwFilterType < 0x00010000)? dwFilterType : fltNoFilter;
if (pSubstId->IsEmpty())
pTwinTables->DeleteRecords(filter);
else
{
while (pTblTo->FindFirst(filter))
{
if(bHasPrimaryKey)
{
while(IdToPresents(pSubstId, pTblTo->GetPrimaryKey(), IdCache))
if(fltUniqueIndex == dwFilterType || !pTblTo->FindNext())
goto LoopExit;
}
if (!pTwinTables->DeleteRecord())
break;
}
LoopExit: ;
}
}
if(!pTwinTables->FindFirstFrom(dwFilterType))
continue;
}
CDownstairsContext context;
context.m_bConvert = (NULL != pSelfLink);
context.m_lPKTo = CopyIterator.ByPK()? ID_NOT_DEF : CopyIterator.GetValueTo(nValue);
context.m_pSubstParentId = pSubstParentId;
int nPos = arrOutpSubstRec->GetSize();
do
{
if (HasParams(dwFilterType) && !CopyIterator.ByPK()
&& pTwinTables->GetFieldSlaveFrom() != CopyIterator.GetValueFrom(nValue))
continue;
try
{
TransferData(static_cast<CTblCopyHelperDownstairs*>(this), context,
pTwinTables, EXTRA_SPACE, bForceAdd,
pSubstId, arrOutpSubstRec);
}
catch(transfer_exception&)
{
return false;
}
}
while(!CopyIterator.ByPK() && dwFilterType != fltUniqueIndex
&& pTwinTables->FindNextFrom());
if(bHasPrimaryKey && !bNextSubType && lkLeaveData != eLeaveData)
{
if(IdCache.empty())
IdToPresents(pSubstId, ID_NOT_DEF, IdCache); // To fill for the first time
else
for(; nPos < arrOutpSubstRec->GetSize(); ++nPos)
IdCache.insert((*arrOutpSubstRec)[nPos].m_lKeyTo);
}
}
bNextSubType = true;
}
while(NULL == pSelfLink
&& pTwinTables->NextSubType(&CopyIterator, dwFilterType));
if(NULL == pSelfLink)
{
pSelfLink = GetSelfLink(pTwinTables->GetTblSlaveTo());
ASSERT(pSelfLink != pTwinTables);
if(NULL != pSelfLink)
pSelfLink->SetPassed();
}
if(NULL != pSelfLink)
if(arrOutpSubstRec->GetSize() > nPrevCount)
{
CSubstRecArrayPtr arrSelfSubstRec = new CSubstRecArray;
for(i = nPrevCount, nPrevCount = arrOutpSubstRec->GetSize();
i < nPrevCount;
i++)
arrSelfSubstRec->Add((*arrOutpSubstRec)[i]);
CopyIterator.SetData(arrSelfSubstRec);
pTwinTables = pSelfLink;
}
else pSelfLink = NULL;
}
while(NULL != pSelfLink);
if(!pTwinTables->PostCopyAll(arrOutpSubstRec))
return FALSE;
GetHolderTo()->FreeStatements();
if (!HasSameDatabases())
GetHolderFrom()->FreeStatements();
return DoCopyLinkedTables(arrOutpSubstRec, pTwinTables, true);
}
BOOL CTblCopyHelper::DoCopyLinkedTables(CSubstRecArrayPtr& parrSubstRec,
COrderVariantKey* pTwinTables, bool bPrimary)
{
MarkRelatedXLinksPassed(pTwinTables->GetTblMasterTo());
CTableId pTblTo = pTwinTables->GetCopyTableId();
for(int i = m_Links.GetSize(); --i >= 0; )
{
DECLARE_GET_pLink(i);
if(pLink->GetTblMasterTo() == pTblTo)
if(bPrimary && pLink->IsSelfLink())
{
pLink->SetPassed();
MarkRelatedXLinksPassed(pLink->GetTblSlaveTo());
}
else
{
if(parrSubstRec->GetSize()
|| bPrimary && pLink->GetTblSlaveTo() != pTwinTables->GetTblMasterTo())
{
COrderEntry* pEntry = pLink->ForkEntry(parrSubstRec);
if(NULL != pEntry)
{
m_WorkFlowEntries.insert(pEntry);
++m_nProgressDelay;
}
}
else
{
pLink->SetPassed();
MarkRelatedXLinksPassed(pLink->GetTblSlaveTo());
}
}
}
return TRUE;
}
//////////////////////////////////////////////////////////////
struct CUpstairsContext {};
class CTblCopyHelperUpstairs : public CTblCopyHelper
{
template<typename T, typename C, typename H>
friend void TransferData(T* pHolder, const C& rContext, COrderVariant* pVar,
int nCount, bool bForceAdd, CMapIdentities* pSubstId, H& rIdHandler);
bool DoConvertAndFilter(COrderVariant*, CMapIdentities*,
const CUpstairsContext&)
{
return true;
}
void DoAddDropRecord(COrderVariant* pVar, bool& bUpdate)
{
VERIFY(pVar->GetTblCopyTo()->AddRecord(FALSE));
bUpdate = true;
}
};
//////////////////////////////////////////////////////////////
BOOL CTblCopyHelper::GoUpstairs(CDBTable* pTblTo, int nCount)
{
int i;
if(0 > nCount)
{
ASSERT(FALSE); return FALSE;
}
for(i = m_XLinks.GetSize(); --i >= 0; )
{
DECLARE_GET_pXLink(i);
if(pXLink->GetTblSlaveTo() == pTblTo)
{
pXLink->FirstSubType();
if(pXLink->Convert()
|| !pXLink->IsDontShortcutRef() && pXLink->IsByReference() && HasSameDatabases())
continue;
Identity idFrom = pXLink->GetFieldSlaveFrom();
if(!IsValid(idFrom))
{
pXLink->SetFieldSlaveTo(idFrom);
}
else if (pXLink->GetTblMasterTo() == pTblTo)
{
pXLink->SetFieldSlaveTo(ID_NULL);
}
else
{
if(pXLink->FindByPrimaryKeyFrom(idFrom))
{
CSubstRecArrayPtr arrOutpSubstRec = new CSubstRecArray;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -