// 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;
}
//***********************************************