Click here to Skip to main content
15,886,581 members
Articles / Database Development / SQL Server

High Performance OLE DB library : Ease of ADO, power of OLE DB

Rate me:
Please Sign up or sign in to vote.
2.50/5 (6 votes)
2 Dec 20013 min read 83.3K   3.4K   41  
Introduction to OLE DB extended classes
// SypODLObjects.cpp: implementation of the CSypODLObject classes.
//
//////////////////////////////////////////////////////////////////////
//
// CSypODLObjects are the set of classes that provide a very rich, 
// sophisticated, and user-friendly wrappers around ATL consumer 
// templates for OLEDB. These classes provide a lot of flexibility and
// functionality over OLEDB templates without loosing their power and  
// performance
//
// Author: G. Naik, GNaik@SypramTech.com (or Ghannaik@yahoo.com)
// You may freely use these classes in non-commercial products.These
// library is not to be sold for profit. 
//
// NOTE : Prior permission required by Sypram Technology (www.sypram.com)
// if you want to use this library in commercial projects. Send me an email
// if that is the case.
// 
// CopyRight(C)2001. Sypram Technology. WWW.SYPRAM.COM
// Version : 1.0
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#define INITGUID
#include <initguid.h>

#include "SypODLObjects.h"
#include <assert.h>
#include "resource.h"
#include <Math.h>

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

#define SYPMSG_MAX_MSG_SIZE 2048


//********************************************************************************
/////////////////////  CSypODLException Object ////////////////////////////////
//********************************************************************************

CSypODLException::CSypODLException(UINT m_cause, HRESULT hr, CComPtr<IUnknown> m_spUnk)
{
	m_nCause = m_cause;
	m_nHr = hr;
	m_pUnknown = m_spUnk;
}

//********************************************************************************

void CSypODLException::GetError(CString& RetStr)
{
	CSypOLEDBErr mErr;
	TCHAR mError[2048], mErrNum[10];

	memset(mError, 0, sizeof(TCHAR) * 2048);

	if(m_nHr != 0)
	{
		mErr.GetHRRESULTMessage(m_nHr, mError);

		if(_tcsstr(mError, _T("No such interface supported")) != NULL \
			|| _tcsstr(mError, _T("Unspecified error")) != NULL  \
			|| _tcsstr(mError, _T("Errors occurred")) != NULL)
		{
			mError[0] = 0;

			if(!m_pUnknown)
				mErr.GetSingleError(mError);
			else
				if(mErr.AreDBErrorsSupported(m_pUnknown))
					mErr.GetDBErrors((CComPtr<struct IUnknown>)m_pUnknown, mError);	
		}
	}
	
	CString str;
	
	if(!str.LoadString(m_nCause))
		str = _T("(Unable to load error string)");

	lstrcat(mError, _T("\n"));
	lstrcat(mError, str); 

	_itot(m_nCause, mErrNum, 10);

	RetStr = CString("Errorcode : ") + CString(mErrNum) + CString("\n");
	RetStr += mError;
}

//********************************************************************************

void CSypODLException::DisplayError()
{
	CString str;

	GetError(str);
	::MessageBox(NULL, str, _T("Error"), MB_OK + MB_ICONSTOP);
}

//********************************************************************************
/////////////////////  CSypOLEDBConnection Object ////////////////////////////////
//********************************************************************************

CSypODLConnection::CSypODLConnection()
{
	m_Provider = "MSDASQL";
	m_bEnableThrow = true;
	m_bIsOpen = false;
}

//********************************************************************************

CSypODLConnection::~CSypODLConnection()
{
	Close();
}

//********************************************************************************

bool CSypODLConnection::IsOpen()
{
	return m_bIsOpen;
}

//********************************************************************************

void CSypODLConnection::SetProvider(CString mProv)
{
	assert(!mProv.IsEmpty());
	m_Provider = mProv;
}

//********************************************************************************

bool CSypODLConnection::Open(CString m_DSN, CString m_UID, CString m_PWD)
{
	if(m_bIsOpen)
		Close();
	
	CDBPropSet	dbinit(DBPROPSET_DBINIT);

	dbinit.AddProperty(DBPROP_AUTH_PASSWORD, m_PWD);
	dbinit.AddProperty(DBPROP_AUTH_USERID, m_UID);
	dbinit.AddProperty(DBPROP_INIT_DATASOURCE, m_DSN);
	dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)4);
	dbinit.AddProperty(DBPROP_INIT_LCID, (long)1033);

	hr = m_db.OpenWithServiceComponents(m_Provider, &dbinit);
	if (FAILED(hr))
	{
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_CONTOPENDB, hr);
		return false;
	}

	hr = m_session.Open(m_db);
	if (FAILED(hr))
	{
		m_db.Close();
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_CONTOPENSESSION, hr);
		return false;
	}

	m_bIsOpen = true;
	return true;
}

//********************************************************************************

bool CSypODLConnection::Open(CDBPropSet dbinit)
{
	if(m_bIsOpen)
		Close();

	hr = m_db.OpenWithServiceComponents(m_Provider, &dbinit);
	if (FAILED(hr))
	{
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_CONTOPENDB, hr);
		return false;
	}

	hr = m_session.Open(m_db);
	if (FAILED(hr))
	{
		m_db.Close();
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_CONTOPENSESSION, hr);
		return false;
	}

	m_bIsOpen = true;
	return true;
}

//********************************************************************************

void CSypODLConnection::Close()
{
	if(m_bIsOpen)
	{
		m_bIsOpen = false;
		m_session.Close();
		m_db.Close();
	}
}

//********************************************************************************

