#include "StdAfx.h"
#include "AdoImplSvr.h"
#include "DataDef.h"

AdoImpl::AdoImpl(void)
{
	m_pADODatabase = NULL;
	memset(m_szConnectString,0,1024);
	InitializeCriticalSection(&m_csAdo);
}

AdoImpl::~AdoImpl(void)
{
	DeleteCriticalSection(&m_csAdo);
	closedatabase();
}

void AdoImpl::SetConnectString(IN const int &nType,IN const STDatabaseInfo &tagSTDatabaseInfo)
{
	switch (nType)
	{
	case ADO_ACCESS97:
		_stprintf(m_szConnectString, _T("Provider=Microsoft.Jet.OLEDB.3.51;Data Source=%s"), tagSTDatabaseInfo.szDatabaseFile);
		break;
	case ADO_ACCESS2000:
		_stprintf(m_szConnectString, _T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s"), tagSTDatabaseInfo.szDatabaseFile);
		break;
	case ADO_ACCESS2007:
		_stprintf(m_szConnectString, _T("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=%s"), tagSTDatabaseInfo.szDatabaseFile);
		break;
	case ADO_SQLSERVER:
		{
			if ( !_tcsicmp(tagSTDatabaseInfo.szDatabaseTCPPort, _T("0")))
			{
				//sprintf(m_szConnectString, "Provider=sqloledb.1;Persist Security Info=false;Data Source=%s;Initial Catalog=%s;User Id=%s;Password=%s; ",
				_stprintf(m_szConnectString, _T("Provider=sqloledb;Data Source=%s;Initial Catalog=%s;User Id=%s;Password=%s; "),
					tagSTDatabaseInfo.szDataSource,			// IP��ַ���������;
					tagSTDatabaseInfo.szDatabaseName, 
					tagSTDatabaseInfo.szDatabaseAccount,
					tagSTDatabaseInfo.szDatabasePassword);
			}
			else
			{
				//sprintf(m_szConnectString, "Provider=sqloledb.1;Persist Security Info=false;Data Source=%s,%s;Initial Catalog=%s;User Id=%s;Password=%s; ",
				_stprintf(m_szConnectString, _T("Provider=sqloledb;Data Source=%s,%s;Initial Catalog=%s;User Id=%s;Password=%s; "),
					tagSTDatabaseInfo.szDataSource,			// IP��ַ���������;
					tagSTDatabaseInfo.szDatabaseTCPPort, 
					tagSTDatabaseInfo.szDatabaseName, 
					tagSTDatabaseInfo.szDatabaseAccount,
					tagSTDatabaseInfo.szDatabasePassword);
			}
		}
		break;
	case ADO_PGSQL:
		{
			_stprintf(m_szConnectString, _T("DRIVER={PostgreSQL ODBC Driver(UNICODE)}; SERVER=%s; port=%s; DATABASE=%s; UID=%s; PWD=%s;"),
				tagSTDatabaseInfo.szDataSource,			// IP��ַ���������;
				tagSTDatabaseInfo.szDatabaseTCPPort, 
				tagSTDatabaseInfo.szDatabaseName, 
				tagSTDatabaseInfo.szDatabaseAccount,
				tagSTDatabaseInfo.szDatabasePassword);
		}
		break;
	default:
		break;
	}
}

bool AdoImpl::opendatabase(IN const TCHAR *pConnectString)
{
	bool bResult = false;
	if( NULL == m_pADODatabase )
	{
		m_pADODatabase = new CADODatabase();
		if( m_pADODatabase )
		{
			if( pConnectString == NULL )
				m_pADODatabase->SetConnectionString(m_szConnectString);
			else
			{
				m_pADODatabase->SetConnectionString(pConnectString);
				_tcscpy_s(m_szConnectString, pConnectString);
			}

			if( TRUE == m_pADODatabase->Open() )
			{
				//LOG4C((LOG_NOTICE, "Database Connetion Success!"));
				bResult = true;
			}
			else
			{
				if( m_pADODatabase->IsOpen() )
					m_pADODatabase->Close();

				delete m_pADODatabase;
				m_pADODatabase = NULL;
				//LOG4C((LOG_NOTICE, "Database Connetion Lost!"));
			}
		}
	}

	return bResult;
}

void AdoImpl::closedatabase()
{
	if( NULL != m_pADODatabase )
	{
		if( m_pADODatabase->IsOpen() )
			m_pADODatabase->Close();

		if( m_pADODatabase )
			delete m_pADODatabase;
		m_pADODatabase = NULL;
	}
}

void AdoImpl::dump_com_error(_com_error &e)
{
	CString ErrorStr;
	_bstr_t bstrSource(e.Source());
	_bstr_t bstrDescription(e.Description());
	ErrorStr.Format(_T("CADORecordset Error\n\tCode = %08lx\n\tCode meaning = %s\n\tSource = %s\n\tDescription = %s\n"),
		e.Error(), e.ErrorMessage(), (TCHAR*)bstrSource, (TCHAR*)bstrDescription );
	m_strLastError = _T("Query = " + GetQuery() + '\n' + ErrorStr);
	m_dwLastError = e.Error();
#ifdef _DEBUG
	AfxMessageBox( ErrorStr, MB_OK | MB_ICONERROR );
#endif	
}


int AdoImpl::Execute(TCHAR *pSQL)
{
	INT iRetCode = 0;

	if( NULL == m_pADODatabase )
		return -1;

	try
	{
		EnterCriticalSection(&m_csAdo);
		if ( m_pADODatabase->IsOpen() )
		{
			iRetCode = m_pADODatabase->Execute(pSQL);
			LeaveCriticalSection(&m_csAdo);
		}
		else
		{
			LeaveCriticalSection(&m_csAdo);
			return -1;
		}
	}
	catch (_com_error &e)
	{
		dump_com_error(e);
		return -1;
	}

	return iRetCode;
}

void AdoImpl::DeleteADORecordSet(CADORecordset* pRSet)
{
	CloseADORecordSet(pRSet);

	if( pRSet )
	{
		delete pRSet;
		pRSet = NULL;
	}
}

bool AdoImpl::OpenADORecordSet(CADORecordset* pRSet, const TCHAR *pSQL)
{
	int iRetCode;
	bool bResult = true;

	if( NULL == pRSet ) return false;
	try
	{
		iRetCode = pRSet->Open(pSQL, CADORecordset::openQuery);

		if (iRetCode == 0)
		{
			DeleteADORecordSet(pRSet);
			bResult = false;
		}
	}
	catch (_com_error &e)
	{
		dump_com_error(e);
		//LOG4C( ( LOG_ERROR, "Execute SQL Script Error, Script:%s, ErrorMsg:%s", pSql, e.ErrorMessage() ) );
		DeleteADORecordSet(pRSet);
		bResult = false;
	}

	return bResult;
}

void AdoImpl::CloseADORecordSet(CADORecordset* pRSet)
{
	if( NULL != pRSet )
	{
		if( pRSet->IsOpen() )
		{
			pRSet->Close();
		}
	}
}

bool AdoImpl::GetADODateBaseStatus()
{
	if( NULL == m_pADODatabase || !m_pADODatabase->IsOpen()) 
		return false;

	return true;
}


DWORD AdoImpl::GetTableRecordCount(IN LPCTSTR lpTableName, IN LPCTSTR lpFilters)
{
	if ( lpTableName == NULL)
		return -1;

	TCHAR szSQL[1024] = _T("");
	if(lpFilters == NULL || _tcscmp(lpFilters,_T("")) == 0)
		_stprintf_s(szSQL,_T("select count(*) as cot from %s"),lpTableName);
	else
		_stprintf_s(szSQL,_T("select count(*) as cot from %s where %s"),lpTableName,lpFilters);

	DWORD nRecordCount = 0;			
	_variant_t vtFieldValue;

	bool bResult = false;
	//AutoThreadSection aSection(&s_critSection);
	EnterCriticalSection(&m_csAdo);
	bResult = GetADODateBaseStatus();
	if( false == bResult )
	{
		LeaveCriticalSection(&m_csAdo);
		return -1;
	}

	CADORecordset* pRSet = new CADORecordset(m_pADODatabase);
	if( NULL == pRSet )
	{
		LeaveCriticalSection(&m_csAdo);
		//LOG4C((LOG_NOTICE, "GetFieldValueList1 pRSet == NULL"));
		return -1;
	}


	bResult = OpenADORecordSet(pRSet, szSQL);
	if( false == bResult )
	{
		LeaveCriticalSection(&m_csAdo);
		//LOG4C((LOG_NOTICE, "GetFieldValueList1 OpenADORecordSet <%s>", pSql));
		DeleteADORecordSet(pRSet);
		return -1;
	}


	if( !pRSet->IsFieldNull(_T("cot")) )
		pRSet->GetFieldValue(_T("cot"), nRecordCount);
	else
		nRecordCount = -1;

	DeleteADORecordSet(pRSet);
	LeaveCriticalSection(&m_csAdo);
	return nRecordCount;
}

int AdoImpl::GetFieldValueList(IN const TCHAR *pTableName,__in const TCHAR *pFilters, const TCHAR *pSql, INT &nFieldCount, vector<TString>& vtRet)
{
	TCHAR szSQL[1024] = _T("");
	_stprintf_s(szSQL, _T("select count(*) as cot from %s where %s"), pTableName, pFilters);

	int nRecordCount = 0;			
	_variant_t vtFieldValue;

	bool bResult = false;
	EnterCriticalSection( &m_csAdo );
	bResult = GetADODateBaseStatus();
	if( false == bResult )
	{
		LeaveCriticalSection( &m_csAdo );
		return -1;
	}

	CADORecordset* pRSet = new CADORecordset(m_pADODatabase);
	LeaveCriticalSection( &m_csAdo );
	if( NULL == pRSet )
	{
		//LOG4C((LOG_NOTICE, "GetFieldValueList1 pRSet == NULL"));
		return -1;
	}

	bResult = OpenADORecordSet(pRSet, szSQL);
	if( false == bResult )
	{
		DeleteADORecordSet(pRSet);
		return -1;
	}

	if( !pRSet->IsFieldNull(_T("cot")) )
		pRSet->GetFieldValue(_T("cot"), nRecordCount);
	else
		nRecordCount = -1;

	DeleteADORecordSet(pRSet);
	pRSet = new CADORecordset(m_pADODatabase);
	LeaveCriticalSection( &m_csAdo );
	if( NULL == pRSet )
	{
		//LOG4C((LOG_NOTICE, "GetFieldValueList1 pRSet == NULL"));
		return -1;
	}

	bResult = OpenADORecordSet(pRSet, pSql);
	if( false == bResult )
	{
		DeleteADORecordSet(pRSet);
		return -1;
	}

	nFieldCount = pRSet->GetFieldCount();

	for( int i = 0; i < nRecordCount*nFieldCount; i++ )
	{
		if( !pRSet->IsFieldNull(i%nFieldCount) )
		{
			pRSet->GetFieldValue(i%nFieldCount, vtFieldValue);
			TString strFieldValue = TString((TCHAR*)(_bstr_t)vtFieldValue);
			vtRet.push_back(strFieldValue);
		}
		else
		{
			vtRet.insert(vtRet.end(), _T(""));
		}

		if ((i != 0) && (i%nFieldCount == 0))
			pRSet->MoveNext();
	}

	DeleteADORecordSet(pRSet);
	return nRecordCount;
}

/*-------------------------------------------------------------------------------*/
/*
������:	GetFieldValueList
˵��:	��ȡ�����¼
����:	
	__in const TCHAR *pTableName,								����
	__in const TCHAR *pSql,										sql���
	__out int &nFieldCount,										���ز�ѯ����
	__out CArray<CStringArray,CStringArray>& strArray			�������ݼ�
����:	��������,ʧ��=-1
*/
/*-------------------------------------------------------------------------------*/
int AdoImpl::GetFieldValueList(__in const TCHAR *pTableName, __in const TCHAR *pSql, __out int &nFieldCount, __out CArray<CStringArray,CStringArray>& strArray)
{
	int nRecordCount = 0;			
	_variant_t vtFieldValue;

	bool bResult = false;
	EnterCriticalSection( &m_csAdo );
	bResult = GetADODateBaseStatus();
	if( false == bResult )
	{
		LeaveCriticalSection( &m_csAdo );
		return -1;
	}

	CADORecordset* pRSet = new CADORecordset(m_pADODatabase);
	LeaveCriticalSection( &m_csAdo );
	if( NULL == pRSet )
	{
		//LOG4C((LOG_NOTICE, "GetFieldValueList1 pRSet == NULL"));
		return -1;
	}

	bResult = OpenADORecordSet(pRSet, pSql);
	if( false == bResult )
	{
		DeleteADORecordSet(pRSet);
		return -1;
	}

	nRecordCount = pRSet->GetRecordCount();
	nFieldCount = pRSet->GetFieldCount();

	strArray.SetSize(nRecordCount,1);
	for( int i = 0; i < nRecordCount; i++ )
	{
		for ( int n = 0; n < nFieldCount; n++)
		{
			if( !pRSet->IsFieldNull(n) )
			{
				pRSet->GetFieldValue(n, vtFieldValue);
				TString strFieldValue = TString((TCHAR*)(_bstr_t)vtFieldValue);
				strArray.ElementAt(i).Add(strFieldValue.c_str());
			}
			else
			{
				strArray.ElementAt(i).Add(_T(""));
			}
		}
		pRSet->MoveNext();
	}

	DeleteADORecordSet(pRSet);
	return nRecordCount;
}

/////////////////////////////////////////////////////////////////////////////////////
/*
������:	GetFieldValueList
˵��:	��ȡ�����¼
����:	
	__in vector<CDataBase*>& vtValues		�����ӵ����ݼ�
����:	��������,ʧ��=-1
*/
/////////////////////////////////////////////////////////////////////////////////////
int AdoImpl::InsertIntoTable(__in vector<CDataBase*>& vtValues)
{
	CString strInsert = _T("");
	vector<CDataBase*>::iterator it = vtValues.begin();
	for ( ; it != vtValues.end(); it++ )
	{
		CDataBase* p = (*it);
		if(p != NULL)
		{
			TCHAR tszInsert[4096] = {0};
			p->GetInsertSql(tszInsert);
			if ( !Execute(tszInsert) )
			{
				// ִ��SQL���ʧ��;
				continue;
			}
		}
	}
	return 1;
}