// ADO.cpp: implementation of the CMirAdo class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MirAdo.h"

#ifdef _DEBUG
#undef THIS_FILE
static TCHAR THIS_FILE[]=_T(__FILE__);
#define new DEBUG_NEW
#endif

///////////////////////////////////////////////////////////////////////////////////
// < DataBase Connect String >
// 
// ORACLE : "Provider=OraOLEDB.Oracle;Data Source=truepos;User ID=true;Password=true;"
// MS-SQL : "Provider=sqloledb;DSN=iret;User Id=sa;Password=;"
// MS-SQL : "Provider=sqloledb;Data Source=155.230.29.10;User Id=sa;Password=pass;"
// Access : "Provider=MSDASQL;DSN=iretpos;UID=;PWD=;"
//
///////////////////////////////////////////////////////////////////////////////////





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

CMirAdo::CMirAdo()
{
	InitMirAdo();
}

CMirAdo::~CMirAdo()
{
	//CloseMirAdo();
}

BOOL CMirAdo::InitMirAdo()
{
    m_pConnect		=	NULL;
    m_pCommand		=	NULL;
	m_pRecordSet	=	NULL;

	ClearError();

	// initialize COM configuration
	::CoInitialize(NULL);

	return		TRUE;
}

// connect recordset?
BOOL CMirAdo::IsRSOpen()
{
	if(m_pRecordSet)
		return ( ( m_pRecordSet->GetState() != 0 ) ? TRUE : FALSE );
	else
		return		FALSE;
}

// connect database?
BOOL CMirAdo::IsOpen()
{
	return ( ( m_pConnect->GetState() != 0 ) ? TRUE : FALSE );
}

BOOL CMirAdo::IsDBOpen()
{
	return	IsOpen();
}