bool CSypODLConnection::StartTransaction(ISOLEVEL isoLevel /*=ISOLATIONLEVEL_READCOMMITTED*/, \
										 ULONG isoFlags /*=0*/)
{
	if(!m_bIsOpen)
	{
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_DBNOTOPEN, NULL);
		return false;
	}

	hr = m_session.StartTransaction(isoLevel, isoFlags);
	if(FAILED(hr))
	{
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_STARTTRANSFAILED, hr);
		return false;
	}

	return true;
}

//********************************************************************************

bool CSypODLConnection::Abort(BOID	*pboidReason)
{
	if(!m_bIsOpen)
	{
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_DBNOTOPEN, NULL);
		return false;
	}

	hr = m_session.Abort(pboidReason);
	if(FAILED(hr))
	{
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_ABORTTRANSFAILED, hr);
		return false;
	}

	return true;
}

//********************************************************************************

bool CSypODLConnection::Commit(BOOL bRetaining /*=FALSE*/, DWORD grfTC/*=XACTTC_SYNC*/, \
							   DWORD grfRM/*=0*/)
{
	if(!m_bIsOpen)
	{
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_DBNOTOPEN, NULL);
		return false;
	}

	hr = m_session.Commit(bRetaining, grfTC, grfRM);
	if(FAILED(hr))
	{
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_COMMITTRANSFAILED, hr);
		return false;
	}

	return true;
}

//********************************************************************************

bool CSypODLConnection::Execute(CString sSQL)
{
	if(!m_bIsOpen)
	{
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_DBNOTOPEN, NULL);
		return false;
	}

	CCommand<CNoAccessor, CNoRowset>	mRs;

	hr = mRs.Open(m_session, sSQL);
	if(FAILED(hr))
	{
		if(m_bEnableThrow)
			throw CSypODLException(IDS_SYPODL_ERR_EXECUTEFAILED, hr);
		return false;
	}

	mRs.Close();

	return true;
}


//********************************************************************************
/////////////////////  CSypOLEDBErr Object ///////////////////////////////////////
//********************************************************************************

bool CSypOLEDBErr::AreDBErrorsSupported(CComPtr<IUnknown> m_spUnk)
{
	CComPtr<ISupportErrorInfo> spSupportErrorInfo;

	if (SUCCEEDED(m_spUnk->QueryInterface(IID_ISupportErrorInfo,(void **) &spSupportErrorInfo))) 
	{
		if (SUCCEEDED(spSupportErrorInfo->InterfaceSupportsErrorInfo(IID_ICommandPrepare)))
			return true;
	}
	return true;
}

//*******************************************************************************

bool CSypOLEDBErr::GetDBErrors(CComPtr<IUnknown> m_spUnk, TCHAR  *msg)
{
	CDBErrorInfo errInfo;
	IErrorInfo *pErrorInfo = NULL;
	BSTR pErrorDescription = NULL;
	ULONG ulRecords = 0;

	try
	{
		HRESULT hr = errInfo.GetErrorRecords(m_spUnk, IID_ICommandPrepare, &ulRecords);
		if (FAILED(hr) || hr == S_FALSE || ulRecords == 0) 
		{
			//The error info object could not be retrieved
			_tcscat(msg, _T("\n\nUnable to retrieve error details."));
		}
		else 
		{
			// Error info object was retrieved successfully
			LCID lcid = GetUserDefaultLCID();
			for (ULONG loop = 0; loop < ulRecords; loop ++) 
			{
				// Get the error information from the source
				hr = errInfo.GetErrorInfo(loop, lcid, &pErrorInfo);
				if (FAILED(hr)) 
				{
					continue;
				}
				//Get the error description
				pErrorInfo->GetDescription(&pErrorDescription);
				//Convert error description to single-width character
				_stprintf(msg, _T("%s\n\n%S"), msg, pErrorDescription);
				//Get SQLState and Error Code
				GetSQLCodes(msg, &errInfo, loop);
				//Clean up
				SysFreeString(pErrorDescription);
				pErrorInfo->Release();
			}
		}
	}
	catch(...)
	{
		_tcscat(msg, _T("Internal error occurred. (GetDBErrors)"));		
		return false;
	}

	return true;
}

//*********************************************************************************

bool CSypOLEDBErr::GetSingleError(TCHAR    *msg) 
{
	IErrorInfo *pErrorInfo = NULL;
	BSTR pErrorDescription = NULL;

	try
	{
		if (SUCCEEDED(GetErrorInfo(0, &pErrorInfo))) 
		{
			if (SUCCEEDED(pErrorInfo->GetDescription(&pErrorDescription))) 
			{
				_stprintf(msg, _T("%s\n\n%S"), msg, pErrorDescription);

				SysFreeString(pErrorDescription);
			}
			else 
				_tcscat(msg, _T("Could not find the error description"));

			pErrorInfo->Release();
		}
		else 
			_tcscat(msg, _T("Could not retrieve error information"));
	}
	catch(...)
	{
		_tcscat(msg, _T("Internal error occurred. (GetSingleError)"));		
		return false;
	}

	return true;
}

//*********************************************************************************

bool CSypOLEDBErr::GetSQLCodes(TCHAR    *msg, CDBErrorInfo *errInfo, ULONG errorNum)
{
	CComPtr<ISQLErrorInfo> spSQLErrorInfo;
	TCHAR  SQLState[100];	//Buffer for error message

	try
	{
		if (SUCCEEDED(errInfo->GetCustomErrorObject(errorNum, 
					IID_ISQLErrorInfo, (IUnknown**) &spSQLErrorInfo))) 
		{
			BSTR bstrSQLState = NULL;	//SQLState that's returned
			LONG errorCode;		//SQL Code that's returned

			if (SUCCEEDED(spSQLErrorInfo->GetSQLInfo(&bstrSQLState, &errorCode))) 
			{
				_stprintf(SQLState, _T("\n\nSQLState is %S\nError code is %ld"),	bstrSQLState, errorCode);
				
				_tcscat(msg, SQLState);
				SysFreeString(bstrSQLState);	//Clean up
			}
			else 
				_tcscat(msg, _T("\n\nCould not get SQL details."));
		}
		else 
			_tcscat(msg, _T("\n\nCould not get error or SQLState code."));
	}
	catch(...)
	{
		_tcscat(msg, _T("Internal error occurred. (GetSQLCodes)"));		
		return false;
	}

	return true;
}

