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

📄 dbtable.cpp

📁 Data Replication Prototype Using ADO
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// DBTable.cpp: implementation of the CDBTable class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ETLLib.h"
#include "DBTable.h"
#include "OrderVariant.h"

#pragma warning(disable:4018 4663)
#include <vector>
#pragma warning(default:4018 4663)

#include "TableHolder.h"

using std::wstring;

using _com_util::CheckError;

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

enum { pkFilters = fltAutoNumber | fltPrimaryKey };

const VARIANT g_vNull = { VT_NULL };

HRESULT SafeArrayZeroVector(SAFEARRAY * psa)
{
	LONG iLBound, iUBound;
	HRESULT hr = SafeArrayGetLBound(psa, 1, &iLBound);
	if(FAILED(hr))
		return hr;
	hr = SafeArrayGetUBound(psa, 1, &iUBound);
	if(FAILED(hr))
		return hr;
	UINT nElemSize = SafeArrayGetElemsize(psa);

	void* pData = NULL;

	hr = SafeArrayAccessData(psa, (void**)&pData);
	if(FAILED(hr))
		return hr;

	memset(pData, 0, (iUBound - iLBound + 1) * nElemSize);

	hr = SafeArrayUnaccessData(psa);
	if(FAILED(hr))
		return hr;

	return S_OK;
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDBTable::CDBTable(CTableHolder* pHolder)
: m_pHolder(pHolder)
, m_pstrTableName(NULL)
, m_nAtomCount(0)
, m_pAtomDesc(NULL)

, m_dwFilter(DWORD(-1L))
, m_dwDeleteFilter(DWORD(-1L))
, m_bAddMode(false)
, m_bFieldsListed(false)
{
}

CDBTable::~CDBTable()
{
}

void CDBTable::InitData()
{
	for (MapValues::iterator iter = m_mapValues.begin()
	; iter != m_mapValues.end()
	; ++iter)
		iter->second = g_vNull;
}

void CDBTable::FreeStatements()
{
	if (m_pRFind != NULL)
		m_pRFind->Close();

	m_pRFind = NULL;
	m_pCFind = NULL;
	m_pCAdd = NULL;
	m_pCId = NULL;
	m_pCDelete = NULL;

	m_dwFilter = DWORD(-1L);
	m_dwDeleteFilter = DWORD(-1L);
	m_bAddMode = false;
}

//////////////////////////////////////////////////////////////////////

LPCWSTR CDBTable::GetColumnName(DWORD filter) const
{
	for (int i = 0; i < GetAtomCount(); i++)
	{
		DWORD id = GetAtomId(i);
		if ((id & filter) == id)
			return GetAtomName(i);
	}
	return NULL;
}


void CDBTable::SetIdentityValue(DWORD id, Identity value)
{
	if (id != 0)
	{
		LPCWSTR colName = GetColumnName(id);
		ASSERT(colName);
		_variant_t buf;
		value.Get(buf);
		m_mapValues[colName].Attach(buf);
	}
}

Identity CDBTable::GetIdentityValue(DWORD id) const
{
	LPCWSTR colName = GetColumnName(id);
	if (!colName)
		return ID_NOT_DEF;
	const _variant_t& val = const_cast<CDBTable*>(this)->
		m_mapValues[colName];
	Identity identity;
	identity.Set(val, GetIdentityShared());
	return identity;
}

Identity CDBTable::GetPrimaryKey() const
{
	return GetIdentityValue(pkFilters);
}

bool CDBTable::HasPrimaryKey() const
{
	return GetColumnName(pkFilters) != NULL;
}

bool CDBTable::HasUniqueFilter() const
{
	return GetColumnName(fltUniqueIndex) != NULL;
}


//////////////////////////////////////////////////////////////////////


bool CDBTable::FindFirst(DWORD filter)
{
	long i;

	if (m_dwFilter != filter)
	{
		wstring query(L"SELECT * FROM ");
		query += GetTableName();
		if (filter != 0)
			if (filter < 0x00010000)
			{
				bool first = true;
				for (int i = 0; i < GetAtomCount(); i++)
				{
					DWORD id = GetAtomId(i);
					if ((id & filter) == id)
					{
						if (first)
						{
							query += L" WHERE ";
							first = false;
						}
						else 
							query += L" AND ";
						query += GetAtomName(i);
						query += L"=?";
					}
				}
			}
			else
			{
				query += L" WHERE ";
				USES_CONVERSION;
				query += T2CW((LPCTSTR) filter);
			}

		if(FAILED(m_pCFind.CreateInstance(__uuidof(Command))))
		{
			ASSERT(0);
			return false;
		}

		m_pCFind->ActiveConnection = GetConnectionPtr();
		
		TRACE(CString(query.c_str()) + _T("\n"));
		m_pCFind->CommandText = query.c_str();
		m_pCFind->Prepared = true;

		if (filter != 0 && filter < 0x00010000)
			for (i = 0; i < GetAtomCount(); i++)
			{
				DWORD id = GetAtomId(i);
				if ((id & filter) == id)
				{
					MapValues::iterator iter = m_mapValues.find(GetAtomName(i));
					if (iter != m_mapValues.end())
					{
						DataTypeEnum param_type = adPropVariant;
						int param_size = 0;
						switch (V_VT(&iter->second))
						{
						case VT_I4: 
							param_type = adInteger;
							param_size = 4;
							break;
						case VT_BSTR:
							param_type = adBSTR;
							param_size = 255;
							break;
						default: ASSERT(0);
						}

						_ParameterPtr pprm = 
							m_pCFind->CreateParameter(iter->first.c_str(), param_type, 
								adParamInput, param_size, iter->second);
						m_pCFind->Parameters->Append(pprm);
					}
					else
						ASSERT(0);
				}
			}

		m_dwFilter = filter;

		// recordset
		if(FAILED(m_pRFind.CreateInstance(__uuidof(Recordset))))
		{
			ASSERT(0);
			return false;
		}

		m_pRFind->Open(_variant_t((IDispatch*)m_pCFind), vtMissing
			, IsReadOnly()? adOpenForwardOnly : adOpenKeyset
			, IsReadOnly()? adLockReadOnly : adLockOptimistic
			, adCmdText);
	}
	else 
	{
		for (i = 0; i < GetAtomCount(); i++)
		{
			DWORD id = GetAtomId(i);
			if ((id & filter) == id)
			{
				MapValues::iterator iter = m_mapValues.find(GetAtomName(i));
				if (iter != m_mapValues.end())
				{
					m_pCFind->Parameters->Item[iter->first.c_str()]->Value = iter->second;
				}
			}
		}
		m_pRFind->Requery(adCmdText);
	}

	if (m_pRFind->adoEOF)
	{
		return false;
	}
	DoCopyDataFromTable(this);
	return true;
}

bool CDBTable::FindNext()
{
	if (m_pRFind == NULL || !SUCCEEDED(m_pRFind->MoveNext())
			|| m_pRFind->adoEOF)
		return false;
	DoCopyDataFromTable(this);
	return true;
}

bool CDBTable::FindByPrimaryKey(Identity lId)
{
	SetIdentityValue(pkFilters, lId);
	return FindFirst(pkFilters);
}


//////////////////////////////////////////////////////////////////////

void CDBTable::CopyDataFromTable(const CDBTable* pTable, 
								 bool bCopyPK /*= true*/)
{
	if (!m_bFieldsListed)
	{
		if (NULL == m_pRFind)
		{
			_RecordsetPtr pRParams = GetParamsRecordset();
			for (long i = pRParams->Fields->Count; i--; )
				m_mapValues[LPCWSTR(pRParams->Fields->Item[i]->Name)] = g_vNull;
			pRParams->Close();
		}
		m_bFieldsListed = true;
	}
	if (!pTable)
	{
		ASSERT(0); return;
	}

	LPCWSTR pstrPKName = NULL;
	if (!bCopyPK)
	{
		pstrPKName = GetColumnName(fltAutoNumber);
	}

	for (MapValues::const_iterator iter = pTable->m_mapValues.begin()
	; iter != pTable->m_mapValues.end()
	; ++iter)
	{
		if (pstrPKName && iter->first == pstrPKName)
			continue;
		MapValues::iterator iterDest = m_mapValues.find(iter->first);
		if (iterDest != m_mapValues.end())
			iterDest->second = iter->second;
	}
}

void CDBTable::DoCopyDataFromTable(const CDBTable* pTable, 
								 bool bCopyPK /*= true*/)
{
	if (!pTable)
	{
		ASSERT(0); return;
	}
	_RecordsetPtr pOtherRecordset = pTable->GetFindRecorset();
	if (NULL == pOtherRecordset)
	{
		ASSERT(0); return;
	}

	LPCWSTR pstrPKName = NULL;
	if (!bCopyPK)
	{
		pstrPKName = GetColumnName(fltAutoNumber);
	}

	long i;
	for (i = pOtherRecordset->Fields->Count; i--; )
	{
		FieldPtr item = pOtherRecordset->Fields->Item[i];
		_bstr_t pstrItemName(item->GetName());
		if (!pstrItemName)
		{
			ASSERT(0);
			continue;
		}
		if (pstrPKName && !wcscmp(pstrItemName, pstrPKName))
			continue;
		_variant_t buf;
		VERIFY(SUCCEEDED(item->get_Value(&buf)));
		m_mapValues[LPCWSTR(pstrItemName)].Attach(buf);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -