Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

5753 lines
123 KiB

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1995 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#ifdef AFX_DB_SEG
#pragma code_seg(AFX_DB_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// Maintain DAODBEngine object
_AFX_DAO_STATE::_AFX_DAO_STATE()
{
m_pDAODBEngine = NULL;
m_bOleInitialized = FALSE;
}
_AFX_DAO_STATE::~_AFX_DAO_STATE()
{
ASSERT(m_mapWorkspaces.IsEmpty());
ASSERT(m_pDAODBEngine == NULL);
ASSERT(!m_bOleInitialized);
}
//////////////////////////////////////////////////////////////////////////
// Helpers
// Index function return value
#define AFX_DAO_DATA_NOT_FOUND (-1L)
#define AFX_DAO_FETCH_PRIMARY_PROPERTIES \
(AFX_DAO_PRIMARY_INFO | AFX_DAO_SECONDARY_INFO | AFX_DAO_ALL_INFO)
#define AFX_DAO_FETCH_SECONDARY_PROPERTIES \
(AFX_DAO_SECONDARY_INFO | AFX_DAO_ALL_INFO)
#define AFX_DAO_FETCH_ALL_PROPERTIES \
AFX_DAO_ALL_INFO
// Info helpers
void AFX_CDECL AfxGetFieldInfo(DAOField* pDAOField, CDaoFieldInfo& fieldinfo,
DWORD dwInfoOptions = AFX_DAO_PRIMARY_INFO);
void AFX_CDECL AfxSetFieldInfo(DAOField* pDAOField, CDaoFieldInfo& fieldinfo);
void AFX_CDECL AfxGetIndexInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo,
DWORD dwInfoOptions = AFX_DAO_PRIMARY_INFO);
void AFX_CDECL AfxSetIndexInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo);
void AFX_CDECL AfxGetIndexFields(DAOIndex* pDAOIndex,
DAOIndexFields** ppDAOIndexFields);
void AFX_CDECL AfxGetIndexFieldInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo);
void AFX_CDECL AfxSetIndexFieldInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo);
// GetRows helper
void AFX_CDECL ThrowGetRowsDaoException(SCODE scode);
// _AFX_DAO_STATE helper
_AFX_DAO_STATE* AFX_CDECL AfxGetDaoState();
//////////////////////////////////////////////////////////////////////////
// Global data
static const TCHAR szParameters[] = _T("PARAMETERS ");
static const TCHAR szSelect[] = _T("SELECT ");
static const TCHAR szFrom[] = _T(" FROM ");
static const TCHAR szWhere[] = _T(" WHERE ");
static const TCHAR szOrderBy[] = _T(" ORDER BY ");
static const TCHAR szTransform[] = _T("TRANSFORM ");
static const TCHAR szTable[] = _T("TABLE ");
// Need a static VARIANT for optional DAO parameters
static VARIANT _afxOptionalVariant;
struct AFX_INITOPTIONALVARIANT
{
AFX_INITOPTIONALVARIANT()
{
_afxOptionalVariant.vt = VT_ERROR;
_afxOptionalVariant.scode = DISP_E_PARAMNOTFOUND;
};
};
static const AFX_INITOPTIONALVARIANT _afxInitOptionalVariant;
// Need a static VARIANT for NULL DAO parameters
static VARIANT _afxNullVariant;
struct AFX_INITNULLVARIANT
{
AFX_INITNULLVARIANT()
{
_afxNullVariant.vt = VT_NULL;
};
};
static const AFX_INITNULLVARIANT _afxInitNullVariant;
//////////////////////////////////////////////////////////////////////////
// Logging helpers
void AFXAPI AfxDaoCheck(SCODE scode, LPCSTR lpszDaoCall,
LPCSTR lpszFile, int nLine, int nError, BOOL bMemOnly)
{
UNUSED(lpszDaoCall);
UNUSED(lpszFile);
UNUSED(nLine);
if (FAILED(scode))
{
#ifdef _DEBUG
if (afxTraceFlags & traceDatabase)
{
TRACE0("\nDAO Call Failed.");
TRACE1("\n\t%hs", lpszDaoCall);
TRACE2("\n\tIn file %hs on line %d", lpszFile, nLine);
TRACE1("\n\tscode = %X\n", scode);
}
#endif
if (scode == E_OUTOFMEMORY)
AfxThrowMemoryException();
else if (!bMemOnly)
AfxThrowDaoException(nError, scode);
}
}
#ifdef _DEBUG
void AFXAPI AfxDaoTrace(SCODE scode, LPCSTR lpszDaoCall,
LPCSTR lpszFile, int nLine)
{
if (FAILED(scode))
{
if (afxTraceFlags & traceDatabase)
{
TRACE0("\nDAO Call Failed.\n\t");
TRACE1("\n%hs", lpszDaoCall);
TRACE2("\nIn file %hs on line %d\n", lpszFile, nLine);
TRACE1("scode = %X\n", scode);
}
}
}
#endif // _DEBUG
//////////////////////////////////////////////////////////////////////////
// Info structure diagnostics
#ifdef _DEBUG
void CDaoErrorInfo::Dump(CDumpContext& dc) const
{
dc << "a CDaoErrorInfo at " << (void*)this;
dc << "\nm_lErrorCode = " << m_lErrorCode;
dc << "\nm_strSource = " << m_strSource;
dc << "\nm_strDescription = " << m_strDescription;
dc << "\nm_strHelpFile = " << m_strHelpFile;
dc << "\nm_lHelpContext = " << m_lHelpContext;
dc << "\n";
}
#endif // _DEBUG
#ifdef _DEBUG
void CDaoWorkspaceInfo::Dump(CDumpContext& dc) const
{
dc << "a CDaoWorkspaceInfo at " << (void*)this;
dc << "\nm_strName = " << m_strName;
dc << "\nm_strUserName = " << m_strUserName;
dc << "\nb = m_bIsolateODBCTrans" << m_bIsolateODBCTrans;
dc << "\n";
}
#endif // _DEBUG
#ifdef _DEBUG
void CDaoDatabaseInfo::Dump(CDumpContext& dc) const
{
dc << "a CDaoDatabaseInfo at " << (void*)this;
dc << "\nm_strName = " << m_strName;
dc << "\nm_bUpdatable = " << m_bUpdatable;
dc << "\nm_bTransactions = " << m_bTransactions;
dc << "\nm_strVersion = " << m_strVersion;
dc << "\nm_lCollatingOrder = " << m_lCollatingOrder;
dc << "\nm_nQueryTimeout = " << m_nQueryTimeout;
dc << "\nm_strConnect = " << m_strConnect;
dc << "\n";
}
#endif // _DEBUG
#ifdef _DEBUG
void CDaoTableDefInfo::Dump(CDumpContext& dc) const
{
dc << "a CDaoTableDefInfo at " << (void*)this;
dc << "\nm_strName = " << m_strName;
dc << "\nm_bUpdatable = " << m_bUpdatable;
dc << "\nm_lAttributes = " << m_lAttributes;
dc << "\nm_dateDateCreated = " << m_dateCreated;
dc << "\nm_dateLastUpdated = " << m_dateLastUpdated;
dc << "\nm_strSrcTableName = " << m_strSrcTableName;
dc << "\nm_strConnect = " << m_strConnect;
dc << "\nm_strValidationRule = " << m_strValidationRule;
dc << "\nm_strValidationText = " << m_strValidationText;
dc << "\nm_lRecordCount = " << m_lRecordCount;
dc << "\n";
}
#endif // _DEBUG
#ifdef _DEBUG
void CDaoFieldInfo::Dump(CDumpContext& dc) const
{
dc << "a CDaoFieldInfo at " << (void*)this;
dc << "\nm_strName = " << m_strName;
dc << "\nm_nType = " << m_nType;
dc << "\nm_lSize = " << m_lSize;
dc << "\nm_lAttributes = " << m_lAttributes;
dc << "\nm_nOrdinalPosition = " << m_nOrdinalPosition;
dc << "\nm_bRequired = " << m_bRequired;
dc << "\nm_bAllowZeroLength = " << m_bAllowZeroLength;
dc << "\nm_lCollatingOrder = " << m_lCollatingOrder;
dc << "\nm_strForeignName = " << m_strForeignName;
dc << "\nm_strSourceField = " << m_strSourceField;
dc << "\nm_strSourceTable = " << m_strSourceTable;
dc << "\nm_strValidationRule = " << m_strValidationRule;
dc << "\nm_strValidationText = " << m_strValidationText;
dc << "\nm_strDefaultValue = " << m_strDefaultValue;
dc << "\n";
}
#endif // _DEBUG
#ifdef _DEBUG
void CDaoIndexFieldInfo::Dump(CDumpContext& dc) const
{
dc << " a CDaoIndexFieldInfo at " << (void*)this;
dc << "\nm_strName = " << m_strName;
dc << "\nm_bDescending = " << m_bDescending;
}
#endif
CDaoIndexInfo::CDaoIndexInfo()
{
m_pFieldInfos = NULL;
m_nFields = 0;
m_bCleanupFieldInfo = FALSE;
}
CDaoIndexInfo::~CDaoIndexInfo()
{
if (m_bCleanupFieldInfo && m_pFieldInfos != NULL)
{
delete[] m_pFieldInfos;
m_pFieldInfos = NULL;
}
}
#ifdef _DEBUG
void CDaoIndexInfo::Dump(CDumpContext& dc) const
{
dc << "a CDaoIndexInfo at " << (void*)this;
dc << "\nm_strName = " << m_strName;
dc << "\nm_nFields = " << m_nFields;
for (int nIndex = 0; nIndex < m_nFields; nIndex++)
m_pFieldInfos[nIndex].Dump(dc);
dc << "\nm_bPrimary = " << m_bPrimary;
dc << "\nm_bUnique = " << m_bUnique;
dc << "\nm_bClustered = " << m_bClustered;
dc << "\nm_bIgnoreNulls = " << m_bIgnoreNulls;
dc << "\nm_bRequired = " << m_bRequired;
dc << "\nm_bForeign = " << m_bForeign;
dc << "\nm_lDistinctCount = " << m_lDistinctCount;
dc << "\n";
}
#endif // _DEBUG
#ifdef _DEBUG
void CDaoRelationFieldInfo::Dump(CDumpContext& dc) const
{
dc << " a CDaoRelationFieldInfo at " << (void*)this;
dc << "\nm_strName = " << m_strName;
dc << "\nm_strForeignName = " << m_strForeignName;
}
#endif
CDaoRelationInfo::CDaoRelationInfo()
{
m_pFieldInfos = NULL;
m_nFields = 0;
m_bCleanupFieldInfo = FALSE;
}
CDaoRelationInfo::~CDaoRelationInfo()
{
if (m_bCleanupFieldInfo && m_pFieldInfos != NULL)
{
delete[] m_pFieldInfos;
m_pFieldInfos = NULL;
}
}
#ifdef _DEBUG
void CDaoRelationInfo::Dump(CDumpContext& dc) const
{
dc << "a CDaoRelationInfo at " << (void*)this;
dc << "\nm_strName = " << m_strName;
dc << "\nm_strTable = " << m_strTable;
dc << "\nm_strForeignTable = " << m_strForeignTable;
dc << "\nm_lAttributes = " << m_lAttributes;
dc << "\nm_nFields = " << m_nFields;
for (int nIndex = 0; nIndex < m_nFields; nIndex++)
m_pFieldInfos[nIndex].Dump(dc);
dc << "\n";
}
#endif // _DEBUG
#ifdef _DEBUG
void CDaoQueryDefInfo::Dump(CDumpContext& dc) const
{
dc << "a CDaoQueryDefInfo at " << (void*)this;
dc << "\nm_strName = " << m_strName;
dc << "\nm_nType = " << m_nType;
dc << "\nm_dateCreated = " << m_dateCreated;
dc << "\nm_dateLastUpdated = " << m_dateLastUpdated;
dc << "\nm_bUpdatable = " << m_bUpdatable;
dc << "\nm_bReturnsRecords = " << m_bReturnsRecords;
dc << "\nm_strSQL = " << m_strSQL;
dc << "\nm_strConnect = " << m_strConnect;
dc << "\nm_nODBCTimeout = " << m_nODBCTimeout;
dc << "\n";
}
#endif // _DEBUG
#ifdef _DEBUG
void CDaoParameterInfo::Dump(CDumpContext& dc) const
{
dc << "a CDaoParameterInfo at " << (void*)this;
dc << "\nm_strName = " << m_strName;
dc << "\nm_nType = " << m_nType;
dc << "\nm_varValue = " << m_varValue;
dc << "\n";
}
#endif // _DEBUG
//////////////////////////////////////////////////////////////////////////
// CDaoException
IMPLEMENT_DYNAMIC(CDaoException, CException)
CDaoException::CDaoException()
{
m_pDAOError = NULL;
m_pDAOErrors = NULL;
m_pErrorInfo = NULL;
}
CDaoException::~CDaoException()
{
delete m_pErrorInfo;
m_pErrorInfo = NULL;
if (m_pDAOErrors != NULL)
{
m_pDAOErrors->Release();
m_pDAOErrors = NULL;
}
if (m_pDAOError != NULL)
{
m_pDAOError->Release();
m_pDAOError = NULL;
}
}
// Operations
short CDaoException::GetErrorCount()
{
short nErrors = 1;
if (m_pDAOErrors == NULL)
InitErrorsCollection();
if (m_nAfxDaoError != AFX_DAO_ERROR_ENGINE_INITIALIZATION)
DAO_CHECK_MEM(m_pDAOErrors->get_Count(&nErrors));
return nErrors;
}
void CDaoException::GetErrorInfo(int nIndex)
{
ASSERT(m_pDAOError == NULL);
if (m_pDAOErrors == NULL)
InitErrorsCollection();
if (m_nAfxDaoError != AFX_DAO_ERROR_ENGINE_INITIALIZATION)
{
// Get DAOError object and fill in error info struct
DAO_CHECK_MEM(m_pDAOErrors->get_Item(
COleVariant((long)nIndex), &m_pDAOError));
FillErrorInfo();
// Clean up
m_pDAOError->Release();
m_pDAOError = NULL;
}
}
BOOL CDaoException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
PUINT pnHelpContext)
{
ASSERT(lpszError != NULL && AfxIsValidString(lpszError, nMaxError));
BOOL bRetCode = FALSE;
if (m_pErrorInfo != NULL)
{
// DAO help context is not a UINT!
// According to DAO it is positive and should be less 10,000,000
if (pnHelpContext != NULL)
*pnHelpContext = (UINT) m_pErrorInfo->m_lHelpContext;
lstrcpyn(lpszError, m_pErrorInfo->m_strDescription, nMaxError-1);
lpszError[nMaxError-1] = '\0';
bRetCode = TRUE;
}
else
{
// Must be MFC DAO class internal error, get error string
CString strError;
if (strError.LoadString(
AFX_IDP_DAO_FIRST + (m_nAfxDaoError - AFX_DAO_ERROR_MIN)))
{
lstrcpyn(lpszError, strError, nMaxError-1);
bRetCode = TRUE;
}
else
ASSERT(FALSE); // Couldn't get resource.
}
return bRetCode;
}
// Implementation
void CDaoException::InitErrorsCollection()
{
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
// Engine not initialized!
if (pDaoState->m_pDAODBEngine == NULL)
m_nAfxDaoError = AFX_DAO_ERROR_ENGINE_INITIALIZATION;
else
DAO_CHECK_MEM(pDaoState->m_pDAODBEngine->get_Errors(
&m_pDAOErrors));
}
void CDaoException::FillErrorInfo()
{
ASSERT(m_pDAOError != NULL);
// Allocate the error info structure if necessary
if (m_pErrorInfo == NULL)
m_pErrorInfo = new CDaoErrorInfo;
COleVariant var;
DAO_CHECK_MEM(m_pDAOError->get_Number(
&m_pErrorInfo->m_lErrorCode));
DAO_CHECK_MEM(m_pDAOError->get_Source(&V_BSTR(&var)));
var.vt = VT_BSTR;
m_pErrorInfo->m_strSource = V_BSTRT(&var);
var.Clear();
DAO_CHECK_MEM(m_pDAOError->get_Description(&V_BSTR(&var)));
var.vt = VT_BSTR;
m_pErrorInfo->m_strDescription = V_BSTRT(&var);
var.Clear();
DAO_CHECK_MEM(m_pDAOError->get_HelpFile(&V_BSTR(&var)));
var.vt = VT_BSTR;
m_pErrorInfo->m_strHelpFile = V_BSTRT(&var);
var.Clear();
DAO_CHECK_MEM(m_pDAOError->get_HelpContext(
&m_pErrorInfo->m_lHelpContext));
}
void AFXAPI AfxThrowDaoException(int nAfxDaoError, SCODE scode)
{
CDaoException* pException;
pException = new CDaoException;
pException->m_scode = scode;
if (nAfxDaoError == NO_AFX_DAO_ERROR)
{
TRY
{
int nErrors = pException->GetErrorCount();
for (int nIndex = 0; nIndex < nErrors; nIndex++)
{
pException->GetErrorInfo(nIndex);
#ifdef _DEBUG
if (afxTraceFlags & traceDatabase)
{
TRACE1("\nError Code = %d\n",
pException->m_pErrorInfo->m_lErrorCode);
TRACE1("Source = %s\n",
(LPCTSTR)pException->m_pErrorInfo->m_strSource);
TRACE1("Description = %s\n",
(LPCTSTR)pException->m_pErrorInfo->m_strDescription);
}
#endif // _DEBUG
}
}
CATCH_ALL(e)
{
// No DAO error info
e->Delete();
}
END_CATCH_ALL
}
else
pException->m_nAfxDaoError = nAfxDaoError;
THROW(pException);
}
//////////////////////////////////////////////////////////////////////////
// CDaoWorkspace
IMPLEMENT_DYNAMIC(CDaoWorkspace, CObject)
CDaoWorkspace::CDaoWorkspace()
{
m_pDAOWorkspaces = NULL;
m_pDAOWorkspace = NULL;
m_pDAODatabases = NULL;
m_bOpen = FALSE;
m_bNew = FALSE;
m_nStatus = 0;
}
CDaoWorkspace::~CDaoWorkspace()
{
if (IsOpen())
{
m_nStatus |= AFX_DAO_IMPLICIT_CLOSE;
Close();
}
else if (m_bNew)
{
// Remove the workspace from the AFX_DAO_STATE's map
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
pDaoState->m_mapWorkspaces.RemoveKey(this);
}
}
void CDaoWorkspace::Create(LPCTSTR lpszName, LPCTSTR lpszUserName,
LPCTSTR lpszPassword)
{
ASSERT_VALID(this);
ASSERT(!IsOpen());
ASSERT(lpszUserName != NULL);
ASSERT(lpszPassword != NULL);
// Get the DAODBEngine interface and initialize if necessary
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
COleVariant varName(lpszName, VT_BSTRT);
COleVariant varUserName(lpszUserName, VT_BSTRT);
COleVariant varPassword(lpszPassword, VT_BSTRT);
DAO_CHECK(pDaoState->m_pDAODBEngine->CreateWorkspace(
V_BSTR(&varName), V_BSTR(&varUserName),
V_BSTR(&varPassword), &m_pDAOWorkspace));
m_bNew = TRUE;
// Add the workspace to map of Open/New CDaoWorkspaces
pDaoState->m_mapWorkspaces.SetAt(this, this);
}
void CDaoWorkspace::Append()
{
ASSERT_VALID(this);
ASSERT(m_bNew);
ASSERT(m_pDAOWorkspace != NULL);
DAOWorkspaces* pDAOWorkspaces;
// Get the DAODBEngine interface and initialize if necessary
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->get_Workspaces(&pDAOWorkspaces));
TRY
{
DAO_CHECK(pDAOWorkspaces->Append(m_pDAOWorkspace));
}
CATCH_ALL(e)
{
pDAOWorkspaces->Release();
THROW_LAST();
}
END_CATCH_ALL
pDAOWorkspaces->Release();
m_bNew = FALSE;
m_bOpen = TRUE;
}
void CDaoWorkspace::Open(LPCTSTR lpszWorkspaceName)
{
ASSERT_VALID(this);
ASSERT(m_pDAOWorkspaces == NULL);
ASSERT(m_pDAOWorkspace == NULL);
// Re-Opening is invalid.
if (IsOpen())
{
ASSERT(FALSE);
return;
}
// Set the workspace name (or use 0 if opening default)
COleVariant var(lpszWorkspaceName, VT_BSTRT);
if (lpszWorkspaceName == NULL)
{
var = 0L;
// Set status to prevent DAO Workspace Close call
m_nStatus |= AFX_DAO_DEFAULT_WS;
}
// Get the DAODBEngine interface and initialize if necessary
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
// Get the workspace from the workspaces collection
DAO_CHECK(pDaoState->m_pDAODBEngine->get_Workspaces(
&m_pDAOWorkspaces));
DAO_CHECK(m_pDAOWorkspaces->get_Item(var, &m_pDAOWorkspace));
m_bOpen = TRUE;
m_pDAOWorkspaces->Release();
m_pDAOWorkspaces = NULL;
// Add the workspace to map of Open/New CDaoWorkspaces
pDaoState->m_mapWorkspaces.SetAt(this, this);
}
void CDaoWorkspace::Close()
{
ASSERT_VALID(this);
if (m_pDAODatabases != NULL)
{
m_pDAODatabases->Release();
m_pDAODatabases = NULL;
}
// Close any Open CDaoDatabases
void* pvKey;
void* pvObject;
POSITION pos = m_mapDatabases.GetStartPosition();
while (pos != NULL)
{
m_mapDatabases.GetNextAssoc(pos, pvKey, pvObject);
((CDaoDatabase*)pvObject)->Close();
}
m_mapDatabases.RemoveAll();
if (m_pDAOWorkspace != NULL)
{
// If implicit workspace or close, don't call DAO close.
// It will be automatically closed when ref count 0.
if (!(m_nStatus & (AFX_DAO_IMPLICIT_WS | AFX_DAO_IMPLICIT_CLOSE |
AFX_DAO_DEFAULT_WS)))
{
DAO_TRACE(m_pDAOWorkspace->Close());
}
m_pDAOWorkspace->Release();
m_pDAOWorkspace = NULL;
}
if (m_pDAOWorkspaces != NULL)
{
m_pDAOWorkspaces->Release();
m_pDAOWorkspaces = NULL;
}
m_bOpen = FALSE;
m_bNew = FALSE;
m_nStatus &= ~AFX_DAO_DEFAULT_WS;
// Remove the workspace from the AFX_DAO_STATE's map
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
pDaoState->m_mapWorkspaces.RemoveKey(this);
}
CString PASCAL CDaoWorkspace::GetVersion()
{
COleVariant var;
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->get_Version(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
CString PASCAL CDaoWorkspace::GetIniPath()
{
COleVariant var;
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->get_IniPath(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
void PASCAL CDaoWorkspace::SetIniPath(LPCTSTR lpszRegistrySubKey)
{
COleVariant var(lpszRegistrySubKey, VT_BSTRT);
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->put_IniPath(V_BSTR(&var)));
}
void PASCAL CDaoWorkspace::SetDefaultUser(LPCTSTR lpszDefaultUser)
{
COleVariant var(lpszDefaultUser, VT_BSTRT);
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->put_DefaultUser(V_BSTR(&var)));
}
void PASCAL CDaoWorkspace::SetDefaultPassword(LPCTSTR lpszPassword)
{
COleVariant var(lpszPassword, VT_BSTRT);
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->put_DefaultPassword(
V_BSTR(&var)));
}
short PASCAL CDaoWorkspace::GetLoginTimeout()
{
short nSeconds;
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->get_LoginTimeout(&nSeconds));
return nSeconds;
}
void PASCAL CDaoWorkspace::SetLoginTimeout(short nSeconds)
{
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->put_LoginTimeout(nSeconds));
}
CString CDaoWorkspace::GetName()
{
ASSERT_VALID(this);
ASSERT(m_pDAOWorkspace != NULL);
COleVariant var;
DAO_CHECK(m_pDAOWorkspace->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
CString CDaoWorkspace::GetUserName()
{
ASSERT_VALID(this);
ASSERT(m_pDAOWorkspace != NULL);
COleVariant var;
DAO_CHECK(m_pDAOWorkspace->get_UserName(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
void CDaoWorkspace::SetIsolateODBCTrans(BOOL bIsolateODBCTrans)
{
ASSERT_VALID(this);
ASSERT(m_pDAOWorkspace != NULL);
DAO_CHECK(m_pDAOWorkspace->put_IsolateODBCTrans(
(short)(bIsolateODBCTrans ? AFX_DAO_TRUE : AFX_DAO_FALSE)));
}
BOOL CDaoWorkspace::GetIsolateODBCTrans()
{
ASSERT_VALID(this);
ASSERT(m_pDAOWorkspace != NULL);
short nIsolateODBCTrans;
DAO_CHECK(m_pDAOWorkspace->get_IsolateODBCTrans(&nIsolateODBCTrans));
return nIsolateODBCTrans == AFX_DAO_TRUE;
}
void PASCAL CDaoWorkspace::CompactDatabase(LPCTSTR lpszSrcName,
LPCTSTR lpszDestName, LPCTSTR lpszLocale, int nOptions,
LPCTSTR lpszPassword)
{
COleVariant varSrcName(lpszSrcName, VT_BSTRT);
COleVariant varDestName(lpszDestName, VT_BSTRT);
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->CompactDatabase(
V_BSTR(&varSrcName), V_BSTR(&varDestName),
COleVariant(lpszLocale, VT_BSTRT), COleVariant((long)nOptions),
lpszPassword != NULL ? (VARIANT)COleVariant(lpszPassword, VT_BSTRT) :
_afxOptionalVariant));
}
void PASCAL CDaoWorkspace::CompactDatabase(LPCTSTR lpszSrcName,
LPCTSTR lpszDestName, LPCTSTR lpszLocale, int nOptions)
{
CompactDatabase(lpszSrcName, lpszDestName, lpszLocale, nOptions, NULL);
}
void PASCAL CDaoWorkspace::RepairDatabase(LPCTSTR lpszName)
{
COleVariant varName(lpszName, VT_BSTRT);
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->RepairDatabase(
V_BSTR(&varName)));
}
void PASCAL CDaoWorkspace::Idle(int nAction)
{
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->Idle(
COleVariant((long)nAction)));
}
short CDaoWorkspace::GetWorkspaceCount()
{
ASSERT_VALID(this);
short nFields;
if (m_pDAOWorkspaces == NULL)
InitWorkspacesCollection();
DAO_CHECK(m_pDAOWorkspaces->get_Count(&nFields));
return nFields;
}
void CDaoWorkspace::GetWorkspaceInfo(int nIndex,
CDaoWorkspaceInfo& wsinfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOWorkspaces == NULL)
InitWorkspacesCollection();
// Get DAOWorkspace object and fill in workspace info struct
DAOWorkspace* pDAOWorkspace;
DAO_CHECK(m_pDAOWorkspaces->get_Item(
COleVariant((long)nIndex), &pDAOWorkspace));
FillWorkspaceInfo(pDAOWorkspace, wsinfo, dwInfoOptions);
// Clean up
pDAOWorkspace->Release();
}
void CDaoWorkspace::GetWorkspaceInfo(
LPCTSTR lpszName, CDaoWorkspaceInfo& wsinfo,
DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOWorkspaces == NULL)
InitWorkspacesCollection();
// Get DAOWorkspace object and fill in workspace info struct
DAOWorkspace* pDAOWorkspace;
DAO_CHECK(m_pDAOWorkspaces->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOWorkspace));
FillWorkspaceInfo(pDAOWorkspace, wsinfo, dwInfoOptions);
// Clean up
pDAOWorkspace->Release();
}
short CDaoWorkspace::GetDatabaseCount()
{
ASSERT_VALID(this);
if (m_pDAODatabases == NULL)
InitDatabasesCollection();
short nFields;
DAO_CHECK(m_pDAODatabases->get_Count(&nFields));
return nFields;
}
void CDaoWorkspace::GetDatabaseInfo(int nIndex, CDaoDatabaseInfo& dbinfo,
DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAODatabases == NULL)
InitDatabasesCollection();
// Get DAODatabase object and fill in database info struct
DAODatabase* pDAODatabase;
DAO_CHECK(m_pDAODatabases->get_Item(
COleVariant((long)nIndex), &pDAODatabase));
FillDatabaseInfo(pDAODatabase, dbinfo, dwInfoOptions);
// Clean up
pDAODatabase->Release();
}
void CDaoWorkspace::GetDatabaseInfo(LPCTSTR lpszName,
CDaoDatabaseInfo& dbinfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAODatabases == NULL)
InitDatabasesCollection();
// Get DAODatabase object and fill in database info struct
DAODatabase* pDAODatabase;
DAO_CHECK(m_pDAODatabases->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAODatabase));
FillDatabaseInfo(pDAODatabase, dbinfo, dwInfoOptions);
// Clean up
pDAODatabase->Release();
}
void CDaoWorkspace::BeginTrans()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOWorkspace != NULL);
DAO_CHECK(m_pDAOWorkspace->BeginTrans());
}
void CDaoWorkspace::CommitTrans()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOWorkspace != NULL);
DAO_CHECK(m_pDAOWorkspace->CommitTrans());
}
void CDaoWorkspace::Rollback()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOWorkspace != NULL);
DAO_CHECK(m_pDAOWorkspace->Rollback());
}
//Implementation
void AFX_CDECL CDaoWorkspace::InitializeEngine()
{
AfxDaoInit();
}
void CDaoWorkspace::InitWorkspacesCollection()
{
ASSERT_VALID(this);
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
if (pDaoState->m_pDAODBEngine == NULL)
InitializeEngine();
DAO_CHECK(pDaoState->m_pDAODBEngine->get_Workspaces(
&m_pDAOWorkspaces));
}
void CDaoWorkspace::FillWorkspaceInfo(DAOWorkspace* pDAOWorkspace,
CDaoWorkspaceInfo& wsinfo, DWORD dwOptions)
{
ASSERT_VALID(this);
ASSERT(pDAOWorkspace != NULL);
ASSERT(dwOptions != 0);
COleVariant var;
short nBool;
if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
{
DAO_CHECK(pDAOWorkspace->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
wsinfo.m_strName = V_BSTRT(&var);
var.Clear();
}
if (dwOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
{
DAO_CHECK(pDAOWorkspace->get_UserName(&V_BSTR(&var)));
var.vt = VT_BSTR;
wsinfo.m_strUserName = V_BSTRT(&var);
var.Clear();
}
if (dwOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
{
DAO_CHECK(pDAOWorkspace->get_IsolateODBCTrans(&nBool));
wsinfo.m_bIsolateODBCTrans = nBool == AFX_DAO_TRUE;
}
}
void CDaoWorkspace::InitDatabasesCollection()
{
ASSERT_VALID(this);
DAO_CHECK(m_pDAOWorkspace->get_Databases(&m_pDAODatabases));
}
void CDaoWorkspace::FillDatabaseInfo(DAODatabase* pDAODatabase,
CDaoDatabaseInfo& dbinfo, DWORD dwOptions)
{
ASSERT_VALID(this);
ASSERT(pDAODatabase != NULL);
ASSERT(dwOptions != 0);
COleVariant var;
short nBool;
if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
{
DAO_CHECK(pDAODatabase->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
dbinfo.m_strName = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAODatabase->get_Updatable(&nBool));
dbinfo.m_bUpdatable = nBool == AFX_DAO_TRUE;
DAO_CHECK(pDAODatabase->get_Transactions(&nBool));
dbinfo.m_bTransactions = nBool == AFX_DAO_TRUE;
}
if (dwOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
{
DAO_CHECK(pDAODatabase->get_Version(
&V_BSTR(&var)));
var.vt = VT_BSTR;
dbinfo.m_strVersion = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAODatabase->get_CollatingOrder(
&dbinfo.m_lCollatingOrder));
DAO_CHECK(pDAODatabase->get_QueryTimeout(
&dbinfo.m_nQueryTimeout));
}
if (dwOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
{
DAO_CHECK(pDAODatabase->get_Connect(
&V_BSTR(&var)));
var.vt = VT_BSTR;
dbinfo.m_strConnect = V_BSTRT(&var);
var.Clear();
}
}
void CDaoWorkspace::ThrowDaoException(int nAfxDaoError)
{
ASSERT_VALID(this);
AfxThrowDaoException(nAfxDaoError);
}
#ifdef _DEBUG
void CDaoWorkspace::AssertValid() const
{
CObject::AssertValid();
}
void CDaoWorkspace::Dump(CDumpContext& dc) const
{
ASSERT_VALID(this);
CObject::Dump(dc);
dc << "m_bOpen = " << m_bOpen;
dc << "\nm_bNew = " << m_bNew;
dc << "\nm_nStatus = " << m_nStatus;
dc << "\n";
}
#endif //_DEBUG
//////////////////////////////////////////////////////////////////////////
// CDaoDatabase
IMPLEMENT_DYNAMIC(CDaoDatabase, CObject)
CDaoDatabase::CDaoDatabase(CDaoWorkspace* pWorkspace)
{
m_bOpen = FALSE;
m_pDAODatabase = NULL;
m_pDAOTableDefs = NULL;
m_pDAORelations = NULL;
m_pDAOQueryDefs = NULL;
m_pDAORecordsets = NULL;
m_pWorkspace = pWorkspace;
m_nStatus = 0;
}
CDaoDatabase::~CDaoDatabase()
{
if (IsOpen())
Close();
// Clean up workspace if necessary
if (m_pWorkspace != NULL && (m_nStatus & AFX_DAO_IMPLICIT_WS))
{
m_pWorkspace->Close();
delete m_pWorkspace;
m_pWorkspace = NULL;
}
}
void CDaoDatabase::Create(LPCTSTR lpszName, LPCTSTR lpszLocale,
int nOptions)
{
ASSERT_VALID(this);
ASSERT(!IsOpen());
// Allocate and maintain workspace if necessary
InitWorkspace();
COleVariant varName(lpszName, VT_BSTRT);
COleVariant varLocale(lpszLocale, VT_BSTRT);
DAO_CHECK(m_pWorkspace->m_pDAOWorkspace->CreateDatabase(V_BSTR(&varName),
V_BSTR(&varLocale), COleVariant((long)nOptions),
&m_pDAODatabase));
m_bOpen = TRUE;
// Add the database to map of Open CDaoDatabases
m_pWorkspace->m_mapDatabases.SetAt(this, this);
}
void CDaoDatabase::Open(LPCTSTR lpszName, BOOL bExclusive,
BOOL bReadOnly, LPCTSTR lpszConnect)
{
ASSERT_VALID(this);
// Re-Opening is invalid.
if (IsOpen())
{
ASSERT(FALSE);
return;
}
// Allocate, maintain and/or open workspace if necessary
InitWorkspace();
COleVariant var(lpszName, VT_BSTRT);
DAO_CHECK(m_pWorkspace->m_pDAOWorkspace->OpenDatabase(
V_BSTR(&var),
COleVariant((long)bExclusive, VT_BOOL),
COleVariant((long)bReadOnly, VT_BOOL),
COleVariant(lpszConnect, VT_BSTRT),
&m_pDAODatabase));
m_bOpen = TRUE;
// Add the database to map of Open CDaoDatabases
m_pWorkspace->m_mapDatabases.SetAt(this, this);
}
// Disconnect connection
void CDaoDatabase::Close()
{
ASSERT_VALID(this);
if (m_pDAORecordsets != NULL)
{
m_pDAORecordsets->Release();
m_pDAORecordsets = NULL;
}
if (m_pDAOQueryDefs != NULL)
{
m_pDAOQueryDefs->Release();
m_pDAOQueryDefs = NULL;
}
if (m_pDAORelations != NULL)
{
m_pDAORelations->Release();
m_pDAORelations = NULL;
}
if (m_pDAOTableDefs != NULL)
{
m_pDAOTableDefs->Release();
m_pDAOTableDefs = NULL;
}
// Close any Open CDaoRecordsets
void* pvKey;
void* pvObject;
POSITION pos = m_mapRecordsets.GetStartPosition();
while (pos != NULL)
{
m_mapRecordsets.GetNextAssoc(pos, pvKey, pvObject);
((CDaoRecordset*)pvObject)->Close();
}
m_mapRecordsets.RemoveAll();
// Close any Open CDaoQueryDefs
pos = m_mapQueryDefs.GetStartPosition();
while (pos != NULL)
{
m_mapQueryDefs.GetNextAssoc(pos, pvKey, pvObject);
((CDaoQueryDef*)pvObject)->Close();
}
m_mapQueryDefs.RemoveAll();
// Close any Open CDaoTableDefs
pos = m_mapTableDefs.GetStartPosition();
while (pos != NULL)
{
m_mapTableDefs.GetNextAssoc(pos, pvKey, pvObject);
((CDaoTableDef*)pvObject)->Close();
}
m_mapTableDefs.RemoveAll();
if (m_pDAODatabase != NULL)
{
// If implicit database, don't close.
// It will be automatically closed when ref count 0.
if (!(m_nStatus & AFX_DAO_IMPLICIT_DB))
DAO_TRACE(m_pDAODatabase->Close());
m_pDAODatabase->Release();
m_pDAODatabase = NULL;
}
m_bOpen = FALSE;
// Remove the CDaoDatabase from the CDaoWorkspace's map
m_pWorkspace->m_mapDatabases.RemoveKey(this);
}
BOOL CDaoDatabase::CanUpdate()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAODatabase != NULL);
short nUpdatable;
DAO_CHECK(m_pDAODatabase->get_Updatable(&nUpdatable));
return nUpdatable == AFX_DAO_TRUE;
}
BOOL CDaoDatabase::CanTransact()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAODatabase != NULL);
short nTransactable;
DAO_CHECK(m_pDAODatabase->get_Transactions(&nTransactable));
return nTransactable == AFX_DAO_TRUE;
}
CString CDaoDatabase::GetName()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAODatabase != NULL);
COleVariant var;
DAO_CHECK(m_pDAODatabase->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
CString CDaoDatabase::GetConnect()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAODatabase != NULL);
COleVariant var;
DAO_CHECK(m_pDAODatabase->get_Connect(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
CString CDaoDatabase::GetVersion()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAODatabase != NULL);
COleVariant var;
DAO_CHECK(m_pDAODatabase->get_Version(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
short CDaoDatabase::GetQueryTimeout()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAODatabase != NULL);
short nQueryTimeout;
DAO_CHECK(m_pDAODatabase->get_QueryTimeout(&nQueryTimeout));
return nQueryTimeout;
}
void CDaoDatabase::SetQueryTimeout(short nSeconds)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAODatabase != NULL);
DAO_CHECK(m_pDAODatabase->put_QueryTimeout(nSeconds));
}
long CDaoDatabase::GetRecordsAffected()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAODatabase != NULL);
long lRecordsAffected;
DAO_CHECK(m_pDAODatabase->get_RecordsAffected(&lRecordsAffected));
return lRecordsAffected;
}
void CDaoDatabase::DeleteTableDef(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
if (m_pDAOTableDefs == NULL)
InitTableDefsCollection();
COleVariant var(lpszName, VT_BSTRT);
DAO_CHECK(m_pDAOTableDefs->Delete(V_BSTR(&var)));
}
void CDaoDatabase::DeleteQueryDef(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
if (m_pDAOQueryDefs == NULL)
InitQueryDefsCollection();
COleVariant var(lpszName, VT_BSTRT);
DAO_CHECK(m_pDAOQueryDefs->Delete(V_BSTR(&var)));
}
void CDaoDatabase::CreateRelation(LPCTSTR lpszName, LPCTSTR lpszTable,
LPCTSTR lpszForeignTable, long lAttributes, LPCTSTR lpszField,
LPCTSTR lpszForeignField)
{
ASSERT_VALID(this);
CDaoRelationInfo relinfo;
CDaoRelationFieldInfo fieldinfo;
relinfo.m_strName = lpszName;
relinfo.m_strTable = lpszTable;
relinfo.m_strForeignTable = lpszForeignTable;
relinfo.m_lAttributes = lAttributes;
relinfo.m_nFields = 1;
relinfo.m_pFieldInfos = &fieldinfo;
relinfo.m_pFieldInfos->m_strName = lpszField;
relinfo.m_pFieldInfos->m_strForeignName = lpszForeignField;
CreateRelation(relinfo);
}
void CDaoDatabase::CreateRelation(CDaoRelationInfo& relinfo)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(relinfo.m_nFields > 0);
// Initialize relations collection so that relation can be appended later
if (m_pDAORelations == NULL)
InitRelationsCollection();
DAORelation* pDAORelation = NULL;
DAOFields* pDAOFields = NULL;
DAOField* pDAOField = NULL;
// Create the relation
DAO_CHECK(m_pDAODatabase->CreateRelation(
COleVariant(relinfo.m_strName, VT_BSTRT),
COleVariant(relinfo.m_strTable, VT_BSTRT),
COleVariant(relinfo.m_strForeignTable, VT_BSTRT),
COleVariant(relinfo.m_lAttributes), &pDAORelation));
TRY
{
// Get the fields collection for later append of created field
DAO_CHECK(pDAORelation->get_Fields(&pDAOFields));
// Create field(s) and set the name and foreign name
for (int nIndex = 0; nIndex < relinfo.m_nFields; nIndex++)
{
DAO_CHECK(pDAORelation->CreateField(
COleVariant(relinfo.m_pFieldInfos[nIndex].m_strName, VT_BSTRT),
_afxOptionalVariant, _afxOptionalVariant, &pDAOField));
COleVariant var(relinfo.m_pFieldInfos[nIndex].m_strForeignName, VT_BSTRT);
DAO_CHECK(pDAOField->put_ForeignName(V_BSTR(&var)));
// Append the field to relation fields collection and release
DAO_CHECK(pDAOFields->Append(pDAOField));
pDAOField->Release();
}
DAO_CHECK(m_pDAORelations->Append(pDAORelation));
}
CATCH_ALL(e)
{
// Clean up before throw
if (pDAOField != NULL)
pDAOField->Release();
if (pDAOFields != NULL)
pDAOFields->Release();
pDAORelation->Release();
THROW_LAST();
}
END_CATCH_ALL
// Clean up
if (pDAOField != NULL)
pDAOField->Release();
pDAOFields->Release();
pDAORelation->Release();
}
void CDaoDatabase::DeleteRelation(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
if (m_pDAORelations == NULL)
InitRelationsCollection();
COleVariant var(lpszName, VT_BSTRT);
DAO_CHECK(m_pDAORelations->Delete(V_BSTR(&var)));
}
void CDaoDatabase::Execute(LPCTSTR lpszSQL, int nOptions)
{
ASSERT_VALID(this);
ASSERT(m_pDAODatabase != NULL);
COleVariant var(lpszSQL, VT_BSTRT);
DAO_CHECK(m_pDAODatabase->Execute(
V_BSTR(&var), COleVariant((long)nOptions)));
}
short CDaoDatabase::GetTableDefCount()
{
ASSERT_VALID(this);
short nTables;
if (m_pDAOTableDefs == NULL)
InitTableDefsCollection();
DAO_CHECK(m_pDAOTableDefs->get_Count(&nTables));
return nTables;
}
void CDaoDatabase::GetTableDefInfo(int nIndex, CDaoTableDefInfo& tabledefinfo,
DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOTableDefs == NULL)
InitTableDefsCollection();
// Get DAOTableDef object and fill in table info struct
DAOTableDef* pDAOTableDef;
DAO_CHECK(m_pDAOTableDefs->get_Item(
COleVariant((long)nIndex), &pDAOTableDef));
FillTableDefInfo(pDAOTableDef, tabledefinfo, dwInfoOptions);
// Clean up
pDAOTableDef->Release();
}
void CDaoDatabase::GetTableDefInfo(LPCTSTR lpszName,
CDaoTableDefInfo& tabledefinfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOTableDefs == NULL)
InitTableDefsCollection();
// Get DAOTableDef object and fill in table info struct
DAOTableDef* pDAOTableDef;
DAO_CHECK(m_pDAOTableDefs->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOTableDef));
FillTableDefInfo(pDAOTableDef, tabledefinfo, dwInfoOptions);
// Clean up
pDAOTableDef->Release();
}
short CDaoDatabase::GetRelationCount()
{
ASSERT_VALID(this);
short nRelations;
if (m_pDAORelations == NULL)
InitRelationsCollection();
DAO_CHECK(m_pDAORelations->get_Count(&nRelations));
return nRelations;
}
void CDaoDatabase::GetRelationInfo(int nIndex, CDaoRelationInfo& relinfo,
DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAORelations == NULL)
InitRelationsCollection();
// Get DAORelation object and fill in relation info struct
DAORelation* pDAORelation;
DAO_CHECK(m_pDAORelations->get_Item(
COleVariant((long)nIndex), &pDAORelation));
FillRelationInfo(pDAORelation, relinfo, dwInfoOptions);
// Clean up
pDAORelation->Release();
}
void CDaoDatabase::GetRelationInfo(LPCTSTR lpszName,
CDaoRelationInfo& relinfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAORelations == NULL)
InitRelationsCollection();
// Get DAORelation object and fill in relation info struct
DAORelation* pDAORelation;
DAO_CHECK(m_pDAORelations->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAORelation));
FillRelationInfo(pDAORelation, relinfo, dwInfoOptions);
// Clean up
pDAORelation->Release();
}
short CDaoDatabase::GetQueryDefCount()
{
ASSERT_VALID(this);
short nQueryDefs;
if (m_pDAOQueryDefs == NULL)
InitQueryDefsCollection();
DAO_CHECK(m_pDAOQueryDefs->get_Count(&nQueryDefs));
return nQueryDefs;
}
void CDaoDatabase::GetQueryDefInfo(int nIndex, CDaoQueryDefInfo& querydefinfo,
DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOQueryDefs == NULL)
InitQueryDefsCollection();
// Get DAOQueryDef object and fill in query info struct
DAOQueryDef* pDAOQueryDef;
DAO_CHECK(m_pDAOQueryDefs->get_Item(
COleVariant((long)nIndex), &pDAOQueryDef));
FillQueryDefInfo(pDAOQueryDef, querydefinfo, dwInfoOptions);
// Clean up
pDAOQueryDef->Release();
}
void CDaoDatabase::GetQueryDefInfo(LPCTSTR lpszName,
CDaoQueryDefInfo& querydefinfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOQueryDefs == NULL)
InitQueryDefsCollection();
// Get DAOQueryDef object and fill in query info struct
DAOQueryDef* pDAOQueryDef;
DAO_CHECK(m_pDAOQueryDefs->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOQueryDef));
FillQueryDefInfo(pDAOQueryDef, querydefinfo, dwInfoOptions);
// Clean up
pDAOQueryDef->Release();
}
// Implementation
void CDaoDatabase::InitWorkspace()
{
ASSERT_VALID(this);
if (m_pWorkspace == NULL)
{
// Allocate workspace and mark as implicit
m_pWorkspace = new CDaoWorkspace;
m_pWorkspace->m_nStatus |= AFX_DAO_IMPLICIT_WS;
m_nStatus |= AFX_DAO_IMPLICIT_WS;
}
// Open workspace if not open and not new (unappended)
if (!m_pWorkspace->IsOpen() && !m_pWorkspace->IsNew())
{
// Open the default workspace
m_pWorkspace->Open();
}
}
void CDaoDatabase::InitTableDefsCollection()
{
ASSERT_VALID(this);
DAO_CHECK(m_pDAODatabase->get_TableDefs(&m_pDAOTableDefs));
}
void CDaoDatabase::FillTableDefInfo(DAOTableDef* pDAOTableDef,
CDaoTableDefInfo& tabledefinfo, DWORD dwOptions)
{
ASSERT_VALID(this);
ASSERT(pDAOTableDef != NULL);
ASSERT(dwOptions != 0);
COleVariant var;
short nBool;
if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
{
DAO_CHECK(pDAOTableDef->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
tabledefinfo.m_strName = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOTableDef->get_Updatable(&nBool));
tabledefinfo.m_bUpdatable = nBool == AFX_DAO_TRUE;
DAO_CHECK(pDAOTableDef->get_Attributes(
&tabledefinfo.m_lAttributes));
}
if (dwOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
{
DAO_CHECK(pDAOTableDef->get_DateCreated(&var));
tabledefinfo.m_dateCreated = var;
DAO_CHECK(pDAOTableDef->get_LastUpdated(&var));
tabledefinfo.m_dateLastUpdated = var;
DAO_CHECK(pDAOTableDef->get_SourceTableName(
&V_BSTR(&var)));
var.vt = VT_BSTR;
tabledefinfo.m_strSrcTableName = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOTableDef->get_Connect(
&V_BSTR(&var)));
var.vt = VT_BSTR;
tabledefinfo.m_strConnect = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOTableDef->get_ValidationRule(
&V_BSTR(&var)));
var.vt = VT_BSTR;
tabledefinfo.m_strValidationRule = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOTableDef->get_ValidationText(
&V_BSTR(&var)));
var.vt = VT_BSTR;
tabledefinfo.m_strValidationText = V_BSTRT(&var);
var.Clear();
}
// This may be expensive, so only get it if absolutely necessary
if (dwOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
{
DAO_CHECK(pDAOTableDef->get_RecordCount(
&tabledefinfo.m_lRecordCount));
}
}
void CDaoDatabase::InitRelationsCollection()
{
ASSERT_VALID(this);
DAO_CHECK(m_pDAODatabase->get_Relations(&m_pDAORelations));
}
void CDaoDatabase::FillRelationInfo(DAORelation* pDAORelation,
CDaoRelationInfo& relinfo, DWORD dwOptions)
{
ASSERT_VALID(this);
ASSERT(pDAORelation != NULL);
ASSERT(dwOptions != 0);
COleVariant var;
if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
{
// All the relation info is primary
DAO_CHECK(pDAORelation->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
relinfo.m_strName = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAORelation->get_Table(&V_BSTR(&var)));
var.vt = VT_BSTR;
relinfo.m_strTable = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAORelation->get_ForeignTable(
&V_BSTR(&var)));
var.vt = VT_BSTR;
relinfo.m_strForeignTable = V_BSTRT(&var);
var.Clear();
}
if (dwOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
{
DAOFields* pDAOFields = NULL;
DAOField* pDAOField = NULL;
DAO_CHECK(pDAORelation->get_Attributes(
&relinfo.m_lAttributes));
// Get the fields collection
DAO_CHECK(pDAORelation->get_Fields(&pDAOFields));
TRY
{
// Get the number of fields in the relation
short nCount;
DAO_CHECK(pDAOFields->get_Count(&nCount));
// Allocate or reallocate memory for array if necessary
if (nCount != relinfo.m_nFields)
{
if (relinfo.m_nFields != 0)
{
// Check that allocation is correct.
ASSERT(relinfo.m_nFields == 0 ||
relinfo.m_bCleanupFieldInfo);
delete[] relinfo.m_pFieldInfos;
relinfo.m_pFieldInfos = NULL;
}
// Now allocate required memory
relinfo.m_pFieldInfos = new CDaoRelationFieldInfo[nCount];
relinfo.m_bCleanupFieldInfo = TRUE;
relinfo.m_nFields = nCount;
}
// Now get field info for each field
for (int nIndex = 0; nIndex < relinfo.m_nFields; nIndex++)
{
// Get the field item
DAO_CHECK(pDAOFields->get_Item(
COleVariant((long)nIndex), &pDAOField));
// Get the field name
DAO_CHECK(pDAOField->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
relinfo.m_pFieldInfos[nIndex].m_strName =
V_BSTRT(&var);
var.Clear();
// Get the foreign field name
DAO_CHECK(pDAOField->get_ForeignName(&V_BSTR(&var)));
var.vt = VT_BSTR;
relinfo.m_pFieldInfos[nIndex].m_strForeignName =
V_BSTRT(&var);
var.Clear();
// Release and reset the field object
pDAOField->Release();
pDAOField = NULL;
}
}
CATCH_ALL(e)
{
if (pDAOField != NULL)
pDAOField->Release();
pDAOFields->Release();
THROW_LAST();
}
END_CATCH_ALL
// Release the objects
pDAOFields->Release();
}
}
void CDaoDatabase::InitQueryDefsCollection()
{
ASSERT_VALID(this);
DAO_CHECK(m_pDAODatabase->get_QueryDefs(&m_pDAOQueryDefs));
}
void CDaoDatabase::FillQueryDefInfo(DAOQueryDef* pDAOQueryDef,
CDaoQueryDefInfo& querydefinfo, DWORD dwOptions)
{
ASSERT_VALID(this);
ASSERT(pDAOQueryDef != NULL);
ASSERT(dwOptions != 0);
COleVariant var;
short nBool;
if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
{
DAO_CHECK(pDAOQueryDef->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
querydefinfo.m_strName = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOQueryDef->get_Type(&querydefinfo.m_nType));
}
if (dwOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
{
DAO_CHECK(pDAOQueryDef->get_Updatable(&nBool));
querydefinfo.m_bUpdatable = nBool == AFX_DAO_TRUE;
DAO_CHECK(pDAOQueryDef->get_DateCreated(&var));
querydefinfo.m_dateCreated = var;
DAO_CHECK(pDAOQueryDef->get_LastUpdated(&var));
querydefinfo.m_dateLastUpdated = var;
DAO_CHECK(pDAOQueryDef->get_ReturnsRecords(&nBool));
querydefinfo.m_bReturnsRecords = nBool == AFX_DAO_TRUE;
}
if (dwOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
{
DAO_CHECK(pDAOQueryDef->get_SQL(&V_BSTR(&var)));
var.vt = VT_BSTR;
querydefinfo.m_strSQL = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOQueryDef->get_Connect(&V_BSTR(
(LPVARIANT)var)));
var.vt = VT_BSTR;
querydefinfo.m_strConnect = V_BSTRT(&var);
var.Clear();
// DAO will display ODBC connect dialog
// if data source no longer exists. This must
// be avoided during bulk info retrieval.
// Call CDaoQueryDef::GetODBCTimeout directly.
// DAO_CHECK(pDAOQueryDef->get_ODBCTimeout(
// &querydefinfo.m_nODBCTimeout));
// Set the m_nODBCTimeout variable to invalid value.
querydefinfo.m_nODBCTimeout = -1;
}
}
void CDaoDatabase::ThrowDaoException(int nAfxDaoError)
{
ASSERT_VALID(this);
AfxThrowDaoException(nAfxDaoError);
}
#ifdef _DEBUG
void CDaoDatabase::AssertValid() const
{
CObject::AssertValid();
}
void CDaoDatabase::Dump(CDumpContext& dc) const
{
ASSERT_VALID(this);
CObject::Dump(dc);
dc << "m_bOpen = " << m_bOpen;
dc << "\nm_nStatus = " << m_nStatus;
dc << "\n";
}
#endif //_DEBUG
//////////////////////////////////////////////////////////////////////////
// CDaoTableDef
IMPLEMENT_DYNAMIC(CDaoTableDef, CObject)
CDaoTableDef::CDaoTableDef(CDaoDatabase* pDatabase)
{
m_bOpen = FALSE;
m_bNew = FALSE;
m_pDatabase = pDatabase;
m_pDAOTableDef = NULL;
m_pDAOFields = NULL;
m_pDAOIndexes = NULL;
}
CDaoTableDef::~CDaoTableDef()
{
if (IsOpen())
Close();
else if (m_bNew)
{
// Remove the tabledef from the CDaoDatabase's map
m_pDatabase->m_mapTableDefs.RemoveKey(this);
}
}
void CDaoTableDef::Create(LPCTSTR lpszName, long lAttributes,
LPCTSTR lpszSrcTable, LPCTSTR lpszConnect)
{
ASSERT_VALID(this);
ASSERT(!IsOpen());
DAO_CHECK(m_pDatabase->m_pDAODatabase->CreateTableDef(
COleVariant(lpszName, VT_BSTRT), COleVariant(lAttributes),
COleVariant(lpszSrcTable, VT_BSTRT),
COleVariant(lpszConnect, VT_BSTRT), &m_pDAOTableDef));
m_bNew = TRUE;
// Add the tabledef to map of Open/New CDaoTableDefs
m_pDatabase->m_mapTableDefs.SetAt(this, this);
}
void CDaoTableDef::Append()
{
ASSERT_VALID(this);
ASSERT(m_bNew);
ASSERT(m_pDAOTableDef != NULL);
DAOTableDefs* pDAOTableDefs;
DAO_CHECK(m_pDatabase->m_pDAODatabase->get_TableDefs(
&pDAOTableDefs));
TRY
{
DAO_CHECK(pDAOTableDefs->Append(m_pDAOTableDef));
}
CATCH_ALL(e)
{
pDAOTableDefs->Release();
THROW_LAST();
}
END_CATCH_ALL
pDAOTableDefs->Release();
m_bNew = FALSE;
m_bOpen = TRUE;
}
void CDaoTableDef::Open(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(lpszName != NULL);
// Re-open is invalid
if (IsOpen())
{
ASSERT(FALSE);
return;
}
DAOTableDefs* pDAOTableDefs = NULL;
TRY
{
DAO_CHECK(m_pDatabase->m_pDAODatabase->get_TableDefs(
&pDAOTableDefs));
DAO_CHECK(pDAOTableDefs->get_Item(
COleVariant(lpszName, VT_BSTRT),&m_pDAOTableDef));
}
CATCH_ALL(e)
{
if (pDAOTableDefs != NULL)
pDAOTableDefs->Release();
THROW_LAST();
}
END_CATCH_ALL
pDAOTableDefs->Release();
m_bOpen = TRUE;
// Add the tabledef to map of Open/New CDaoTableDefs
m_pDatabase->m_mapTableDefs.SetAt(this, this);
}
void CDaoTableDef::Close()
{
ASSERT_VALID(this);
if (m_pDAOIndexes != NULL)
{
m_pDAOIndexes->Release();
m_pDAOIndexes = NULL;
}
if (m_pDAOFields != NULL)
{
m_pDAOFields->Release();
m_pDAOFields = NULL;
}
if (m_pDAOTableDef != NULL)
{
m_pDAOTableDef->Release();
m_pDAOTableDef = NULL;
}
m_bOpen = FALSE;
m_bNew = FALSE;
// Remove the tabledef from the CDaoDatabase's map
m_pDatabase->m_mapTableDefs.RemoveKey(this);
}
BOOL CDaoTableDef::CanUpdate()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
short nUpdatable;
DAO_CHECK(m_pDAOTableDef->get_Updatable(&nUpdatable));
return nUpdatable == AFX_DAO_TRUE;
}
void CDaoTableDef::SetName(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
ASSERT(m_pDAOTableDef != NULL);
COleVariant var(lpszName, VT_BSTRT);
DAO_CHECK(m_pDAOTableDef->put_Name(V_BSTR(&var)));
}
CString CDaoTableDef::GetName()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
COleVariant var;
DAO_CHECK(m_pDAOTableDef->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
void CDaoTableDef::SetSourceTableName(LPCTSTR lpszSrcTableName)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
ASSERT(m_pDAOTableDef != NULL);
COleVariant var(lpszSrcTableName, VT_BSTRT);
DAO_CHECK(m_pDAOTableDef->put_SourceTableName(
V_BSTR(&var)));
}
CString CDaoTableDef::GetSourceTableName()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
COleVariant var;
DAO_CHECK(m_pDAOTableDef->get_SourceTableName(
&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
void CDaoTableDef::SetConnect(LPCTSTR lpszConnect)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
ASSERT(m_pDAOTableDef != NULL);
COleVariant var(lpszConnect, VT_BSTRT);
DAO_CHECK(m_pDAOTableDef->put_Connect(V_BSTR(&var)));
}
CString CDaoTableDef::GetConnect()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
COleVariant var;
DAO_CHECK(m_pDAOTableDef->get_Connect(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
void CDaoTableDef::SetAttributes(long lAttributes)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
ASSERT(m_pDAOTableDef != NULL);
DAO_CHECK(m_pDAOTableDef->put_Attributes(lAttributes));
}
long CDaoTableDef::GetAttributes()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
long lAttributes;
DAO_CHECK(m_pDAOTableDef->get_Attributes(&lAttributes));
return lAttributes;
}
COleDateTime CDaoTableDef::GetDateCreated()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
COleVariant varDate;
DAO_CHECK(m_pDAOTableDef->get_DateCreated(&varDate));
return varDate.date;
}
COleDateTime CDaoTableDef::GetDateLastUpdated()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
COleVariant varDate;
DAO_CHECK(m_pDAOTableDef->get_LastUpdated(&varDate));
return varDate.date;
}
void CDaoTableDef::SetValidationRule(
LPCTSTR lpszValidationRule)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
ASSERT(m_pDAOTableDef != NULL);
COleVariant var(lpszValidationRule, VT_BSTRT);
DAO_CHECK(m_pDAOTableDef->put_ValidationRule(
V_BSTR(&var)));
}
CString CDaoTableDef::GetValidationRule()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
COleVariant var;
DAO_CHECK(m_pDAOTableDef->get_ValidationRule(
&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
void CDaoTableDef::SetValidationText(
LPCTSTR lpszValidationText)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
ASSERT(m_pDAOTableDef != NULL);
COleVariant var(lpszValidationText, VT_BSTRT);
DAO_CHECK(m_pDAOTableDef->put_ValidationText(
V_BSTR(&var)));
}
CString CDaoTableDef::GetValidationText()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
COleVariant var;
DAO_CHECK(m_pDAOTableDef->get_ValidationText(
&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
long CDaoTableDef::GetRecordCount()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
long lRecordCount;
DAO_CHECK(m_pDAOTableDef->get_RecordCount(&lRecordCount));
return lRecordCount;
}
void CDaoTableDef::CreateField(LPCTSTR lpszName, short nType, long lSize,
long lAttributes)
{
ASSERT_VALID(this);
CDaoFieldInfo fieldinfo;
// Initialize everything so only correct properties will be set
fieldinfo.m_strName = lpszName;
fieldinfo.m_nType = nType;
fieldinfo.m_lSize = lSize;
fieldinfo.m_lAttributes = lAttributes;
fieldinfo.m_nOrdinalPosition = 0;
fieldinfo.m_bRequired = FALSE;
fieldinfo.m_bAllowZeroLength = FALSE;
fieldinfo.m_lCollatingOrder = 0;
CreateField(fieldinfo);
}
void CDaoTableDef::CreateField(CDaoFieldInfo& fieldinfo)
{
ASSERT_VALID(this);
DAOField* pDAOField;
// Create the DAO field object (setting basic properties)
DAO_CHECK(m_pDAOTableDef->CreateField(
COleVariant(fieldinfo.m_strName, VT_BSTRT),
COleVariant(fieldinfo.m_nType),
COleVariant(fieldinfo.m_lSize), &pDAOField));
TRY
{
// Basic properties already set, so set the rest
AfxSetFieldInfo(pDAOField, fieldinfo);
// Append the field object to the fields collection
if (m_pDAOFields == NULL)
InitFieldsCollection();
DAO_CHECK(m_pDAOFields->Append(pDAOField));
}
CATCH_ALL(e)
{
pDAOField->Release();
THROW_LAST();
}
END_CATCH_ALL
pDAOField->Release();
}
void CDaoTableDef::DeleteField(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(lpszName != NULL);
if (m_pDAOFields == NULL)
InitFieldsCollection();
COleVariant var(lpszName, VT_BSTRT);
DAO_CHECK(m_pDAOFields->Delete(V_BSTR(&var)));
}
void CDaoTableDef::DeleteField(int nIndex)
{
ASSERT_VALID(this);
CDaoFieldInfo fieldinfo;
GetFieldInfo(nIndex, fieldinfo, AFX_DAO_PRIMARY_INFO);
DeleteField((LPCTSTR)fieldinfo.m_strName);
}
void CDaoTableDef::CreateIndex(CDaoIndexInfo& indexinfo)
{
ASSERT_VALID(this);
DAOIndex* pDAOIndex;
DAO_CHECK(m_pDAOTableDef->CreateIndex(
COleVariant(indexinfo.m_strName, VT_BSTRT), &pDAOIndex));
TRY
{
// Set the index info
AfxSetIndexInfo(pDAOIndex, indexinfo);
// Append the field object to the fields collection
if (m_pDAOIndexes == NULL)
InitIndexesCollection();
DAO_CHECK(m_pDAOIndexes->Append(pDAOIndex));
}
CATCH_ALL(e)
{
pDAOIndex->Release();
THROW_LAST();
}
END_CATCH_ALL
pDAOIndex->Release();
}
void CDaoTableDef::DeleteIndex(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(lpszName != NULL);
if (m_pDAOIndexes == NULL)
InitIndexesCollection();
COleVariant var(lpszName, VT_BSTRT);
DAO_CHECK(m_pDAOIndexes->Delete(V_BSTR(&var)));
}
void CDaoTableDef::DeleteIndex(int nIndex)
{
ASSERT_VALID(this);
CDaoIndexInfo indexinfo;
GetIndexInfo(nIndex, indexinfo, AFX_DAO_PRIMARY_INFO);
DeleteIndex((LPCTSTR)indexinfo.m_strName);
}
short CDaoTableDef::GetFieldCount()
{
ASSERT_VALID(this);
short nFields;
if (m_pDAOFields == NULL)
InitFieldsCollection();
DAO_CHECK(m_pDAOFields->get_Count(&nFields));
return nFields;
}
void CDaoTableDef::GetFieldInfo(int nIndex, CDaoFieldInfo& fieldinfo,
DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOFields == NULL)
InitFieldsCollection();
// Get DAOField object and fill in field info struct
DAOField* pDAOField;
DAO_CHECK(m_pDAOFields->get_Item(
COleVariant((long)nIndex), &pDAOField));
AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
// Clean up
pDAOField->Release();
}
void CDaoTableDef::GetFieldInfo(LPCTSTR lpszName,
CDaoFieldInfo& fieldinfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOFields == NULL)
InitFieldsCollection();
// Get DAOField object and fill in field info struct
DAOField* pDAOField;
DAO_CHECK(m_pDAOFields->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOField));
AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
// Clean up
pDAOField->Release();
}
short CDaoTableDef::GetIndexCount()
{
ASSERT_VALID(this);
short nIndexes;
if (m_pDAOIndexes == NULL)
InitIndexesCollection();
DAO_CHECK(m_pDAOIndexes->get_Count(&nIndexes));
return nIndexes;
}
void CDaoTableDef::GetIndexInfo(int nIndex, CDaoIndexInfo& indexinfo,
DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOIndexes == NULL)
InitIndexesCollection();
// Get DAOField object and fill in field info struct
DAOIndex* pDAOIndex;
DAO_CHECK(m_pDAOIndexes->get_Item(
COleVariant((long)nIndex), &pDAOIndex));
AfxGetIndexInfo(pDAOIndex, indexinfo, dwInfoOptions);
// Clean up
pDAOIndex->Release();
}
void CDaoTableDef::GetIndexInfo(LPCTSTR lpszName,
CDaoIndexInfo& indexinfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOIndexes == NULL)
InitIndexesCollection();
// Get DAOField object and fill in field info struct
DAOIndex* pDAOIndex;
DAO_CHECK(m_pDAOIndexes->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOIndex));
AfxGetIndexInfo(pDAOIndex, indexinfo, dwInfoOptions);
// Clean up
pDAOIndex->Release();
}
void CDaoTableDef::RefreshLink()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOTableDef != NULL);
DAO_CHECK(m_pDAOTableDef->RefreshLink());
}
//Implementation functions
void CDaoTableDef::InitFieldsCollection()
{
ASSERT_VALID(this);
DAO_CHECK(m_pDAOTableDef->get_Fields(&m_pDAOFields));
}
void CDaoTableDef::InitIndexesCollection()
{
ASSERT_VALID(this);
DAO_CHECK(m_pDAOTableDef->get_Indexes(&m_pDAOIndexes));
}
void CDaoTableDef::ThrowDaoException(int nAfxDaoError)
{
ASSERT_VALID(this);
AfxThrowDaoException(nAfxDaoError);
}
#ifdef _DEBUG
void CDaoTableDef::AssertValid() const
{
CObject::AssertValid();
}
void CDaoTableDef::Dump(CDumpContext& dc) const
{
ASSERT_VALID(this);
CObject::Dump(dc);
dc << "m_bOpen = " << m_bOpen;
dc << "\nm_bNew = " << m_bNew;
dc << "\n";
}
#endif //_DEBUG
//////////////////////////////////////////////////////////////////////////
// CDaoQueryDef
IMPLEMENT_DYNAMIC(CDaoQueryDef, CObject)
CDaoQueryDef::CDaoQueryDef(CDaoDatabase* pDatabase)
{
m_bOpen = FALSE;
m_bNew = FALSE;
m_pDatabase = pDatabase;
m_pDAOQueryDef = NULL;
m_pDAOParameters = NULL;
m_pDAOFields = NULL;
}
CDaoQueryDef::~CDaoQueryDef()
{
if (IsOpen())
Close();
else if (m_bNew)
{
// Remove the querydef from the CDaoDatabase's map
m_pDatabase->m_mapQueryDefs.RemoveKey(this);
}
}
void CDaoQueryDef::Create(LPCTSTR lpszName, LPCTSTR lpszSQL)
{
ASSERT_VALID(this);
ASSERT(!IsOpen());
// Create a temp querydef if lpszName is NULL or empty string
if (lpszName == NULL || *lpszName == '\0')
{
DAO_CHECK(m_pDatabase->m_pDAODatabase->CreateQueryDef(
COleVariant(_T(""), VT_BSTRT),
COleVariant(lpszSQL, VT_BSTRT),
&m_pDAOQueryDef));
m_bOpen = TRUE;
}
else
{
// Create a template querydef
// (preventing automatic append to QueryDefs collection)
DAO_CHECK(m_pDatabase->m_pDAODatabase->CreateQueryDef(
_afxOptionalVariant, _afxOptionalVariant, &m_pDAOQueryDef));
m_bNew = TRUE;
// Now set the name and SQL if necessary
SetName(lpszName);
if (lpszSQL != NULL)
SetSQL(lpszSQL);
}
// Add the querydef to map of Open/New CDaoQueryDefs
m_pDatabase->m_mapQueryDefs.SetAt(this, this);
}
void CDaoQueryDef::Append()
{
ASSERT_VALID(this);
ASSERT(m_bNew);
ASSERT(m_pDAOQueryDef != NULL);
DAOQueryDefs* pDAOQueryDefs;
DAO_CHECK(m_pDatabase->m_pDAODatabase->get_QueryDefs(
&pDAOQueryDefs));
TRY
{
DAO_CHECK(pDAOQueryDefs->Append(m_pDAOQueryDef));
}
CATCH_ALL(e)
{
pDAOQueryDefs->Release();
THROW_LAST();
}
END_CATCH_ALL
pDAOQueryDefs->Release();
m_bNew = FALSE;
m_bOpen = TRUE;
}
// Open a pre-defined query or create a temp query
void CDaoQueryDef::Open(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(!m_bNew);
// Re-open is not allowed
if (IsOpen())
{
ASSERT(FALSE);
return;
}
// Null lpszName implies create a temp query
if (lpszName == NULL)
{
DAO_CHECK(m_pDatabase->m_pDAODatabase->CreateQueryDef(
COleVariant(_T(""), VT_BSTRT), _afxOptionalVariant, &m_pDAOQueryDef));
}
else
{
COleVariant varName(lpszName, VT_BSTRT);
DAO_CHECK(m_pDatabase->m_pDAODatabase->OpenQueryDef(
V_BSTR(&varName), &m_pDAOQueryDef));
}
m_bOpen = TRUE;
// Add the querydef to map of Open/New CDaoQueryDefs
m_pDatabase->m_mapQueryDefs.SetAt(this, this);
}
void CDaoQueryDef::Close()
{
ASSERT_VALID(this);
if (m_pDAOParameters != NULL)
{
m_pDAOParameters->Release();
m_pDAOParameters = NULL;
}
if (m_pDAOFields != NULL)
{
m_pDAOFields->Release();
m_pDAOFields = NULL;
}
if (m_pDAOQueryDef != NULL)
{
// DAO Close is a no op, but call it anyway
DAO_TRACE(m_pDAOQueryDef->Close());
m_pDAOQueryDef->Release();
m_pDAOQueryDef = NULL;
}
m_bOpen = FALSE;
m_bNew = FALSE;
// Remove the querydef from the CDaoDatabase's map
m_pDatabase->m_mapQueryDefs.RemoveKey(this);
}
BOOL CDaoQueryDef::CanUpdate()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
short nUpdatable;
DAO_CHECK(m_pDAOQueryDef->get_Updatable(&nUpdatable));
return nUpdatable == AFX_DAO_TRUE;
}
CString CDaoQueryDef::GetName()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
COleVariant var;
DAO_CHECK(m_pDAOQueryDef->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
void CDaoQueryDef::SetName(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
COleVariant var(lpszName, VT_BSTRT);
DAO_CHECK(m_pDAOQueryDef->put_Name(V_BSTR(&var)));
}
CString CDaoQueryDef::GetSQL()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
COleVariant var;
DAO_CHECK(m_pDAOQueryDef->get_SQL(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
void CDaoQueryDef::SetSQL(LPCTSTR lpszSQL)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
COleVariant var(lpszSQL, VT_BSTRT);
DAO_CHECK(m_pDAOQueryDef->put_SQL(V_BSTR(&var)));
}
short CDaoQueryDef::GetType()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
short nType;
DAO_CHECK(m_pDAOQueryDef->get_Type(&nType));
return nType;
}
COleDateTime CDaoQueryDef::GetDateCreated()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
COleVariant varDate;
DAO_CHECK(m_pDAOQueryDef->get_DateCreated(&varDate));
return varDate.date;
}
COleDateTime CDaoQueryDef::GetDateLastUpdated()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
COleVariant varDate;
DAO_CHECK(m_pDAOQueryDef->get_LastUpdated(&varDate));
return varDate.date;
}
CString CDaoQueryDef::GetConnect()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
COleVariant var;
DAO_CHECK(m_pDAOQueryDef->get_Connect(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
void CDaoQueryDef::SetConnect(LPCTSTR lpszConnect)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
COleVariant var(lpszConnect, VT_BSTRT);
DAO_CHECK(m_pDAOQueryDef->put_Connect(V_BSTR(&var)));
}
short CDaoQueryDef::GetODBCTimeout()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
short nTimeout;
DAO_CHECK(m_pDAOQueryDef->get_ODBCTimeout(&nTimeout));
return nTimeout;
}
void CDaoQueryDef::SetODBCTimeout(short nODBCTimeout)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
DAO_CHECK(m_pDAOQueryDef->put_ODBCTimeout(nODBCTimeout));
}
BOOL CDaoQueryDef::GetReturnsRecords()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
short nReturnsRecords;
DAO_CHECK(m_pDAOQueryDef->get_ReturnsRecords(&nReturnsRecords));
return nReturnsRecords == AFX_DAO_TRUE;
}
void CDaoQueryDef::SetReturnsRecords(BOOL bReturnsRecords)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
DAO_CHECK(m_pDAOQueryDef->put_ReturnsRecords(
(short)(bReturnsRecords ? AFX_DAO_TRUE : AFX_DAO_FALSE)));
}
long CDaoQueryDef::GetRecordsAffected()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
long lRecordsAffected;
DAO_CHECK(m_pDAOQueryDef->get_RecordsAffected(&lRecordsAffected));
return lRecordsAffected;
}
void CDaoQueryDef::Execute(int nOptions)
{
ASSERT_VALID(this);
ASSERT(m_pDAOQueryDef != NULL);
DAO_CHECK(m_pDAOQueryDef->Execute(COleVariant((long)nOptions)));
}
COleVariant CDaoQueryDef::GetParamValue(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOQueryDef != NULL);
if (m_pDAOParameters == NULL)
InitParametersCollection();
DAOParameter* pDAOParameter = NULL;
COleVariant var;
TRY
{
DAO_CHECK(m_pDAOParameters->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOParameter));
DAO_CHECK(pDAOParameter->get_Value(&var));
}
CATCH_ALL(e)
{
if (pDAOParameter != NULL)
pDAOParameter->Release();
THROW_LAST();
}
END_CATCH_ALL
pDAOParameter->Release();
return var;
}
COleVariant CDaoQueryDef::GetParamValue(int nIndex)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAOQueryDef != NULL);
if (m_pDAOParameters == NULL)
InitParametersCollection();
DAOParameter* pDAOParameter = NULL;
COleVariant var;
TRY
{
DAO_CHECK(m_pDAOParameters->get_Item(
COleVariant((long)nIndex), &pDAOParameter));
DAO_CHECK(pDAOParameter->get_Value(&var));
}
CATCH_ALL(e)
{
if (pDAOParameter != NULL)
pDAOParameter->Release();
THROW_LAST();
}
END_CATCH_ALL
pDAOParameter->Release();
return var;
}
void CDaoQueryDef::SetParamValue(LPCTSTR lpszName,
const COleVariant& varValue)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
ASSERT(m_pDAOQueryDef != NULL);
if (m_pDAOParameters == NULL)
InitParametersCollection();
DAOParameter* pDAOParameter = NULL;
TRY
{
DAO_CHECK(m_pDAOParameters->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOParameter));
DAO_CHECK(pDAOParameter->put_Value(varValue));
}
CATCH_ALL(e)
{
if (pDAOParameter != NULL)
pDAOParameter->Release();
THROW_LAST();
}
END_CATCH_ALL
pDAOParameter->Release();
}
void CDaoQueryDef::SetParamValue(int nIndex,
const COleVariant& varValue)
{
ASSERT_VALID(this);
ASSERT(IsOpen() || m_bNew);
ASSERT(m_pDAOQueryDef != NULL);
if (m_pDAOParameters == NULL)
InitParametersCollection();
DAOParameter* pDAOParameter = NULL;
TRY
{
DAO_CHECK(m_pDAOParameters->get_Item(
COleVariant((long)nIndex), &pDAOParameter));
DAO_CHECK(pDAOParameter->put_Value(varValue));
}
CATCH_ALL(e)
{
if (pDAOParameter != NULL)
pDAOParameter->Release();
THROW_LAST();
}
END_CATCH_ALL
pDAOParameter->Release();
}
void CDaoQueryDef::SetParamValueNull(LPCTSTR lpszName)
{
ASSERT_VALID(this);
SetParamValue(lpszName, _afxNullVariant);
}
void CDaoQueryDef::SetParamValueNull(int nIndex)
{
ASSERT_VALID(this);
SetParamValue(nIndex, _afxNullVariant);
}
short CDaoQueryDef::GetFieldCount()
{
ASSERT_VALID(this);
short nFields;
if (m_pDAOFields == NULL)
InitFieldsCollection();
DAO_CHECK(m_pDAOFields->get_Count(&nFields));
return nFields;
}
void CDaoQueryDef::GetFieldInfo(int nIndex, CDaoFieldInfo& fieldinfo,
DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOFields == NULL)
InitFieldsCollection();
// Get DAOField object and fill in field info struct
DAOField* pDAOField;
DAO_CHECK(m_pDAOFields->get_Item(
COleVariant((long)nIndex), &pDAOField));
AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
// Clean up
pDAOField->Release();
}
void CDaoQueryDef::GetFieldInfo(LPCTSTR lpszName,
CDaoFieldInfo& fieldinfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOFields == NULL)
InitFieldsCollection();
// Get DAOField object and fill in field info struct
DAOField* pDAOField;
DAO_CHECK(m_pDAOFields->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOField));
AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
// Clean up
pDAOField->Release();
}
short CDaoQueryDef::GetParameterCount()
{
ASSERT_VALID(this);
short nParameters;
if (m_pDAOParameters == NULL)
InitParametersCollection();
DAO_CHECK(m_pDAOParameters->get_Count(&nParameters));
return nParameters;
}
void CDaoQueryDef::GetParameterInfo(int nIndex,
CDaoParameterInfo& paraminfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOParameters == NULL)
InitParametersCollection();
// Get DAOParameter object and fill in parameter info struct
DAOParameter* pDAOParameter;
DAO_CHECK(m_pDAOParameters->get_Item(
COleVariant((long)nIndex), &pDAOParameter));
FillParameterInfo(pDAOParameter, paraminfo, dwInfoOptions);
// Clean up
pDAOParameter->Release();
}
void CDaoQueryDef::GetParameterInfo(LPCTSTR lpszName,
CDaoParameterInfo& paraminfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOParameters == NULL)
InitParametersCollection();
// Get DAOParameter object and fill in parameter info struct
DAOParameter* pDAOParameter;
DAO_CHECK(m_pDAOParameters->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOParameter));
FillParameterInfo(pDAOParameter, paraminfo, dwInfoOptions);
// Clean up
pDAOParameter->Release();
}
//Implementation functions
void CDaoQueryDef::InitFieldsCollection()
{
ASSERT_VALID(this);
DAO_CHECK(m_pDAOQueryDef->get_Fields(&m_pDAOFields));
}
void CDaoQueryDef::InitParametersCollection()
{
ASSERT_VALID(this);
DAO_CHECK(m_pDAOQueryDef->get_Parameters(&m_pDAOParameters));
}
void CDaoQueryDef::FillParameterInfo(DAOParameter* pDAOParameter,
CDaoParameterInfo& paraminfo, DWORD dwOptions)
{
ASSERT_VALID(this);
ASSERT(pDAOParameter != NULL);
ASSERT(dwOptions != NULL);
COleVariant var;
if (dwOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
{
// All parameter info is basic info
DAO_CHECK(pDAOParameter->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
paraminfo.m_strName = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOParameter->get_Type(
&paraminfo.m_nType));
DAO_CHECK(pDAOParameter->get_Value(
&paraminfo.m_varValue));
}
}
void CDaoQueryDef::ThrowDaoException(int nAfxDaoError)
{
ASSERT_VALID(this);
AfxThrowDaoException(nAfxDaoError);
}
#ifdef _DEBUG
void CDaoQueryDef::AssertValid() const
{
CObject::AssertValid();
}
void CDaoQueryDef::Dump(CDumpContext& dc) const
{
ASSERT_VALID(this);
CObject::Dump(dc);
dc << "m_bOpen = " << m_bOpen;
dc << "\nm_bNew = " << m_bNew;
dc << "\n";
}
#endif //_DEBUG
//////////////////////////////////////////////////////////////////////////
// CDaoRecordset
IMPLEMENT_DYNAMIC(CDaoRecordset, CObject )
CDaoRecordset::CDaoRecordset(CDaoDatabase* pDatabase)
{
m_bOpen = FALSE;
m_pMapFieldCache = NULL;
m_pMapFieldIndex = NULL;
m_bCheckCacheForDirtyFields = TRUE;
m_prgDaoColBindInfo = NULL;
m_pulColumnLengths = NULL;
m_pbFieldFlags = NULL;
m_pbParamFlags = NULL;
m_pDAORecordset = NULL;
m_pICDAORecordsetGetRows = NULL;
m_pQueryDef = NULL;
m_pTableDef = NULL;
m_pDAOFields = NULL;
m_pDAOIndexes = NULL;
m_pDatabase = pDatabase;
m_nDefaultType = dbOpenDynaset;
m_nStatus = 0;
m_nFields = 0;
m_nParams = 0;
}
CDaoRecordset::~CDaoRecordset()
{
if (IsOpen())
Close();
// Clean up database if necessary
if (m_pDatabase != NULL && (m_nStatus & AFX_DAO_IMPLICIT_DB))
{
m_pDatabase->Close();
delete m_pDatabase;
m_pDatabase = NULL;
}
}
void CDaoRecordset::Open(int nOpenType, LPCTSTR lpszSQL, int nOptions)
{
ASSERT_VALID(this);
ASSERT(nOpenType == AFX_DAO_USE_DEFAULT_TYPE ||
nOpenType == dbOpenDynaset || nOpenType == dbOpenSnapshot ||
dbOpenTable);
// Re-Opening is invalid.
if (IsOpen())
{
ASSERT(FALSE);
return;
}
if (nOpenType == AFX_DAO_USE_DEFAULT_TYPE)
m_nOpenType = m_nDefaultType;
else
m_nOpenType = nOpenType;
// Snapshots readOnly in DAO model.
if (m_nOpenType == dbOpenSnapshot)
nOptions |= dbReadOnly;
// Cache parameters and initialize
m_nOptions = nOptions;
m_cbFixedLengthFields = 0;
// Cache information for use in Requery
m_strRequerySQL = lpszSQL;
m_strRequeryFilter = m_strFilter;
m_strRequerySort = m_strSort;
AllocDatabase();
m_strSQL = lpszSQL;
if (m_strSQL.IsEmpty())
m_strSQL = GetDefaultSQL();
// Open table directly if option specified
if (m_nOpenType == dbOpenTable)
{
m_pTableDef = new CDaoTableDef(m_pDatabase);
m_nStatus |= AFX_DAO_IMPLICIT_TD;
TRY
{
// Must remove the bracket from the name
StripBrackets(m_strSQL, m_strSQL.GetBuffer(0));
m_strSQL.ReleaseBuffer();
m_pTableDef->Open(m_strSQL);
// Open the DAO recordset (implicit MoveFirst)
DAO_CHECK(m_pTableDef->m_pDAOTableDef->OpenRecordset(
COleVariant((long)m_nOpenType), COleVariant((long)m_nOptions),
&m_pDAORecordset));
}
CATCH_ALL(e)
{
// Once recordset marked as open, Close handles this
if (m_pTableDef->IsOpen())
m_pTableDef->Close();
delete m_pTableDef;
THROW_LAST();
}
END_CATCH_ALL
}
else
{
m_pQueryDef = new CDaoQueryDef(m_pDatabase);
m_nStatus |= AFX_DAO_IMPLICIT_QD;
TRY
{
// If initial clause includes potential start of row returning
// query, then SQL passed to Open must be valid
// (Note: TABLE is valid for UNION-type queries)
if ((_tcsnicmp(m_strSQL, szSelect, _countof(szSelect)-1) != 0) &&
(_tcsnicmp(m_strSQL, szParameters, _countof(szParameters)-1) != 0) &&
(_tcsnicmp(m_strSQL, szTransform, _countof(szTransform)-1) != 0) &&
(_tcsnicmp(m_strSQL, szTable, _countof(szTable)-1) != 0))
{
BuildSQL();
}
else
{
// Add the filter and sort
if (!m_strFilter.IsEmpty())
m_strSQL += szWhere + m_strFilter;
if (!m_strSort.IsEmpty())
m_strSQL += szOrderBy + m_strSort;
}
// Create and define temp query
m_pQueryDef->Open();
m_pQueryDef->SetSQL(m_strSQL);
BindParameters();
// Open the DAO recordset (implicit MoveFirst)
DAO_CHECK(m_pQueryDef->m_pDAOQueryDef->OpenRecordset(
COleVariant((long)m_nOpenType), COleVariant((long)m_nOptions),
&m_pDAORecordset));
}
CATCH_ALL(e)
{
// Once recordset marked as open, Close handles this
if (m_pQueryDef->IsOpen())
m_pQueryDef->Close();
delete m_pQueryDef;
THROW_LAST();
}
END_CATCH_ALL
}
m_bOpen = TRUE;
// Add the recordset to map of Open CDaoRecordsets
m_pDatabase->m_mapRecordsets.SetAt(this, this);
TRY
{
BindFields();
GetDataAndFixupNulls();
SetCursorAttributes();
}
CATCH_ALL(e)
{
Close();
THROW_LAST();
}
END_CATCH_ALL
}
void CDaoRecordset::Open(CDaoQueryDef* pQueryDef, int nOpenType,
int nOptions)
{
ASSERT_VALID(this);
// Must pass valid, open QueryDef
ASSERT(pQueryDef != NULL);
if (!pQueryDef->IsOpen())
ThrowDaoException(AFX_DAO_ERROR_OBJECT_NOT_OPEN);
// Re-Opening is invalid.
if (IsOpen())
{
ASSERT(FALSE);
return;
}
if (nOpenType == AFX_DAO_USE_DEFAULT_TYPE)
m_nOpenType = m_nDefaultType;
else
m_nOpenType = nOpenType;
// Can't open table type recordsets with QueryDef
ASSERT(m_nOpenType == dbOpenDynaset || m_nOpenType == dbOpenSnapshot);
// Snapshots readOnly in DAO model.
if (m_nOpenType == dbOpenSnapshot)
nOptions |= dbReadOnly;
// Cache parameters and initialize
m_nOptions = nOptions;
m_cbFixedLengthFields = 0;
// Use pre-defined query
m_pQueryDef = pQueryDef;
// Share the same database object
m_pDatabase = m_pQueryDef->m_pDatabase;
BindParameters();
// Open the DAO recordset (implicit MoveFirst)
DAO_CHECK(m_pQueryDef->m_pDAOQueryDef->OpenRecordset(
COleVariant((long)m_nOpenType), COleVariant((long)m_nOptions),
&m_pDAORecordset));
m_bOpen = TRUE;
// Add the recordset to map of Open CDaoRecordsets
m_pDatabase->m_mapRecordsets.SetAt(this, this);
TRY
{
BindFields();
GetDataAndFixupNulls();
SetCursorAttributes();
}
CATCH_ALL(e)
{
Close();
THROW_LAST();
}
END_CATCH_ALL
}
void CDaoRecordset::Open(CDaoTableDef* pTableDef, int nOpenType,
int nOptions)
{
ASSERT_VALID(this);
// Must pass valid, open TableDef
ASSERT(pTableDef != NULL);
if (!pTableDef->IsOpen())
ThrowDaoException(AFX_DAO_ERROR_OBJECT_NOT_OPEN);
m_pTableDef = pTableDef;
// Re-Opening is invalid.
if (IsOpen())
{
ASSERT(FALSE);
return;
}
if (nOpenType == AFX_DAO_USE_DEFAULT_TYPE)
m_nOpenType = m_nDefaultType;
else
m_nOpenType = nOpenType;
// Cache parameters and initialize
m_nOptions = nOptions;
m_cbFixedLengthFields = 0;
// Share the same database object
m_pDatabase = m_pTableDef->m_pDatabase;
// Open the DAO recordset (implicit MoveFirst)
DAO_CHECK(m_pTableDef->m_pDAOTableDef->OpenRecordset(
COleVariant((long)m_nOpenType), COleVariant((long)m_nOptions),
&m_pDAORecordset));
m_bOpen = TRUE;
// Add the recordset to map of Open CDaoRecordsets
m_pDatabase->m_mapRecordsets.SetAt(this, this);
TRY
{
BindFields();
GetDataAndFixupNulls();
SetCursorAttributes();
}
CATCH_ALL(e)
{
Close();
THROW_LAST();
}
END_CATCH_ALL
}
void CDaoRecordset::Close()
{
ASSERT_VALID(this);
if (IsOpen())
FreeCache();
// Clean up name strings in ColBindInfo struct
if (m_prgDaoColBindInfo != NULL)
{
for (int nIndex = 0; nIndex < m_nFields; nIndex++)
{
#ifndef _UNICODE
delete[] (LPTSTR)m_prgDaoColBindInfo[nIndex].columnID.lpstr;
m_prgDaoColBindInfo[nIndex].columnID.lpstr = NULL;
#else
delete[] (LPTSTR)m_prgDaoColBindInfo[nIndex].columnID.lpwstr;
m_prgDaoColBindInfo[nIndex].columnID.lpwstr = NULL;
#endif
}
}
delete[] m_prgDaoColBindInfo;
m_prgDaoColBindInfo = NULL;
delete[] m_pulColumnLengths;
m_pulColumnLengths = NULL;
delete[] m_pbFieldFlags;
m_pbFieldFlags = NULL;
if (m_pMapFieldIndex != NULL)
{
delete m_pMapFieldIndex;
m_pMapFieldIndex = NULL;
}
if (m_pDAOIndexes != NULL)
{
m_pDAOIndexes->Release();
m_pDAOIndexes = NULL;
}
if (m_pDAOFields != NULL)
{
m_pDAOFields->Release();
m_pDAOFields = NULL;
}
if (m_pICDAORecordsetGetRows != NULL)
{
m_pICDAORecordsetGetRows->Release();
m_pICDAORecordsetGetRows = NULL;
}
if (m_pDAORecordset != NULL)
{
DAO_TRACE(m_pDAORecordset->Close());
m_pDAORecordset->Release();
m_pDAORecordset = NULL;
}
// Cleanup TableDef if not user supplied
if (m_pTableDef != NULL && m_nStatus & AFX_DAO_IMPLICIT_TD)
{
m_pTableDef->Close();
delete m_pTableDef;
m_pTableDef = NULL;
}
// Cleanup QueryDef if not user supplied
if (m_pQueryDef != NULL && m_nStatus & AFX_DAO_IMPLICIT_QD)
{
m_pQueryDef->Close();
delete m_pQueryDef;
m_pQueryDef = NULL;
}
m_nStatus &= ~AFX_DAO_IMPLICIT_QD;
m_nStatus &= ~AFX_DAO_IMPLICIT_TD;
m_pQueryDef = NULL;
m_pTableDef = NULL;
m_bOpen = FALSE;
// Remove the recordset from the CDaoDatabase's map
m_pDatabase->m_mapRecordsets.RemoveKey(this);
}
void CDaoRecordset::Requery()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(CanRestart());
// If filter or sort strings changed, must Close and Open
// This is only effective if m_strFilter/m_strSort used
if ((m_pQueryDef != NULL &&
(m_nStatus & AFX_DAO_IMPLICIT_QD)) &&
((m_strRequeryFilter != m_strFilter) ||
(m_strRequerySort != m_strSort)))
{
Close();
Open(m_nOpenType, m_strRequerySQL, m_nOptions);
}
else
{
// Rebind parameters in case values have changed
BindParameters();
if (m_pQueryDef != NULL)
{
COleVariant varDisp;
varDisp.pdispVal = m_pQueryDef->m_pDAOQueryDef;
varDisp.vt = VT_DISPATCH;
TRY
{
DAO_CHECK(m_pDAORecordset->Requery(varDisp));
}
CATCH_ALL(e)
{
// Reset vt to prevent release of DAOQueryDef
varDisp.vt = VT_EMPTY;
THROW_LAST();
}
END_CATCH_ALL
// Reset vt to prevent release of DAOQueryDef
varDisp.vt = VT_EMPTY;
}
else
// Must be a table type recordset (this will fail!)
DAO_CHECK(m_pDAORecordset->Requery(_afxOptionalVariant));
GetDataAndFixupNulls();
}
}
CString CDaoRecordset::GetDefaultDBName()
{
ASSERT_VALID(this);
// Override and add UNC path to .MDB file
return _T("");
}
CString CDaoRecordset::GetDefaultSQL()
{
ASSERT_VALID(this);
// Override and add table name or entire SQL SELECT statement
return _T("");
}
void CDaoRecordset::DoFieldExchange(CDaoFieldExchange* /* pFX */)
{
ASSERT_VALID(this);
// Do nothing if dynamic binding, otherwise override and add DFX calls
}
BOOL CDaoRecordset::IsBOF()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
short nBOF;
DAO_CHECK(m_pDAORecordset->get_BOF(&nBOF));
return nBOF == AFX_DAO_TRUE;
}
BOOL CDaoRecordset::IsEOF()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
short nEOF;
DAO_CHECK(m_pDAORecordset->get_EOF(&nEOF));
return nEOF == AFX_DAO_TRUE;
}
BOOL CDaoRecordset::IsDeleted() const
{
ASSERT_VALID(this);
ASSERT(IsOpen());
return m_bDeleted;
}
BOOL CDaoRecordset::CanScroll() const
{
ASSERT_VALID(this);
ASSERT(IsOpen());
return m_bScrollable;
}
BOOL CDaoRecordset::CanUpdate() const
{
ASSERT_VALID(this);
ASSERT(IsOpen());
short nUpdatable;
DAO_CHECK(m_pDAORecordset->get_Updatable(&nUpdatable));
return nUpdatable == AFX_DAO_TRUE;
}
BOOL CDaoRecordset::CanAppend() const
{
ASSERT_VALID(this);
ASSERT(IsOpen());
return m_bAppendable;
}
BOOL CDaoRecordset::CanRestart()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
short nRestartable;
DAO_CHECK(m_pDAORecordset->get_Restartable(&nRestartable));
return nRestartable == AFX_DAO_TRUE;
}
BOOL CDaoRecordset::CanTransact()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
short nTransactions;
DAO_CHECK(m_pDAORecordset->get_Transactions(&nTransactions));
return nTransactions == AFX_DAO_TRUE;
}
BOOL CDaoRecordset::CanBookmark()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
short nBookmarkable;
DAO_CHECK(m_pDAORecordset->get_Bookmarkable(&nBookmarkable));
return nBookmarkable == AFX_DAO_TRUE;
}
CString CDaoRecordset::GetName()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant var;
DAO_CHECK(m_pDAORecordset->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
short CDaoRecordset::GetType()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
short nType;
DAO_CHECK(m_pDAORecordset->get_Type(&nType));
return nType;
}
short CDaoRecordset::GetEditMode()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
short nEditMode;
DAO_CHECK(m_pDAORecordset->get_EditMode(&nEditMode));
return nEditMode;
}
CString CDaoRecordset::GetSQL() const
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
return m_strSQL;
}
COleDateTime CDaoRecordset::GetDateCreated()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant varDate;
DAO_CHECK(m_pDAORecordset->get_DateCreated(&varDate));
return varDate.date;
}
COleDateTime CDaoRecordset::GetDateLastUpdated()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant varDate;
DAO_CHECK(m_pDAORecordset->get_LastUpdated(&varDate));
return varDate.date;
}
COleVariant CDaoRecordset::GetLastModifiedBookmark()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant var;
DAO_CHECK(m_pDAORecordset->get_LastModified(&var.parray));
var.vt = VT_ARRAY | VT_UI1;
return var;
}
CString CDaoRecordset::GetValidationRule()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant var;
DAO_CHECK(m_pDAORecordset->get_ValidationRule(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
CString CDaoRecordset::GetValidationText()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant var;
DAO_CHECK(m_pDAORecordset->get_ValidationText(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
CString CDaoRecordset::GetCurrentIndex()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant var;
DAO_CHECK(m_pDAORecordset->get_Index(&V_BSTR(&var)));
var.vt = VT_BSTR;
return V_BSTRT(&var);
}
void CDaoRecordset::SetCurrentIndex(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant var(lpszName, VT_BSTRT);
DAO_CHECK(m_pDAORecordset->put_Index(V_BSTR(&var)));
// Refetch the data
GetDataAndFixupNulls();
}
long CDaoRecordset::GetRecordCount()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
long lRecordCount;
DAO_CHECK(m_pDAORecordset->get_RecordCount(&lRecordCount));
return lRecordCount;
}
void CDaoRecordset::SetFieldDirty(void* pv, BOOL bDirty)
{
ASSERT_VALID(this);
if (m_nFields <= 0)
{
// Can't set fields dirty if no bound fields
ASSERT(FALSE);
return;
}
int nIndex = 0, nIndexEnd;
if (pv == NULL)
nIndexEnd = m_nFields - 1;
else
{
nIndex = nIndexEnd = GetFieldIndex(pv);
ASSERT(nIndex != AFX_DAO_DATA_NOT_FOUND);
}
while (nIndex <= nIndexEnd)
{
if (bDirty)
SetDirtyFieldStatus(nIndex);
else
ClearDirtyFieldStatus(nIndex);
nIndex++;
}
}
BOOL CDaoRecordset::IsFieldDirty(void* pv)
{
ASSERT_VALID(this);
short nEditMode = GetEditMode();
// Fields can't be dirty if not in edit/addnew mode or no fields bound
if (nEditMode == dbEditNone || m_nFields <= 0)
return FALSE;
// Check if cache field values have changed and mark as dirty
if (m_bCheckCacheForDirtyFields)
{
if (nEditMode == dbEditInProgress)
MarkForEdit();
else
MarkForAddNew();
}
int nIndex = 0, nIndexEnd;
if (pv == NULL)
nIndexEnd = m_nFields - 1;
else
{
// Get the field index to use status array
nIndex = nIndexEnd = GetFieldIndex(pv);
ASSERT(nIndex != AFX_DAO_DATA_NOT_FOUND);
}
BOOL bDirty = FALSE;
while (nIndex <= nIndexEnd && !bDirty)
bDirty = IsFieldStatusDirty(nIndex++);
return bDirty;
}
void CDaoRecordset::SetFieldNull(void* pv, BOOL bNull)
{
ASSERT_VALID(this);
if (m_nFields <= 0)
{
ASSERT(FALSE);
return;
}
if (bNull)
{
// Need field exchange to set value to PSEUDO NULL.
CDaoFieldExchange fx(CDaoFieldExchange::SetFieldNull, this, pv);
fx.m_nFieldFound = 0;
DoFieldExchange(&fx);
// If no field found, index will still be zero
ASSERT(fx.m_nFieldFound != 0);
}
else
{
// Set status array not NULL. Don't need field exchange mechanism.
int nIndex = 0, nIndexEnd;
if (pv == NULL)
nIndexEnd = m_nFields - 1;
else
{
nIndex = nIndexEnd = GetFieldIndex(pv);
ASSERT(nIndex != AFX_DAO_DATA_NOT_FOUND);
}
while (nIndex <= nIndexEnd)
{
ClearNullFieldStatus(nIndex);
nIndex++;
}
}
}
BOOL CDaoRecordset::IsFieldNull(void* pv)
{
ASSERT_VALID(this);
if (m_nFields <= 0)
{
ASSERT(FALSE);
return FALSE;
}
int nIndex = 0, nIndexEnd;
if (pv == NULL)
nIndexEnd = m_nFields - 1;
else
{
// Get the field index to use status array
nIndex = nIndexEnd = GetFieldIndex(pv);
ASSERT(nIndex != AFX_DAO_DATA_NOT_FOUND);
}
BOOL bNull = FALSE;
while (nIndex <= nIndexEnd && !bNull)
bNull = IsFieldStatusNull(nIndex++);
return bNull;
}
BOOL CDaoRecordset::IsFieldNullable(void* pv)
{
ASSERT_VALID(this);
if (m_nFields <= 0)
{
ASSERT(FALSE);
return FALSE;
}
int nIndex = 0, nIndexEnd;
if (pv == NULL)
nIndexEnd = m_nFields - 1;
else
{
// Get the field index to use status array
nIndex = nIndexEnd = GetFieldIndex(pv);
ASSERT(nIndex != AFX_DAO_DATA_NOT_FOUND);
}
BOOL bNullable = FALSE;
while (nIndex <= nIndexEnd && !bNullable)
{
if (!IsFieldStatusNullableKnown(nIndex))
{
CDaoFieldInfo fieldinfo;
GetFieldInfo(nIndex, fieldinfo, AFX_DAO_SECONDARY_INFO);
bNullable = !fieldinfo.m_bRequired;
if (bNullable)
SetNullableFieldStatus(nIndex);
SetNullableKnownFieldStatus(nIndex);
}
else
bNullable = IsFieldStatusNullable(nIndex);
nIndex++;
}
return bNullable;
}
short CDaoRecordset::GetFieldCount()
{
ASSERT_VALID(this);
short nFields;
if (m_pDAOFields == NULL)
InitFieldsCollection();
DAO_CHECK(m_pDAOFields->get_Count(&nFields));
return nFields;
}
void CDaoRecordset::GetFieldInfo(int nIndex, CDaoFieldInfo& fieldinfo,
DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOFields == NULL)
InitFieldsCollection();
// Get DAOField object and fill in field info struct
DAOField* pDAOField;
DAO_CHECK(m_pDAOFields->get_Item(
COleVariant((long)nIndex), &pDAOField));
AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
// Clean up
pDAOField->Release();
}
void CDaoRecordset::GetFieldInfo(LPCTSTR lpszName,
CDaoFieldInfo& fieldinfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOFields == NULL)
InitFieldsCollection();
// Get DAOField object and fill in field info struct
DAOField* pDAOField;
DAO_CHECK(m_pDAOFields->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOField));
AfxGetFieldInfo(pDAOField, fieldinfo, dwInfoOptions);
// Clean up
pDAOField->Release();
}
short CDaoRecordset::GetIndexCount()
{
ASSERT_VALID(this);
short nIndexes;
if (m_pDAOIndexes == NULL)
InitIndexesCollection();
DAO_CHECK(m_pDAOIndexes->get_Count(&nIndexes));
return nIndexes;
}
void CDaoRecordset::GetIndexInfo(int nIndex, CDaoIndexInfo& indexinfo,
DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOIndexes == NULL)
InitIndexesCollection();
// Get DAOField object and fill in field info struct
DAOIndex* pDAOIndex;
DAO_CHECK(m_pDAOIndexes->get_Item(
COleVariant((long)nIndex), &pDAOIndex));
AfxGetIndexInfo(pDAOIndex, indexinfo, dwInfoOptions);
// Clean up
pDAOIndex->Release();
}
void CDaoRecordset::GetIndexInfo(LPCTSTR lpszName,
CDaoIndexInfo& indexinfo, DWORD dwInfoOptions)
{
ASSERT_VALID(this);
if (m_pDAOIndexes == NULL)
InitIndexesCollection();
// Get DAOField object and fill in field info struct
DAOIndex* pDAOIndex;
DAO_CHECK(m_pDAOIndexes->get_Item(
COleVariant(lpszName, VT_BSTRT), &pDAOIndex));
AfxGetIndexInfo(pDAOIndex, indexinfo, dwInfoOptions);
// Clean up
pDAOIndex->Release();
}
COleVariant CDaoRecordset::GetBookmark()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant var;
DAO_CHECK(m_pDAORecordset->get_Bookmark(&var.parray));
var.vt = VT_ARRAY | VT_UI1;
return var;
}
void CDaoRecordset::SetBookmark(COleVariant varBookmark)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
DAO_CHECK(m_pDAORecordset->put_Bookmark(&varBookmark.parray));
GetDataAndFixupNulls();
}
long CDaoRecordset::GetAbsolutePosition()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
long lPosition;
DAO_CHECK(m_pDAORecordset->get_AbsolutePosition(&lPosition));
return lPosition;
}
void CDaoRecordset::SetAbsolutePosition(long lPosition)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
DAO_CHECK(m_pDAORecordset->put_AbsolutePosition(lPosition));
GetDataAndFixupNulls();
}
float CDaoRecordset::GetPercentPosition()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
float fPosition;
DAO_CHECK(m_pDAORecordset->get_PercentPosition(&fPosition));
return fPosition;
}
void CDaoRecordset::SetPercentPosition(float fPosition)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
DAO_CHECK(m_pDAORecordset->put_PercentPosition(fPosition));
GetDataAndFixupNulls();
}
void CDaoRecordset::MoveNext()
{
ASSERT_VALID(this);
Move(AFX_DAO_NEXT);
}
void CDaoRecordset::MovePrev()
{
ASSERT_VALID(this);
Move(AFX_DAO_PREV);
}
void CDaoRecordset::MoveFirst()
{
ASSERT_VALID(this);
Move(AFX_DAO_FIRST);
}
void CDaoRecordset::MoveLast()
{
ASSERT_VALID(this);
Move(AFX_DAO_LAST);
}
void CDaoRecordset::Move(long lRows)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
switch(lRows)
{
case AFX_DAO_NEXT:
DAO_CHECK(m_pDAORecordset->MoveNext());
break;
case AFX_DAO_PREV:
DAO_CHECK(m_pDAORecordset->MovePrevious());
break;
case AFX_DAO_FIRST:
DAO_CHECK(m_pDAORecordset->MoveFirst());
break;
case AFX_DAO_LAST:
DAO_CHECK(m_pDAORecordset->MoveLast());
break;
// General case
default:
// Call Move without getting Bookmark (using unitialized variant).
DAO_CHECK(m_pDAORecordset->Move(lRows, COleVariant()));
}
GetDataAndFixupNulls();
}
BOOL CDaoRecordset::FindNext(LPCTSTR lpszFilter)
{
ASSERT_VALID(this);
return Find(AFX_DAO_NEXT, lpszFilter);
}
BOOL CDaoRecordset::FindPrev(LPCTSTR lpszFilter)
{
ASSERT_VALID(this);
return Find(AFX_DAO_PREV, lpszFilter);
}
BOOL CDaoRecordset::FindFirst(LPCTSTR lpszFilter)
{
ASSERT_VALID(this);
return Find(AFX_DAO_FIRST, lpszFilter);
}
BOOL CDaoRecordset::FindLast(LPCTSTR lpszFilter)
{
ASSERT_VALID(this);
return Find(AFX_DAO_LAST, lpszFilter);
}
BOOL CDaoRecordset::Find(long lType, LPCTSTR lpszFilter)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant var(lpszFilter, VT_BSTRT);
switch(lType)
{
default:
// Invalid Find type!
ASSERT(FALSE);
// fall through to FindNext case
case AFX_DAO_NEXT:
DAO_CHECK(m_pDAORecordset->FindNext(V_BSTR(&var)));
break;
case AFX_DAO_PREV:
DAO_CHECK(m_pDAORecordset->FindPrevious(V_BSTR(&var)));
break;
case AFX_DAO_FIRST:
DAO_CHECK(m_pDAORecordset->FindFirst(V_BSTR(&var)));
break;
case AFX_DAO_LAST:
DAO_CHECK(m_pDAORecordset->FindLast(V_BSTR(&var)));
break;
}
BOOL bMatch = IsMatch();
if (bMatch)
GetDataAndFixupNulls();
return bMatch;
}
BOOL CDaoRecordset::Seek(LPCTSTR lpszComparison, COleVariant* pKey1,
COleVariant* pKey2, COleVariant* pKey3)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
ASSERT(m_nOpenType == dbOpenTable);
// Must have at least one key
ASSERT(pKey1 != NULL);
COleVariant varComparison(lpszComparison, VT_BSTRT);
DAO_CHECK(m_pDAORecordset->Seek(V_BSTR(&varComparison),
pKey1 != NULL ? (VARIANT)*pKey1 : _afxOptionalVariant,
pKey2 != NULL ? (VARIANT)*pKey2 : _afxOptionalVariant,
pKey3 != NULL ? (VARIANT)*pKey3 : _afxOptionalVariant,
_afxOptionalVariant, _afxOptionalVariant, _afxOptionalVariant,
_afxOptionalVariant, _afxOptionalVariant, _afxOptionalVariant,
_afxOptionalVariant, _afxOptionalVariant, _afxOptionalVariant,
_afxOptionalVariant));
BOOL bMatch = IsMatch();
if (bMatch)
GetDataAndFixupNulls();
return bMatch;
}
BOOL CDaoRecordset::Seek(LPCTSTR lpszComparison, COleVariant* pKeyArray,
WORD nKeys)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
ASSERT(m_nOpenType == dbOpenTable);
// Must have at least one key and no more than 13
ASSERT(nKeys > 0);
ASSERT(nKeys < 14);
COleVariant varComparison(lpszComparison, VT_BSTRT);
LPVARIANT pVarArray[13];
for (WORD nIndex = 0; nIndex < nKeys; nIndex++)
pVarArray[nIndex] = &pKeyArray[nIndex];
for (;nIndex < 13; nIndex++)
pVarArray[nIndex] = &_afxOptionalVariant;
DAO_CHECK(m_pDAORecordset->Seek(V_BSTR(&varComparison),
*pVarArray[0], *pVarArray[1], *pVarArray[2], *pVarArray[3],
*pVarArray[4], *pVarArray[5], *pVarArray[6], *pVarArray[7],
*pVarArray[8], *pVarArray[9], *pVarArray[10], *pVarArray[11],
*pVarArray[12]));
BOOL bMatch = IsMatch();
if (bMatch)
GetDataAndFixupNulls();
return bMatch;
}
void CDaoRecordset::CancelUpdate()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
DAO_CHECK(m_pDAORecordset->CancelUpdate());
// Restore cache if necessary
if (m_bCheckCacheForDirtyFields && m_nFields > 0)
LoadFields();
}
void CDaoRecordset::SetLockingMode(BOOL bPessimistic)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
DAO_CHECK(m_pDAORecordset->put_LockEdits(
(short)(bPessimistic ? AFX_DAO_TRUE : AFX_DAO_FALSE)));
}
BOOL CDaoRecordset::GetLockingMode()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
short nLockEdits;
DAO_CHECK(m_pDAORecordset->get_LockEdits(&nLockEdits));
return nLockEdits == AFX_DAO_TRUE;
}
void CDaoRecordset::SetCacheStart(COleVariant varBookmark)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
DAO_CHECK(m_pDAORecordset->put_CacheStart(&varBookmark.parray));
}
COleVariant CDaoRecordset::GetCacheStart()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
COleVariant var;
DAO_CHECK(m_pDAORecordset->get_CacheStart(&var.parray));
var.vt = VT_ARRAY | VT_UI1;
return var;
}
void CDaoRecordset::SetCacheSize(long lSize)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
DAO_CHECK(m_pDAORecordset->put_CacheSize(lSize));
}
long CDaoRecordset::GetCacheSize()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
long lSize;
DAO_CHECK(m_pDAORecordset->get_CacheSize(&lSize));
return lSize;
}
void CDaoRecordset::FillCache(long* pSize, COleVariant* pBookmark)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
DAO_CHECK(m_pDAORecordset->FillCache(
pSize != NULL ? (VARIANT)COleVariant(*pSize) : _afxOptionalVariant,
pBookmark != NULL ? (VARIANT)*pBookmark : _afxOptionalVariant));
}
void CDaoRecordset::AddNew()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
if (m_bCheckCacheForDirtyFields && m_nFields > 0)
{
short nEditMode = GetEditMode();
if (nEditMode != dbEditAdd)
{
// Store fields if necessary (fields already stored if edit mode)
if (nEditMode != dbEditInProgress)
{
AllocCache();
StoreFields();
}
// Set all fields NULL and not dirty
SetFieldNull(NULL);
SetFieldDirty(NULL, FALSE);
}
}
DAO_CHECK(m_pDAORecordset->AddNew());
}
void CDaoRecordset::Edit()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
if (m_bCheckCacheForDirtyFields && m_nFields > 0)
{
short nEditMode = GetEditMode();
if (nEditMode != dbEditInProgress)
{
if (nEditMode == dbEditNone)
{
// Save fields for restore/dirty checking later
AllocCache();
StoreFields();
SetFieldDirty(NULL, FALSE);
}
else
// Load in fields cached on AddNew call prior to Edit
LoadFields();
}
}
DAO_CHECK(m_pDAORecordset->Edit());
}
void CDaoRecordset::Update()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
int nMode;
// If caching, compare cache to current values and save state
if (m_nFields > 0)
{
if (m_bCheckCacheForDirtyFields)
{
IsFieldDirty(NULL);
nMode = GetEditMode();
}
// Set all field values of all fields marked dirty
SetDirtyFields();
}
DAO_CHECK(m_pDAORecordset->Update());
// Restore data if data cached and were in add mode
if (m_bCheckCacheForDirtyFields && m_nFields > 0 &&
nMode == dbEditAdd)
{
LoadFields();
}
}
void CDaoRecordset::Delete()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
DAO_CHECK(m_pDAORecordset->Delete());
if (m_bCheckCacheForDirtyFields && m_nFields > 0)
{
SetFieldNull(NULL);
SetFieldDirty(NULL, FALSE);
}
m_bDeleted = TRUE;
}
COleVariant CDaoRecordset::GetFieldValue(LPCTSTR lpszName)
{
COleVariant var;
GetFieldValue(lpszName, var);
return var;
}
COleVariant CDaoRecordset::GetFieldValue(int nIndex)
{
COleVariant var;
GetFieldValue(nIndex, var);
return var;
}
void CDaoRecordset::GetFieldValue(LPCTSTR lpszName, COleVariant& varValue)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
// Clear out variant
varValue.Clear();
// Use DAO optimization. get_Collect will get the field object from
// the fields collection and fetch the value
DAO_CHECK(m_pDAORecordset->get_Collect(
COleVariant(lpszName, VT_BSTRT), &varValue));
}
void CDaoRecordset::GetFieldValue(int nIndex, COleVariant& varValue)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
// Clear out variant
varValue.Clear();
// Use DAO optimization. get_Collect will get the field object from
// the fields collection and fetch the value
DAO_CHECK(m_pDAORecordset->get_Collect(
COleVariant((long)nIndex), &varValue));
}
void CDaoRecordset::SetFieldValue(LPCTSTR lpszName,
const COleVariant& varValue)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
// Use DAO optimization. get_Collect will get the field object from
// the fields collection and fetch the value
DAO_CHECK(m_pDAORecordset->put_Collect(
COleVariant(lpszName, VT_BSTRT), varValue));
}
void CDaoRecordset::SetFieldValue(int nIndex,
const COleVariant& varValue)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pDAORecordset != NULL);
// Use DAO optimization. put_Collect will get the field object from
// the fields collection and write the value
DAO_CHECK(m_pDAORecordset->put_Collect(
COleVariant((long)nIndex), varValue));
}
void CDaoRecordset::SetFieldValue(int nIndex,
LPCTSTR lpszValue)
{
COleVariant varValue(lpszValue, VT_BSTRT);
SetFieldValue(nIndex, varValue);
}
void CDaoRecordset::SetFieldValue(LPCTSTR lpszName,
LPCTSTR lpszValue)
{
COleVariant varValue(lpszValue, VT_BSTRT);
SetFieldValue(lpszName, varValue);
}
void CDaoRecordset::SetFieldValueNull(LPCTSTR lpszName)
{
ASSERT_VALID(this);
SetFieldValue(lpszName, _afxNullVariant);
}
void CDaoRecordset::SetFieldValueNull(int nIndex)
{
ASSERT_VALID(this);
SetFieldValue(nIndex, _afxNullVariant);
}
COleVariant CDaoRecordset::GetParamValue(LPCTSTR lpszName)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pQueryDef != NULL);
return m_pQueryDef->GetParamValue(lpszName);
}
COleVariant CDaoRecordset::GetParamValue(int nIndex)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pQueryDef != NULL);
return m_pQueryDef->GetParamValue(nIndex);
}
void CDaoRecordset::SetParamValue(LPCTSTR lpszName,
const COleVariant& varValue)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pQueryDef != NULL);
m_pQueryDef->SetParamValue(lpszName, varValue);
}
void CDaoRecordset::SetParamValue(int nIndex,
const COleVariant& varValue)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
ASSERT(m_pQueryDef != NULL);
m_pQueryDef->SetParamValue(nIndex, varValue);
}
void CDaoRecordset::SetParamValueNull(LPCTSTR lpszName)
{
ASSERT_VALID(this);
SetParamValue(lpszName, _afxNullVariant);
}
void CDaoRecordset::SetParamValueNull(int nIndex)
{
ASSERT_VALID(this);
SetParamValue(nIndex, _afxNullVariant);
}
//Implementation functions
DWORD CDaoRecordset::GetFieldLength(int nFieldIndex)
{
ASSERT_VALID(this);
ASSERT(IsOpen());
return m_pulColumnLengths[nFieldIndex];
}
void CDaoRecordset::InitFieldsCollection()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
DAO_CHECK(m_pDAORecordset->get_Fields(&m_pDAOFields));
}
void CDaoRecordset::InitIndexesCollection()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
DAO_CHECK(m_pTableDef->m_pDAOTableDef->get_Indexes(&m_pDAOIndexes));
}
// "PARAMETERS <parameter list>;"
// "SELECT <select list> FROM <table list>"
// " WHERE <m_strFilter> ORDER BY <m_strSort>"
void CDaoRecordset::BuildSQL()
{
ASSERT_VALID(this);
// Assumes m_strSQL represents table list
CString strTableName = m_strSQL;
m_strSQL.Empty();
if (m_nParams > 0)
BuildParameterList();
BuildSelectList();
m_strSQL += szFrom + strTableName;
if (!m_strFilter.IsEmpty())
{
m_strSQL += szWhere;
m_strSQL += m_strFilter;
}
if (!m_strSort.IsEmpty())
{
m_strSQL += szOrderBy;
m_strSQL += m_strSort;
}
}
void CDaoRecordset::AllocDatabase()
{
ASSERT_VALID(this);
// Allocate and maintain database if necessary
if (m_pDatabase == NULL)
{
m_pDatabase = new CDaoDatabase;
m_pDatabase->m_nStatus |= AFX_DAO_IMPLICIT_DB;
m_nStatus |= AFX_DAO_IMPLICIT_DB;
}
// Open Database if necessary
if (!m_pDatabase->IsOpen())
m_pDatabase->Open((LPCTSTR)GetDefaultDBName(), FALSE, FALSE, NULL);
}
void CDaoRecordset::BuildSelectList()
{
ASSERT_VALID(this);
ASSERT(m_nFields > 0);
m_strSQL += szSelect;
CDaoFieldExchange fx(CDaoFieldExchange::AddToSelectList, this);
DoFieldExchange(&fx);
}
void CDaoRecordset::BuildParameterList()
{
ASSERT_VALID(this);
ASSERT(m_nParams > 0);
m_strSQL += szParameters;
CDaoFieldExchange fx(CDaoFieldExchange::AddToParameterList, this);
DoFieldExchange(&fx);
if (fx.m_nParam != 0)
m_strSQL += _T(";");
else
m_strSQL.Empty();
}
void CDaoRecordset::BindFields()
{
ASSERT_VALID(this);
if (m_nFields > 0)
{
// Setup the DAO binding struct
ASSERT(m_prgDaoColBindInfo == NULL);
m_prgDaoColBindInfo = new DAOCOLUMNBINDING[m_nFields];
memset(m_prgDaoColBindInfo, 0, sizeof(DAOCOLUMNBINDING) * m_nFields);
m_pulColumnLengths = new DWORD[m_nFields];
m_pbFieldFlags = new BYTE[m_nFields];
memset(m_pbFieldFlags, 0, m_nFields);
m_DaoFetchRows.cRowsRequested = 1;
m_DaoFetchRows.dwFlags = DAOROWFETCH_BINDABSOLUTE;
m_DaoFetchRows.pData = NULL;
// Allocate the index map
ASSERT(m_pMapFieldIndex == NULL);
m_pMapFieldIndex = new CMapPtrToPtr;
CDaoFieldExchange fx(CDaoFieldExchange::BindField, this);
DoFieldExchange(&fx);
}
}
void CDaoRecordset::BindParameters()
{
ASSERT_VALID(this);
if (m_nParams > 0)
{
// Since Jet treats non-bindable names as implicit parameters
// this should catch some SQL syntax errors that would otherwise
// appear to be uninitialized parameters.
ASSERT(m_pQueryDef->GetParameterCount() == m_nParams);
CDaoFieldExchange fx(CDaoFieldExchange::BindParam, this);
DoFieldExchange(&fx);
}
}
void CDaoRecordset::Fixup()
{
ASSERT_VALID(this);
CDaoFieldExchange fx(CDaoFieldExchange::Fixup, this);
DoFieldExchange(&fx);
}
void CDaoRecordset::AllocCache()
{
ASSERT_VALID(this);
// Do nothing if caching disabled by master switch
if (m_bCheckCacheForDirtyFields && m_nFields > 0 &&
m_pMapFieldCache == NULL)
{
m_pMapFieldCache = new CMapPtrToPtr;
CDaoFieldExchange fx(CDaoFieldExchange::AllocCache, this);
DoFieldExchange(&fx);
}
}
void CDaoRecordset::StoreFields()
{
ASSERT_VALID(this);
// Do nothing if caching disabled by master switch
if (m_bCheckCacheForDirtyFields && m_nFields > 0)
{
ASSERT(m_pMapFieldCache != NULL);
CDaoFieldExchange fx(CDaoFieldExchange::StoreField, this);
DoFieldExchange(&fx);
}
}
void CDaoRecordset::LoadFields()
{
ASSERT_VALID(this);
// Do nothing if caching disabled by master switch
if (m_bCheckCacheForDirtyFields && m_nFields > 0)
{
CDaoFieldExchange fx(CDaoFieldExchange::LoadField, this);
DoFieldExchange(&fx);
// Clear the dirty status flags
SetFieldDirty(NULL, FALSE);
}
}
void CDaoRecordset::FreeCache()
{
ASSERT_VALID(this);
// Do nothing if caching disabled by master switch
if (m_bCheckCacheForDirtyFields && m_nFields > 0 &&
m_pMapFieldCache != NULL)
{
// Free up dynamically allocated mem in cache
CDaoFieldExchange fx(CDaoFieldExchange::FreeCache, this);
// Delete any cached data
void* pvKey;
void* pvObject;
POSITION pos = m_pMapFieldCache->GetStartPosition();
while (pos != NULL)
{
m_pMapFieldCache->GetNextAssoc(pos, pvKey, pvObject);
fx.DeleteCacheValue((CDaoFieldCache*)pvObject,
((CDaoFieldCache*)pvObject)->m_nDataType);
}
m_pMapFieldCache->RemoveAll();
delete m_pMapFieldCache;
m_pMapFieldCache = NULL;
}
}
void CDaoRecordset::MarkForAddNew()
{
ASSERT_VALID(this);
CDaoFieldExchange fx(CDaoFieldExchange::MarkForAddNew, this);
DoFieldExchange(&fx);
}
void CDaoRecordset::MarkForEdit()
{
ASSERT_VALID(this);
CDaoFieldExchange fx(CDaoFieldExchange::MarkForEdit, this);
DoFieldExchange(&fx);
}
int CDaoRecordset::GetFieldIndex(void* pv)
{
ASSERT_VALID(this);
ASSERT(m_pMapFieldIndex != NULL);
void* pvIndex;
if (!m_pMapFieldIndex->Lookup(pv, pvIndex))
return AFX_DAO_DATA_NOT_FOUND;
else
// Index was stored rather than ptr, make it 0-based
return ((int)pvIndex) - 1;
}
void CDaoRecordset::SetDirtyFields()
{
ASSERT_VALID(this);
if (m_pDAOFields == NULL)
InitFieldsCollection();
CDaoFieldExchange fx(CDaoFieldExchange::SetDirtyField, this);
DoFieldExchange(&fx);
}
void CDaoRecordset::SetCursorAttributes()
{
ASSERT_VALID(this);
m_bScrollable = !(m_nOptions & dbForwardOnly);
m_bAppendable = CanUpdate() ||
(!(m_nOptions & dbReadOnly) && (m_nOptions & dbAppendOnly));
}
void CDaoRecordset::GetDataAndFixupNulls()
{
ASSERT_VALID(this);
// Don't need to do anything if no fields bound
if (m_nFields > 0)
{
if (IsEOF() || IsBOF())
{
// If no current record, simple mark fields NULL
if (m_nFields > 0)
SetFieldNull(NULL);
}
else
{
if (m_pICDAORecordsetGetRows == NULL)
{
DAO_CHECK(m_pDAORecordset->QueryInterface(
IID_ICDAORecordset, (void**)&m_pICDAORecordsetGetRows));
}
// Call GetRows to fill in the bound data
SCODE scode = m_pICDAORecordsetGetRows->GetRows(
0, m_nFields, m_prgDaoColBindInfo,
m_cbFixedLengthFields, &m_DaoFetchRows);
// Check for GetRows specific errors
// This is necessary as ICDAORecordset::GetRows
// errors are not appended to DAO errors collection
if (FAILED(scode))
ThrowGetRowsDaoException(scode);
// Check to see if row deleted as it is just warning
m_bDeleted = scode == S_RECORDDELETED;
// Reset the status array
ClearFieldStatusFlags();
// Fixup Null fields
Fixup();
}
}
}
BOOL CDaoRecordset::IsFieldStatusDirty(UINT nField)
{
ASSERT_VALID(this);
return ((m_pbFieldFlags[nField] & AFX_DAO_FIELD_FLAG_DIRTY) ==
AFX_DAO_FIELD_FLAG_DIRTY);
}
void CDaoRecordset::SetDirtyFieldStatus(UINT nField)
{
ASSERT_VALID(this);
m_pbFieldFlags[nField] |= AFX_DAO_FIELD_FLAG_DIRTY;
}
void CDaoRecordset::ClearDirtyFieldStatus(UINT nField)
{
ASSERT_VALID(this);
m_pbFieldFlags[nField] &= ~AFX_DAO_FIELD_FLAG_DIRTY;
}
BOOL CDaoRecordset::IsFieldStatusNull(UINT nField)
{
ASSERT_VALID(this);
return ((m_pbFieldFlags[nField] & AFX_DAO_FIELD_FLAG_NULL) ==
AFX_DAO_FIELD_FLAG_NULL);
}
void CDaoRecordset::SetNullFieldStatus(UINT nField)
{
ASSERT_VALID(this);
m_pbFieldFlags[nField] |= AFX_DAO_FIELD_FLAG_NULL;
}
void CDaoRecordset::ClearNullFieldStatus(UINT nField)
{
ASSERT_VALID(this);
m_pbFieldFlags[nField] &= ~AFX_DAO_FIELD_FLAG_NULL;
}
BOOL CDaoRecordset::IsFieldStatusNullable(UINT nField)
{
ASSERT_VALID(this);
return ((m_pbFieldFlags[nField] & AFX_DAO_FIELD_FLAG_NULLABLE) ==
AFX_DAO_FIELD_FLAG_NULLABLE);
}
void CDaoRecordset::SetNullableFieldStatus(UINT nField)
{
ASSERT_VALID(this);
m_pbFieldFlags[nField] |= AFX_DAO_FIELD_FLAG_NULLABLE;
}
BOOL CDaoRecordset::IsFieldStatusNullableKnown(UINT nField)
{
ASSERT_VALID(this);
return ((m_pbFieldFlags[nField] & AFX_DAO_FIELD_FLAG_NULLABLE_KNOWN)
== AFX_DAO_FIELD_FLAG_NULLABLE_KNOWN);
}
void CDaoRecordset::SetNullableKnownFieldStatus(UINT nField)
{
ASSERT_VALID(this);
m_pbFieldFlags[nField] |= AFX_DAO_FIELD_FLAG_NULLABLE_KNOWN;
}
void CDaoRecordset::ClearFieldStatusFlags()
{
ASSERT_VALID(this);
memset(m_pbFieldFlags, 0, m_nFields);
}
BOOL CDaoRecordset::IsMatch()
{
ASSERT_VALID(this);
ASSERT(IsOpen());
short nNoMatch;
DAO_CHECK(m_pDAORecordset->get_NoMatch(&nNoMatch));
// Return TRUE if NoMatch is FALSE
return nNoMatch == AFX_DAO_FALSE;
}
void AFX_CDECL CDaoRecordset::StripBrackets(LPCTSTR lpszSrc, LPTSTR lpszDest)
{
while (*lpszSrc != '\0')
{
// Ignore all brackets
while (*lpszSrc == '[' || *lpszSrc == ']')
lpszSrc = _tcsinc(lpszSrc);
// Quit if at the end of the string
if (*lpszSrc == '\0')
break;
// Copy the data and increment the buffers
if (_istlead(*lpszSrc))
*lpszDest++ = *lpszSrc++;
*lpszDest++ = *lpszSrc++;
}
// Add the trailing '\0'
*lpszDest = '\0';
}
void CDaoRecordset::ThrowDaoException(int nAfxDaoError)
{
ASSERT_VALID(this);
AfxThrowDaoException(nAfxDaoError);
}
#ifdef _DEBUG
void CDaoRecordset::AssertValid() const
{
CObject::AssertValid();
}
void CDaoRecordset::Dump(CDumpContext& dc) const
{
ASSERT_VALID(this);
CObject::Dump(dc);
dc << "\nm_bOpen = " << m_bOpen;
dc << "\nm_bAppendable = " << m_bAppendable;
dc << "\nm_bScrollable = " << m_bScrollable;
dc << "\nm_bDeleted = " << m_bDeleted;
dc << "\nm_nOpenType = " << m_nOpenType;
dc << "\nm_nDefaultType = " << m_nDefaultType;
dc << "\nm_nOptions = " << m_nOptions;
dc << "\nm_strSQL = " << m_strSQL;
dc << "\nm_strFilter = " << m_strFilter;
dc << "\nm_strSort = " << m_strSort;
dc << "\nm_strRequerySQL = " << m_strRequerySQL;
dc << "\nm_strRequeryFilter = " << m_strRequeryFilter;
dc << "\nm_strRequerySort = " << m_strRequerySort;
dc << "\nm_nFields = " << m_nFields;
dc << "\nm_nParams = " << m_nParams;
dc << "\nm_bCheckCacheForDirtyFields = " << m_bCheckCacheForDirtyFields;
dc << "\nm_nStatus = " << m_nStatus;
dc << "\n";
}
#endif //_DEBUG
//////////////////////////////////////////////////////////////////////////
// Helpers - implementation
void AFX_CDECL AfxGetFieldInfo(DAOField* pDAOField, CDaoFieldInfo& fieldinfo,
DWORD dwInfoOptions)
{
ASSERT(pDAOField != NULL);
ASSERT(dwInfoOptions != 0);
COleVariant var;
short nBool;
// Always fetch the Primary properties
if (dwInfoOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
{
DAO_CHECK(pDAOField->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
fieldinfo.m_strName = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOField->get_Type(&fieldinfo.m_nType));
DAO_CHECK(pDAOField->get_Size(&fieldinfo.m_lSize));
DAO_CHECK(pDAOField->get_Attributes(&fieldinfo.m_lAttributes));
}
if (dwInfoOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
{
DAO_CHECK(pDAOField->get_OrdinalPosition(
&fieldinfo.m_nOrdinalPosition));
DAO_CHECK(pDAOField->get_Required(&nBool));
fieldinfo.m_bRequired = nBool == AFX_DAO_TRUE;
DAO_CHECK(pDAOField->get_AllowZeroLength(&nBool));
fieldinfo.m_bAllowZeroLength = nBool == AFX_DAO_TRUE;
DAO_CHECK(pDAOField->get_CollatingOrder(
&fieldinfo.m_lCollatingOrder));
DAO_CHECK(pDAOField->get_SourceField(&V_BSTR(&var)));
var.vt = VT_BSTR;
fieldinfo.m_strSourceField = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOField->get_SourceTable(&V_BSTR(&var)));
var.vt = VT_BSTR;
fieldinfo.m_strSourceTable = V_BSTRT(&var);
var.Clear();
TRY
{
DAO_CHECK(pDAOField->get_ForeignName(&V_BSTR(&var)));
var.vt = VT_BSTR;
fieldinfo.m_strForeignName = V_BSTRT(&var);
var.Clear();
}
AND_CATCH(CDaoException, e)
{
// If this property not appropriate, set foreign name empty
if (e->m_scode != E_DAO_IllegalOperation)
THROW_LAST();
else
{
fieldinfo.m_strForeignName.Empty();
e->Delete();
}
}
END_CATCH
}
if (dwInfoOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
{
DAO_CHECK(pDAOField->get_DefaultValue(&V_BSTR(&var)));
var.vt = VT_BSTR;
fieldinfo.m_strDefaultValue = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOField->get_ValidationRule(&V_BSTR(&var)));
var.vt = VT_BSTR;
fieldinfo.m_strValidationRule = V_BSTRT(&var);
var.Clear();
DAO_CHECK(pDAOField->get_ValidationText(&V_BSTR(&var)));
var.vt = VT_BSTR;
fieldinfo.m_strValidationText = V_BSTRT(&var);
var.Clear();
}
}
void AFX_CDECL AfxSetFieldInfo(DAOField* pDAOField, CDaoFieldInfo& fieldinfo)
{
// Assumes name, type and size set on direct DAO CreateField call
ASSERT(pDAOField != NULL);
if (fieldinfo.m_lAttributes != 0)
DAO_CHECK(pDAOField->put_Attributes(fieldinfo.m_lAttributes));
if (fieldinfo.m_nOrdinalPosition != 0)
{
DAO_CHECK(pDAOField->put_OrdinalPosition(
fieldinfo.m_nOrdinalPosition));
}
if (fieldinfo.m_bRequired)
DAO_CHECK(pDAOField->put_Required(AFX_DAO_TRUE));
if (fieldinfo.m_bAllowZeroLength)
DAO_CHECK(pDAOField->put_AllowZeroLength(AFX_DAO_TRUE));
if (!fieldinfo.m_strForeignName.IsEmpty())
{
COleVariant var(fieldinfo.m_strForeignName, VT_BSTRT);
DAO_CHECK(pDAOField->put_ForeignName(V_BSTR(&var)));
}
if (!fieldinfo.m_strValidationRule.IsEmpty())
{
COleVariant var(fieldinfo.m_strValidationRule, VT_BSTRT);
DAO_CHECK(pDAOField->put_ValidationRule(V_BSTR(&var)));
}
if (!fieldinfo.m_strValidationText.IsEmpty())
{
COleVariant var(fieldinfo.m_strValidationText, VT_BSTRT);
DAO_CHECK(pDAOField->put_ValidationText(V_BSTR(&var)));
}
if (!fieldinfo.m_strDefaultValue.IsEmpty())
{
COleVariant var(fieldinfo.m_strDefaultValue, VT_BSTRT);
DAO_CHECK(pDAOField->put_DefaultValue(V_BSTR(&var)));
}
}
void AFX_CDECL AfxGetIndexInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo,
DWORD dwInfoOptions)
{
ASSERT(pDAOIndex != NULL);
ASSERT(dwInfoOptions != 0);
COleVariant var;
short nBool;
if (dwInfoOptions & AFX_DAO_FETCH_PRIMARY_PROPERTIES)
{
DAO_CHECK(pDAOIndex->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
indexinfo.m_strName = V_BSTRT(&var);
var.Clear();
AfxGetIndexFieldInfo(pDAOIndex, indexinfo);
}
if (dwInfoOptions & AFX_DAO_FETCH_SECONDARY_PROPERTIES)
{
DAO_CHECK(pDAOIndex->get_Primary(&nBool));
indexinfo.m_bPrimary = nBool == AFX_DAO_TRUE;
DAO_CHECK(pDAOIndex->get_Unique(&nBool));
indexinfo.m_bUnique = nBool == AFX_DAO_TRUE;
DAO_CHECK(pDAOIndex->get_Clustered(&nBool));
indexinfo.m_bClustered = nBool == AFX_DAO_TRUE;
DAO_CHECK(pDAOIndex->get_IgnoreNulls(&nBool));
indexinfo.m_bIgnoreNulls = nBool == AFX_DAO_TRUE;
DAO_CHECK(pDAOIndex->get_Required(&nBool));
indexinfo.m_bRequired = nBool == AFX_DAO_TRUE;
DAO_CHECK(pDAOIndex->get_Foreign(&nBool));
indexinfo.m_bForeign = nBool == AFX_DAO_TRUE;
}
if (dwInfoOptions & AFX_DAO_FETCH_ALL_PROPERTIES)
{
DAO_CHECK(pDAOIndex->get_DistinctCount(
&indexinfo.m_lDistinctCount));
}
}
void AFX_CDECL AfxSetIndexInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo)
{
// Assumes name,set on direct DAO CreateIndex call
ASSERT(pDAOIndex != NULL);
AfxSetIndexFieldInfo(pDAOIndex, indexinfo);
if (indexinfo.m_bPrimary)
DAO_CHECK(pDAOIndex->put_Primary(AFX_DAO_TRUE));
if (indexinfo.m_bUnique)
DAO_CHECK(pDAOIndex->put_Unique(AFX_DAO_TRUE));
if (indexinfo.m_bClustered)
DAO_CHECK(pDAOIndex->put_Clustered(AFX_DAO_TRUE));
if (indexinfo.m_bIgnoreNulls)
DAO_CHECK(pDAOIndex->put_IgnoreNulls(AFX_DAO_TRUE));
if (indexinfo.m_bRequired)
DAO_CHECK(pDAOIndex->put_Required(AFX_DAO_TRUE));
}
void AFX_CDECL AfxGetIndexFields(DAOIndex* pDAOIndex,
DAOIndexFields** ppDAOIndexFields)
{
COleVariant var;
// Set the desired interface
GUID guidIndexFields;
#ifdef _UNICODE
guidIndexFields = IID_IDAOIndexFieldsW;
#else
guidIndexFields = IID_IDAOIndexFields;
#endif
// Get dispatch pointer to fields collection
DAO_CHECK(pDAOIndex->get_Fields(&var));
DAO_CHECK(var.pdispVal->QueryInterface(
guidIndexFields, (void**)ppDAOIndexFields));
}
void AFX_CDECL AfxGetIndexFieldInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo)
{
COleVariant var;
DAOIndexFields* pDAOIndexFields = NULL;
DAOField* pDAOField = NULL;
// Get the index fields collection
AfxGetIndexFields(pDAOIndex, &pDAOIndexFields);
TRY
{
// Get the number of fields in the index
short nCount;
DAO_CHECK(pDAOIndexFields->get_Count(&nCount));
// Allocate or reallocate memory for array if necessary
if (nCount != indexinfo.m_nFields)
{
if (indexinfo.m_nFields != 0)
{
// Check that allocation is correct.
ASSERT(indexinfo.m_nFields == 0 ||
indexinfo.m_bCleanupFieldInfo);
delete[] indexinfo.m_pFieldInfos;
indexinfo.m_pFieldInfos = NULL;
}
// Now allocate required memory
indexinfo.m_pFieldInfos = new CDaoIndexFieldInfo[nCount];
indexinfo.m_bCleanupFieldInfo = TRUE;
indexinfo.m_nFields = nCount;
}
// Now get field info for each field
long lAttributes;
for (short nIndex = 0; nIndex < indexinfo.m_nFields; nIndex++)
{
// Set the desired interface
GUID guidField;
#ifdef _UNICODE
guidField = IID_IDAOFieldW;
#else
guidField = IID_IDAOField;
#endif
// Get the field item
DAO_CHECK(pDAOIndexFields->get_Item(COleVariant(nIndex), &var));
DAO_CHECK(var.pdispVal->QueryInterface(
guidField, (void**)&pDAOField));
var.Clear();
// Get the field name
DAO_CHECK(pDAOField->get_Name(&V_BSTR(&var)));
var.vt = VT_BSTR;
indexinfo.m_pFieldInfos[nIndex].m_strName = V_BSTRT(&var);
var.Clear();
// Get the field attributes
DAO_CHECK(pDAOField->get_Attributes(&lAttributes));
indexinfo.m_pFieldInfos[nIndex].m_bDescending =
(lAttributes & dbDescending);
// Release and reset the field object
pDAOField->Release();
pDAOField = NULL;
}
// Release the index fields object
pDAOIndexFields->Release();
}
CATCH_ALL(e)
{
// Release the field object if necessary
if (pDAOField != NULL)
pDAOField->Release();
// Must always release index fields collection
pDAOIndexFields->Release();
THROW_LAST();
}
END_CATCH_ALL
}
void AFX_CDECL AfxSetIndexFieldInfo(DAOIndex* pDAOIndex, CDaoIndexInfo& indexinfo)
{
COleVariant var;
long lAttributes;
DAOIndexFields* pDAOIndexFields = NULL;
DAOField* pDAOField = NULL;
// Get the index fields collection
AfxGetIndexFields(pDAOIndex, &pDAOIndexFields);
TRY
{
for (int nIndex = 0; nIndex < indexinfo.m_nFields; nIndex++)
{
// Create the field and set the name
DAO_CHECK(pDAOIndex->CreateField(
COleVariant(indexinfo.m_pFieldInfos[nIndex].m_strName, VT_BSTRT),
_afxOptionalVariant, _afxOptionalVariant, &pDAOField));
// Set the descending property
if (indexinfo.m_pFieldInfos[nIndex].m_bDescending)
lAttributes = dbDescending;
else
lAttributes = 0;
DAO_CHECK(pDAOField->put_Attributes(lAttributes));
// Append field to collection, release and reset
pDAOIndexFields->Append(pDAOField);
pDAOField->Release();
pDAOField = NULL;
}
// Always release the index fields object
pDAOIndexFields->Release();
}
CATCH_ALL(e)
{
if (pDAOField != NULL)
pDAOField->Release();
pDAOIndexFields->Release();
THROW_LAST();
}
END_CATCH_ALL
}
//////////////////////////////////////////////////////////////////////////////
// GetRows helper
void AFX_CDECL ThrowGetRowsDaoException(SCODE scode)
{
switch (scode)
{
case E_OUTOFMEMORY:
AfxThrowMemoryException();
default:
AfxThrowDaoException(NO_AFX_DAO_ERROR, scode);
// These are only (known) DAO 3.0 GetRows errors
case E_ROWTOOSHORT:
case E_BADBINDINFO:
case E_COLUMNUNAVAILABLE:
break;
}
CDaoException* pException;
pException = new CDaoException;
pException->m_pErrorInfo = new CDaoErrorInfo;
// Fill out the DAO error info struct
pException->m_scode = scode;
pException->m_pErrorInfo->m_strSource = _T("ICDAORecordset.GetRows");
pException->m_pErrorInfo->m_lErrorCode = LOWORD(scode);
// There is no help context or help file
pException->m_pErrorInfo->m_lHelpContext = 0;
int nID = 0;
if (scode == E_ROWTOOSHORT)
nID = AFX_IDP_DAO_ROWTOOSHORT;
else if (scode == E_BADBINDINFO)
nID = AFX_IDP_DAO_BADBINDINFO;
else
nID = AFX_IDP_DAO_COLUMNUNAVAILABLE;
VERIFY(pException->m_pErrorInfo->m_strDescription.LoadString(nID));
#ifdef _DEBUG
if (afxTraceFlags & traceDatabase)
{
TRACE1("\nError Code = %d\n",
pException->m_pErrorInfo->m_lErrorCode);
TRACE1("Source = %s\n",
(LPCTSTR)pException->m_pErrorInfo->m_strSource);
TRACE1("Description = %s\n",
(LPCTSTR)pException->m_pErrorInfo->m_strDescription);
}
#endif
THROW(pException);
}
//////////////////////////////////////////////////////////////////////////////
// _AFX_DAO_STATE helper
_AFX_DAO_STATE* AFX_CDECL AfxGetDaoState()
{
// The DAO state is store in the module state
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
_AFX_DAO_STATE* pDaoState = pModuleState->m_pDaoState;
// Allocate a new DAO state if necessary
if (pDaoState == NULL)
{
pDaoState = new _AFX_DAO_STATE;
pModuleState->m_pDaoState = pDaoState;
}
return pDaoState;
}
//////////////////////////////////////////////////////////////////////////////
// DAODBEngine helpers
void AFXAPI AfxDaoInit()
{
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
// Attempt to initialize OLE component objects
// (use default IMalloc allocator)
DAO_CHECK_ERROR(::CoInitialize(NULL),
AFX_DAO_ERROR_ENGINE_INITIALIZATION);
pDaoState->m_bOleInitialized = TRUE;
// Hook AfxDaoTerm to CWinApp, otherwise explicit AfxDaoTerm call req'd
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
pApp->m_lpfnDaoTerm = AfxDaoTerm;
// Set the interface type
GUID guidEngine;
#ifdef _UNICODE
guidEngine = IID_IDAODBEngineW;
#else
guidEngine = IID_IDAODBEngine;
#endif
LPCLASSFACTORY2 pCF2;
DAO_CHECK_ERROR(::CoGetClassObject(CLSID_CDAODBEngine,
CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory2, (LPVOID*)&pCF2),
AFX_DAO_ERROR_ENGINE_INITIALIZATION);
TRY
{
// DAO runtime key
COleVariant varKey(_T("mjgcqcejfchcijecpdhckcdjqigdejfccjri"));
DAO_CHECK_ERROR(pCF2->CreateInstanceLic( NULL, NULL, guidEngine,
V_BSTR(&varKey), (LPVOID*)&pDaoState->m_pDAODBEngine),
AFX_DAO_ERROR_ENGINE_INITIALIZATION);
}
CATCH_ALL(e)
{
pCF2->Release();
THROW_LAST();
}
END_CATCH_ALL
pCF2->Release();
}
DAODBEngine* AFXAPI AfxDaoGetEngine()
{
// Return DAODBEngine object for direct access
return AfxGetDaoState()->m_pDAODBEngine;
}
void AFXAPI AfxDaoTerm()
{
_AFX_DAO_STATE* pDaoState = AfxGetDaoState();
// Close any CDaoWorkspaces left around
void* pvKey;
void* pvObject;
POSITION pos = pDaoState->m_mapWorkspaces.GetStartPosition();
while (pos != NULL)
{
pDaoState->m_mapWorkspaces.GetNextAssoc(pos, pvKey, pvObject);
((CDaoWorkspace*)pvObject)->Close();
}
pDaoState->m_mapWorkspaces.RemoveAll();
// Clean up engine object if necessary
if (pDaoState->m_pDAODBEngine != NULL)
{
pDaoState->m_pDAODBEngine->Release();
pDaoState->m_pDAODBEngine = NULL;
}
// Shutdown OLE component objects if necessary
if (pDaoState->m_bOleInitialized)
{
::CoUninitialize();
pDaoState->m_bOleInitialized = FALSE;
}
// If hooked up to CWinApp, make sure to unhook
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
pApp->m_lpfnDaoTerm = NULL;
}
//////////////////////////////////////////////////////////////////////////////
// Inline function declarations expanded out-of-line
#ifndef _AFX_ENABLE_INLINES
static char _szAfxDaoInl[] = "afxdao.inl";
#undef THIS_FILE
#define THIS_FILE _szAfxDaoInl
#define _AFXDAOCORE_INLINE
#include "afxdao.inl"
#endif
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
#pragma warning(disable: 4074)
#pragma init_seg(lib)
/////////////////////////////////////////////////////////////////////////////