//*********************************************************************************

void CSypOLEDBErr::GetHRRESULTMessage(HRESULT hr, TCHAR    *msg)
{

	LPVOID 	lpMsgBuf;
	HMODULE	hModule = LoadLibrary(_T("C:\\Program Files\\Common Files\\System\\ole db\\MSDAERR.DLL"));

	if(hModule)
	{
		long l = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE |
			FORMAT_MESSAGE_FROM_SYSTEM, hModule, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			(LPTSTR) &lpMsgBuf, 0, NULL);

		lstrcpy(msg, (LPTSTR)lpMsgBuf);

		// Free the buffer.
		LocalFree( lpMsgBuf );

		FreeLibrary(hModule);

		return;
	}

	_stprintf(msg, _T("%s\nERROR :"), msg, hr);
	switch (hr) 
	{
	case DB_E_ABORTLIMITREACHED :
		_tcscat(msg, _T("\nYour execution was aborted because a resource limit has been reached. No results are returned when this error occurs."));
		break;
	case DB_E_ALREADYINITIALIZED :
		_tcscat(msg, _T("\nYou tried to initialize a data source that has already been initialized."));
		break;
	case DB_E_BADACCESSORFLAGS :
		_tcscat(msg, _T("\nInvalid accessor flags"));
		break;
	case DB_E_BADACCESSORHANDLE :
		_tcscat(msg, _T("\nInvalid accessor handle"));
		break;
	case DB_E_BADACCESSORTYPE :
		_tcscat(msg, _T("\nThe specified accessor was not a parameter accessor"));
		break;
	case DB_E_BADBINDINFO :
		_tcscat(msg, _T("\nInvalid binding information"));
		break;
	case DB_E_BADBOOKMARK :
		_tcscat(msg, _T("\nInvalid bookmark"));
		break;
	case DB_E_BADCHAPTER :
		_tcscat(msg, _T("\nInvalid chapter"));
		break;
	case DB_E_BADCOLUMNID :
		_tcscat(msg, _T("\nInvalid column ID"));
		break;
	case DB_E_BADCOMPAREOP :
		_tcscat(msg, _T("\nThe comparison operator was invalid"));
		break;
	case DB_E_BADCONVERTFLAG :
		_tcscat(msg, _T("\nInvalid conversion flag"));
		break;
	case DB_E_BADCOPY :
		_tcscat(msg, _T("\nErrors were detected during a copy"));
		break;
	case DB_E_BADDYNAMICERRORID :
		_tcscat(msg, _T("\nThe supplied DynamicErrorID was invalid"));
		break;
	case DB_E_BADHRESULT :
		_tcscat(msg, _T("\nThe supplied HRESULT was invalid"));
		break;
	case DB_E_BADLOCKMODE :
		_tcscat(msg, _T("\nInvalid lock mode"));
		break;
	case DB_E_BADLOOKUPID :
		_tcscat(msg, _T("\nInvalid LookupID"));
		break;
	case DB_E_BADORDINAL :
		_tcscat(msg, _T("\nThe specified column number does not exist."));
		break;
	case DB_E_BADPARAMETERNAME :
		_tcscat(msg, _T("\nThe given parameter name is not recognized."));
		break;
	case DB_E_BADPRECISION :
		_tcscat(msg, _T("\nA specified precision is invalid"));
		break;
	case DB_E_BADPROPERTYVALUE :
		_tcscat(msg, _T("\nThe value of a property is invalid"));
		break;
	case DB_E_BADRATIO :
		_tcscat(msg, _T("\nInvalid ratio"));
		break;
	case DB_E_BADRECORDNUM :
		_tcscat(msg, _T("\nThe specified record number is invalid"));
		break;
	case DB_E_BADROWHANDLE :
		_tcscat(msg, _T("\nInvalid row handle.  This error often occurs when you are at BOF or EOF of a rowset and you try to update your data set."));
		break;
	case DB_E_BADSCALE :
		_tcscat(msg, _T("\nA specified scale was invalid"));
		break;
	case DB_E_BADSOURCEHANDLE :
		_tcscat(msg, _T("\nInvalid source handle"));
		break;
	case DB_E_BADSTARTPOSITION :
		_tcscat(msg, _T("\nThe rows offset specified would position you before the beginning or past the end of the rowset."));
		break;
	case DB_E_BADSTATUSVALUE :
		_tcscat(msg, _T("\nThe specified status flag was neither DBCOLUMNSTATUS_OK nor DBCOLUMNSTATUS_ISNULL"));
		break;
	case DB_E_BADSTORAGEFLAG :
		_tcscat(msg, _T("\nOne of the specified storage flags was not supported"));
		break;
	case DB_E_BADSTORAGEFLAGS :
		_tcscat(msg, _T("\nInvalid storage flags"));
		break;
	case DB_E_BADTABLEID :
		_tcscat(msg, _T("\nInvalid table ID"));
		break;
	case DB_E_BADTYPE :
		_tcscat(msg, _T("\nA specified type was invalid"));
		break;
	case DB_E_BADTYPENAME :
		_tcscat(msg, _T("\nThe given type name was unrecognized"));
		break;
	case DB_E_BADVALUES :
		_tcscat(msg, _T("\nInvalid value"));
		break;
	case DB_E_BOOKMARKSKIPPED :
		_tcscat(msg, _T("\nAlthough the bookmark was validly formed, no row could be found to match it"));
		break;
	case DB_E_BYREFACCESSORNOTSUPPORTED :
		_tcscat(msg, _T("\nBy reference accessors are not supported by this provider"));
		break;
	case DB_E_CANCELED :
		_tcscat(msg, _T("\nThe change was canceled during notification; no columns are changed"));
		break;
	case DB_E_CANNOTRESTART :
		_tcscat(msg, _T("\nThe rowset was built over a live data feed and cannot be restarted."));
		break;
	case DB_E_CANTCANCEL :
		_tcscat(msg, _T("\nThe executing command cannot be canceled."));
		break;
	case DB_E_CANTCONVERTVALUE :
		_tcscat(msg, _T("\nA literal value in the command could not be converted to the correct type due to a reason other than data overflow."));
		break;
	case DB_E_CANTFETCHBACKWARDS :
		_tcscat(msg, _T("\nThe rowset does not support backward scrolling."));
		break;
	case DB_E_CANTFILTER :
		_tcscat(msg, _T("\nThe requested filter could not be opened."));
		break;
	case DB_E_CANTORDER :
		_tcscat(msg, _T("\nThe requested order could not be opened."));
		break;
	case DB_E_CANTSCROLLBACKWARDS :
		_tcscat(msg, _T("\nThe rowset cannot scroll backwards."));
		break;
	case DB_E_CANTTRANSLATE :
		_tcscat(msg, _T("\nCannot represent the current tree as text."));
		break;
	case DB_E_CHAPTERNOTRELEASED :
		_tcscat(msg, _T("\nThe rowset was single-chaptered and the chapter was not released when a new chapter formation is attempted."));
		break;
	case DB_E_CONCURRENCYVIOLATION :
		_tcscat(msg, _T("\nThe rowset was using optimistic concurrency and the value of a column has been changed since it was last read."));
		break;
	case DB_E_DATAOVERFLOW :
		_tcscat(msg, _T("\nA literal value in the command overflowed the range of the type of the associated column"));
		break;
	case DB_E_DELETEDROW :
		_tcscat(msg, _T("\nThe row that is referred to has been deleted."));
		break;
	case DB_E_DIALECTNOTSUPPORTED :
		_tcscat(msg, _T("\nThe provider does not support the specified dialect"));
		break;
	case DB_E_DUPLICATECOLUMNID :
		_tcscat(msg, _T("\nA column ID was occurred more than once in the specification"));
		break;
	case DB_E_DUPLICATEDATASOURCE :
		_tcscat(msg, _T("\nA new data source is trying to be formed when a data source with that specified name already exists."));
		break;
	case DB_E_DUPLICATEINDEXID :
		_tcscat(msg, _T("\nThe specified index already exists."));
		break;
	case DB_E_DUPLICATETABLEID :
		_tcscat(msg, _T("\nThe specified table already exists."));
		break;
	case DB_E_ERRORSINCOMMAND :
		_tcscat(msg, _T("\nThe command contained one or more errors."));
		break;
	case DB_E_ERRORSOCCURRED :
		_tcscat(msg, _T("\nErrors occurred.  This message is thrown when an error occurs that is not captured by one of the other error messages."));
		break;
	case DB_E_INDEXINUSE :
		_tcscat(msg, _T("\nThe specified index was in use."));
		break;
	case DB_E_INTEGRITYVIOLATION :
		_tcscat(msg, _T("\nA specified value violated the referential integrity constraints for a column or table."));
		break;
	case DB_E_INVALID :
		_tcscat(msg, _T("\nThe rowset is invalide."));
		break;
	case DB_E_MAXPENDCHANGESEXCEEDED :
		_tcscat(msg, _T("\nThe number of rows with pending changes has exceeded the set limit."));
		break;
	case DB_E_MULTIPLESTATEMENTS :
		_tcscat(msg, _T("\nThe provider does not support multi-statement commands."));
		break;
	case DB_E_MULTIPLESTORAGE :
		_tcscat(msg, _T("\nMultiple storage objects can not be open simultaneously."));
		break;
	case DB_E_NEWLYINSERTED :
		_tcscat(msg, _T("\nThe provider is unable to determine identity for newly inserted rows."));
		break;
	case DB_E_NOAGGREGATION :
		_tcscat(msg, _T("\nA non-NULL controlling IUnknown was specified and the object being created does not support aggregation."));
		break;
	case DB_E_NOCOMMAND :
		_tcscat(msg, _T("\nNo command has been set for the command object."));
		break;
	case DB_E_NOINDEX :
		_tcscat(msg, _T("\nThe specified index does not exist."));
		break;
	case DB_E_NOLOCALE :
		_tcscat(msg, _T("\nThe specified locale ID was not supported."));
		break;
	case DB_E_NOQUERY :
		_tcscat(msg, _T("\nInformation was requested for a query, and the query was not set."));
		break;
	case DB_E_NOTABLE :
		_tcscat(msg, _T("\nThe specified table does not exist."));
		break;
	case DB_E_NOTAREFERENCECOLUMN :
		_tcscat(msg, _T("\nSpecified column does not contain bookmarks or chapters."));
		break;
	case DB_E_NOTFOUND :
		_tcscat(msg, _T("\nNo key matching the described characteristics could be found within the current range."));
		break;
	case DB_E_NOTPREPARED :
		_tcscat(msg, _T("\nThe command was not prepared."));
		break;
	case DB_E_NOTREENTRANT :
		_tcscat(msg, _T("\nProvider called a method from IRowsetNotify in the consumer and the method has not yet returned."));
		break;
	case DB_E_NOTSUPPORTED :
		_tcscat(msg, _T("\nThe provider does not support this method."));
		break;
	case DB_E_NULLACCESSORNOTSUPPORTED :
		_tcscat(msg, _T("\nNull accessors are not supported by this provider."));
		break;
	case DB_E_OBJECTOPEN :
		_tcscat(msg, _T("\nAn object was open."));
		break;
	case DB_E_PARAMNOTOPTIONAL :
		_tcscat(msg, _T("\nNo value given for one or more required parameters."));
		break;
	case DB_E_PARAMUNAVAILABLE :
		_tcscat(msg, _T("\nThe provider cannot derive parameter info and SetParameterInfo has not been called."));
		break;
	case DB_E_PENDINGCHANGES :
		_tcscat(msg, _T("\nThere are pending changes on a row with a reference count of zero."));
		break;
	case DB_E_PENDINGINSERT :
		_tcscat(msg, _T("\nUnable to get visible data for a newly-inserted row that has not yet been updated."));
		break;
	case DB_E_READONLYACCESSOR :
		_tcscat(msg, _T("\nUnable to write with a read-only accessor."));
		break;
	case DB_E_ROWLIMITEXCEEDED :
		_tcscat(msg, _T("\nCreating another row would have exceeded the total number of active rows supported by the rowset."));
		break;
	case DB_E_ROWSETINCOMMAND :
		_tcscat(msg, _T("\nCannot clone a command object whose command tree contains a rowset or rowsets."));
		break;
	case DB_E_ROWSNOTRELEASED :
		_tcscat(msg, _T("\nAll HROWs must be released before new ones can be obtained."));
		break;
	case DB_E_SCHEMAVIOLATION :
		_tcscat(msg, _T("\nGiven values violate the database schema."));
		break;
	case DB_E_TABLEINUSE :
		_tcscat(msg, _T("\nThe specified table was in use."));
		break;
	case DB_E_UNSUPPORTEDCONVERSION :
		_tcscat(msg, _T("\nRequested conversion is not supported."));
		break;
	case DB_E_WRITEONLYACCESSOR :
		_tcscat(msg, _T("\nThe given accessor was write-only."));
		break;
	case DB_S_ASYNCHRONOUS :
		_tcscat(msg, _T("\nThe operation is being processed asynchronously."));
		break;
	case DB_S_BADROWHANDLE :
		_tcscat(msg, _T("\nInvalid row handle. This error often occurs when you are at BOF or EOF of a rowset and you try to update your data set."));
		break;
	case DB_S_BOOKMARKSKIPPED :
		_tcscat(msg, _T("\nSkipped bookmark for deleted or non-member row."));
		break;
	case DB_S_BUFFERFULL :
		_tcscat(msg, _T("\nVariable data buffer full.  Increase system memory, commit open transactions, free more system memory, or declare larger buffers in you database setup."));
		break;
	case DB_S_CANTRELEASE :
		_tcscat(msg, _T("\nServer cannot release or downgrade a lock until the end of the transaction."));
		break;
	case DB_S_COLUMNSCHANGED :
		_tcscat(msg, _T("\nIn order to reposition to the start of the rowset, the provider had to reexecute the query; either the order of the columns changed or columns were added to or removed from the rowset."));
		break;
	case DB_S_COLUMNTYPEMISMATCH :
		_tcscat(msg, _T("\nOne or more column types are incompatible. Conversion errors will occur during copying."));
		break;
	case DB_S_COMMANDREEXECUTED :
		_tcscat(msg, _T("\nThe provider re-executed the command."));
		break;
	case DB_S_DELETEDROW :
		_tcscat(msg, _T("\nA given HROW referred to a hard-deleted row."));
		break;
	case DB_S_DIALECTIGNORED :
		_tcscat(msg, _T("\nInput dialect was ignored and text was returned in different dialect."));
		break;
	case DB_S_ENDOFROWSET :
		_tcscat(msg, _T("\nReached start or end of rowset or chapter."));
		break;
	case DB_S_ERRORSOCCURRED :
		_tcscat(msg, _T("\nErrors occurred. DB_S_ERRORSOCCURRED flag was set."));
		break;
	case DB_S_ERRORSRETURNED :
		_tcscat(msg, _T("\nThe method had some errors; errors have been returned in the error array."));
		break;
	case DB_S_LOCKUPGRADED :
		_tcscat(msg, _T("\nA lock was upgraded from the value specified."));
		break;
	case DB_S_MULTIPLECHANGES :
		_tcscat(msg, _T("\nUpdating this row caused more than one row to be updated in the data source."));
		break;
	case DB_S_NONEXTROWSET :
		_tcscat(msg, _T("\nThere are no more rowsets."));
		break;
	case DB_S_NORESULT :
		_tcscat(msg, _T("\nThere are no more results."));
		break;
	case DB_S_PARAMUNAVAILABLE :
		_tcscat(msg, _T("\nA specified parameter was invalid."));
		break;
	case DB_S_PROPERTIESCHANGED :
		_tcscat(msg, _T("\nOne or more properties were changed as allowed by provider."));
		break;
	case DB_S_ROWLIMITEXCEEDED :
		_tcscat(msg, _T("\nFetching requested number of rows would have exceeded total number of active rows supported by the rowset."));
		break;
	case DB_S_STOPLIMITREACHED :
		_tcscat(msg, _T("\nExecution stopped because a resource limit has been reached. Results obtained so far have been returned but execution cannot be resumed."));
		break;
	case DB_S_TYPEINFOOVERRIDDEN :
		_tcscat(msg, _T("\nCaller has overridden parameter type information."));
		break;
	case DB_S_UNWANTEDOPERATION :
		_tcscat(msg, _T("\nConsumer is uninterested in receiving further notification calls for this reason"));
		break;
	case DB_S_UNWANTEDPHASE :
		_tcscat(msg, _T("\nConsumer is uninterested in receiving further notification calls for this phase"));
		break;
	case DB_S_UNWANTEDREASON :
		_tcscat(msg, _T("\nConsumer is uninterested in receiving further notification calls for this reason."));
		break;
	case DB_SEC_E_AUTH_FAILED :
		_tcscat(msg, _T("\nAuthentication failed"));
		break;
	case DB_SEC_E_PERMISSIONDENIED :
		_tcscat(msg, _T("\nPermission denied"));
		break;
	case MD_E_BADCOORDINATE :
		_tcscat(msg, _T("\nBad coordinate for the OLAP dataset."));
		break;
	case MD_E_BADTUPLE :
		_tcscat(msg, _T("\nBad tuple for the OLAP dataset"));
		break;
	case MD_E_INVALIDAXIS :
		_tcscat(msg, _T("\nThe given axis was not valid for this OLAP dataset."));
		break;
	case MD_E_INVALIDCELLRANGE :
		_tcscat(msg, _T("\nOne or more of the given cell ordinals was invalid for this OLAP dataset."));
		break;
#if(OLEDBVER >= 0x0250)	
	//Errors if OLE DB version is greater than 2.5
	case DB_E_BADREGIONHANDLE :
		_tcscat(msg, _T("\nInvalid region handle"));
		break;
	case DB_E_CANNOTFREE :
		_tcscat(msg, _T("\nOwnership of this tree has been given to the provider.  You cannot free the tree."));
		break;
	case DB_E_COSTLIMIT :
		_tcscat(msg, _T("\nUnable to find a query plan within the given cost limit"));
		break;
	case DB_E_GOALREJECTED :
		_tcscat(msg, _T("\nNo nonzero weights specified for any goals supported, so goal was rejected; current goal was not changed."));
		break;
	case DB_E_INVALIDTRANSITION :
		_tcscat(msg, _T("\nA transition from ALL* to MOVE* or EXTEND* was specified."));
		break;
	case DB_E_LIMITREJECTED :
		_tcscat(msg, _T("\nSome cost limits were rejected."));
		break;
	case DB_E_NONCONTIGUOUSRANGE :
		_tcscat(msg, _T("\nThe specified set of rows was not contiguous to or overlapping the rows in the specified watch region."));
		break;
	case DB_S_GOALCHANGED :
		_tcscat(msg, _T("\nSpecified weight was not supported or exceeded the supported limit and was set to 0 or the supported limit."));
		break;
	case DB_S_TOOMANYCHANGES :
		_tcscat(msg, _T("\nThe provider was unable to keep track of all the changes. You must refetch the data associated with the watch region using another method."));
		break;
#endif	//OLEDBVER >= 0x0250
// BLOB ISequentialStream errors
	case STG_E_INVALIDFUNCTION :
		_tcscat(msg, _T("\nYou tried an invalid function."));
		break;
	case S_FALSE :
		_tcscat(msg, _T("\nS_FALSE was returned.  The ISequentialStream data could not be read from the stream object."));
		break;
	case E_PENDING :
		_tcscat(msg, _T("\nAsynchronous Storage only: Part or all of the data to be written is currently unavailable. For more information, see IFillLockBytes and Asynchronous Storage in MSDN."));
		break;
	case STG_E_MEDIUMFULL :
		_tcscat(msg, _T("\nThe write operation was not completed because there is no space left on the storage device."));
		break;
	case STG_E_ACCESSDENIED :
		_tcscat(msg, _T("\nThe caller does not have sufficient permissions for writing this stream object."));
		break;
	case STG_E_CANTSAVE :
		_tcscat(msg, _T("\nData cannot be written for reasons other than lack of access or space."));
		break;
	case STG_E_INVALIDPOINTER :
		_tcscat(msg, _T("\nOne of the pointer values is invalid."));
		break;
	case STG_E_REVERTED :
		_tcscat(msg, _T("\nThe object has been invalidated by a revert operation above it in the transaction tree."));
		break;
	case STG_E_WRITEFAULT :
		_tcscat(msg, _T("\nThe write operation was not completed due to a disk error."));
		break;
	default :
		_tcscat(msg, _T("\nNo such interface supported"));
		break;
	}


} 

