⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 copyhelper.cpp

📁 Data Replication Prototype Using ADO
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	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 + -