BOOL CMirAdo::DBConnectOLE(TCHAR *pSource)
{
	TCHAR	strConnect[256];
	memset( strConnect, 0, sizeof(strConnect) );	

	lstrcpy( strConnect, _T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=") );
	lstrcat( strConnect, pSource );

	return	DBConnectProc(strConnect);
}

BOOL CMirAdo::DBConnectMDB(TCHAR* pDSN, TCHAR* pUID, TCHAR* pPWD)
{
//	InitMirAdo();

	TCHAR	strConnect[256];
	memset( strConnect, 0, sizeof(strConnect) );	

	lstrcpy( strConnect, _T("Provider=MSDASQL;DSN=") );
	lstrcat( strConnect, pDSN );
	lstrcat( strConnect, _T(";UID=") );
	lstrcat( strConnect, pUID );
	lstrcat( strConnect, _T(";PWD=") );
	lstrcat( strConnect, pPWD );

	return	DBConnectProc(strConnect);
}

BOOL CMirAdo::DBConnectSQL(TCHAR* connectSTR)
{
	InitMirAdo();

	return	DBConnectProc(connectSTR);
}

BOOL CMirAdo::DBConnectProc(_bstr_t strConnect)
{
	HRESULT         hr = S_OK;

	hr = ::CoInitialize( NULL );

	if( !FAILED( hr ) )
	hr = m_pConnect.CreateInstance( __uuidof( Connection ) );

	// The exception handling below assumes a valid Connection object,
	// so drop out if we couldn't create one for any reason.
	if ( FAILED(hr) )
	return false;

	try
	{
		//m_pConnect->Open(strConnect, _bstr_t(L""), _bstr_t(L""), adConnectUnspecified);
		m_pConnect->Open(strConnect, _bstr_t(L""), _bstr_t(L""), adConnectUnspecified);

		INSTHR(m_pCommand.CreateInstance(__uuidof(Command)));
		m_pCommand->PutRefActiveConnection(m_pConnect);	

		INSTHR(m_pRecordSet.CreateInstance(__uuidof(Recordset)));
		m_pRecordSet->PutRefActiveConnection( m_pConnect );	
	}
    catch (_com_error &e)
    {
        AlertProviderError();
        AlertComError(e);
		TRACE( _T("\tCode meaning = %s\n"), e.ErrorMessage());
		return false;
    }
	return true;
}

long CMirAdo::BeginTrans()
{
	return m_pConnect->BeginTrans();
}

void CMirAdo::CommitTrans()
{
	m_pConnect->CommitTrans();
}

void CMirAdo::RollbackTrans()
{
	m_pConnect->RollbackTrans();
}

void CMirAdo::ConCancel()
{
	m_pConnect->Cancel();
}

BOOL CMirAdo::MoveFirst()
{
	// top record set
	return ( FAILED(m_pRecordSet->MoveFirst()) ? FALSE : TRUE ) ; 	
}

BOOL CMirAdo::MoveNext()
{
	return ( FAILED(m_pRecordSet->MoveNext()) ? FALSE : TRUE ) ; 	
}

BOOL CMirAdo::MovePrev()  
{ 
	return ( FAILED(m_pRecordSet->MovePrevious() ) ? FALSE : TRUE ); 
}

BOOL CMirAdo::MoveLast()  
{ 
	return ( FAILED(m_pRecordSet->MoveLast() ) ? FALSE : TRUE ) ; 
}

BOOL CMirAdo::IsEOF()
{
	// DB Conversion 시작
	if (m_pRecordSet->GetState() == 0)
		return 1;
	else
	return m_pRecordSet->ADOEOF;
	// DB Conversion 끝
	//return m_pRecordSet->ADOEOF;
}

int CMirAdo::GetRecordCount()
{	
	return (int)m_pRecordSet->GetRecordCount();
}

int CMirAdo::GetFieldCount()
{
	return (int)m_pRecordSet->Fields->GetCount();	
}

BOOL CMirAdo::Open(_bstr_t strSql, long lnOption)
{
	ClearError();
	try	
	{
		Close();

		m_pRecordSet->Open( strSql, m_pConnect.GetInterfacePtr(), 
					adOpenKeyset, adLockReadOnly, adCmdText );

		return true;
	}
	catch (_com_error &e)
	{
		AlertProviderError();
		AlertComError(e);

		return false;
	}
}

BOOL CMirAdo::Open(LPCTSTR strSql, long lnOption)
{
	ClearError();
	try	
	{
		Close();

		m_pRecordSet->Open( (LPCTSTR)strSql, m_pConnect.GetInterfacePtr(), 
					adOpenKeyset, adLockReadOnly, adCmdText );

		return true;
	}
	catch (_com_error &e)
	{
		AlertProviderError();
		AlertComError(e);

		return false;
	}
}

BOOL CMirAdo::RSClose()
{
	try
	{
//		if(IsRSOpen())
		if(m_pRecordSet->GetState())
		{
			m_pRecordSet->Close();
		}
		return true;
	}
	catch(_com_error& e)
	{
		AlertProviderError();
		AlertComError(e);
		return false;
	}
}

void CMirAdo::Close()
{
	RSClose();
}

void CMirAdo::CloseMirAdo()
{
	if(IsRSOpen()) m_pRecordSet->Close();
	if(IsDBOpen()) m_pConnect->Close();

	if(m_pRecordSet) {
		m_pRecordSet.Release();
		m_pRecordSet = NULL;
	}
    if(m_pCommand) {
		m_pCommand.Release();
		m_pCommand = NULL;
	}
    if(m_pConnect) {
		m_pConnect.Release();
		m_pConnect = NULL;
	}

	::CoUninitialize();	// close COM
}

BOOL CMirAdo::ReQuery()
{
	return ( FAILED(m_pRecordSet->Requery(adCmdUnknown) ) ? FALSE : TRUE ); 
}

BOOL CMirAdo::Execute(_bstr_t strSql, long lnOption)
{
	ClearError();

	for(int i=0; i<10; i++)
	{
		try	{
			Close();
			// 20060912 0251 db처리가 동시에 일어나서 RESPONSE가 늦어질 경우를 대비해
			// m_pCommand->CommandTimeout을 5분으로 조정 BY CBJ
			m_pCommand->CommandTimeout = 300;
			m_pCommand->CommandText = (LPCTSTR)strSql;
			m_pRecordSet = m_pCommand->Execute(NULL, NULL, adCmdText);

			return true;
		}
		catch (_com_error &e)
		{
			AlertProviderError();
			AlertComError(e);

			if(m_ErrorCode.Compare(ADO_SQL_OPEN_FAILURE) == 0) {
				TRACE(e.ErrorMessage());
				Sleep(100);
				continue;
			}
			else
				break;
		}
	}
	return false;
}

BOOL CMirAdo::Execute(LPCTSTR strSql, long lnOption)
{
	ClearError();

	for(int i=0; i<10; i++)
	{
		try	{
			Close();

			m_pCommand->CommandText = (LPCTSTR)strSql;
			m_pRecordSet = m_pCommand->Execute(NULL, NULL, adCmdText);

			return true;
		}
		catch (_com_error &e)
		{
			AlertProviderError();
			AlertComError(e);

			if(m_ErrorCode.Compare(ADO_SQL_OPEN_FAILURE) == 0) {
				//WriteFileLog((LPCTSTR)strSql);
				Sleep(100);
				continue;
			}
			else
				break;
		}
	}
	return false;
}

int CMirAdo::ExecuteUpDel(CString strSql, long lnOption)
{
	ClearError();

	for(int i=0; i<10; i++)
	{
		try	{
			Close();

			m_pCommand->CommandText = (LPCTSTR)strSql;
			m_pRecordSet = m_pCommand->Execute(NULL, NULL, adCmdText);

			return m_pRecordSet->RecordCount;
		}
		catch (_com_error &e)
		{
			AlertProviderError();
			AlertComError(e);

			if(m_ErrorCode.Compare(ADO_SQL_OPEN_FAILURE) == 0) {
				//WriteFileLog((LPCTSTR)strSql);
				Sleep(100);
				continue;
			}
			else
				break;
		}
	}
	return false;
}
void CMirAdo::GetValue( short shFieldNo, CString& ret )
{
	_variant_t	vValue;
	vValue = m_pRecordSet->Fields->GetItem(_variant_t(shFieldNo))->Value;
	if(vValue.vt == VT_NULL)
		ret = _T("");
	else {
		vValue.ChangeType(VT_BSTR);
		ret = vValue.bstrVal;
	}
}

void CMirAdo::GetValue( short shFieldNo, _variant_t& ret )
{
	ret = m_pRecordSet->Fields->GetItem(_variant_t(shFieldNo))->Value;
}

void CMirAdo::GetValue( short shFieldNo, _bstr_t& ret )
{
	_variant_t vValue;
	vValue = m_pRecordSet->Fields->GetItem(_variant_t(shFieldNo))->Value;
	if(vValue.vt == VT_NULL)
		ret = _T("");
	else {
		vValue.ChangeType(VT_BSTR);
		ret = vValue.bstrVal;
	}
}

void CMirAdo::GetValue( short shFieldNo, TCHAR* ret )
{
	_variant_t vValue;
	vValue = m_pRecordSet->Fields->GetItem(_variant_t(shFieldNo))->Value;
	if(vValue.vt == VT_NULL)
		lstrcpy(ret, _T(""));
	else {
		vValue.ChangeType(VT_BSTR);

		_bstr_t temp = vValue.bstrVal;
		lstrcpy(ret, (TCHAR *)temp);
	}
}

void CMirAdo::GetValue( short shFieldNo, TCHAR& ret )
{
	_variant_t vValue;
	vValue = m_pRecordSet->Fields->GetItem(_variant_t(shFieldNo))->Value;
	if(vValue.vt == VT_NULL)
		ret = 0x00;
	else {
		vValue.ChangeType(VT_BSTR);
		ret = ((LPCTSTR)vValue.bstrVal)[0];
	}
}

void CMirAdo::GetValue( short shFieldNo, double& ret )
{
/*
	_variant_t	vValue;
	vValue = m_pRecordSet->Fields->GetItem(_variant_t(shFieldNo))->Value;
	if(vValue.vt == VT_NULL)
		ret = 0;
	else if(vValue.vt == VT_DECIMAL) {
		vValue.ChangeType(VT_DECIMAL);
		ret = vValue.lVal;
	}
	else if(vValue.vt == VT_R8)	{
		vValue.ChangeType(VT_R8);
		ret = vValue.dblVal;
	}
*/
	ret = m_pRecordSet->Fields->GetItem(_variant_t(shFieldNo))->Value;
}

void CMirAdo::GetValue( short shFieldNo, float& ret )
{
	ret = m_pRecordSet->Fields->GetItem(_variant_t(shFieldNo))->Value;
}

void CMirAdo::GetValue( short shFieldNo, long& ret )
{
	_variant_t	vValue;
	vValue = m_pRecordSet->Fields->GetItem(_variant_t(shFieldNo))->Value;
	if(vValue.vt == VT_NULL)
		ret = 0;
	else {
		vValue.ChangeType(VT_DECIMAL);
		ret = vValue.lVal;
	}
}

void CMirAdo::GetValue( short shFieldNo, int& ret )
{
	_variant_t	vValue;
	vValue = m_pRecordSet->Fields->GetItem(_variant_t(shFieldNo))->Value;
	if(vValue.vt == VT_NULL)
		ret = 0;
	else {
		vValue.ChangeType(VT_INT);
		ret = vValue.intVal;
	}
}

void CMirAdo::AlertProviderError()
{
    // Print Provider Errors from Connection object.
    // pErr is a record object in the Connection's Error collection.
    ErrorPtr  pErr = NULL;

    long nCount = m_pConnect->Errors->Count;

    if( nCount > 0)
    {
        // Collection ranges from 0 to nCount -1.
        for(long i = 0; i < nCount; i++)
        {
            pErr = m_pConnect->Errors->GetItem(0L);

			CString strMessage;
			this->m_ErrorMessgae.Format(_T("%x:%s[%s]"), pErr->Number, (TCHAR *)pErr->Description, (TCHAR *)pErr->GetSQLState());
			if(pErr->GetSQLState().length() > 0)
				this->m_ErrorCode.Format(_T("%s"), (TCHAR *)pErr->GetSQLState());

//			AfxMessageBox(m_ErrorMessgae);
        }
		m_pConnect->Errors->Clear();
    }
}

void CMirAdo::AlertComError(_com_error &e)
{
	CString strMessage;
	strMessage.Format(_T("%08lx:%s\n"), e.Error(), (TCHAR *)e.ErrorMessage());
}

void CMirAdo::ClearError()
{
	this->m_ErrorCode.Empty();
	this->m_ErrorMessgae.Empty();
}


CString	CMirAdo::GetErrorMessage()
{
	return this->m_ErrorMessgae;
}

CString CMirAdo::GetErrorCode()
{
	return this->m_ErrorCode;
}