//********************************************************************************
/////////////////////  GENERIC FUNCTIONS ////////////////////////////////
//********************************************************************************

DATE DateFromDBTS(DBTIMESTAMP dbts)
{
	DATE dtDest;

	int anMonthDayInYear[13] = {0, 31, 59, 90, 120, 151, 181, 
                                       212, 243, 273, 304, 334, 365};

	// Validate year and month (ignore day of week and milliseconds)
	if (dbts.year > 9999 || dbts.month < 1 || dbts.month > 12)
		return NULL;

	//  Check for leap year and set the number of days in the month
	BOOL bLeapYear = ((dbts.year & 3) == 0) &&
		((dbts.year % 100) != 0 || (dbts.year % 400) == 0);

	int nDaysInMonth =
		anMonthDayInYear[dbts.month] - anMonthDayInYear[dbts.month-1] +
		((bLeapYear && dbts.day == 29 && dbts.month == 2) ? 1 : 0);

	// Finish validating the date
	if (dbts.day < 1 || dbts.day > nDaysInMonth)
	{
		return NULL;
	}

	if(dbts.hour > 23 || dbts.minute > 59 || dbts.second > 59)
	{
		dbts.hour = 0;
		dbts.minute = 0;
		dbts.second = 0;
	}

	// Cache the date in days and time in fractional days
	long nDate;
	double dblTime;

	//It is a valid date; make Jan 1, 1AD be 1
	nDate = dbts.year * 365L + dbts.year/4 - dbts.year/100 + dbts.year/400 +
		anMonthDayInYear[dbts.month-1] + dbts.day;

	//  If leap year and it's before March, subtract 1:
	if (dbts.month <= 2 && bLeapYear)
		--nDate;

	//  Offset so that 12/30/1899 is 0
	nDate -= 693959L;

	dblTime = (((long)dbts.hour * 3600L) +  // hrs in seconds
		((long)dbts.minute * 60L) +  // mins in seconds
 		((long)dbts.second)) / 86400.;

	dtDest = (double) nDate + ((nDate >= 0) ? dblTime : -dblTime);

	return dtDest;
}

//*******************************************************************************

DBTIMESTAMP DBTSFromDate(DATE dtSrc)
{
	DBTIMESTAMP dbts;

	int anMonthDayInYear[13] = {0, 31, 59, 90, 120, 151, 181, 
                                       212, 243, 273, 304, 334, 365};
	
	memset(&dbts, 0, sizeof(DBTIMESTAMP));

	long nDays;             // Number of days since Dec. 30, 1899
	long nDaysAbsolute;     // Number of days since 1/1/0
	long nSecsInDay;        // Time in seconds since midnight
	long nMinutesInDay;     // Minutes in day

	long n400Years;         // Number of 400 year increments since 1/1/0
	long n400Century;       // Century within 400 year block (0,1,2 or 3)
	long n4Years;           // Number of 4 year increments since 1/1/0
	long n4Day;             // Day within 4 year block
							//  (0 is 1/1/yr1, 1460 is 12/31/yr4)
	long n4Yr;              // Year within 4 year block (0,1,2 or 3)
	BOOL bLeap4 = TRUE;     // TRUE if 4 year block includes leap year

	double dblDate = dtSrc; // tempory serial date

	// If a valid date, then this conversion should not overflow
	nDays = (long)dblDate;

	// Round to the second
	dblDate += ((dtSrc > 0.0) ? (1.0/172800.0) : (-1 * (1.0/172800.0)));

	nDaysAbsolute = (long)dblDate + 693959L; // Add days from 1/1/0 to 12/30/1899

	dblDate = fabs(dblDate);
	nSecsInDay = (long)((dblDate - floor(dblDate)) * 86400.);

	// Calculate the day of week (sun=1, mon=2...)
	//   -1 because 1/1/0 is Sat.  +1 because we want 1-based
	//tmDest.tm_wday = (int)((nDaysAbsolute - 1) % 7L) + 1;
	
	// Leap years every 4 yrs except centuries not multiples of 400.
	n400Years = (long)(nDaysAbsolute / 146097L);

	// Set nDaysAbsolute to day within 400-year block
	nDaysAbsolute %= 146097L;

	// -1 because first century has extra day
	n400Century = (long)((nDaysAbsolute - 1) / 36524L);

	// Non-leap century
	if (n400Century != 0)
	{
		// Set nDaysAbsolute to day within century
		nDaysAbsolute = (nDaysAbsolute - 1) % 36524L;

		// +1 because 1st 4 year increment has 1460 days
		n4Years = (long)((nDaysAbsolute + 1) / 1461L);

		if (n4Years != 0)
			n4Day = (long)((nDaysAbsolute + 1) % 1461L);
		else
		{
			bLeap4 = FALSE;
			n4Day = (long)nDaysAbsolute;
		}
	}
	else
	{
		// Leap century - not special case!
		n4Years = (long)(nDaysAbsolute / 1461L);
		n4Day = (long)(nDaysAbsolute % 1461L);
	}

	if (bLeap4)
	{
		// -1 because first year has 366 days
		n4Yr = (n4Day - 1) / 365;

		if (n4Yr != 0)
			n4Day = (n4Day - 1) % 365;
	}
	else
	{
		n4Yr = n4Day / 365;
		n4Day %= 365;
	}

	// n4Day is now 0-based day of year. Save 1-based day of year, year number
	//tmDest.tm_yday = (int)n4Day + 1;
	dbts.year = (short)(n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr);

	// Handle leap year: before, on, and after Feb. 29.
	if (n4Yr == 0 && bLeap4)
	{
		// Leap Year
		if (n4Day == 59)
		{
			dbts.month = 2;
			dbts.day = 29;
			goto DoTime;
		}

		// Pretend it's not a leap year for month/day comp.
		if (n4Day >= 60)
			--n4Day;
	}

	// Make n4DaY a 1-based day of non-leap year and compute
	//  month/day for everything but Feb. 29.
	++n4Day;

	// Month number always >= n/32, so save some loop time 
	for (dbts.month = (n4Day >> 5) + 1;
		n4Day > anMonthDayInYear[dbts.month]; dbts.month++);
		
	dbts.day = (int)(n4Day - anMonthDayInYear[dbts.month - 1]);

DoTime:
	if (nSecsInDay == 0)
		dbts.hour = dbts.minute = dbts.second = 0;
	else
	{
		dbts.second = (short)((int)nSecsInDay % 60L);
		nMinutesInDay = nSecsInDay / 60L;
		dbts.minute = (int)nMinutesInDay % 60;
		dbts.hour = (int)nMinutesInDay / 60;
	}

	return dbts;
}

//********************************************************************************

DBDATE DBDateFromDBTS(DBTIMESTAMP dtSrc)
{
	DBDATE mDDRet;

	mDDRet.day = dtSrc.day;
	mDDRet.month = dtSrc.month;
	mDDRet.year = dtSrc.year;

	return mDDRet;
}

//********************************************************************************

DBTIMESTAMP DBTSFromDBDate(DBDATE mDDRet)
{
	DBTIMESTAMP dtSrc;

	memset(&dtSrc, 0, sizeof(DBTIMESTAMP));

	dtSrc.day = mDDRet.day;
	dtSrc.month = mDDRet.month;
	dtSrc.year = mDDRet.year;

	return dtSrc;
}

//********************************************************************************

DBTIME DBTimeFromDBTS(DBTIMESTAMP dtSrc)
{
	DBTIME mDDRet;

	mDDRet.hour = dtSrc.hour;
	mDDRet.minute = dtSrc.minute;
	mDDRet.second = dtSrc.second;

	return mDDRet;
}

//********************************************************************************

DBTIMESTAMP DBTSFromDBTime(DBTIME mDDRet)
{
	DBTIMESTAMP dtSrc;

	memset(&dtSrc, 0, sizeof(DBTIMESTAMP));

	dtSrc.hour = mDDRet.hour;
	dtSrc.minute = mDDRet.minute;
	dtSrc.second = mDDRet.second;

	return dtSrc;
}

//********************************************************************************

LPCTSTR GetDataTypeName(WORD dbtype)
{
	LPCTSTR mStr;

	switch(dbtype)
	{
	case  0:	//DBTYPE_EMPTY = 0,
		mStr = _T("Empty");
		break;
	case 1:		//DBTYPE_NULL = 1,
		mStr = _T("NULL");
		break;
	case 2:		//DBTYPE_I2 = 2,
		mStr = _T("Short");
		break;
	case 3:		//DBTYPE_I4 = 3,
		mStr = _T("Long");
		break;
	case 4:		//DBTYPE_R4 = 4,
		mStr = _T("Float");
		break;
	case 5:		//DBTYPE_R8 = 5,
		mStr = _T("Double");
		break;
	case 6:		//DBTYPE_CY = 6,
		mStr = _T("Currency");
		break;
	case 7:		//DBTYPE_DATE = 7,
		mStr = _T("Date");
		break;
	case 8:		//DBTYPE_BSTR = 8,
		mStr = _T("BSTR");
		break;
	case 9:		//DBTYPE_IDISPATCH = 9,
		mStr = _T("IDispatch Pointer");
		break;
	case 10:	//DBTYPE_ERROR = 10,
		mStr = _T("ErrorCode");
		break;
	case 11:	//DBTYPE_BOOL = 11,
		mStr = _T("Boolean");
		break;
	case 12:	//DBTYPE_VARIANT = 12,
		mStr = _T("Variant");
		break;
	case 13:	//DBTYPE_IUNKNOWN = 13,
		mStr = _T("IUnknown Pointer");
		break;
	case 14:	//DBTYPE_DECIMAL = 14,
		mStr = _T("Decimal");
		break;
	case 17:	//DBTYPE_UI1 = 17,
		mStr = _T("Byte");
		break;
	case 0x2000: //DBTYPE_ARRAY = 0x2000,
		mStr = _T("SafeArray");
		break;
	case 0x4000: //DBTYPE_BYREF = 0x4000,
		mStr = _T("void *");
		break;
	case 16:	//DBTYPE_I1 = 16,
		mStr = _T("Signed Char");
		break;
	case 18:	//DBTYPE_UI2 = 18,
		mStr = _T("USHORT");
		break;
	case 19:	//DBTYPE_UI4 = 19,
		mStr = _T("ULONG");
		break;
	case 20:	//DBTYPE_I8 = 20,
		mStr = _T("LARGE_INTEGER");
		break;
	case 21:	//DBTYPE_UI8 = 21,
		mStr = _T("Unsigned LARGE_INTEGER");
		break;
	case 72:	//DBTYPE_GUID = 72,
		mStr = _T("GUID");
		break;
	case 0x1000: //DBTYPE_VECTOR = 0x1000,
		mStr = _T("DBVECTOR");
		break;
	case 64:	//DBTYPE_FILETIME = 64,
		mStr = _T("FileTime");
		break;
	case 128:	//DBTYPE_BYTES = 128,
		mStr = _T("Byte Array");
		break;
	case 129:	//DBTYPE_STR = 129,
		mStr = _T("CHAR");
		break;
	case 130: //DBTYPE_WSTR = 130,
		mStr = _T("Unicode String");
		break;
	case 131: //DBTYPE_NUMERIC = 131,
		mStr = _T("Numeric");
		break;
	case 132: //DBTYPE_UDT = 132,
		mStr = _T("User-Defined Type");
		break;
	case 133: //DBTYPE_DBDATE = 133,
		mStr = _T("DBDATE");
		break;
	case 134: //DBTYPE_DBTIME = 134,
		mStr = _T("DBTIME");
		break;
	case 135: //DBTYPE_DBTIMESTAMP = 135
		mStr = _T("DBTIMESTAMP");
		break;
	case 136: //DBTYPE_HCHAPTER = 136
		mStr = _T("Chapter");
		break;
	case 138: //DBTYPE_PROPVARIANT = 138,
		mStr = _T("PROPVARIANT");
		break;
	case 139: //DBTYPE_VARNUMERIC = 139
		mStr = _T("VARNUMERIC");
		break;
	default:
		mStr = _T("");
	}

	return mStr; 
}

//********************************************************************************
/////////////////////  CSypODLError Object ////////////////////////////////
//********************************************************************************

CSypODLError::CSypODLError()
{
	mErrMsg = "";
	mErrLoc = "";
	mErrCtx = "";
}

//***********************************************

CSypODLError::~CSypODLError()
{

}

//***********************************************

CString CSypODLError::GetErrorMsg()
{
	return mErrMsg;
}

//***********************************************

CString CSypODLError::GetErrorLoc()
{
	return mErrLoc;
}

//***********************************************

CString CSypODLError::GetErrorCtx()
{
	return mErrCtx;
}

//***********************************************

void CSypODLError::ClearErrors()
{
	mErrMsg = "";
	mErrLoc = "";
	mErrCtx = "";
}

//***********************************************

void CSypODLError::SetError(CString msg, CString loc, CString ctx)
{
	mErrMsg = msg;
	mErrLoc = loc;
	mErrCtx = ctx;
}

//***********************************************

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions